decode output ChangeSrc rather than value

When an output change was decoded, we were decoding the raw value rather
than the ChangeSrc, which lost any encoded marks for that value.
This commit is contained in:
James Bardin 2021-05-11 17:55:27 -04:00
parent e29eb78cfd
commit f0ee0ef5cc
2 changed files with 65 additions and 2 deletions

View File

@ -446,3 +446,64 @@ resource "test_resource" "b" {
t.Fatal(diags.ErrWithWarnings())
}
}
func TestContext2Apply_sensitiveOutputPassthrough(t *testing.T) {
// Ensure we're not trying to double-mark values decoded from state
m := testModuleInline(t, map[string]string{
"main.tf": `
module "mod" {
source = "./mod"
}
resource "test_object" "a" {
test_string = module.mod.out
}
`,
"mod/main.tf": `
variable "in" {
sensitive = true
default = "foo"
}
output "out" {
value = var.in
}
`,
})
p := simpleMockProvider()
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})
_, diags := ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.ErrWithWarnings())
}
state, diags := ctx.Apply()
if diags.HasErrors() {
t.Fatal(diags.ErrWithWarnings())
}
obj := state.ResourceInstance(mustResourceInstanceAddr("test_object.a"))
if len(obj.Current.AttrSensitivePaths) != 1 {
t.Fatalf("Expected 1 sensitive mark for test_object.a, got %#v\n", obj.Current.AttrSensitivePaths)
}
plan, diags := ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.ErrWithWarnings())
}
// make sure the same marks are compared in the next plan as well
for _, c := range plan.Changes.Resources {
if c.Action != plans.NoOp {
t.Errorf("Unexpcetd %s change for %s", c.Action, c.Addr)
}
}
}

View File

@ -259,9 +259,11 @@ func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) (diags
// we we have a change recorded, we don't need to re-evaluate if the value
// was known
if changeRecorded {
var err error
val, err = n.Change.After.Decode(cty.DynamicPseudoType)
change, err := n.Change.Decode()
diags = diags.Append(err)
if err == nil {
val = change.After
}
}
// If there was no change recorded, or the recorded change was not wholly