Skip to content

Commit bf484a3

Browse files
authoredDec 8, 2022
Merge pull request #103 from vmware/vasundharas/schema-image-policy
Add image registry policy resource with scope and flatten tests
2 parents a27da7a + 8de017e commit bf484a3

34 files changed

+798
-127
lines changed
 

‎go.mod

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/hashicorp/terraform-plugin-sdk/v2 v2.12.0
1010
github.com/pkg/errors v0.9.1
1111
github.com/stretchr/testify v1.7.0
12+
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9
1213
k8s.io/apiextensions-apiserver v0.18.2
1314
k8s.io/apimachinery v0.22.0
1415
k8s.io/client-go v0.22.0
@@ -37,7 +38,7 @@ require (
3738
github.com/go-stack/stack v1.8.0 // indirect
3839
github.com/gogo/protobuf v1.3.2 // indirect
3940
github.com/golang/protobuf v1.5.2 // indirect
40-
github.com/google/go-cmp v0.5.7 // indirect
41+
github.com/google/go-cmp v0.5.8 // indirect
4142
github.com/google/gofuzz v1.1.0 // indirect
4243
github.com/googleapis/gnostic v0.5.5 // indirect
4344
github.com/hashicorp/errwrap v1.0.0 // indirect
@@ -81,7 +82,7 @@ require (
8182
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect
8283
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
8384
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
84-
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
85+
golang.org/x/sys v0.1.0 // indirect
8586
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
8687
golang.org/x/text v0.3.6 // indirect
8788
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect

‎go.sum

+6-3
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,9 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
306306
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
307307
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
308308
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
309-
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
310309
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
310+
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
311+
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
311312
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
312313
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
313314
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -651,6 +652,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
651652
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
652653
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
653654
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
655+
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 h1:yZNXmy+j/JpX19vZkVktWqAo7Gny4PBWYYK3zskGpx4=
656+
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
654657
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
655658
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
656659
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -790,8 +793,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
790793
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
791794
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
792795
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
793-
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
794-
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
796+
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
797+
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
795798
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
796799
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
797800
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=

‎internal/helper/helper.go

+4
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,7 @@ func SetPrimitiveValue(input, model interface{}, key string) {
118118
}
119119
}
120120
}
121+
122+
func BoolPointer(b bool) *bool {
123+
return &b
124+
}

‎internal/provider/provider.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func Provider() *schema.Provider {
3838
iampolicy.ResourceName: iampolicy.ResourceIAMPolicy(),
3939
custompolicy.ResourceName: custompolicyresource.ResourceCustomPolicy(),
4040
securitypolicy.ResourceName: securitypolicyresource.ResourceSecurityPolicy(),
41-
imagepolicy.ResourceName: imagepolicyresource.ResourceImageRegistryPolicy(),
41+
imagepolicy.ResourceName: imagepolicyresource.ResourceImagePolicy(),
4242
credential.ResourceName: credential.ResourceCredential(),
4343
integration.ResourceName: integration.ResourceIntegration(),
4444
},

