Skip to content

Commit 95cef99

Browse files
Merge pull request #378 from vmware/bangerar/custom-policy-guide-fix
Update the doc link and add the example link to the cutom policy guide
2 parents 0ac792a + 7df2dcd commit 95cef99

File tree

4 files changed

+281
-5
lines changed

4 files changed

+281
-5
lines changed

docs/guides/tanzu-mission-control_policy.md

+138-2
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ resource "tanzu-mission-control_iam_policy" "namespace_scoped_iam_policy" {
211211
}
212212
```
213213

214-
## Custom Policy on a CLuster Group
214+
## Custom Policy on a Cluster Group
215215

216216
```terraform
217217
/*
@@ -278,5 +278,141 @@ resource "tanzu-mission-control_custom_policy" "cluster_group_scoped_tmc-block-r
278278
## Custom Template and Custom Policy
279279

280280
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.
281+
Custom policy consumes these declared custom templates to enforce specific policies. One must create the [custom template][custom-policy-template] before consuming it in the custom policy.
282282
Please refer to custom policy template and custom policy terraform scripts within examples.
283+
284+
[custom-policy-template]: https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/services/tanzumc-using/GUID-F147492B-04FD-4CFD-8D1F-66E36D40D49C.html
285+
286+
## Refer the following example for creating custom policy template and assign it to custom policy
287+
288+
```terraform
289+
/*
290+
NOTE: Creation of custom policy depends on cluster group and custom policy template.
291+
*/
292+
293+
terraform {
294+
required_providers {
295+
tanzu-mission-control = {
296+
source = "vmware/tanzu-mission-control"
297+
}
298+
}
299+
}
300+
301+
# Create cluster group.
302+
resource "tanzu-mission-control_cluster_group" "create_cluster_group" {
303+
name = "tf-demo-cluster-group"
304+
}
305+
306+
# Create custom policy template.
307+
resource "tanzu-mission-control_custom_policy_template" "sample_template" {
308+
name = "tf-custom-template-test"
309+
310+
spec {
311+
object_type = "ConstraintTemplate"
312+
template_type = "OPAGatekeeper"
313+
314+
data_inventory {
315+
kind = "ConfigMap"
316+
group = "admissionregistration.k8s.io"
317+
version = "v1"
318+
}
319+
320+
data_inventory {
321+
kind = "Deployment"
322+
group = "extensions"
323+
version = "v1"
324+
}
325+
326+
template_manifest = <<YAML
327+
apiVersion: templates.gatekeeper.sh/v1beta1
328+
kind: ConstraintTemplate
329+
metadata:
330+
name: tf-custom-template-test
331+
annotations:
332+
description: Requires Pods to have readiness and/or liveness probes.
333+
spec:
334+
crd:
335+
spec:
336+
names:
337+
kind: tf-custom-template-test
338+
validation:
339+
openAPIV3Schema:
340+
properties:
341+
probes:
342+
type: array
343+
items:
344+
type: string
345+
probeTypes:
346+
type: array
347+
items:
348+
type: string
349+
targets:
350+
- target: admission.k8s.gatekeeper.sh
351+
rego: |
352+
package k8srequiredprobes
353+
probe_type_set = probe_types {
354+
probe_types := {type | type := input.parameters.probeTypes[_]}
355+
}
356+
violation[{"msg": msg}] {
357+
container := input.review.object.spec.containers[_]
358+
probe := input.parameters.probes[_]
359+
probe_is_missing(container, probe)
360+
msg := get_violation_message(container, input.review, probe)
361+
}
362+
probe_is_missing(ctr, probe) = true {
363+
not ctr[probe]
364+
}
365+
probe_is_missing(ctr, probe) = true {
366+
probe_field_empty(ctr, probe)
367+
}
368+
probe_field_empty(ctr, probe) = true {
369+
probe_fields := {field | ctr[probe][field]}
370+
diff_fields := probe_type_set - probe_fields
371+
count(diff_fields) == count(probe_type_set)
372+
}
373+
get_violation_message(container, review, probe) = msg {
374+
msg := sprintf("Container <%v> in your <%v> <%v> has no <%v>", [container.name, review.kind.kind, review.object.metadata.name, probe])
375+
}
376+
YAML
377+
}
378+
}
379+
380+
381+
# Cluster group scoped custom template assigned Custom Policy
382+
resource "tanzu-mission-control_custom_policy" "cluster_group_scoped_custom_template_assigned_custom_policy" {
383+
name = "tf-custom-template-policy-test"
384+
385+
scope {
386+
cluster_group {
387+
cluster_group = tanzu-mission-control_cluster_group.create_cluster_group.name
388+
}
389+
}
390+
391+
spec {
392+
input {
393+
custom {
394+
template_name = tanzu-mission-control_custom_policy_template.sample_template.name
395+
audit = false
396+
397+
target_kubernetes_resources {
398+
api_groups = [
399+
"apps",
400+
]
401+
kinds = [
402+
"Deployment"
403+
]
404+
}
405+
406+
target_kubernetes_resources {
407+
api_groups = [
408+
"apps",
409+
]
410+
kinds = [
411+
"StatefulSet",
412+
]
413+
}
414+
}
415+
}
416+
}
417+
}
418+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
NOTE: Creation of custom policy depends on cluster group and custom policy template.
3+
*/
4+
5+
terraform {
6+
required_providers {
7+
tanzu-mission-control = {
8+
source = "vmware/tanzu-mission-control"
9+
}
10+
}
11+
}
12+
13+
# Create cluster group.
14+
resource "tanzu-mission-control_cluster_group" "create_cluster_group" {
15+
name = "tf-demo-cluster-group"
16+
}
17+
18+
# Create custom policy template.
19+
resource "tanzu-mission-control_custom_policy_template" "sample_template" {
20+
name = "tf-custom-template-test"
21+
22+
spec {
23+
object_type = "ConstraintTemplate"
24+
template_type = "OPAGatekeeper"
25+
26+
data_inventory {
27+
kind = "ConfigMap"
28+
group = "admissionregistration.k8s.io"
29+
version = "v1"
30+
}
31+
32+
data_inventory {
33+
kind = "Deployment"
34+
group = "extensions"
35+
version = "v1"
36+
}
37+
38+
template_manifest = <<YAML
39+
apiVersion: templates.gatekeeper.sh/v1beta1
40+
kind: ConstraintTemplate
41+
metadata:
42+
name: tf-custom-template-test
43+
annotations:
44+
description: Requires Pods to have readiness and/or liveness probes.
45+
spec:
46+
crd:
47+
spec:
48+
names:
49+
kind: tf-custom-template-test
50+
validation:
51+
openAPIV3Schema:
52+
properties:
53+
probes:
54+
type: array
55+
items:
56+
type: string
57+
probeTypes:
58+
type: array
59+
items:
60+
type: string
61+
targets:
62+
- target: admission.k8s.gatekeeper.sh
63+
rego: |
64+
package k8srequiredprobes
65+
probe_type_set = probe_types {
66+
probe_types := {type | type := input.parameters.probeTypes[_]}
67+
}
68+
violation[{"msg": msg}] {
69+
container := input.review.object.spec.containers[_]
70+
probe := input.parameters.probes[_]
71+
probe_is_missing(container, probe)
72+
msg := get_violation_message(container, input.review, probe)
73+
}
74+
probe_is_missing(ctr, probe) = true {
75+
not ctr[probe]
76+
}
77+
probe_is_missing(ctr, probe) = true {
78+
probe_field_empty(ctr, probe)
79+
}
80+
probe_field_empty(ctr, probe) = true {
81+
probe_fields := {field | ctr[probe][field]}
82+
diff_fields := probe_type_set - probe_fields
83+
count(diff_fields) == count(probe_type_set)
84+
}
85+
get_violation_message(container, review, probe) = msg {
86+
msg := sprintf("Container <%v> in your <%v> <%v> has no <%v>", [container.name, review.kind.kind, review.object.metadata.name, probe])
87+
}
88+
YAML
89+
}
90+
}
91+
92+
93+
# Cluster group scoped custom template assigned Custom Policy
94+
resource "tanzu-mission-control_custom_policy" "cluster_group_scoped_custom_template_assigned_custom_policy" {
95+
name = "tf-custom-template-policy-test"
96+
97+
scope {
98+
cluster_group {
99+
cluster_group = tanzu-mission-control_cluster_group.create_cluster_group.name
100+
}
101+
}
102+
103+
spec {
104+
input {
105+
custom {
106+
template_name = tanzu-mission-control_custom_policy_template.sample_template.name
107+
audit = false
108+
109+
target_kubernetes_resources {
110+
api_groups = [
111+
"apps",
112+
]
113+
kinds = [
114+
"Deployment"
115+
]
116+
}
117+
118+
target_kubernetes_resources {
119+
api_groups = [
120+
"apps",
121+
]
122+
kinds = [
123+
"StatefulSet",
124+
]
125+
}
126+
}
127+
}
128+
}
129+
}

