Skip to content

Commit 50bbbf8

Browse files
authored
Merge pull request #371 from vmware/mshobha/acc-test-custom-policy-assignment
Add acceptance test and guide for custom policy resource
2 parents 47745de + da0f966 commit 50bbbf8

File tree

4 files changed

+178
-3
lines changed

4 files changed

+178
-3
lines changed

docs/guides/tanzu-mission-control_policy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,8 @@ resource "tanzu-mission-control_custom_policy" "cluster_group_scoped_tmc-block-r
275275
}
276276
```
277277

278+
## Custom Template and Custom Policy
279+
280+
Template provides a declarative definition of a policy, which can be used to apply custom constraints on managed kubernetes resources.
281+
Custom policy consumes these declared custom templates to enforce specific policies. One must create the custom template before consuming it the custom policy.
282+
Please refer to custom policy template and custom policy terraform scripts within examples.

internal/resources/policy/kind/custom/resource/custom_policy_provider_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ import (
1414
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/authctx"
1515
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/cluster"
1616
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/clustergroup"
17+
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/custompolicytemplate"
1718
policykindcustom "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/custom"
1819
)
1920

2021
func initTestProvider(t *testing.T) *schema.Provider {
2122
testAccProvider := &schema.Provider{
2223
Schema: authctx.ProviderAuthSchema(),
2324
ResourcesMap: map[string]*schema.Resource{
24-
policykindcustom.ResourceName: ResourceCustomPolicy(),
25-
cluster.ResourceName: cluster.ResourceTMCCluster(),
26-
clustergroup.ResourceName: clustergroup.ResourceClusterGroup(),
25+
policykindcustom.ResourceName: ResourceCustomPolicy(),
26+
cluster.ResourceName: cluster.ResourceTMCCluster(),
27+
clustergroup.ResourceName: clustergroup.ResourceClusterGroup(),
28+
custompolicytemplate.ResourceName: custompolicytemplate.ResourceCustomPolicyTemplate(),
2729
},
2830
ConfigureContextFunc: authctx.ProviderConfigureContext,
2931
}

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

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
policyclustermodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/cluster"
2727
policyclustergroupmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/clustergroup"
2828
policyorganizationmodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/organization"
29+
custompolicytemplateres "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/custompolicytemplate"
2930
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy"
3031
policykindCustom "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/kind/custom"
3132
policyoperations "github.com/vmware/terraform-provider-tanzu-mission-control/internal/resources/policy/operations"
@@ -61,6 +62,7 @@ func testGetDefaultAcceptanceConfig(t *testing.T) *testAcceptanceConfig {
6162

6263
func TestAcceptanceForCustomPolicyResource(t *testing.T) {
6364
testConfig := testGetDefaultAcceptanceConfig(t)
65+
customPolicyTemplateResource := fmt.Sprintf("%s.%s", custompolicytemplateres.ResourceName, "test_custom_policy_template")
6466

6567
t.Log("start custom policy resource acceptance tests!")
6668

@@ -267,9 +269,64 @@ func TestAcceptanceForCustomPolicyResource(t *testing.T) {
267269
)
268270

269271
t.Log("Custom policy resource acceptance test complete for tmc-require-labels recipe!")
272+
273+
// Test case for custom policy template assignment resource
274+
resource.Test(t, resource.TestCase{
275+
PreCheck: testhelper.TestPreCheck(t),
276+
ProviderFactories: testhelper.GetTestProviderFactories(testConfig.Provider),
277+
CheckDestroy: nil,
278+
Steps: []resource.TestStep{
279+
{
280+
Config: testConfig.getTestCustomPolicyTemplateConfigValue(),
281+
Check: resource.ComposeTestCheckFunc(
282+
resource.TestCheckResourceAttr(customPolicyTemplateResource, "name", "tf-custom-template-test"),
283+
),
284+
},
285+
{
286+
PreConfig: func() {
287+
if testConfig.ScopeHelperResources.Cluster.KubeConfigPath == "" {
288+
t.Skip("KUBECONFIG env var is not set for cluster scoped custom policy acceptance test")
289+
}
290+
},
291+
ResourceName: customPolicyTemplateResource,
292+
ImportState: true,
293+
ImportStateVerify: true,
294+
Config: testConfig.getTestCustomPolicyConfigValue(scope.ClusterScope, policykindCustom.TMCCustomRecipe),
295+
Check: testConfig.checkCustomPolicyResourceAttributes(scope.ClusterScope),
296+
},
297+
{
298+
Config: testConfig.getTestCustomPolicyConfigValue(scope.ClusterGroupScope, policykindCustom.TMCCustomRecipe),
299+
ResourceName: customPolicyTemplateResource,
300+
ImportState: true,
301+
ImportStateVerify: true,
302+
Check: resource.ComposeTestCheckFunc(
303+
testConfig.checkCustomPolicyResourceAttributes(scope.ClusterGroupScope),
304+
),
305+
},
306+
{
307+
PreConfig: func() {
308+
if testConfig.ScopeHelperResources.OrgID == "" {
309+
t.Skip("ORG_ID env var is not set for organization scoped custom policy acceptance test")
310+
}
311+
},
312+
ResourceName: customPolicyTemplateResource,
313+
ImportState: true,
314+
ImportStateVerify: true,
315+
Config: testConfig.getTestCustomPolicyConfigValue(scope.OrganizationScope, policykindCustom.TMCCustomRecipe),
316+
Check: testConfig.checkCustomPolicyResourceAttributes(scope.OrganizationScope),
317+
},
318+
},
319+
},
320+
)
321+
322+
t.Log("Custom policy resource acceptance test complete for custom recipe!")
270323
t.Log("all custom policy resource acceptance tests complete!")
271324
}
272325

326+
func (testConfig *testAcceptanceConfig) getTestCustomPolicyConfigValue(scope scope.Scope, recipe policykindCustom.Recipe) string {
327+
return fmt.Sprintf("%s\n%s", testConfig.getTestCustomPolicyTemplateConfigValue(), testConfig.getTestCustomPolicyResourceBasicConfigValue(scope, recipe))
328+
}
329+
273330
func (testConfig *testAcceptanceConfig) getTestCustomPolicyResourceBasicConfigValue(scope scope.Scope, recipe policykindCustom.Recipe) string {
274331
helperBlock, scopeBlock := testConfig.ScopeHelperResources.GetTestPolicyResourceHelperAndScope(scope, policyoperations.ScopeMap[testConfig.CustomPolicyResource], false)
275332
inputBlock := testConfig.getTestCustomPolicyResourceInput(recipe)
@@ -305,6 +362,85 @@ func (testConfig *testAcceptanceConfig) getTestCustomPolicyResourceBasicConfigVa
305362
`, helperBlock, testConfig.CustomPolicyResource, testConfig.CustomPolicyResourceVar, testConfig.CustomPolicyName, scopeBlock, inputBlock)
306363
}
307364

