MCPcopy
hub / github.com/hashicorp/hcl / try

Function try

ext/tryfunc/tryfunc.go:64–127  ·  view source on GitHub ↗
(args []cty.Value)

Source from the content-addressed store, hash-verified

62}
63
64func try(args []cty.Value) (cty.Value, error) {
65 if len(args) == 0 {
66 return cty.NilVal, errors.New("at least one argument is required")
67 }
68
69 // We'll collect up all of the diagnostics we encounter along the way
70 // and report them all if none of the expressions succeed, so that the
71 // user might get some hints on how to make at least one succeed.
72 var diags hcl.Diagnostics
73 for _, arg := range args {
74 closure := customdecode.ExpressionClosureFromVal(arg)
75
76 v, moreDiags := closure.Value()
77 diags = append(diags, moreDiags...)
78
79 if moreDiags.HasErrors() {
80 // If there's an error we know it will always fail and can
81 // continue. A more refined value will not remove an error from
82 // the expression.
83 continue
84 }
85
86 if !v.IsWhollyKnown() {
87 // If there are any unknowns in the value at all, we cannot be
88 // certain that the final value will be consistent or have the same
89 // type, so wee need to be conservative and return a dynamic value.
90
91 // There are two different classes of failure that can happen when
92 // an expression transitions from unknown to known; an operation on
93 // a dynamic value becomes invalid for the type once the type is
94 // known, or an index expression on a collection fails once the
95 // collection value is known. These changes from a
96 // valid-partially-unknown expression to an invalid-known
97 // expression can produce inconsistent results by changing which
98 // "try" argument is returned, which may be a collection with
99 // different previously known values, or a different type entirely
100 // ("try" does not require consistent argument types)
101 return cty.DynamicVal, nil
102 }
103
104 return v, nil // ignore any accumulated diagnostics if one succeeds
105 }
106
107 // If we fall out here then none of the expressions succeeded, and so
108 // we must have at least one diagnostic and we'll return all of them
109 // so that the user can see the errors related to whichever one they
110 // were expecting to have succeeded in this case.
111 //
112 // Because our function must return a single error value rather than
113 // diagnostics, we'll construct a suitable error message string
114 // that will make sense in the context of the function call failure
115 // diagnostic HCL will eventually wrap this in.
116 var buf strings.Builder
117 buf.WriteString("no expression succeeded:\n")
118 for _, diag := range diags {
119 if diag.Subject != nil {
120 buf.WriteString(fmt.Sprintf("- %s (at %s)\n %s\n", diag.Summary, diag.Subject, diag.Detail))
121 } else {

Callers 2

initFunction · 0.85

Calls 4

ExpressionClosureFromValFunction · 0.92
HasErrorsMethod · 0.80
ValueMethod · 0.65
StringMethod · 0.45

Tested by 1