You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
terraform/internal/command/jsonplan/action_invocations_test.go

183 lines
4.8 KiB

// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package jsonplan
import (
"encoding/json"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/msgpack"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/configs/configschema"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/providers"
"github.com/hashicorp/terraform/internal/terraform"
)
func TestMarshalActionInvocations(t *testing.T) {
action := addrs.AbsActionInstance{
Module: addrs.RootModuleInstance,
Action: addrs.ActionInstance{
Action: addrs.Action{
Type: "test_action",
Name: "test",
},
Key: addrs.NoKey,
},
}
provider := addrs.AbsProviderConfig{
Module: addrs.RootModule,
Provider: addrs.Provider{
Type: "test",
Namespace: "hashicorp",
Hostname: addrs.DefaultProviderRegistryHost,
},
}
schemas := &terraform.Schemas{
Providers: map[addrs.Provider]providers.ProviderSchema{
provider.Provider: {
Actions: map[string]providers.ActionSchema{
"test_action": {
ConfigSchema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"optional": {
Type: cty.String,
},
"sensitive": {
Type: cty.String,
Sensitive: true,
},
},
},
},
},
},
},
}
tcs := map[string]struct {
input *plans.ActionInvocationInstanceSrc
output ActionInvocation
}{
"no metadata": {
input: &plans.ActionInvocationInstanceSrc{
Addr: action,
ActionTrigger: new(plans.InvokeActionTrigger),
ConfigValue: mustDynamicValue(t, cty.ObjectVal(map[string]cty.Value{
"optional": cty.StringVal("hello"),
"sensitive": cty.StringVal("world"),
})),
SensitiveConfigPaths: nil,
ProviderAddr: provider,
},
output: ActionInvocation{
Address: "action.test_action.test",
Type: "test_action",
Name: "test",
ConfigValues: mustJson(t, map[string]interface{}{
"optional": "hello",
"sensitive": "world",
}),
ConfigSensitive: mustJson(t, map[string]interface{}{
"sensitive": true,
}),
ConfigUnknown: mustJson(t, map[string]interface{}{}),
ProviderName: "registry.terraform.io/hashicorp/test",
InvokeActionTrigger: new(InvokeActionTrigger),
},
},
"unknown value": {
input: &plans.ActionInvocationInstanceSrc{
Addr: action,
ActionTrigger: new(plans.InvokeActionTrigger),
ConfigValue: mustDynamicValue(t, cty.ObjectVal(map[string]cty.Value{
"optional": cty.UnknownVal(cty.String),
"sensitive": cty.StringVal("world"),
})),
SensitiveConfigPaths: nil,
ProviderAddr: provider,
},
output: ActionInvocation{
Address: "action.test_action.test",
Type: "test_action",
Name: "test",
ConfigValues: mustJson(t, map[string]interface{}{
"sensitive": "world",
}),
ConfigSensitive: mustJson(t, map[string]interface{}{
"sensitive": true,
}),
ConfigUnknown: mustJson(t, map[string]interface{}{
"optional": true,
}),
ProviderName: "registry.terraform.io/hashicorp/test",
InvokeActionTrigger: new(InvokeActionTrigger),
},
},
"extra sensitive": {
input: &plans.ActionInvocationInstanceSrc{
Addr: action,
ActionTrigger: new(plans.InvokeActionTrigger),
ConfigValue: mustDynamicValue(t, cty.ObjectVal(map[string]cty.Value{
"optional": cty.StringVal("hello"),
"sensitive": cty.StringVal("world"),
})),
SensitiveConfigPaths: []cty.Path{cty.GetAttrPath("optional")},
ProviderAddr: provider,
},
output: ActionInvocation{
Address: "action.test_action.test",
Type: "test_action",
Name: "test",
ConfigValues: mustJson(t, map[string]interface{}{
"optional": "hello",
"sensitive": "world",
}),
ConfigSensitive: mustJson(t, map[string]interface{}{
"optional": true,
"sensitive": true,
}),
ConfigUnknown: mustJson(t, map[string]interface{}{}),
ProviderName: "registry.terraform.io/hashicorp/test",
InvokeActionTrigger: new(InvokeActionTrigger),
},
},
}
for name, tc := range tcs {
t.Run(name, func(t *testing.T) {
out, err := MarshalActionInvocation(tc.input, schemas)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(tc.output, out); len(diff) > 0 {
t.Fatal(diff)
}
})
}
}
func mustDynamicValue(t *testing.T, value cty.Value) []byte {
out, err := msgpack.Marshal(value, value.Type())
if err != nil {
t.Fatal(err)
}
return out
}
func mustJson(t *testing.T, data interface{}) json.RawMessage {
out, err := json.Marshal(data)
if err != nil {
t.Fatal(err)
}
return out
}