365+
func (testConfig *testAcceptanceConfig) getTestCustomPolicyTemplateConfigValue() string {
366+
customTemplate := `
367+
resource "tanzu-mission-control_custom_policy_template" "test_custom_policy_template" {
368+
name = "tf-custom-template-test"
369+
370+
spec {
371+
object_type = "ConstraintTemplate"
372+
template_type = "OPAGatekeeper"
373+
374+
data_inventory {
375+
kind = "ConfigMap"
376+
group = "admissionregistration.k8s.io"
377+
version = "v1"
378+
}
379+
380+
data_inventory {
381+
kind = "Deployment"
382+
group = "extensions"
383+
version = "v1"
384+
}
385+
386+
template_manifest = <<YAML
387+
apiVersion: templates.gatekeeper.sh/v1beta1
388+
kind: ConstraintTemplate
389+
metadata:
390+
name: tf-custom-template-test
391+
annotations:
392+
description: Requires Pods to have readiness and/or liveness probes.
393+
spec:
394+
crd:
395+
spec:
396+
names:
397+
kind: tf-custom-template-test
398+
validation:
399+
openAPIV3Schema:
400+
properties:
401+
probes:
402+
type: array
403+
items:
404+
type: string
405+
probeTypes:
406+
type: array
407+
items:
408+
type: string
409+
targets:
410+
- target: admission.k8s.gatekeeper.sh
411+
rego: |
412+
package k8srequiredprobes
413+
probe_type_set = probe_types {
414+
probe_types := {type | type := input.parameters.probeTypes[_]}
415+
}
416+
violation[{"msg": msg}] {
417+
container := input.review.object.spec.containers[_]
418+
probe := input.parameters.probes[_]
419+
probe_is_missing(container, probe)
420+
msg := get_violation_message(container, input.review, probe)
421+
}
422+
probe_is_missing(ctr, probe) = true {
423+
not ctr[probe]
424+
}
425+
probe_is_missing(ctr, probe) = true {
426+
probe_field_empty(ctr, probe)
427+
}
428+
probe_field_empty(ctr, probe) = true {
429+
probe_fields := {field | ctr[probe][field]}
430+
diff_fields := probe_type_set - probe_fields
431+
count(diff_fields) == count(probe_type_set)
432+
}
433+
get_violation_message(container, review, probe) = msg {
434+
msg := sprintf("Container <%v> in your <%v> <%v> has no <%v>", [container.name, review.kind.kind, review.object.metadata.name, probe])
435+
}
436+
YAML
437+
}
438+
}
439+
`
440+
441+
return customTemplate
442+
}
443+
308444
// getTestCustomPolicyResourceInput builds the input block for custom policy resource based a recipe.
309445
func (testConfig *testAcceptanceConfig) getTestCustomPolicyResourceInput(recipe policykindCustom.Recipe) string {
310446
var inputBlock string
@@ -430,6 +566,33 @@ func (testConfig *testAcceptanceConfig) getTestCustomPolicyResourceInput(recipe
430566
}
431567
}
432568
}
569+
`
570+
case policykindCustom.TMCCustomRecipe:
571+
inputBlock = `
572+
input {
573+
custom {
574+
template_name = "tf-custom-template-test"
575+
audit = false
576+
577+
target_kubernetes_resources {
578+
api_groups = [
579+
"apps",
580+
]
581+
kinds = [
582+
"Deployment"
583+
]
584+
}
585+
586+
target_kubernetes_resources {
587+
api_groups = [
588+
"apps",
589+
]
590+
kinds = [
591+
"StatefulSet",
592+
]
593+
}
594+
}
595+
}
433596
`
434597
case policykindCustom.UnknownRecipe:
435598
log.Printf("[ERROR]: No valid input recipe block found: minimum one valid input recipe block is required among: %v. Please check the schema.", strings.Join(policykindCustom.RecipesAllowed[:], `, `))

templates/guides/tanzu-mission-control_policy.md.tmpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,8 @@ In the following example, there are multiple dependencies shown.
4141

4242
{{ tffile "examples/usecases/custom_policy_usecase.tf" }}
4343

44+
## Custom Template and Custom Policy
45+
46+
Template provides a declarative definition of a policy, which can be used to apply custom constraints on managed kubernetes resources.
47+
Custom policy consumes these declared custom templates to enforce specific policies. One must create the custom template before consuming it the custom policy.
48+
Please refer to custom policy template and custom policy terraform scripts within examples.

0 commit comments

Comments
 (0)