‎internal/resources/policy/kind/custom/recipe/tmc_block_rolebinding_subjects_flatten_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestFlattenTMCBlockRolebindingSubjects(t *testing.T) {
2929
expected: nil,
3030
},
3131
{
32-
description: "normal scenario with with complete custom policy tmc_block_rolebinding_subjects recipe",
32+
description: "normal scenario with complete custom policy tmc_block_rolebinding_subjects recipe",
3333
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCBlockRoleBindingSubjects{
3434
Audit: true,
3535
Parameters: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCBlockRoleBindingSubjectsParameters{
@@ -94,7 +94,7 @@ func TestFlattenBlockRoleBindingParameters(t *testing.T) {
9494
expected: nil,
9595
},
9696
{
97-
description: "normal scenario with with complete custom policy tmc_block_rolebinding_subjects parameters",
97+
description: "normal scenario with complete custom policy tmc_block_rolebinding_subjects parameters",
9898
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCBlockRoleBindingSubjectsParameters{
9999
DisallowedSubjects: []*policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCBlockRoleBindingSubjectsParametersDisallowedSubjects{
100100
{
@@ -139,7 +139,7 @@ func TestFlattenDisallowedSubjects(t *testing.T) {
139139
expected: nil,
140140
},
141141
{
142-
description: "normal scenario with with complete custom policy tmc_block_rolebinding_subjects parameters disallowed subjects",
142+
description: "normal scenario with complete custom policy tmc_block_rolebinding_subjects parameters disallowed subjects",
143143
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCBlockRoleBindingSubjectsParametersDisallowedSubjects{
144144
Kind: "nodes",
145145
Name: "test",

‎internal/resources/policy/kind/custom/recipe/tmc_common_recipe_flatten_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
policyrecipecustomcommonmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/custom/common"
1515
)
1616

17-
func TestFlattenTMCBlockNodeportService(t *testing.T) {
17+
func TestFlattenTMCCommonRecipe(t *testing.T) {
1818
t.Parallel()
1919

2020
cases := []struct {
@@ -23,12 +23,12 @@ func TestFlattenTMCBlockNodeportService(t *testing.T) {
2323
expected []interface{}
2424
}{
2525
{
26-
description: "check for nil custom policy tmc_block_nodeport_service recipe",
26+
description: "check for nil custom policy tmc-block-nodeport-service/ tmc-block-resources/ tmc-https-ingress recipes",
2727
input: nil,
2828
expected: nil,
2929
},
3030
{
31-
description: "normal scenario with with complete custom policy tmc_block_nodeport_service recipe",
31+
description: "normal scenario with complete custom policy tmc-block-nodeport-service/ tmc-block-resources/ tmc-https-ingress recipes",
3232
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCCommonRecipe{
3333
Audit: true,
3434
TargetKubernetesResources: []*policyrecipecustomcommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TargetKubernetesResources{

‎internal/resources/policy/kind/custom/recipe/tmc_external_ips_flatten_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestFlattenTMCExternalIPS(t *testing.T) {
2828
expected: nil,
2929
},
3030
{
31-
description: "normal scenario with with complete custom policy tmc_external_ips recipe",
31+
description: "normal scenario with complete custom policy tmc_external_ips recipe",
3232
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCExternalIPS{
3333
Audit: true,
3434
Parameters: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCExternalIPSParameters{
@@ -83,7 +83,7 @@ func TestFlattenExternalIPSParameters(t *testing.T) {
8383
expected: nil,
8484
},
8585
{
86-
description: "normal scenario with with complete custom policy tmc_external_ips parameters",
86+
description: "normal scenario with complete custom policy tmc_external_ips parameters",
8787
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCExternalIPSParameters{
8888
AllowedIPs: []string{"127.0.0.1"},
8989
},

‎internal/resources/policy/kind/custom/recipe/tmc_require_labels_flatten_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestFlattenTMCRequireLabels(t *testing.T) {
2929
expected: nil,
3030
},
3131
{
32-
description: "normal scenario with with complete custom policy tmc_require_labels recipe",
32+
description: "normal scenario with complete custom policy tmc_require_labels recipe",
3333
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCRequireLabels{
3434
Audit: true,
3535
Parameters: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCRequireLabelsParameters{
@@ -94,7 +94,7 @@ func TestFlattenRequiredLabelsParameters(t *testing.T) {
9494
expected: nil,
9595
},
9696
{
97-
description: "normal scenario with with complete custom policy tmc_require_labels parameters",
97+
description: "normal scenario with complete custom policy tmc_require_labels parameters",
9898
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCRequireLabelsParameters{
9999
Labels: []*policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCRequireLabelsParametersLabels{
100100
{
@@ -139,7 +139,7 @@ func TestFlattenRequiredLabelsParametersLabels(t *testing.T) {
139139
expected: nil,
140140
},
141141
{
142-
description: "normal scenario with with complete custom policy tmc_require_labels parameters labels",
142+
description: "normal scenario with complete custom policy tmc_require_labels parameters labels",
143143
input: &policyrecipecustommodel.VmwareTanzuManageV1alpha1CommonPolicySpecCustomV1TMCRequireLabelsParametersLabels{
144144
Key: "key-1",
145145
Value: "value-1",

‎internal/resources/policy/kind/custom/resource/resource_custom_policy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func ResourceCustomPolicy() *schema.Resource {
2424
DeleteContext: schema.DeleteContextFunc(policyoperations.ResourceOperation(policyoperations.WithResourceName(policykindcustom.ResourceName), policyoperations.WithOperationType(policyoperations.Delete))),
2525
Schema: customPolicySchema,
2626
CustomizeDiff: customdiff.All(
27-
scope.ValidateScope,
27+
schema.CustomizeDiffFunc(scope.ValidateScope(policyoperations.ScopeMap[policykindcustom.ResourceName])),
2828
policykindcustom.ValidateInput,
2929
policy.ValidateSpecLabelSelectorRequirement,
3030
),

‎internal/resources/policy/kind/custom/resource/resource_custom_policy_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
policyorganizationmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/organization"
2727
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy"
2828
policykindCustom "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/custom"
29+
policyoperations "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/operations"
2930
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/scope"
3031
testhelper "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/testing"
3132
)
@@ -273,7 +274,7 @@ func TestAcceptanceForCustomPolicyResource(t *testing.T) {
273274
}
274275

275276
func (testConfig *testAcceptanceConfig) getTestCustomPolicyResourceBasicConfigValue(scope scope.Scope, recipe policykindCustom.Recipe) string {
276-
helperBlock, scopeBlock := testConfig.ScopeHelperResources.GetTestPolicyResourceHelperAndScope(scope)
277+
helperBlock, scopeBlock := testConfig.ScopeHelperResources.GetTestPolicyResourceHelperAndScope(scope, policyoperations.ScopeMap[testConfig.CustomPolicyResource])
277278
inputBlock := testConfig.getTestCustomPolicyResourceInput(recipe)
278279

279280
return fmt.Sprintf(`
@@ -455,7 +456,7 @@ func (testConfig *testAcceptanceConfig) checkCustomPolicyResourceAttributes(scop
455456
case scope.OrganizationScope:
456457
check = append(check, resource.TestCheckResourceAttr(testConfig.CustomPolicyResourceName, "scope.0.organization.0.organization", testConfig.ScopeHelperResources.OrgID))
457458
case scope.UnknownScope:
458-
log.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
459+
log.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(policyoperations.ScopeMap[testConfig.CustomPolicyResource], `, `))
459460
}
460461

461462
check = append(check, policy.MetaResourceAttributeCheck(testConfig.CustomPolicyResourceName)...)
@@ -536,7 +537,7 @@ func (testConfig *testAcceptanceConfig) verifyCustomPolicyResourceCreation(scope
536537
return errors.Wrapf(err, "organization scoped custom policy resource is empty, resource: %s", testConfig.CustomPolicyResourceName)
537538
}
538539
case scope.UnknownScope:
539-
return errors.Errorf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
540+
return errors.Errorf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(policyoperations.ScopeMap[testConfig.CustomPolicyResource], `, `))
540541
}
541542

542543
return nil

‎internal/resources/policy/kind/image/constants.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import (
1111
)
1212

1313
const (
14-
ResourceName = "tanzu-mission-control_image_registry_policy"
15-
typeDefaultValue = "image-registry-policy"
14+
ResourceName = "tanzu-mission-control_image_policy"
15+
typeDefaultValue = "image-policy"
1616
)
1717

1818
// Allowed input recipes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright © 2022 VMware, Inc. All Rights Reserved.
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
package policykindimage
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
14+
policyrecipeimagemodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image"
15+
reciperesource "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/image/recipe"
16+
)
17+
18+
func TestFlattenInput(t *testing.T) {
19+
t.Parallel()
20+
21+
cases := []struct {
22+
description string
23+
input *inputRecipe
24+
expected []interface{}
25+
}{
26+
{
27+
description: "check for nil input",
28+
input: nil,
29+
expected: nil,
30+
},
31+
{
32+
description: "normal scenario with complete input",
33+
input: &inputRecipe{
34+
recipe: BlockLatestTagRecipe,
35+
inputBlockLatestTag: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CommonRecipe{
36+
Audit: helper.BoolPointer(true),
37+
},
38+
},
39+
expected: []interface{}{
40+
map[string]interface{}{
41+
reciperesource.BlockLatestTagKey: []interface{}{
42+
map[string]interface{}{
43+
reciperesource.AuditKey: true,
44+
},
45+
},
46+
},
47+
},
48+
},
49+
}
50+
51+
for _, each := range cases {
52+
test := each
53+
t.Run(test.description, func(t *testing.T) {
54+
actual := flattenInput(test.input)
55+
require.Equal(t, test.expected, actual)
56+
})
57+
}
58+
}

‎internal/resources/policy/kind/image/input_schema.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
var (
2121
inputSchema = &schema.Schema{
2222
Type: schema.TypeList,
23-
Description: "Input for the image registry policy, having one of the valid recipes: allowed-name-tag, custom, block-latest-tag or require-digest.",
23+
Description: "Input for the image policy, having one of the valid recipes: allowed-name-tag, custom, block-latest-tag or require-digest.",
2424
Required: true,
2525
MaxItems: 1,
2626
MinItems: 1,
@@ -39,7 +39,7 @@ var (
3939

4040
type (
4141
Recipe string
42-
// InputRecipe is a struct for all types of image registry policy inputs.
42+
// InputRecipe is a struct for all types of image policy inputs.
4343
inputRecipe struct {
4444
recipe Recipe
4545
inputAllowedNameTag *policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTag
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
Copyright © 2022 VMware, Inc. All Rights Reserved.
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
package recipe
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
14+
policyrecipeimagemodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image"
15+
policyrecipeimagecommonmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image/common"
16+
)
17+
18+
func TestFlattenAllowedNameTag(t *testing.T) {
19+
t.Parallel()
20+
21+
cases := []struct {
22+
description string
23+
input *policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTag
24+
expected []interface{}
25+
}{
26+
{
27+
description: "check for nil image policy allowed-name-tag recipe",
28+
input: nil,
29+
expected: nil,
30+
},
31+
{
32+
description: "scenario with nil value of Audit value in allowed-name-tag recipe",
33+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTag{
34+
Audit: nil,
35+
Rules: []*policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTagRules{
36+
{
37+
ImageName: "foo",
38+
Tag: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
39+
Negate: helper.BoolPointer(false),
40+
Value: "test",
41+
},
42+
},
43+
},
44+
},
45+
expected: []interface{}{
46+
map[string]interface{}{
47+
RulesKey: []interface{}{
48+
map[string]interface{}{
49+
ImageNameKey: "foo",
50+
TagKey: []interface{}{
51+
map[string]interface{}{
52+
NegateKey: false,
53+
ValueKey: "test",
54+
},
55+
},
56+
},
57+
},
58+
},
59+
},
60+
},
61+
{
62+
description: "normal scenario with complete image policy allowed-name-tag recipe",
63+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTag{
64+
Audit: helper.BoolPointer(true),
65+
Rules: []*policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTagRules{
66+
{
67+
ImageName: "foo",
68+
Tag: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
69+
Negate: helper.BoolPointer(false),
70+
Value: "test",
71+
},
72+
},
73+
},
74+
},
75+
expected: []interface{}{
76+
map[string]interface{}{
77+
AuditKey: true,
78+
RulesKey: []interface{}{
79+
map[string]interface{}{
80+
ImageNameKey: "foo",
81+
TagKey: []interface{}{
82+
map[string]interface{}{
83+
NegateKey: false,
84+
ValueKey: "test",
85+
},
86+
},
87+
},
88+
},
89+
},
90+
},
91+
},
92+
}
93+
94+
for _, each := range cases {
95+
test := each
96+
t.Run(test.description, func(t *testing.T) {
97+
actual := FlattenAllowedNameTag(test.input)
98+
require.Equal(t, test.expected, actual)
99+
})
100+
}
101+
}
102+
103+
func TestFlattenNameTagRules(t *testing.T) {
104+
t.Parallel()
105+
106+
cases := []struct {
107+
description string
108+
input *policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTagRules
109+
expected interface{}
110+
}{
111+
{
112+
description: "check for nil rules value of allowed-name-tag recipe",
113+
input: nil,
114+
expected: nil,
115+
},
116+
{
117+
description: "normal scenario with all fields of rules spec of allowed-name-tag recipe",
118+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTagRules{
119+
ImageName: "foo",
120+
Tag: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
121+
Negate: helper.BoolPointer(false),
122+
Value: "test",
123+
},
124+
},
125+
expected: map[string]interface{}{
126+
ImageNameKey: "foo",
127+
TagKey: []interface{}{
128+
map[string]interface{}{
129+
NegateKey: false,
130+
ValueKey: "test",
131+
},
132+
},
133+
},
134+
},
135+
}
136+
137+
for _, each := range cases {
138+
test := each
139+
t.Run(test.description, func(t *testing.T) {
140+
actual := flattenNameTagRules(test.input)
141+
require.Equal(t, test.expected, actual)
142+
})
143+
}
144+
}

‎internal/resources/policy/kind/image/recipe/allowed_name_tag_schema.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func ConstructAllowedNameTag(data []interface{}) (nameTag *policyrecipeimagemode
5757
nameTag = &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTag{}
5858

5959
if v, ok := allowedNameTagData[AuditKey]; ok {
60-
helper.SetPrimitiveValue(v, &nameTag.Audit, AuditKey)
60+
nameTag.Audit = helper.BoolPointer(v.(bool))
6161
}
6262

6363
if v, ok := allowedNameTagData[RulesKey]; ok {
@@ -107,7 +107,9 @@ func FlattenAllowedNameTag(nameTag *policyrecipeimagemodel.VmwareTanzuManageV1al
107107

108108
flattenAllowedNameTag := make(map[string]interface{})
109109

110-
flattenAllowedNameTag[AuditKey] = nameTag.Audit
110+
if nameTag.Audit != nil {
111+
flattenAllowedNameTag[AuditKey] = *nameTag.Audit
112+
}
111113

112114
if nameTag.Rules != nil {
113115
var rules []interface{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright © 2022 VMware, Inc. All Rights Reserved.
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
package recipe
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
14+
policyrecipeimagemodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image"
15+
)
16+
17+
func TestFlattenCommonRecipe(t *testing.T) {
18+
t.Parallel()
19+
20+
cases := []struct {
21+
description string
22+
input *policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CommonRecipe
23+
expected []interface{}
24+
}{
25+
{
26+
description: "check for nil image policy block-latest-tag or require-digest recipes",
27+
input: nil,
28+
expected: nil,
29+
},
30+
{
31+
description: "scenario with nil data for Audit",
32+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CommonRecipe{
33+
Audit: nil,
34+
},
35+
expected: nil,
36+
},
37+
{
38+
description: "normal scenario with complete image policy block-latest-tag or require-digest recipes",
39+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CommonRecipe{
40+
Audit: helper.BoolPointer(true),
41+
},
42+
expected: []interface{}{
43+
map[string]interface{}{
44+
AuditKey: true,
45+
},
46+
},
47+
},
48+
}
49+
50+
for _, each := range cases {
51+
test := each
52+
t.Run(test.description, func(t *testing.T) {
53+
actual := FlattenCommonRecipe(test.input)
54+
require.Equal(t, test.expected, actual)
55+
})
56+
}
57+
}

‎internal/resources/policy/kind/image/recipe/block_latest_tag-require_digest_schema.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func ConstructCommonRecipe(data []interface{}) (common *policyrecipeimagemodel.V
5858
common = &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CommonRecipe{}
5959

6060
if v, ok := commonRecipeData[AuditKey]; ok {
61-
helper.SetPrimitiveValue(v, &common.Audit, AuditKey)
61+
common.Audit = helper.BoolPointer(v.(bool))
6262
}
6363

6464
return common
@@ -71,7 +71,11 @@ func FlattenCommonRecipe(common *policyrecipeimagemodel.VmwareTanzuManageV1alpha
7171

7272
flattenCommonRecipe := make(map[string]interface{})
7373

74-
flattenCommonRecipe[AuditKey] = common.Audit
74+
if common.Audit == nil {
75+
return data
76+
}
77+
78+
flattenCommonRecipe[AuditKey] = *common.Audit
7579

7680
return []interface{}{flattenCommonRecipe}
7781
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
Copyright © 2022 VMware, Inc. All Rights Reserved.
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
package recipe
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
14+
policyrecipeimagemodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image"
15+
policyrecipeimagecommonmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image/common"
16+
)
17+
18+
func TestFlattenCustom(t *testing.T) {
19+
t.Parallel()
20+
21+
cases := []struct {
22+
description string
23+
input *policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1Custom
24+
expected []interface{}
25+
}{
26+
{
27+
description: "check for nil image policy custom recipe",
28+
input: nil,
29+
expected: nil,
30+
},
31+
{
32+
description: "scenario with nil value of Audit value in custom recipe",
33+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1Custom{
34+
Audit: nil,
35+
Rules: []*policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CustomRules{
36+
{
37+
Hostname: "bar",
38+
ImageName: "foo",
39+
Port: "80",
40+
RequireDigest: helper.BoolPointer(true),
41+
Tag: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
42+
Negate: helper.BoolPointer(false),
43+
Value: "test",
44+
},
45+
},
46+
},
47+
},
48+
expected: []interface{}{
49+
map[string]interface{}{
50+
RulesKey: []interface{}{
51+
map[string]interface{}{
52+
HostNameKey: "bar",
53+
ImageNameKey: "foo",
54+
PortKey: "80",
55+
RequireKey: true,
56+
TagKey: []interface{}{
57+
map[string]interface{}{
58+
NegateKey: false,
59+
ValueKey: "test",
60+
},
61+
},
62+
},
63+
},
64+
},
65+
},
66+
},
67+
{
68+
description: "normal scenario with complete image policy custom recipe",
69+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1Custom{
70+
Audit: helper.BoolPointer(true),
71+
Rules: []*policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CustomRules{
72+
{
73+
Hostname: "bar",
74+
ImageName: "foo",
75+
Port: "80",
76+
RequireDigest: helper.BoolPointer(true),
77+
Tag: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
78+
Negate: helper.BoolPointer(false),
79+
Value: "test",
80+
},
81+
},
82+
},
83+
},
84+
expected: []interface{}{
85+
map[string]interface{}{
86+
AuditKey: true,
87+
RulesKey: []interface{}{
88+
map[string]interface{}{
89+
HostNameKey: "bar",
90+
ImageNameKey: "foo",
91+
PortKey: "80",
92+
RequireKey: true,
93+
TagKey: []interface{}{
94+
map[string]interface{}{
95+
NegateKey: false,
96+
ValueKey: "test",
97+
},
98+
},
99+
},
100+
},
101+
},
102+
},
103+
},
104+
}
105+
106+
for _, each := range cases {
107+
test := each
108+
t.Run(test.description, func(t *testing.T) {
109+
actual := FlattenCustom(test.input)
110+
require.Equal(t, test.expected, actual)
111+
})
112+
}
113+
}
114+
115+
func TestFlattenCustomRules(t *testing.T) {
116+
t.Parallel()
117+
118+
cases := []struct {
119+
description string
120+
input *policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CustomRules
121+
expected interface{}
122+
}{
123+
{
124+
description: "check for nil rules value of custom recipe",
125+
input: nil,
126+
expected: nil,
127+
},
128+
{
129+
description: "normal scenario with all fields of rules spec of custom recipe",
130+
input: &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1CustomRules{
131+
Hostname: "bar",
132+
ImageName: "foo",
133+
Port: "80",
134+
RequireDigest: helper.BoolPointer(true),
135+
Tag: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
136+
Negate: helper.BoolPointer(false),
137+
Value: "test",
138+
},
139+
},
140+
expected: map[string]interface{}{
141+
HostNameKey: "bar",
142+
ImageNameKey: "foo",
143+
PortKey: "80",
144+
RequireKey: true,
145+
TagKey: []interface{}{
146+
map[string]interface{}{
147+
NegateKey: false,
148+
ValueKey: "test",
149+
},
150+
},
151+
},
152+
},
153+
}
154+
155+
for _, each := range cases {
156+
test := each
157+
t.Run(test.description, func(t *testing.T) {
158+
actual := flattenCustomRules(test.input)
159+
require.Equal(t, test.expected, actual)
160+
})
161+
}
162+
}

‎internal/resources/policy/kind/image/recipe/custom_schema.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func ConstructCustom(data []interface{}) (custom *policyrecipeimagemodel.VmwareT
7575
custom = &policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1Custom{}
7676

7777
if v, ok := customData[AuditKey]; ok {
78-
helper.SetPrimitiveValue(v, &custom.Audit, AuditKey)
78+
custom.Audit = helper.BoolPointer(v.(bool))
7979
}
8080

8181
if v, ok := customData[RulesKey]; ok {
@@ -118,7 +118,7 @@ func expandCustomRules(data interface{}) (rules *policyrecipeimagemodel.VmwareTa
118118
}
119119

120120
if v, ok := rulesData[RequireKey]; ok {
121-
helper.SetPrimitiveValue(v, &rules.RequireDigest, RequireKey)
121+
rules.RequireDigest = helper.BoolPointer(v.(bool))
122122
}
123123

124124
if v, ok := rulesData[TagKey]; ok {
@@ -137,7 +137,9 @@ func FlattenCustom(custom *policyrecipeimagemodel.VmwareTanzuManageV1alpha1Commo
137137

138138
flattenCustom := make(map[string]interface{})
139139

140-
flattenCustom[AuditKey] = custom.Audit
140+
if custom.Audit != nil {
141+
flattenCustom[AuditKey] = *custom.Audit
142+
}
141143

142144
if custom.Rules != nil {
143145
var rules []interface{}
@@ -162,7 +164,10 @@ func flattenCustomRules(rules *policyrecipeimagemodel.VmwareTanzuManageV1alpha1C
162164
flattenRules[HostNameKey] = rules.Hostname
163165
flattenRules[ImageNameKey] = rules.ImageName
164166
flattenRules[PortKey] = rules.Port
165-
flattenRules[RequireKey] = rules.RequireDigest
167+
168+
if rules.RequireDigest != nil {
169+
flattenRules[RequireKey] = *rules.RequireDigest
170+
}
166171

167172
if rules.Tag != nil {
168173
flattenRules[TagKey] = flattenTag(rules.Tag)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
Copyright © 2022 VMware, Inc. All Rights Reserved.
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
package recipe
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
14+
policyrecipeimagecommonmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image/common"
15+
)
16+
17+
func TestFlattenTag(t *testing.T) {
18+
t.Parallel()
19+
20+
cases := []struct {
21+
description string
22+
input *policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag
23+
expected interface{}
24+
}{
25+
{
26+
description: "check for nil tag data",
27+
input: nil,
28+
expected: []interface{}(nil),
29+
},
30+
{
31+
description: "scenario for nil negate value of tag",
32+
input: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
33+
Negate: nil,
34+
Value: "test",
35+
},
36+
expected: []interface{}{
37+
map[string]interface{}{
38+
ValueKey: "test",
39+
},
40+
},
41+
},
42+
{
43+
description: "normal scenario with all values of tag data",
44+
input: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
45+
Negate: helper.BoolPointer(false),
46+
Value: "test",
47+
},
48+
expected: []interface{}{
49+
map[string]interface{}{
50+
NegateKey: false,
51+
ValueKey: "test",
52+
},
53+
},
54+
},
55+
}
56+
57+
for _, each := range cases {
58+
test := each
59+
t.Run(test.description, func(t *testing.T) {
60+
actual := flattenTag(test.input)
61+
require.Equal(t, test.expected, actual)
62+
})
63+
}
64+
}

‎internal/resources/policy/kind/image/recipe/tag_schema.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var tag = &schema.Schema{
1616
Type: schema.TypeList,
1717
Description: "Allowed image tag, wildcards are supported (for example: v1.*). No validation is performed on tag if the field is empty.",
1818
Optional: true,
19+
MaxItems: 1,
1920
Elem: &schema.Resource{
2021
Schema: map[string]*schema.Schema{
2122
NegateKey: {
@@ -34,20 +35,20 @@ var tag = &schema.Schema{
3435
},
3536
}
3637

37-
func expandTag(data interface{}) (tag *policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag) {
38-
if data == nil {
38+
func expandTag(data []interface{}) (tag *policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag) {
39+
if len(data) == 0 || data[0] == nil {
3940
return tag
4041
}
4142

42-
tagsData, ok := data.(map[string]interface{})
43+
tagsData, ok := data[0].(map[string]interface{})
4344
if !ok {
4445
return tag
4546
}
4647

4748
tag = &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{}
4849

4950
if v, ok := tagsData[NegateKey]; ok {
50-
helper.SetPrimitiveValue(v, &tag.Negate, NegateKey)
51+
tag.Negate = helper.BoolPointer(v.(bool))
5152
}
5253

5354
if v, ok := tagsData[ValueKey]; ok {
@@ -57,15 +58,18 @@ func expandTag(data interface{}) (tag *policyrecipeimagecommonmodel.VmwareTanzuM
5758
return tag
5859
}
5960

60-
func flattenTag(tag *policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag) (data interface{}) {
61+
func flattenTag(tag *policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag) (data []interface{}) {
6162
if tag == nil {
6263
return data
6364
}
6465

6566
flattenTag := make(map[string]interface{})
6667

67-
flattenTag[NegateKey] = tag.Negate
68+
if tag.Negate != nil {
69+
flattenTag[NegateKey] = *tag.Negate
70+
}
71+
6872
flattenTag[ValueKey] = tag.Value
6973

70-
return flattenTag
74+
return []interface{}{flattenTag}
7175
}

‎internal/resources/policy/kind/image/resource/resource_image_registry_policy.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,29 @@ import (
1212
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/common"
1313
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy"
1414
policykindimage "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/image"
15+
policyoperations "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/operations"
1516
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/scope"
1617
)
1718

18-
func ResourceImageRegistryPolicy() *schema.Resource {
19+
func ResourceImagePolicy() *schema.Resource {
1920
return &schema.Resource{
20-
Schema: imageRegistryPolicySchema,
21+
CreateContext: schema.CreateContextFunc(policyoperations.ResourceOperation(policyoperations.WithResourceName(policykindimage.ResourceName), policyoperations.WithOperationType(policyoperations.Create))),
22+
ReadContext: schema.ReadContextFunc(policyoperations.ResourceOperation(policyoperations.WithResourceName(policykindimage.ResourceName), policyoperations.WithOperationType(policyoperations.Read))),
23+
UpdateContext: schema.UpdateContextFunc(policyoperations.ResourceOperation(policyoperations.WithResourceName(policykindimage.ResourceName), policyoperations.WithOperationType(policyoperations.Update))),
24+
DeleteContext: schema.DeleteContextFunc(policyoperations.ResourceOperation(policyoperations.WithResourceName(policykindimage.ResourceName), policyoperations.WithOperationType(policyoperations.Delete))),
25+
Schema: imagePolicySchema,
2126
CustomizeDiff: customdiff.All(
22-
scope.ValidateScope,
27+
schema.CustomizeDiffFunc(scope.ValidateScope(policyoperations.ScopeMap[policykindimage.ResourceName])),
2328
policykindimage.ValidateInput,
2429
policy.ValidateSpecLabelSelectorRequirement,
2530
),
2631
}
2732
}
2833

29-
var imageRegistryPolicySchema = map[string]*schema.Schema{
34+
var imagePolicySchema = map[string]*schema.Schema{
3035
policy.NameKey: {
3136
Type: schema.TypeString,
32-
Description: "Name of the image registry policy",
37+
Description: "Name of the image policy",
3338
Required: true,
3439
ForceNew: true,
3540
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
Copyright © 2022 VMware, Inc. All Rights Reserved.
3+
SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
package policykindimage
7+
8+
import (
9+
"encoding/json"
10+
"testing"
11+
12+
"github.com/stretchr/testify/require"
13+
14+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
15+
policymodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy"
16+
policyrecipeimagemodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image"
17+
policyrecipeimagecommonmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/image/common"
18+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy"
19+
reciperesource "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/image/recipe"
20+
)
21+
22+
func TestFlattenSpec(t *testing.T) {
23+
t.Parallel()
24+
25+
cases := []struct {
26+
description string
27+
input *policymodel.VmwareTanzuManageV1alpha1CommonPolicySpec
28+
expected []interface{}
29+
}{
30+
{
31+
description: "check for nil spec",
32+
input: nil,
33+
expected: nil,
34+
},
35+
{
36+
description: "normal scenario with complete spec",
37+
input: &policymodel.VmwareTanzuManageV1alpha1CommonPolicySpec{
38+
Input: constructAllowedNameTag(),
39+
NamespaceSelector: &policymodel.VmwareTanzuManageV1alpha1CommonPolicyLabelSelector{
40+
MatchExpressions: []*policymodel.K8sIoApimachineryPkgApisMetaV1LabelSelectorRequirement{
41+
{
42+
Key: "k1",
43+
Operator: "In",
44+
Values: []string{
45+
"v1",
46+
"v2",
47+
},
48+
},
49+
{
50+
Key: "k2",
51+
Operator: "Exists",
52+
Values: []string{},
53+
},
54+
},
55+
},
56+
Recipe: string(AllowedNameTagRecipe),
57+
},
58+
expected: []interface{}{
59+
map[string]interface{}{
60+
policy.InputKey: []interface{}{
61+
map[string]interface{}{
62+
reciperesource.AllowedNameTagKey: []interface{}{
63+
map[string]interface{}{
64+
reciperesource.AuditKey: true,
65+
reciperesource.RulesKey: []interface{}{
66+
map[string]interface{}{
67+
reciperesource.ImageNameKey: "foo",
68+
reciperesource.TagKey: []interface{}{
69+
map[string]interface{}{
70+
reciperesource.NegateKey: true,
71+
reciperesource.ValueKey: "test",
72+
},
73+
},
74+
},
75+
},
76+
},
77+
},
78+
},
79+
},
80+
policy.NamespaceSelectorKey: []interface{}{
81+
map[string]interface{}{
82+
policy.MatchExpressionsKey: []interface{}{
83+
map[string]interface{}{
84+
policy.KeyKey: "k1",
85+
policy.OperatorKey: "In",
86+
policy.ValuesKey: []string{
87+
"v1",
88+
"v2",
89+
},
90+
},
91+
map[string]interface{}{
92+
policy.KeyKey: "k2",
93+
policy.OperatorKey: "Exists",
94+
policy.ValuesKey: []string{},
95+
},
96+
},
97+
},
98+
},
99+
},
100+
},
101+
},
102+
}
103+
104+
for _, each := range cases {
105+
test := each
106+
t.Run(test.description, func(t *testing.T) {
107+
actual := FlattenSpec(test.input)
108+
require.Equal(t, test.expected, actual)
109+
})
110+
}
111+
}
112+
113+
func constructAllowedNameTag() (allowedNameTagRecipeInput map[string]interface{}) {
114+
allowedNameTagInput := policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTag{
115+
Audit: helper.BoolPointer(true),
116+
Rules: []*policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTagRules{
117+
{
118+
ImageName: "foo",
119+
Tag: &policyrecipeimagecommonmodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1RulesTag{
120+
Negate: helper.BoolPointer(true),
121+
Value: "test",
122+
},
123+
},
124+
},
125+
}
126+
127+
binary, err := allowedNameTagInput.MarshalBinary()
128+
if err != nil {
129+
return nil
130+
}
131+
132+
err = json.Unmarshal(binary, &allowedNameTagRecipeInput)
133+
if err != nil {
134+
return nil
135+
}
136+
137+
return allowedNameTagRecipeInput
138+
}

‎internal/resources/policy/kind/image/spec_schema.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919

2020
var SpecSchema = &schema.Schema{
2121
Type: schema.TypeList,
22-
Description: "Spec for the image registry policy",
22+
Description: "Spec for the image policy",
2323
Required: true,
2424
MaxItems: 1,
2525
Elem: &schema.Resource{
@@ -49,23 +49,23 @@ func ConstructSpec(d *schema.ResourceData) (spec *policymodel.VmwareTanzuManageV
4949
RecipeVersion: policy.RecipeVersionDefaultValue,
5050
}
5151

52-
v, ok := specData[policy.InputKey]
52+
input, ok := specData[policy.InputKey]
5353
if !ok {
5454
return spec
5555
}
5656

57-
v1, ok := v.([]interface{})
57+
inputData, ok := input.([]interface{})
5858
if !ok {
5959
return spec
6060
}
6161

62-
inputRecipeData := constructInput(v1)
62+
inputRecipeData := constructInput(inputData)
6363

6464
if inputRecipeData == nil || inputRecipeData.recipe == "" {
6565
return spec
6666
}
6767

68-
spec.Recipe = string(inputRecipeData.recipe)
68+
spec.Recipe = strings.ReplaceAll(string(inputRecipeData.recipe), "_", "-")
6969

7070
switch inputRecipeData.recipe {
7171
case AllowedNameTagRecipe:
@@ -108,19 +108,19 @@ func FlattenSpec(spec *policymodel.VmwareTanzuManageV1alpha1CommonPolicySpec) (d
108108
return data
109109
}
110110

111-
v1, ok := spec.Input.(map[string]interface{})
111+
input, ok := spec.Input.(map[string]interface{})
112112
if !ok {
113113
return data
114114
}
115115

116116
var inputRecipeData *inputRecipe
117117

118-
byteSlice, err := json.Marshal(v1)
118+
byteSlice, err := json.Marshal(input)
119119
if err != nil {
120120
return data
121121
}
122122

123-
switch spec.Recipe {
123+
switch strings.ReplaceAll(spec.Recipe, "-", "_") {
124124
case string(AllowedNameTagRecipe):
125125
var allowedNameTagRecipeInput policyrecipeimagemodel.VmwareTanzuManageV1alpha1CommonPolicySpecImageV1AllowedNameTag
126126

@@ -166,8 +166,8 @@ func FlattenSpec(spec *policymodel.VmwareTanzuManageV1alpha1CommonPolicySpec) (d
166166
}
167167

168168
inputRecipeData = &inputRecipe{
169-
recipe: RequireDigestRecipe,
170-
inputBlockLatestTag: &requireDigestRecipeInput,
169+
recipe: RequireDigestRecipe,
170+
inputRequireDigest: &requireDigestRecipeInput,
171171
}
172172
case string(UnknownRecipe):
173173
fmt.Printf("[ERROR]: No valid input recipe block found: minimum one valid input recipe block is required among: %v. Please check the schema.", strings.Join(RecipesAllowed[:], `, `))

‎internal/resources/policy/kind/security/resource/resource_security_policy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func ResourceSecurityPolicy() *schema.Resource {
2424
DeleteContext: schema.DeleteContextFunc(policyoperations.ResourceOperation(policyoperations.WithResourceName(policykindsecurity.ResourceName), policyoperations.WithOperationType(policyoperations.Delete))),
2525
Schema: securityPolicySchema,
2626
CustomizeDiff: customdiff.All(
27-
scope.ValidateScope,
27+
schema.CustomizeDiffFunc(scope.ValidateScope(policyoperations.ScopeMap[policykindsecurity.ResourceName])),
2828
policykindsecurity.ValidateInput,
2929
policy.ValidateSpecLabelSelectorRequirement,
3030
),

‎internal/resources/policy/kind/security/resource/resource_security_policy_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
policyorganizationmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/organization"
2727
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy"
2828
policykindsecurity "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/security"
29+
policyoperations "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/operations"
2930
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/scope"
3031
testhelper "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/testing"
3132
)
@@ -168,7 +169,7 @@ func TestAcceptanceForSecurityPolicyResource(t *testing.T) {
168169
}
169170

170171
func (testConfig *testAcceptanceConfig) getTestSecurityPolicyResourceBasicConfigValue(scope scope.Scope, recipe policykindsecurity.Recipe) string {
171-
helperBlock, scopeBlock := testConfig.ScopeHelperResources.GetTestPolicyResourceHelperAndScope(scope)
172+
helperBlock, scopeBlock := testConfig.ScopeHelperResources.GetTestPolicyResourceHelperAndScope(scope, policyoperations.ScopeMap[testConfig.SecurityPolicyResource])
172173
inputBlock := testConfig.getTestSecurityPolicyResourceInput(recipe)
173174

174175
return fmt.Sprintf(`
@@ -371,7 +372,7 @@ func (testConfig *testAcceptanceConfig) checkSecurityPolicyResourceAttributes(sc
371372
case scope.OrganizationScope:
372373
check = append(check, resource.TestCheckResourceAttr(testConfig.SecurityPolicyResourceName, "scope.0.organization.0.organization", testConfig.ScopeHelperResources.OrgID))
373374
case scope.UnknownScope:
374-
log.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
375+
log.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(policyoperations.ScopeMap[testConfig.SecurityPolicyResource], `, `))
375376
}
376377

377378
check = append(check, policy.MetaResourceAttributeCheck(testConfig.SecurityPolicyResourceName)...)
@@ -452,7 +453,7 @@ func (testConfig *testAcceptanceConfig) verifySecurityPolicyResourceCreation(sco
452453
return errors.Wrapf(err, "organization scoped security policy resource is empty, resource: %s", testConfig.SecurityPolicyResourceName)
453454
}
454455
case scope.UnknownScope:
455-
return errors.Errorf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
456+
return errors.Errorf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(policyoperations.ScopeMap[testConfig.SecurityPolicyResource], `, `))
456457
}
457458

458459
return nil

‎internal/resources/policy/operations/create.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func ResourcePolicyCreate(ctx context.Context, d *schema.ResourceData, m interfa
119119
UID = policyResponse.Policy.Meta.UID
120120
}
121121
case scope.UnknownScope:
122-
return diag.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
122+
return diag.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(ScopeMap[rn], `, `))
123123
}
124124

125125
// always run

‎internal/resources/policy/operations/delete.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func ResourcePolicyDelete(ctx context.Context, d *schema.ResourceData, m interfa
5858
}
5959
}
6060
case scope.UnknownScope:
61-
return diag.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
61+
return diag.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(ScopeMap[rn], `, `))
6262
}
6363

6464
// d.SetId("") is automatically called assuming delete returns no errors, but

‎internal/resources/policy/operations/helper.go

+14-5
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,18 @@ import (
1818
objectmetamodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/objectmeta"
1919
policymodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy"
2020
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy"
21+
policykindcustom "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/custom"
22+
policykindimage "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/image"
23+
policykindsecurity "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/security"
2124
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/scope"
2225
)
2326

27+
var ScopeMap = map[string][]string{
28+
policykindcustom.ResourceName: {scope.ClusterKey, scope.ClusterGroupKey, scope.OrganizationKey},
29+
policykindimage.ResourceName: {scope.WorkspaceKey, scope.OrganizationKey},
30+
policykindsecurity.ResourceName: {scope.ClusterKey, scope.ClusterGroupKey, scope.OrganizationKey},
31+
}
32+
2433
// nolint: gocognit
2534
func RetrievePolicyUIDMetaAndSpecFromServer(config authctx.TanzuContext, scopedFullnameData *scope.ScopedFullname, d *schema.ResourceData, policyName, rn string) (string, *objectmetamodel.VmwareTanzuCoreV1alpha1ObjectMeta, *policymodel.VmwareTanzuManageV1alpha1CommonPolicySpec, error) {
2635
var (
@@ -47,7 +56,7 @@ func RetrievePolicyUIDMetaAndSpecFromServer(config authctx.TanzuContext, scopedF
4756
FullnameCluster: resp.Policy.FullName,
4857
}
4958

50-
fullName, name := scope.FlattenScope(scopedFullnameData)
59+
fullName, name := scope.FlattenScope(scopedFullnameData, ScopeMap[rn])
5160

5261
if err := d.Set(policy.NameKey, name); err != nil {
5362
return "", nil, nil, err
@@ -78,7 +87,7 @@ func RetrievePolicyUIDMetaAndSpecFromServer(config authctx.TanzuContext, scopedF
7887
FullnameClusterGroup: resp.Policy.FullName,
7988
}
8089

81-
fullName, name := scope.FlattenScope(scopedFullnameData)
90+
fullName, name := scope.FlattenScope(scopedFullnameData, ScopeMap[rn])
8291

8392
if err := d.Set(policy.NameKey, name); err != nil {
8493
return "", nil, nil, err
@@ -109,7 +118,7 @@ func RetrievePolicyUIDMetaAndSpecFromServer(config authctx.TanzuContext, scopedF
109118
FullnameWorkspace: resp.Policy.FullName,
110119
}
111120

112-
fullName, name := scope.FlattenScope(scopedFullnameData)
121+
fullName, name := scope.FlattenScope(scopedFullnameData, ScopeMap[rn])
113122

114123
if err := d.Set(policy.NameKey, name); err != nil {
115124
return "", nil, nil, err
@@ -140,7 +149,7 @@ func RetrievePolicyUIDMetaAndSpecFromServer(config authctx.TanzuContext, scopedF
140149
FullnameOrganization: resp.Policy.FullName,
141150
}
142151

143-
fullName, name := scope.FlattenScope(scopedFullnameData)
152+
fullName, name := scope.FlattenScope(scopedFullnameData, ScopeMap[rn])
144153

145154
if err := d.Set(policy.NameKey, name); err != nil {
146155
return "", nil, nil, err
@@ -155,7 +164,7 @@ func RetrievePolicyUIDMetaAndSpecFromServer(config authctx.TanzuContext, scopedF
155164
spec = resp.Policy.Spec
156165
}
157166
case scope.UnknownScope:
158-
return "", nil, nil, errors.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
167+
return "", nil, nil, errors.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(ScopeMap[rn], `, `))
159168
}
160169

161170
return UID, meta, spec, nil

‎internal/resources/policy/operations/update.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ func ResourcePolicyInPlaceUpdate(ctx context.Context, d *schema.ResourceData, m
127127
}
128128
}
129129
case scope.UnknownScope:
130-
return diag.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
130+
return diag.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(ScopeMap[rn], `, `))
131131
}
132132

133133
log.Printf("[INFO] %s policy update successful", rn)

‎internal/resources/policy/scope/constants.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ const (
1414
WorkspaceNameKey = "workspace"
1515
OrganizationIDKey = "organization"
1616
ScopeKey = "scope"
17-
clusterKey = "cluster"
18-
clusterGroupKey = "cluster_group"
19-
workspaceKey = "workspace"
20-
organizationKey = "organization"
17+
ClusterKey = "cluster"
18+
ClusterGroupKey = "cluster_group"
19+
WorkspaceKey = "workspace"
20+
OrganizationKey = "organization"
2121
)
2222

2323
// Allowed scopes.

‎internal/resources/policy/scope/scope_flatten_test.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func TestFlattenScope(t *testing.T) {
2222
cases := []struct {
2323
description string
2424
input *ScopedFullname
25+
allowedScope []string
2526
expectedData []interface{}
2627
expectedName string
2728
}{
@@ -44,7 +45,7 @@ func TestFlattenScope(t *testing.T) {
4445
},
4546
expectedData: []interface{}{
4647
map[string]interface{}{
47-
clusterKey: []interface{}{
48+
ClusterKey: []interface{}{
4849
map[string]interface{}{
4950
ManagementClusterNameKey: "m",
5051
ClusterNameKey: "c",
@@ -66,7 +67,7 @@ func TestFlattenScope(t *testing.T) {
6667
},
6768
expectedData: []interface{}{
6869
map[string]interface{}{
69-
clusterGroupKey: []interface{}{
70+
ClusterGroupKey: []interface{}{
7071
map[string]interface{}{
7172
ClusterGroupNameKey: "c",
7273
},
@@ -86,7 +87,7 @@ func TestFlattenScope(t *testing.T) {
8687
},
8788
expectedData: []interface{}{
8889
map[string]interface{}{
89-
workspaceKey: []interface{}{
90+
WorkspaceKey: []interface{}{
9091
map[string]interface{}{
9192
WorkspaceNameKey: "w",
9293
},
@@ -106,7 +107,7 @@ func TestFlattenScope(t *testing.T) {
106107
},
107108
expectedData: []interface{}{
108109
map[string]interface{}{
109-
organizationKey: []interface{}{
110+
OrganizationKey: []interface{}{
110111
map[string]interface{}{
111112
OrganizationIDKey: "o",
112113
},
@@ -120,7 +121,7 @@ func TestFlattenScope(t *testing.T) {
120121
for _, each := range cases {
121122
test := each
122123
t.Run(test.description, func(t *testing.T) {
123-
actualData, actualName := FlattenScope(test.input)
124+
actualData, actualName := FlattenScope(test.input, test.allowedScope)
124125
require.Equal(t, test.expectedData, actualData)
125126
require.Equal(t, test.expectedName, actualName)
126127
})

‎internal/resources/policy/scope/scope_schema.go

+57-49
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"strings"
1212

1313
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
14+
"golang.org/x/exp/slices"
1415

1516
policyclustermodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/cluster"
1617
policyclustergroupmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/clustergroup"
@@ -21,21 +22,20 @@ import (
2122
var (
2223
ScopeSchema = &schema.Schema{
2324
Type: schema.TypeList,
24-
Description: "Scope for the custom, security and image policy, having one of the valid scopes for custom and security policy: cluster, cluster_group or organization and valid scopes for image registry policy: workspace or organization.",
25+
Description: "Scope for the custom, security and image policy, having one of the valid scopes for custom and security policy: cluster, cluster_group or organization and valid scopes for image policy: workspace or organization.",
2526
Required: true,
2627
ForceNew: true,
2728
MaxItems: 1,
2829
MinItems: 1,
2930
Elem: &schema.Resource{
3031
Schema: map[string]*schema.Schema{
31-
clusterKey: ClusterPolicyFullname,
32-
clusterGroupKey: ClusterGroupPolicyFullname,
33-
workspaceKey: WorkspacePolicyFullname,
34-
organizationKey: OrganizationPolicyFullname,
32+
ClusterKey: ClusterPolicyFullname,
33+
ClusterGroupKey: ClusterGroupPolicyFullname,
34+
WorkspaceKey: WorkspacePolicyFullname,
35+
OrganizationKey: OrganizationPolicyFullname,
3536
},
3637
},
3738
}
38-
ScopesAllowed = [...]string{clusterKey, clusterGroupKey, workspaceKey, organizationKey}
3939
)
4040

4141
type (
@@ -64,7 +64,7 @@ func ConstructScope(d *schema.ResourceData, name string) (scopedFullnameData *Sc
6464

6565
scopeData := data[0].(map[string]interface{})
6666

67-
if v, ok := scopeData[clusterKey]; ok {
67+
if v, ok := scopeData[ClusterKey]; ok {
6868
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
6969
scopedFullnameData = &ScopedFullname{
7070
Scope: ClusterScope,
@@ -73,7 +73,7 @@ func ConstructScope(d *schema.ResourceData, name string) (scopedFullnameData *Sc
7373
}
7474
}
7575

76-
if v, ok := scopeData[clusterGroupKey]; ok {
76+
if v, ok := scopeData[ClusterGroupKey]; ok {
7777
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
7878
scopedFullnameData = &ScopedFullname{
7979
Scope: ClusterGroupScope,
@@ -82,7 +82,7 @@ func ConstructScope(d *schema.ResourceData, name string) (scopedFullnameData *Sc
8282
}
8383
}
8484

85-
if v, ok := scopeData[workspaceKey]; ok {
85+
if v, ok := scopeData[WorkspaceKey]; ok {
8686
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
8787
scopedFullnameData = &ScopedFullname{
8888
Scope: WorkspaceScope,
@@ -91,7 +91,7 @@ func ConstructScope(d *schema.ResourceData, name string) (scopedFullnameData *Sc
9191
}
9292
}
9393

94-
if v, ok := scopeData[organizationKey]; ok {
94+
if v, ok := scopeData[OrganizationKey]; ok {
9595
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
9696
scopedFullnameData = &ScopedFullname{
9797
Scope: OrganizationScope,
@@ -103,7 +103,7 @@ func ConstructScope(d *schema.ResourceData, name string) (scopedFullnameData *Sc
103103
return scopedFullnameData
104104
}
105105

106-
func FlattenScope(scopedFullname *ScopedFullname) (data []interface{}, name string) {
106+
func FlattenScope(scopedFullname *ScopedFullname, scopesAllowed []string) (data []interface{}, name string) {
107107
if scopedFullname == nil {
108108
return data, name
109109
}
@@ -113,67 +113,75 @@ func FlattenScope(scopedFullname *ScopedFullname) (data []interface{}, name stri
113113
switch scopedFullname.Scope {
114114
case ClusterScope:
115115
name = scopedFullname.FullnameCluster.Name
116-
flattenScopeData[clusterKey] = FlattenClusterPolicyFullname(scopedFullname.FullnameCluster)
116+
flattenScopeData[ClusterKey] = FlattenClusterPolicyFullname(scopedFullname.FullnameCluster)
117117
case ClusterGroupScope:
118118
name = scopedFullname.FullnameClusterGroup.Name
119-
flattenScopeData[clusterGroupKey] = FlattenClusterGroupPolicyFullname(scopedFullname.FullnameClusterGroup)
119+
flattenScopeData[ClusterGroupKey] = FlattenClusterGroupPolicyFullname(scopedFullname.FullnameClusterGroup)
120120
case WorkspaceScope:
121121
name = scopedFullname.FullnameWorkspace.Name
122-
flattenScopeData[workspaceKey] = FlattenWorkspacePolicyFullname(scopedFullname.FullnameWorkspace)
122+
flattenScopeData[WorkspaceKey] = FlattenWorkspacePolicyFullname(scopedFullname.FullnameWorkspace)
123123
case OrganizationScope:
124124
name = scopedFullname.FullnameOrganization.Name
125-
flattenScopeData[organizationKey] = FlattenOrganizationPolicyFullname(scopedFullname.FullnameOrganization)
125+
flattenScopeData[OrganizationKey] = FlattenOrganizationPolicyFullname(scopedFullname.FullnameOrganization)
126126
case UnknownScope:
127-
fmt.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(ScopesAllowed[:], `, `))
127+
fmt.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scopesAllowed, `, `))
128128
}
129129

130130
return []interface{}{flattenScopeData}, name
131131
}
132132

133-
func ValidateScope(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error {
134-
value, ok := diff.GetOk(ScopeKey)
135-
if !ok {
136-
return fmt.Errorf("scope: %v is not valid: minimum one valid scope block is required", value)
137-
}
133+
type ValidateScopeType func(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error
138134

139-
data, _ := value.([]interface{})
135+
func ValidateScope(scopesAllowed []string) ValidateScopeType {
136+
return func(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error {
137+
value, ok := diff.GetOk(ScopeKey)
138+
if !ok {
139+
return fmt.Errorf("scope: %v is not valid: minimum one valid scope block is required", value)
140+
}
140141

141-
if len(data) == 0 || data[0] == nil {
142-
return fmt.Errorf("scope data: %v is not valid: minimum one valid scope block is required among: %v", data, strings.Join(ScopesAllowed[:], `, `))
143-
}
142+
data, _ := value.([]interface{})
144143

145-
scopeData := data[0].(map[string]interface{})
146-
scopesFound := make([]string, 0)
144+
if len(data) == 0 || data[0] == nil {
145+
return fmt.Errorf("scope data: %v is not valid: minimum one valid scope block is required among: %v", data, strings.Join(scopesAllowed, `, `))
146+
}
147147

148-
if v, ok := scopeData[clusterKey]; ok {
149-
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
150-
scopesFound = append(scopesFound, clusterKey)
148+
scopeData := data[0].(map[string]interface{})
149+
scopesFound := make([]string, 0)
150+
151+
if v, ok := scopeData[ClusterKey]; ok {
152+
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
153+
scopesFound = append(scopesFound, ClusterKey)
154+
}
151155
}
152-
}
153156

154-
if v, ok := scopeData[clusterGroupKey]; ok {
155-
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
156-
scopesFound = append(scopesFound, clusterGroupKey)
157+
if v, ok := scopeData[ClusterGroupKey]; ok {
158+
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
159+
scopesFound = append(scopesFound, ClusterGroupKey)
160+
}
157161
}
158-
}
159162

160-
if v, ok := scopeData[workspaceKey]; ok {
161-
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
162-
scopesFound = append(scopesFound, workspaceKey)
163+
if v, ok := scopeData[WorkspaceKey]; ok {
164+
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
165+
scopesFound = append(scopesFound, WorkspaceKey)
166+
}
163167
}
164-
}
165168

166-
if v, ok := scopeData[organizationKey]; ok {
167-
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
168-
scopesFound = append(scopesFound, organizationKey)
169+
if v, ok := scopeData[OrganizationKey]; ok {
170+
if v1, ok := v.([]interface{}); ok && len(v1) != 0 {
171+
scopesFound = append(scopesFound, OrganizationKey)
172+
}
169173
}
170-
}
171174

172-
if len(scopesFound) == 0 {
173-
return fmt.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v", strings.Join(ScopesAllowed[:], `, `))
174-
} else if len(scopesFound) > 1 {
175-
return fmt.Errorf("found scopes: %v are not valid: maximum one valid scope type block is allowed", strings.Join(scopesFound, `, `))
176-
}
175+
if len(scopesFound) == 0 {
176+
return fmt.Errorf("no valid scope type block found: minimum one valid scope type block is required among: %v", strings.Join(scopesAllowed, `, `))
177+
} else if len(scopesFound) > 1 {
178+
return fmt.Errorf("found scopes: %v are not valid: maximum one valid scope type block is allowed", strings.Join(scopesFound, `, `))
179+
}
177180

178-
return nil
181+
if !slices.Contains(scopesAllowed, scopesFound[0]) {
182+
return fmt.Errorf("found scope: %v is not valid: minimum one valid scope type block is required among: %v", scopesFound[0], strings.Join(scopesAllowed, `, `))
183+
}
184+
185+
return nil
186+
}
179187
}

‎internal/resources/policy/test_helper.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ resource "%s" "%s" {
116116
}
117117

118118
// GetTestPolicyResourceHelperAndScope builds the helper resource and scope blocks for policy resource based on a scope type.
119-
func (shr *ScopeHelperResources) GetTestPolicyResourceHelperAndScope(scopeType scope.Scope) (string, string) {
119+
func (shr *ScopeHelperResources) GetTestPolicyResourceHelperAndScope(scopeType scope.Scope, scopesAllowed []string) (string, string) {
120120
var (
121121
helperBlock string
122122
scopeBlock string
@@ -153,7 +153,7 @@ func (shr *ScopeHelperResources) GetTestPolicyResourceHelperAndScope(scopeType s
153153
}
154154
`, shr.OrgID)
155155
case scope.UnknownScope:
156-
log.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scope.ScopesAllowed[:], `, `))
156+
log.Printf("[ERROR]: No valid scope type block found: minimum one valid scope type block is required among: %v. Please check the schema.", strings.Join(scopesAllowed, `, `))
157157
}
158158

159159
return helperBlock, scopeBlock

0 commit comments

Comments
 (0)
Please sign in to comment.