mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
We previously would optimize away the graph nodes for any resource instance without a real change pending, but that means we don't get an opportunity to re-check any invariants associated with the instance, such as preconditions and postconditions. Other upstream changes during apply can potentially decide the outcome of a condition even if the instance itself isn't being changed, so we do still need to revisit these during apply or else we might skip running certain checks altogether, if they yielded unknown results during planning and then don't get run during apply.
129 lines
3.3 KiB
Go
129 lines
3.3 KiB
Go
package terraform
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/terraform/internal/addrs"
|
|
"github.com/hashicorp/terraform/internal/plans"
|
|
)
|
|
|
|
func TestDiffTransformer_nilDiff(t *testing.T) {
|
|
g := Graph{Path: addrs.RootModuleInstance}
|
|
tf := &DiffTransformer{}
|
|
if err := tf.Transform(&g); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
if len(g.Vertices()) > 0 {
|
|
t.Fatal("graph should be empty")
|
|
}
|
|
}
|
|
|
|
func TestDiffTransformer(t *testing.T) {
|
|
g := Graph{Path: addrs.RootModuleInstance}
|
|
|
|
beforeVal, err := plans.NewDynamicValue(cty.StringVal(""), cty.String)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
afterVal, err := plans.NewDynamicValue(cty.StringVal(""), cty.String)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
tf := &DiffTransformer{
|
|
Changes: &plans.Changes{
|
|
Resources: []*plans.ResourceInstanceChangeSrc{
|
|
{
|
|
Addr: addrs.Resource{
|
|
Mode: addrs.ManagedResourceMode,
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
|
ProviderAddr: addrs.AbsProviderConfig{
|
|
Provider: addrs.NewDefaultProvider("aws"),
|
|
Module: addrs.RootModule,
|
|
},
|
|
ChangeSrc: plans.ChangeSrc{
|
|
Action: plans.Update,
|
|
Before: beforeVal,
|
|
After: afterVal,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
if err := tf.Transform(&g); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
actual := strings.TrimSpace(g.String())
|
|
expected := strings.TrimSpace(testTransformDiffBasicStr)
|
|
if actual != expected {
|
|
t.Fatalf("bad:\n\n%s", actual)
|
|
}
|
|
}
|
|
|
|
func TestDiffTransformer_noOpChange(t *testing.T) {
|
|
// "No-op" changes are how we record explicitly in a plan that we did
|
|
// indeed visit a particular resource instance during the planning phase
|
|
// and concluded that no changes were needed, as opposed to the resource
|
|
// instance not existing at all or having been excluded from planning
|
|
// entirely.
|
|
//
|
|
// We must include nodes for resource instances with no-op changes in the
|
|
// apply graph, even though they won't take any external actions, because
|
|
// there are some secondary effects such as precondition/postcondition
|
|
// checks that can refer to objects elsewhere and so might have their
|
|
// results changed even if the resource instance they are attached to
|
|
// didn't actually change directly itself.
|
|
|
|
g := Graph{Path: addrs.RootModuleInstance}
|
|
|
|
beforeVal, err := plans.NewDynamicValue(cty.StringVal(""), cty.String)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
tf := &DiffTransformer{
|
|
Changes: &plans.Changes{
|
|
Resources: []*plans.ResourceInstanceChangeSrc{
|
|
{
|
|
Addr: addrs.Resource{
|
|
Mode: addrs.ManagedResourceMode,
|
|
Type: "aws_instance",
|
|
Name: "foo",
|
|
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
|
|
ProviderAddr: addrs.AbsProviderConfig{
|
|
Provider: addrs.NewDefaultProvider("aws"),
|
|
Module: addrs.RootModule,
|
|
},
|
|
ChangeSrc: plans.ChangeSrc{
|
|
// A "no-op" change has the no-op action and has the
|
|
// same object as both Before and After.
|
|
Action: plans.NoOp,
|
|
Before: beforeVal,
|
|
After: beforeVal,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
if err := tf.Transform(&g); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
actual := strings.TrimSpace(g.String())
|
|
expected := strings.TrimSpace(testTransformDiffBasicStr)
|
|
if actual != expected {
|
|
t.Fatalf("bad:\n\n%s", actual)
|
|
}
|
|
}
|
|
|
|
const testTransformDiffBasicStr = `
|
|
aws_instance.foo
|
|
`
|