add (forces new resource) to provider test diffs
Add the (forces new resource) annotation to the diff output for provider tests failures when we can. This helps providers narrow down what might be triggering changes when encountering test failures with the new SDK.
This commit is contained in:
parent
2e15f6f585
commit
bb62aba651
|
@ -251,3 +251,26 @@ func pathFromFlatmapKeySet(key string, ty cty.Type) (cty.Path, error) {
|
||||||
// set as a whole changed.
|
// set as a whole changed.
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlatmapKeyFromPath returns the flatmap equivalent of the given cty.Path for
|
||||||
|
// use in generating legacy style diffs.
|
||||||
|
func FlatmapKeyFromPath(path cty.Path) string {
|
||||||
|
var parts []string
|
||||||
|
|
||||||
|
for _, step := range path {
|
||||||
|
switch step := step.(type) {
|
||||||
|
case cty.GetAttrStep:
|
||||||
|
parts = append(parts, step.Name)
|
||||||
|
case cty.IndexStep:
|
||||||
|
switch ty := step.Key.Type(); {
|
||||||
|
case ty == cty.String:
|
||||||
|
parts = append(parts, step.Key.AsString())
|
||||||
|
case ty == cty.Number:
|
||||||
|
i, _ := step.Key.AsBigFloat().Int64()
|
||||||
|
parts = append(parts, strconv.Itoa(int(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(parts, ".")
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package hcl2shim
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -365,5 +366,43 @@ func TestRequiresReplace(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFlatmapKeyFromPath(t *testing.T) {
|
||||||
|
for i, tc := range []struct {
|
||||||
|
path cty.Path
|
||||||
|
attr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
path: cty.Path{
|
||||||
|
cty.GetAttrStep{Name: "force_new"},
|
||||||
|
},
|
||||||
|
attr: "force_new",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: cty.Path{
|
||||||
|
cty.GetAttrStep{Name: "attr"},
|
||||||
|
cty.IndexStep{Key: cty.NumberIntVal(0)},
|
||||||
|
cty.GetAttrStep{Name: "force_new"},
|
||||||
|
},
|
||||||
|
attr: "attr.0.force_new",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: cty.Path{
|
||||||
|
cty.GetAttrStep{Name: "attr"},
|
||||||
|
cty.IndexStep{Key: cty.StringVal("key")},
|
||||||
|
cty.GetAttrStep{Name: "obj_attr"},
|
||||||
|
cty.IndexStep{Key: cty.NumberIntVal(0)},
|
||||||
|
cty.GetAttrStep{Name: "force_new"},
|
||||||
|
},
|
||||||
|
attr: "attr.key.obj_attr.0.force_new",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
|
attr := FlatmapKeyFromPath(tc.path)
|
||||||
|
if attr != tc.attr {
|
||||||
|
t.Fatalf("expected:%q got:%q", tc.attr, attr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ func legacyDiffComparisonString(changes *plans.Changes) string {
|
||||||
}
|
}
|
||||||
byModule := map[string]map[string]*ResourceChanges{}
|
byModule := map[string]map[string]*ResourceChanges{}
|
||||||
resourceKeys := map[string][]string{}
|
resourceKeys := map[string][]string{}
|
||||||
|
requiresReplace := map[string][]string{}
|
||||||
var moduleKeys []string
|
var moduleKeys []string
|
||||||
for _, rc := range changes.Resources {
|
for _, rc := range changes.Resources {
|
||||||
if rc.Action == plans.NoOp {
|
if rc.Action == plans.NoOp {
|
||||||
|
@ -239,6 +240,12 @@ func legacyDiffComparisonString(changes *plans.Changes) string {
|
||||||
} else {
|
} else {
|
||||||
byModule[moduleKey][resourceKey].Deposed[rc.DeposedKey] = rc
|
byModule[moduleKey][resourceKey].Deposed[rc.DeposedKey] = rc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rr := []string{}
|
||||||
|
for _, p := range rc.RequiredReplace.List() {
|
||||||
|
rr = append(rr, hcl2shim.FlatmapKeyFromPath(p))
|
||||||
|
}
|
||||||
|
requiresReplace[resourceKey] = rr
|
||||||
}
|
}
|
||||||
sort.Strings(moduleKeys)
|
sort.Strings(moduleKeys)
|
||||||
for _, ks := range resourceKeys {
|
for _, ks := range resourceKeys {
|
||||||
|
@ -254,6 +261,8 @@ func legacyDiffComparisonString(changes *plans.Changes) string {
|
||||||
for _, resourceKey := range resourceKeys[moduleKey] {
|
for _, resourceKey := range resourceKeys[moduleKey] {
|
||||||
rc := rcs[resourceKey]
|
rc := rcs[resourceKey]
|
||||||
|
|
||||||
|
forceNewAttrs := requiresReplace[resourceKey]
|
||||||
|
|
||||||
crud := "UPDATE"
|
crud := "UPDATE"
|
||||||
if rc.Current != nil {
|
if rc.Current != nil {
|
||||||
switch rc.Current.Action {
|
switch rc.Current.Action {
|
||||||
|
@ -341,7 +350,17 @@ func legacyDiffComparisonString(changes *plans.Changes) string {
|
||||||
// at the core layer.
|
// at the core layer.
|
||||||
|
|
||||||
updateMsg := ""
|
updateMsg := ""
|
||||||
// TODO: Mark " (forces new resource)" in updateMsg when appropriate.
|
|
||||||
|
// This may not be as precise as in the old diff, as it matches
|
||||||
|
// everything under the attribute that was originally marked as
|
||||||
|
// ForceNew, but should help make it easier to determine what
|
||||||
|
// caused replacement here.
|
||||||
|
for _, k := range forceNewAttrs {
|
||||||
|
if strings.HasPrefix(attrK, k) {
|
||||||
|
updateMsg = " (forces new resource)"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintf(
|
fmt.Fprintf(
|
||||||
&mBuf, " %s:%s %#v => %#v%s\n",
|
&mBuf, " %s:%s %#v => %#v%s\n",
|
||||||
|
|
Loading…
Reference in New Issue