|
|
|
|
@ -15,6 +15,7 @@ import (
|
|
|
|
|
terraformProvider "github.com/hashicorp/terraform/internal/builtin/providers/terraform"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/collections"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/configs/configschema"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/lang/marks"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/plans"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/providers"
|
|
|
|
|
"github.com/hashicorp/terraform/internal/stacks/stackaddrs"
|
|
|
|
|
@ -236,6 +237,152 @@ func TestPlanVariableOutputRoundtripNested(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cmpCollectionsSet = cmp.Comparer(func(x, y collections.Set[stackaddrs.AbsComponent]) bool {
|
|
|
|
|
if x.Len() != y.Len() {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, v := range x.Elems() {
|
|
|
|
|
if !y.Has(v) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
func TestPlanSensitiveOutput(t *testing.T) {
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
cfg := loadMainBundleConfigForTest(t, "sensitive-output")
|
|
|
|
|
|
|
|
|
|
fakePlanTimestamp, err := time.Parse(time.RFC3339, "1991-08-25T20:57:08Z")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
changesCh := make(chan stackplan.PlannedChange, 8)
|
|
|
|
|
diagsCh := make(chan tfdiags.Diagnostic, 2)
|
|
|
|
|
req := PlanRequest{
|
|
|
|
|
Config: cfg,
|
|
|
|
|
ForcePlanTimestamp: &fakePlanTimestamp,
|
|
|
|
|
}
|
|
|
|
|
resp := PlanResponse{
|
|
|
|
|
PlannedChanges: changesCh,
|
|
|
|
|
Diagnostics: diagsCh,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
go Plan(ctx, &req, &resp)
|
|
|
|
|
gotChanges, diags := collectPlanOutput(changesCh, diagsCh)
|
|
|
|
|
|
|
|
|
|
if len(diags) != 0 {
|
|
|
|
|
t.Errorf("unexpected diagnostics\n%s", diags.ErrWithWarnings().Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wantChanges := []stackplan.PlannedChange{
|
|
|
|
|
&stackplan.PlannedChangeApplyable{
|
|
|
|
|
Applyable: true,
|
|
|
|
|
},
|
|
|
|
|
&stackplan.PlannedChangeComponentInstance{
|
|
|
|
|
Addr: stackaddrs.Absolute(
|
|
|
|
|
stackaddrs.RootStackInstance,
|
|
|
|
|
stackaddrs.ComponentInstance{
|
|
|
|
|
Component: stackaddrs.Component{Name: "self"},
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
Action: plans.Create,
|
|
|
|
|
PlannedInputValues: make(map[string]plans.DynamicValue),
|
|
|
|
|
PlannedOutputValues: map[string]cty.Value{
|
|
|
|
|
"out": cty.StringVal("secret").Mark(marks.Sensitive),
|
|
|
|
|
},
|
|
|
|
|
PlanTimestamp: fakePlanTimestamp,
|
|
|
|
|
},
|
|
|
|
|
&stackplan.PlannedChangeHeader{
|
|
|
|
|
TerraformVersion: version.SemVer,
|
|
|
|
|
},
|
|
|
|
|
&stackplan.PlannedChangeOutputValue{
|
|
|
|
|
Addr: stackaddrs.OutputValue{Name: "result"},
|
|
|
|
|
Action: plans.Create,
|
|
|
|
|
OldValue: plans.DynamicValue{0xc0}, // MessagePack nil
|
|
|
|
|
NewValue: mustPlanDynamicValue(cty.StringVal("secret")),
|
|
|
|
|
NewValueMarks: []cty.PathValueMarks{{Marks: cty.NewValueMarks(marks.Sensitive)}},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
sort.SliceStable(gotChanges, func(i, j int) bool {
|
|
|
|
|
// An arbitrary sort just to make the result stable for comparison.
|
|
|
|
|
return fmt.Sprintf("%T", gotChanges[i]) < fmt.Sprintf("%T", gotChanges[j])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantChanges, gotChanges, ctydebug.CmpOptions, cmpCollectionsSet); diff != "" {
|
|
|
|
|
t.Errorf("wrong changes\n%s", diff)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPlanSensitiveOutputNested(t *testing.T) {
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
cfg := loadMainBundleConfigForTest(t, "sensitive-output-nested")
|
|
|
|
|
|
|
|
|
|
fakePlanTimestamp, err := time.Parse(time.RFC3339, "1991-08-25T20:57:08Z")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
changesCh := make(chan stackplan.PlannedChange, 8)
|
|
|
|
|
diagsCh := make(chan tfdiags.Diagnostic, 2)
|
|
|
|
|
req := PlanRequest{
|
|
|
|
|
Config: cfg,
|
|
|
|
|
ForcePlanTimestamp: &fakePlanTimestamp,
|
|
|
|
|
}
|
|
|
|
|
resp := PlanResponse{
|
|
|
|
|
PlannedChanges: changesCh,
|
|
|
|
|
Diagnostics: diagsCh,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
go Plan(ctx, &req, &resp)
|
|
|
|
|
gotChanges, diags := collectPlanOutput(changesCh, diagsCh)
|
|
|
|
|
|
|
|
|
|
if len(diags) != 0 {
|
|
|
|
|
t.Errorf("unexpected diagnostics\n%s", diags.ErrWithWarnings().Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wantChanges := []stackplan.PlannedChange{
|
|
|
|
|
&stackplan.PlannedChangeApplyable{
|
|
|
|
|
Applyable: true,
|
|
|
|
|
},
|
|
|
|
|
&stackplan.PlannedChangeComponentInstance{
|
|
|
|
|
Addr: stackaddrs.Absolute(
|
|
|
|
|
stackaddrs.RootStackInstance.Child("child", addrs.NoKey),
|
|
|
|
|
stackaddrs.ComponentInstance{
|
|
|
|
|
Component: stackaddrs.Component{Name: "self"},
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
Action: plans.Create,
|
|
|
|
|
PlannedInputValues: make(map[string]plans.DynamicValue),
|
|
|
|
|
PlannedOutputValues: map[string]cty.Value{
|
|
|
|
|
"out": cty.StringVal("secret").Mark(marks.Sensitive),
|
|
|
|
|
},
|
|
|
|
|
PlanTimestamp: fakePlanTimestamp,
|
|
|
|
|
},
|
|
|
|
|
&stackplan.PlannedChangeHeader{
|
|
|
|
|
TerraformVersion: version.SemVer,
|
|
|
|
|
},
|
|
|
|
|
&stackplan.PlannedChangeOutputValue{
|
|
|
|
|
Addr: stackaddrs.OutputValue{Name: "result"},
|
|
|
|
|
Action: plans.Create,
|
|
|
|
|
OldValue: plans.DynamicValue{0xc0}, // MessagePack nil
|
|
|
|
|
NewValue: mustPlanDynamicValue(cty.StringVal("secret")),
|
|
|
|
|
NewValueMarks: []cty.PathValueMarks{{Marks: cty.NewValueMarks(marks.Sensitive)}},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
sort.SliceStable(gotChanges, func(i, j int) bool {
|
|
|
|
|
// An arbitrary sort just to make the result stable for comparison.
|
|
|
|
|
return fmt.Sprintf("%T", gotChanges[i]) < fmt.Sprintf("%T", gotChanges[j])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if diff := cmp.Diff(wantChanges, gotChanges, ctydebug.CmpOptions, cmpCollectionsSet); diff != "" {
|
|
|
|
|
t.Errorf("wrong changes\n%s", diff)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPlanWithProviderConfig(t *testing.T) {
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
cfg := loadMainBundleConfigForTest(t, "with-provider-config")
|
|
|
|
|
|