Skip to content

Commit ef1d452

Browse files
Add parameters to google_org_policy_policy (#12008) (#8881)
[upstream:971f4cc87fb960871a449798d060c749e831e43c] Signed-off-by: Modular Magician <[email protected]>
1 parent 4605de7 commit ef1d452

File tree

4 files changed

+228
-10
lines changed

4 files changed

+228
-10
lines changed

Diff for: .changelog/12008.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
orgpolicy: added `parameters` fields to `google_org_policy_policy` resource (beta)
3+
```

Diff for: google-beta/services/orgpolicy/resource_org_policy_policy.go

+91-10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package orgpolicy
1919

2020
import (
21+
"encoding/json"
2122
"fmt"
2223
"log"
2324
"net/http"
@@ -27,6 +28,8 @@ import (
2728
"time"
2829

2930
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
31+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
32+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
3033

3134
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
3235
transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
@@ -139,6 +142,13 @@ func ResourceOrgPolicyPolicy() *schema.Resource {
139142
Optional: true,
140143
Description: `If '"TRUE"', then the 'Policy' is enforced. If '"FALSE"', then any configuration is acceptable. This field can be set only in Policies for boolean constraints.`,
141144
},
145+
"parameters": {
146+
Type: schema.TypeString,
147+
Optional: true,
148+
ValidateFunc: validation.StringIsJSON,
149+
StateFunc: func(v interface{}) string { s, _ := structure.NormalizeJsonString(v); return s },
150+
Description: `Optional. Required for Managed Constraints if parameters defined in constraints. Pass parameter values when policy enforcement is enabled. Ensure that parameter value types match those defined in the constraint definition. For example: { \"allowedLocations\" : [\"us-east1\", \"us-west1\"], \"allowAll\" : true }`,
151+
},
142152
"values": {
143153
Type: schema.TypeList,
144154
Optional: true,
@@ -250,6 +260,13 @@ func ResourceOrgPolicyPolicy() *schema.Resource {
250260
Optional: true,
251261
Description: `If '"TRUE"', then the 'Policy' is enforced. If '"FALSE"', then any configuration is acceptable. This field can be set only in Policies for boolean constraints.`,
252262
},
263+
"parameters": {
264+
Type: schema.TypeString,
265+
Optional: true,
266+
ValidateFunc: validation.StringIsJSON,
267+
StateFunc: func(v interface{}) string { s, _ := structure.NormalizeJsonString(v); return s },
268+
Description: `Optional. Required for Managed Constraints if parameters defined in constraints. Pass parameter values when policy enforcement is enabled. Ensure that parameter value types match those defined in the constraint definition. For example: { \"allowedLocations\" : [\"us-east1\", \"us-west1\"], \"allowAll\" : true }`,
269+
},
253270
"values": {
254271
Type: schema.TypeList,
255272
Optional: true,
@@ -609,11 +626,12 @@ func flattenOrgPolicyPolicySpecRules(v interface{}, d *schema.ResourceData, conf
609626
continue
610627
}
611628
transformed = append(transformed, map[string]interface{}{
612-
"values": flattenOrgPolicyPolicySpecRulesValues(original["values"], d, config),
613-
"allow_all": flattenOrgPolicyPolicySpecRulesAllowAll(original["allowAll"], d, config),
614-
"deny_all": flattenOrgPolicyPolicySpecRulesDenyAll(original["denyAll"], d, config),
615-
"enforce": flattenOrgPolicyPolicySpecRulesEnforce(original["enforce"], d, config),
616-
"condition": flattenOrgPolicyPolicySpecRulesCondition(original["condition"], d, config),
629+
"values": flattenOrgPolicyPolicySpecRulesValues(original["values"], d, config),
630+
"allow_all": flattenOrgPolicyPolicySpecRulesAllowAll(original["allowAll"], d, config),
631+
"deny_all": flattenOrgPolicyPolicySpecRulesDenyAll(original["denyAll"], d, config),
632+
"enforce": flattenOrgPolicyPolicySpecRulesEnforce(original["enforce"], d, config),
633+
"parameters": flattenOrgPolicyPolicySpecRulesParameters(original["parameters"], d, config),
634+
"condition": flattenOrgPolicyPolicySpecRulesCondition(original["condition"], d, config),
617635
})
618636
}
619637
return transformed
@@ -662,6 +680,18 @@ func flattenOrgPolicyPolicySpecRulesEnforce(v interface{}, d *schema.ResourceDat
662680
return strings.ToUpper(strconv.FormatBool(v.(bool)))
663681
}
664682

683+
func flattenOrgPolicyPolicySpecRulesParameters(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
684+
if v == nil {
685+
return nil
686+
}
687+
b, err := json.Marshal(v)
688+
if err != nil {
689+
// TODO: return error once https://github.com/GoogleCloudPlatform/magic-modules/issues/3257 is fixed.
690+
log.Printf("[ERROR] failed to marshal schema to JSON: %v", err)
691+
}
692+
return string(b)
693+
}
694+
665695
func flattenOrgPolicyPolicySpecRulesCondition(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
666696
if v == nil {
667697
return nil
@@ -747,11 +777,12 @@ func flattenOrgPolicyPolicyDryRunSpecRules(v interface{}, d *schema.ResourceData
747777
continue
748778
}
749779
transformed = append(transformed, map[string]interface{}{
750-
"values": flattenOrgPolicyPolicyDryRunSpecRulesValues(original["values"], d, config),
751-
"allow_all": flattenOrgPolicyPolicyDryRunSpecRulesAllowAll(original["allowAll"], d, config),
752-
"deny_all": flattenOrgPolicyPolicyDryRunSpecRulesDenyAll(original["denyAll"], d, config),
753-
"enforce": flattenOrgPolicyPolicyDryRunSpecRulesEnforce(original["enforce"], d, config),
754-
"condition": flattenOrgPolicyPolicyDryRunSpecRulesCondition(original["condition"], d, config),
780+
"values": flattenOrgPolicyPolicyDryRunSpecRulesValues(original["values"], d, config),
781+
"allow_all": flattenOrgPolicyPolicyDryRunSpecRulesAllowAll(original["allowAll"], d, config),
782+
"deny_all": flattenOrgPolicyPolicyDryRunSpecRulesDenyAll(original["denyAll"], d, config),
783+
"enforce": flattenOrgPolicyPolicyDryRunSpecRulesEnforce(original["enforce"], d, config),
784+
"parameters": flattenOrgPolicyPolicyDryRunSpecRulesParameters(original["parameters"], d, config),
785+
"condition": flattenOrgPolicyPolicyDryRunSpecRulesCondition(original["condition"], d, config),
755786
})
756787
}
757788
return transformed
@@ -800,6 +831,18 @@ func flattenOrgPolicyPolicyDryRunSpecRulesEnforce(v interface{}, d *schema.Resou
800831
return strings.ToUpper(strconv.FormatBool(v.(bool)))
801832
}
802833

834+
func flattenOrgPolicyPolicyDryRunSpecRulesParameters(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
835+
if v == nil {
836+
return nil
837+
}
838+
b, err := json.Marshal(v)
839+
if err != nil {
840+
// TODO: return error once https://github.com/GoogleCloudPlatform/magic-modules/issues/3257 is fixed.
841+
log.Printf("[ERROR] failed to marshal schema to JSON: %v", err)
842+
}
843+
return string(b)
844+
}
845+
803846
func flattenOrgPolicyPolicyDryRunSpecRulesCondition(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
804847
if v == nil {
805848
return nil
@@ -944,6 +987,13 @@ func expandOrgPolicyPolicySpecRules(v interface{}, d tpgresource.TerraformResour
944987
transformed["enforce"] = transformedEnforce
945988
}
946989

990+
transformedParameters, err := expandOrgPolicyPolicySpecRulesParameters(original["parameters"], d, config)
991+
if err != nil {
992+
return nil, err
993+
} else if val := reflect.ValueOf(transformedParameters); val.IsValid() && !tpgresource.IsEmptyValue(val) {
994+
transformed["parameters"] = transformedParameters
995+
}
996+
947997
transformedCondition, err := expandOrgPolicyPolicySpecRulesCondition(original["condition"], d, config)
948998
if err != nil {
949999
return nil, err
@@ -1026,6 +1076,18 @@ func expandOrgPolicyPolicySpecRulesEnforce(v interface{}, d tpgresource.Terrafor
10261076
return b, nil
10271077
}
10281078

1079+
func expandOrgPolicyPolicySpecRulesParameters(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1080+
b := []byte(v.(string))
1081+
if len(b) == 0 {
1082+
return nil, nil
1083+
}
1084+
m := make(map[string]interface{})
1085+
if err := json.Unmarshal(b, &m); err != nil {
1086+
return nil, err
1087+
}
1088+
return m, nil
1089+
}
1090+
10291091
func expandOrgPolicyPolicySpecRulesCondition(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
10301092
l := v.([]interface{})
10311093
if len(l) == 0 || l[0] == nil {
@@ -1183,6 +1245,13 @@ func expandOrgPolicyPolicyDryRunSpecRules(v interface{}, d tpgresource.Terraform
11831245
transformed["enforce"] = transformedEnforce
11841246
}
11851247

1248+
transformedParameters, err := expandOrgPolicyPolicyDryRunSpecRulesParameters(original["parameters"], d, config)
1249+
if err != nil {
1250+
return nil, err
1251+
} else if val := reflect.ValueOf(transformedParameters); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1252+
transformed["parameters"] = transformedParameters
1253+
}
1254+
11861255
transformedCondition, err := expandOrgPolicyPolicyDryRunSpecRulesCondition(original["condition"], d, config)
11871256
if err != nil {
11881257
return nil, err
@@ -1265,6 +1334,18 @@ func expandOrgPolicyPolicyDryRunSpecRulesEnforce(v interface{}, d tpgresource.Te
12651334
return b, nil
12661335
}
12671336

1337+
func expandOrgPolicyPolicyDryRunSpecRulesParameters(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1338+
b := []byte(v.(string))
1339+
if len(b) == 0 {
1340+
return nil, nil
1341+
}
1342+
m := make(map[string]interface{})
1343+
if err := json.Unmarshal(b, &m); err != nil {
1344+
return nil, err
1345+
}
1346+
return m, nil
1347+
}
1348+
12681349
func expandOrgPolicyPolicyDryRunSpecRulesCondition(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
12691350
l := v.([]interface{})
12701351
if len(l) == 0 || l[0] == nil {

Diff for: google-beta/services/orgpolicy/resource_org_policy_policy_test.go

+103
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,106 @@ func testAccCheckOrgPolicyPolicyDestroyProducer(t *testing.T) func(s *terraform.
460460
return nil
461461
}
462462
}
463+
func TestAccOrgPolicyPolicy_EnforceParameterizedMCPolicy(t *testing.T) {
464+
// Skip this test as no constraints yet launched in production, verified functionality with manual testing.
465+
t.Skip()
466+
t.Parallel()
467+
468+
context := map[string]interface{}{
469+
"org_id": envvar.GetTestOrgFromEnv(t),
470+
"random_suffix": acctest.RandString(t, 10),
471+
}
472+
473+
acctest.VcrTest(t, resource.TestCase{
474+
PreCheck: func() { acctest.AccTestPreCheck(t) },
475+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
476+
CheckDestroy: testAccCheckOrgPolicyPolicyDestroyProducer(t),
477+
Steps: []resource.TestStep{
478+
{
479+
Config: testAccOrgPolicyPolicy_EnforceParameterizedMCPolicy(context),
480+
},
481+
{
482+
ResourceName: "google_org_policy_policy.primary",
483+
ImportState: true,
484+
ImportStateVerify: true,
485+
ImportStateVerifyIgnore: []string{"name", "spec.0.rules.0.condition.0.expression"},
486+
},
487+
},
488+
})
489+
}
490+
func testAccOrgPolicyPolicy_EnforceParameterizedMCPolicy(context map[string]interface{}) string {
491+
return acctest.Nprintf(`
492+
resource "google_org_policy_policy" "primary" {
493+
name = "projects/${google_project.basic.name}/policies/essentialcontacts.managed.allowedContactDomains"
494+
parent = "projects/${google_project.basic.name}"
495+
496+
spec {
497+
rules {
498+
enforce = "TRUE"
499+
parameters = "{\"allowedDomains\": [\"@google.com\"]}"
500+
}
501+
}
502+
}
503+
504+
resource "google_project" "basic" {
505+
project_id = "tf-test-id%{random_suffix}"
506+
name = "tf-test-id%{random_suffix}"
507+
org_id = "%{org_id}"
508+
deletion_policy = "DELETE"
509+
}
510+
511+
512+
`, context)
513+
}
514+
515+
func TestAccOrgPolicyPolicy_EnforceParameterizedMCDryRunPolicy(t *testing.T) {
516+
// Skip this test as no constraints yet launched in production, verified functionality with manual testing.
517+
t.Skip()
518+
t.Parallel()
519+
520+
context := map[string]interface{}{
521+
"org_id": envvar.GetTestOrgFromEnv(t),
522+
"random_suffix": acctest.RandString(t, 10),
523+
}
524+
525+
acctest.VcrTest(t, resource.TestCase{
526+
PreCheck: func() { acctest.AccTestPreCheck(t) },
527+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
528+
CheckDestroy: testAccCheckOrgPolicyPolicyDestroyProducer(t),
529+
Steps: []resource.TestStep{
530+
{
531+
Config: testAccOrgPolicyPolicy_EnforceParameterizedMCDryRunPolicy(context),
532+
},
533+
{
534+
ResourceName: "google_org_policy_policy.primary",
535+
ImportState: true,
536+
ImportStateVerify: true,
537+
ImportStateVerifyIgnore: []string{"name", "spec.0.rules.0.condition.0.expression"},
538+
},
539+
},
540+
})
541+
}
542+
func testAccOrgPolicyPolicy_EnforceParameterizedMCDryRunPolicy(context map[string]interface{}) string {
543+
return acctest.Nprintf(`
544+
resource "google_org_policy_policy" "primary" {
545+
name = "projects/${google_project.basic.name}/policies/essentialcontacts.managed.allowedContactDomains"
546+
parent = "projects/${google_project.basic.name}"
547+
548+
dry_run_spec {
549+
rules {
550+
enforce = "TRUE"
551+
parameters = "{\"allowedDomains\": [\"@google.com\"]}"
552+
}
553+
}
554+
}
555+
556+
resource "google_project" "basic" {
557+
project_id = "tf-test-id%{random_suffix}"
558+
name = "tf-test-id%{random_suffix}"
559+
org_id = "%{org_id}"
560+
deletion_policy = "DELETE"
561+
}
562+
563+
564+
`, context)
565+
}

Diff for: website/docs/r/org_policy_policy.html.markdown

+31
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,29 @@ resource "google_org_policy_policy" "primary" {
157157
}
158158
}
159159
```
160+
## Example Usage - Org Policy Policy Parameters Enforce
161+
162+
163+
```hcl
164+
resource "google_org_policy_policy" "primary" {
165+
name = "projects/${google_project.basic.name}/policies/compute.managed.restrictDiskCreation"
166+
parent = "projects/${google_project.basic.name}"
167+
168+
spec {
169+
rules {
170+
enforce = "TRUE"
171+
parameters = jsonencode({"isSizeLimitCheck" : true, "allowedDiskTypes" : ["pd-ssd", "pd-standard"]})
172+
}
173+
}
174+
}
175+
176+
resource "google_project" "basic" {
177+
project_id = "id"
178+
name = "id"
179+
org_id = "123456789"
180+
deletion_policy = "DELETE"
181+
}
182+
```
160183

161184
## Argument Reference
162185

@@ -229,6 +252,10 @@ The following arguments are supported:
229252
(Optional)
230253
If `"TRUE"`, then the `Policy` is enforced. If `"FALSE"`, then any configuration is acceptable. This field can be set only in Policies for boolean constraints.
231254

255+
* `parameters` -
256+
(Optional)
257+
Optional. Required for Managed Constraints if parameters defined in constraints. Pass parameter values when policy enforcement is enabled. Ensure that parameter value types match those defined in the constraint definition. For example: { \"allowedLocations\" : [\"us-east1\", \"us-west1\"], \"allowAll\" : true }
258+
232259
* `condition` -
233260
(Optional)
234261
A condition which determines whether this rule is used in the evaluation of the policy. When set, the `expression` field in the `Expr' must include from 1 to 10 subexpressions, joined by the "||" or "&&" operators. Each subexpression must be of the form "resource.matchTag('/tag_key_short_name, 'tag_value_short_name')". or "resource.matchTagId('tagKeys/key_id', 'tagValues/value_id')". where key_name and value_name are the resource names for Label Keys and Values. These names are available from the Tag Manager Service. An example expression is: "resource.matchTag('123456789/environment, 'prod')". or "resource.matchTagId('tagKeys/123', 'tagValues/456')".
@@ -306,6 +333,10 @@ The following arguments are supported:
306333
(Optional)
307334
If `"TRUE"`, then the `Policy` is enforced. If `"FALSE"`, then any configuration is acceptable. This field can be set only in Policies for boolean constraints.
308335

336+
* `parameters` -
337+
(Optional)
338+
Optional. Required for Managed Constraints if parameters defined in constraints. Pass parameter values when policy enforcement is enabled. Ensure that parameter value types match those defined in the constraint definition. For example: { \"allowedLocations\" : [\"us-east1\", \"us-west1\"], \"allowAll\" : true }
339+
309340
* `condition` -
310341
(Optional)
311342
A condition which determines whether this rule is used in the evaluation of the policy. When set, the `expression` field in the `Expr' must include from 1 to 10 subexpressions, joined by the "||" or "&&" operators. Each subexpression must be of the form "resource.matchTag('/tag_key_short_name, 'tag_value_short_name')". or "resource.matchTagId('tagKeys/key_id', 'tagValues/value_id')". where key_name and value_name are the resource names for Label Keys and Values. These names are available from the Tag Manager Service. An example expression is: "resource.matchTag('123456789/environment, 'prod')". or "resource.matchTagId('tagKeys/123', 'tagValues/456')".

0 commit comments

Comments
 (0)