diff --git a/terraform/evaluate.go b/terraform/evaluate.go index 0647bb68e..9d3e565b4 100644 --- a/terraform/evaluate.go +++ b/terraform/evaluate.go @@ -426,6 +426,10 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc } instance[cfg.Name] = outputState + + if cfg.Sensitive { + instance[cfg.Name] = outputState.Mark("sensitive") + } } // any pending changes override the state state values @@ -451,6 +455,10 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc } instance[cfg.Name] = change.After + + if change.Sensitive { + instance[cfg.Name] = change.After.Mark("sensitive") + } } } diff --git a/terraform/evaluate_test.go b/terraform/evaluate_test.go index d5b13893e..3957d283e 100644 --- a/terraform/evaluate_test.go +++ b/terraform/evaluate_test.go @@ -9,6 +9,8 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -121,3 +123,108 @@ func TestEvaluatorGetInputVariable(t *testing.T) { t.Errorf("wrong result %#v; want %#v", got, want) } } + +func TestEvaluatorGetModule(t *testing.T) { + // Create a new evaluator with an existing state + stateSync := states.BuildState(func(ss *states.SyncState) { + ss.SetOutputValue( + addrs.OutputValue{Name: "out"}.Absolute(addrs.ModuleInstance{addrs.ModuleInstanceStep{Name: "mod"}}), + cty.StringVal("bar"), + true, + ) + }).SyncWrapper() + evaluator := evaluatorForModule(stateSync, plans.NewChanges().SyncWrapper()) + data := &evaluationStateData{ + Evaluator: evaluator, + } + scope := evaluator.Scope(data, nil) + want := cty.ObjectVal(map[string]cty.Value{"out": cty.StringVal("bar").Mark("sensitive")}) + got, diags := scope.Data.GetModule(addrs.ModuleCall{ + Name: "mod", + }, tfdiags.SourceRange{}) + + if len(diags) != 0 { + t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) + } + if !got.RawEquals(want) { + t.Errorf("wrong result %#v; want %#v", got, want) + } + + // Changes should override the state value + changesSync := plans.NewChanges().SyncWrapper() + change := &plans.OutputChange{ + Addr: addrs.OutputValue{Name: "out"}.Absolute(addrs.ModuleInstance{addrs.ModuleInstanceStep{Name: "mod"}}), + Sensitive: true, + Change: plans.Change{ + After: cty.StringVal("baz"), + }, + } + cs, _ := change.Encode() + changesSync.AppendOutputChange(cs) + evaluator = evaluatorForModule(stateSync, changesSync) + data = &evaluationStateData{ + Evaluator: evaluator, + } + scope = evaluator.Scope(data, nil) + want = cty.ObjectVal(map[string]cty.Value{"out": cty.StringVal("baz").Mark("sensitive")}) + got, diags = scope.Data.GetModule(addrs.ModuleCall{ + Name: "mod", + }, tfdiags.SourceRange{}) + + if len(diags) != 0 { + t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) + } + if !got.RawEquals(want) { + t.Errorf("wrong result %#v; want %#v", got, want) + } + + // Test changes with empty state + evaluator = evaluatorForModule(states.NewState().SyncWrapper(), changesSync) + data = &evaluationStateData{ + Evaluator: evaluator, + } + scope = evaluator.Scope(data, nil) + want = cty.ObjectVal(map[string]cty.Value{"out": cty.StringVal("baz").Mark("sensitive")}) + got, diags = scope.Data.GetModule(addrs.ModuleCall{ + Name: "mod", + }, tfdiags.SourceRange{}) + + if len(diags) != 0 { + t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) + } + if !got.RawEquals(want) { + t.Errorf("wrong result %#v; want %#v", got, want) + } +} + +func evaluatorForModule(stateSync *states.SyncState, changesSync *plans.ChangesSync) *Evaluator { + return &Evaluator{ + Meta: &ContextMeta{ + Env: "foo", + }, + Config: &configs.Config{ + Module: &configs.Module{ + ModuleCalls: map[string]*configs.ModuleCall{ + "mod": { + Name: "mod", + }, + }, + }, + Children: map[string]*configs.Config{ + "mod": { + Path: addrs.Module{"module.mod"}, + Module: &configs.Module{ + Outputs: map[string]*configs.Output{ + "out": { + Name: "out", + Sensitive: true, + }, + }, + }, + }, + }, + }, + State: stateSync, + Changes: changesSync, + } +}