Merge pull request #28326 from hashicorp/alisdair/allow-nonsensitive-on-non-sensitive-values

lang/funcs: Make nonsensitive more permissive
This commit is contained in:
Alisdair McDiarmid 2021-04-12 14:00:41 -04:00 committed by GitHub
commit 33e5d111fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 6 deletions

View File

@ -48,7 +48,7 @@ var NonsensitiveFunc = function.New(&function.Spec{
return args[0].Type(), nil
},
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
if !args[0].HasMark("sensitive") {
if args[0].IsKnown() && !args[0].HasMark("sensitive") {
return cty.DynamicVal, function.NewArgErrorf(0, "the given value is not sensitive, so this call is redundant")
}
v, marks := args[0].Unmark()

View File

@ -133,17 +133,20 @@ func TestNonsensitive(t *testing.T) {
cty.NumberIntVal(1),
`the given value is not sensitive, so this call is redundant`,
},
{
cty.DynamicVal,
`the given value is not sensitive, so this call is redundant`,
},
{
cty.NullVal(cty.String),
`the given value is not sensitive, so this call is redundant`,
},
// Unknown values may become sensitive once they are known, so we
// permit them to be marked nonsensitive.
{
cty.DynamicVal,
``,
},
{
cty.UnknownVal(cty.String),
`the given value is not sensitive, so this call is redundant`,
``,
},
}

View File

@ -377,3 +377,65 @@ resource "test_object" "a" {
}
}
}
func TestContext2Plan_unmarkingSensitiveAttributeForOutput(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
resource "test_resource" "foo" {
}
output "result" {
value = nonsensitive(test_resource.foo.sensitive_attr)
}
`,
})
p := new(MockProvider)
p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(&ProviderSchema{
ResourceTypes: map[string]*configschema.Block{
"test_resource": {
Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Computed: true,
},
"sensitive_attr": {
Type: cty.String,
Computed: true,
Sensitive: true,
},
},
},
},
})
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
return providers.PlanResourceChangeResponse{
PlannedState: cty.UnknownVal(cty.Object(map[string]cty.Type{
"id": cty.String,
"sensitive_attr": cty.String,
})),
}
}
state := states.NewState()
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
State: state,
})
plan, diags := ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.ErrWithWarnings())
}
for _, res := range plan.Changes.Resources {
if res.Action != plans.Create {
t.Fatalf("expected create, got: %q %s", res.Addr, res.Action)
}
}
}