internal/resources/policy/kind/custom/recipe/tmc_custom_schema.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/pkg/errors"
1515

1616
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/authctx"
17+
clienterrors "github.com/vmware/terraform-provider-tanzu-mission-control/internal/client/errors"
1718
"github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper"
1819
openapiv3 "github.com/vmware/terraform-provider-tanzu-mission-control/internal/helper/openapi_v3_schema_validator"
1920
policyrecipecustommodel "github.com/vmware/terraform-provider-tanzu-mission-control/internal/models/policy/recipe/custom"
@@ -117,7 +118,11 @@ func ValidateCustomRecipe(config authctx.TanzuContext, customRecipe map[string]i
117118
recipeData, err := config.TMCConnection.RecipeResourceService.RecipeResourceServiceGet(recipeModel)
118119

119120
if err != nil {
120-
errMessages = append(errMessages, err.Error())
121+
// NOTE: If error is 404 not found then do not fail the planning. This fix ensures that if user tries to create the new custom template
122+
// and assign the same template to the custom policy in a single terraform apply operation will be able to proceed, instead of failing in the planning phase.
123+
if !clienterrors.IsNotFoundError(err) {
124+
errMessages = append(errMessages, err.Error())
125+
}
121126
} else {
122127
errs := ValidateRecipeParameters(recipeData.Recipe.Spec.InputSchema, customRecipe[ParametersKey].(string))
123128

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,18 @@ In the following example, there are multiple dependencies shown.
3737

3838
{{ tffile "examples/usecases/access_policy_usecase.tf" }}
3939

40-
## Custom Policy on a CLuster Group
40+
## Custom Policy on a Cluster Group
4141

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

4444
## Custom Template and Custom Policy
4545

4646
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.
47+
Custom policy consumes these declared custom templates to enforce specific policies. One must create the [custom template][custom-policy-template] before consuming it in the custom policy.
4848
Please refer to custom policy template and custom policy terraform scripts within examples.
49+
50+
[custom-policy-template]: https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/services/tanzumc-using/GUID-F147492B-04FD-4CFD-8D1F-66E36D40D49C.html
51+
52+
## Refer the following example for creating custom policy template and assign it to custom policy
53+
54+
{{ tffile "examples/usecases/custom_policy_with_custom_template_usecase.tf" }}

0 commit comments

Comments
 (0)