Skip to content

Commit 1108ceb

Browse files
authored
Surface diagnostic instead of panic when morpher fails to determine terraform type (#2018)
1 parent 04c9b76 commit 1108ceb

File tree

2 files changed

+47
-18
lines changed

2 files changed

+47
-18
lines changed

.changelog/2018.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:note
2+
manifest/morph.go: Add Diagnostic message when determining a type fails
3+
```

manifest/morph/morph.go

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func ValueToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath) (tft
2626
return tftypes.Value{}, diags
2727
}
2828
if v.IsNull() {
29-
return tftypes.NewValue(t, nil), nil
29+
return newValue(t, nil, p)
3030
}
3131
switch {
3232
case v.Type().Is(tftypes.String):
@@ -84,7 +84,7 @@ func morphBoolToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath)
8484
}
8585
switch {
8686
case t.Is(tftypes.String):
87-
return tftypes.NewValue(t, strconv.FormatBool(bnat)), nil
87+
return newValue(t, strconv.FormatBool(bnat), p)
8888
case t.Is(tftypes.DynamicPseudoType):
8989
return v, diags
9090
}
@@ -115,7 +115,7 @@ func morphNumberToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath
115115
}
116116
switch {
117117
case t.Is(tftypes.String):
118-
return tftypes.NewValue(t, vnat.String()), nil
118+
return newValue(t, vnat.String(), p)
119119
case t.Is(tftypes.DynamicPseudoType):
120120
return v, diags
121121
}
@@ -157,7 +157,7 @@ func morphStringToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath
157157
return tftypes.Value{}, diags
158158
}
159159
nv := new(big.Float).SetFloat64(fv)
160-
return tftypes.NewValue(t, nv), nil
160+
return newValue(t, nv, p)
161161
case t.Is(tftypes.Bool):
162162
bv, err := strconv.ParseBool(vnat)
163163
if err != nil {
@@ -169,7 +169,7 @@ func morphStringToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath
169169
})
170170
return tftypes.Value{}, diags
171171
}
172-
return tftypes.NewValue(t, bv), nil
172+
return newValue(t, bv, p)
173173
case t.Is(tftypes.DynamicPseudoType):
174174
return v, diags
175175
}
@@ -217,7 +217,7 @@ func morphListToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath)
217217
}
218218
nlvals[i] = nv
219219
}
220-
return tftypes.NewValue(t, nlvals), nil
220+
return newValue(t, nlvals, p)
221221
case t.Is(tftypes.Tuple{}):
222222
if len(t.(tftypes.Tuple).ElementTypes) != len(lvals) {
223223
diags = append(diags, &tfprotov5.Diagnostic{
@@ -248,7 +248,7 @@ func morphListToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath)
248248
}
249249
tvals[i] = nv
250250
}
251-
return tftypes.NewValue(t, tvals), nil
251+
return newValue(t, tvals, p)
252252
case t.Is(tftypes.Set{}):
253253
var svals []tftypes.Value = make([]tftypes.Value, len(lvals))
254254
for i, v := range lvals {
@@ -270,7 +270,7 @@ func morphListToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath)
270270
}
271271
svals[i] = nv
272272
}
273-
return tftypes.NewValue(t, svals), nil
273+
return newValue(t, svals, p)
274274
case t.Is(tftypes.DynamicPseudoType):
275275
return v, diags
276276
}
@@ -339,7 +339,7 @@ func morphTupleIntoType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePat
339339
lvals[i] = nv
340340
eltypes[i] = nv.Type()
341341
}
342-
return tftypes.NewValue(tftypes.Tuple{ElementTypes: eltypes}, lvals), diags
342+
return newValue(tftypes.Tuple{ElementTypes: eltypes}, lvals, p)
343343
case t.Is(tftypes.List{}):
344344
var lvals []tftypes.Value = make([]tftypes.Value, len(tvals))
345345
for i, v := range tvals {
@@ -361,7 +361,7 @@ func morphTupleIntoType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePat
361361
}
362362
lvals[i] = nv
363363
}
364-
return tftypes.NewValue(t, lvals), diags
364+
return newValue(t, lvals, p)
365365
case t.Is(tftypes.Set{}):
366366
var svals []tftypes.Value = make([]tftypes.Value, len(tvals))
367367
for i, v := range tvals {
@@ -383,7 +383,7 @@ func morphTupleIntoType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePat
383383
}
384384
svals[i] = nv
385385
}
386-
return tftypes.NewValue(t, svals), diags
386+
return newValue(t, svals, p)
387387
case t.Is(tftypes.DynamicPseudoType):
388388
return v, diags
389389
}
@@ -431,7 +431,7 @@ func morphSetToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath) (
431431
}
432432
svals[i] = nv
433433
}
434-
return tftypes.NewValue(t, svals), diags
434+
return newValue(t, svals, p)
435435
case t.Is(tftypes.List{}):
436436
var lvals []tftypes.Value = make([]tftypes.Value, len(svals))
437437
for i, v := range svals {
@@ -453,7 +453,7 @@ func morphSetToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath) (
453453
}
454454
lvals[i] = nv
455455
}
456-
return tftypes.NewValue(t, lvals), diags
456+
return newValue(t, lvals, p)
457457
case t.Is(tftypes.Tuple{}):
458458
if len(t.(tftypes.Tuple).ElementTypes) != len(svals) {
459459
diags = append(diags, &tfprotov5.Diagnostic{
@@ -484,7 +484,7 @@ func morphSetToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath) (
484484
}
485485
tvals[i] = nv
486486
}
487-
return tftypes.NewValue(t, tvals), diags
487+
return newValue(t, tvals, p)
488488
case t.Is(tftypes.DynamicPseudoType):
489489
return v, diags
490490
}
@@ -542,7 +542,7 @@ func morphMapToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath) (
542542
}
543543
ovals[k] = nv
544544
}
545-
return tftypes.NewValue(t, ovals), diags
545+
return newValue(t, ovals, p)
546546
case t.Is(tftypes.Map{}):
547547
var nmvals map[string]tftypes.Value = make(map[string]tftypes.Value, len(mvals))
548548
for k, v := range mvals {
@@ -564,7 +564,7 @@ func morphMapToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath) (
564564
}
565565
nmvals[k] = nv
566566
}
567-
return tftypes.NewValue(t, nmvals), diags
567+
return newValue(t, nmvals, p)
568568
case t.Is(tftypes.DynamicPseudoType):
569569
return v, diags
570570
}
@@ -626,7 +626,12 @@ func morphObjectToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath
626626
// tftypes.NewValue() fails if any of the attributes in the object don't have a corresponding value
627627
for k := range t.(tftypes.Object).AttributeTypes {
628628
if _, ok := ovals[k]; !ok {
629-
ovals[k] = tftypes.NewValue(t.(tftypes.Object).AttributeTypes[k], nil)
629+
nv, d := newValue(t.(tftypes.Object).AttributeTypes[k], nil, p)
630+
if d != nil {
631+
diags = append(diags, d...)
632+
return tftypes.Value{}, diags
633+
}
634+
ovals[k] = nv
630635
}
631636
}
632637
otypes := make(map[string]tftypes.Type, len(ovals))
@@ -655,7 +660,7 @@ func morphObjectToType(v tftypes.Value, t tftypes.Type, p *tftypes.AttributePath
655660
}
656661
mvals[k] = nv
657662
}
658-
return tftypes.NewValue(t, mvals), diags
663+
return newValue(t, mvals, p)
659664
case t.Is(tftypes.DynamicPseudoType):
660665
return v, diags
661666
}
@@ -713,3 +718,24 @@ func attributePathSummary(p *tftypes.AttributePath) string {
713718
}
714719
return b.String()
715720
}
721+
722+
func validateValue(t tftypes.Type, val interface{}, p *tftypes.AttributePath) []*tfprotov5.Diagnostic {
723+
var diags []*tfprotov5.Diagnostic
724+
if err := tftypes.ValidateValue(t, val); err != nil {
725+
diags = append(diags, &tfprotov5.Diagnostic{
726+
Attribute: p,
727+
Severity: tfprotov5.DiagnosticSeverityError,
728+
Summary: "Provider encountered an error when trying to determine the Terraform type information for the configured manifest",
729+
Detail: err.(error).Error(),
730+
})
731+
return diags
732+
}
733+
return nil
734+
}
735+
736+
func newValue(t tftypes.Type, val interface{}, p *tftypes.AttributePath) (tftypes.Value, []*tfprotov5.Diagnostic) {
737+
if diags := validateValue(t, val, p); diags != nil {
738+
return tftypes.Value{}, diags
739+
}
740+
return tftypes.NewValue(t, val), nil
741+
}

0 commit comments

Comments
 (0)