Document that a policy must be defined. (#3611)

Signed-off-by: Modular Magician <magic-modules@google.com>
This commit is contained in:
The Magician 2019-05-16 13:10:44 -07:00 committed by Chris Stephens
parent de550575be
commit f34848f974
7 changed files with 86 additions and 9 deletions

View File

@ -51,12 +51,16 @@ func resourceFolderOrgPolicyImporter(d *schema.ResourceData, meta interface{}) (
} }
func resourceGoogleFolderOrganizationPolicyCreate(d *schema.ResourceData, meta interface{}) error { func resourceGoogleFolderOrganizationPolicyCreate(d *schema.ResourceData, meta interface{}) error {
d.SetId(fmt.Sprintf("%s:%s", d.Get("folder"), d.Get("constraint")))
if isOrganizationPolicyUnset(d) {
return resourceGoogleFolderOrganizationPolicyDelete(d, meta)
}
if err := setFolderOrganizationPolicy(d, meta); err != nil { if err := setFolderOrganizationPolicy(d, meta); err != nil {
return err return err
} }
d.SetId(fmt.Sprintf("%s:%s", d.Get("folder"), d.Get("constraint")))
return resourceGoogleFolderOrganizationPolicyRead(d, meta) return resourceGoogleFolderOrganizationPolicyRead(d, meta)
} }
@ -84,6 +88,10 @@ func resourceGoogleFolderOrganizationPolicyRead(d *schema.ResourceData, meta int
} }
func resourceGoogleFolderOrganizationPolicyUpdate(d *schema.ResourceData, meta interface{}) error { func resourceGoogleFolderOrganizationPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
if isOrganizationPolicyUnset(d) {
return resourceGoogleFolderOrganizationPolicyDelete(d, meta)
}
if err := setFolderOrganizationPolicy(d, meta); err != nil { if err := setFolderOrganizationPolicy(d, meta); err != nil {
return err return err
} }

View File

@ -144,12 +144,16 @@ func resourceGoogleOrganizationPolicy() *schema.Resource {
} }
func resourceGoogleOrganizationPolicyCreate(d *schema.ResourceData, meta interface{}) error { func resourceGoogleOrganizationPolicyCreate(d *schema.ResourceData, meta interface{}) error {
d.SetId(fmt.Sprintf("%s:%s", d.Get("org_id"), d.Get("constraint").(string)))
if isOrganizationPolicyUnset(d) {
return resourceGoogleOrganizationPolicyDelete(d, meta)
}
if err := setOrganizationPolicy(d, meta); err != nil { if err := setOrganizationPolicy(d, meta); err != nil {
return err return err
} }
d.SetId(fmt.Sprintf("%s:%s", d.Get("org_id"), d.Get("constraint").(string)))
return resourceGoogleOrganizationPolicyRead(d, meta) return resourceGoogleOrganizationPolicyRead(d, meta)
} }
@ -177,6 +181,10 @@ func resourceGoogleOrganizationPolicyRead(d *schema.ResourceData, meta interface
} }
func resourceGoogleOrganizationPolicyUpdate(d *schema.ResourceData, meta interface{}) error { func resourceGoogleOrganizationPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
if isOrganizationPolicyUnset(d) {
return resourceGoogleOrganizationPolicyDelete(d, meta)
}
if err := setOrganizationPolicy(d, meta); err != nil { if err := setOrganizationPolicy(d, meta); err != nil {
return err return err
} }
@ -211,6 +219,19 @@ func resourceGoogleOrganizationPolicyImportState(d *schema.ResourceData, meta in
return []*schema.ResourceData{d}, nil return []*schema.ResourceData{d}, nil
} }
// Organization policies can be "inherited from parent" the UI, and this is the default
// state of the resource without any policy set. In order to revert to this state the current
// resource cannot be updated it must instead be Deleted. This allows Terraform to assert that
// no policy has been set even if previously one had.
// See https://github.com/terraform-providers/terraform-provider-google/issues/3607
func isOrganizationPolicyUnset(d *schema.ResourceData) bool {
listPolicy := d.Get("list_policy").([]interface{})
booleanPolicy := d.Get("boolean_policy").([]interface{})
restorePolicy := d.Get("restore_policy").([]interface{})
return len(listPolicy)+len(booleanPolicy)+len(restorePolicy) == 0
}
func setOrganizationPolicy(d *schema.ResourceData, meta interface{}) error { func setOrganizationPolicy(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
org := "organizations/" + d.Get("org_id").(string) org := "organizations/" + d.Get("org_id").(string)

View File

@ -50,12 +50,16 @@ func resourceProjectOrgPolicyImporter(d *schema.ResourceData, meta interface{})
} }
func resourceGoogleProjectOrganizationPolicyCreate(d *schema.ResourceData, meta interface{}) error { func resourceGoogleProjectOrganizationPolicyCreate(d *schema.ResourceData, meta interface{}) error {
d.SetId(fmt.Sprintf("%s:%s", d.Get("project"), d.Get("constraint")))
if isOrganizationPolicyUnset(d) {
return resourceGoogleProjectOrganizationPolicyDelete(d, meta)
}
if err := setProjectOrganizationPolicy(d, meta); err != nil { if err := setProjectOrganizationPolicy(d, meta); err != nil {
return err return err
} }
d.SetId(fmt.Sprintf("%s:%s", d.Get("project"), d.Get("constraint")))
return resourceGoogleProjectOrganizationPolicyRead(d, meta) return resourceGoogleProjectOrganizationPolicyRead(d, meta)
} }
@ -83,6 +87,10 @@ func resourceGoogleProjectOrganizationPolicyRead(d *schema.ResourceData, meta in
} }
func resourceGoogleProjectOrganizationPolicyUpdate(d *schema.ResourceData, meta interface{}) error { func resourceGoogleProjectOrganizationPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
if isOrganizationPolicyUnset(d) {
return resourceGoogleProjectOrganizationPolicyDelete(d, meta)
}
if err := setProjectOrganizationPolicy(d, meta); err != nil { if err := setProjectOrganizationPolicy(d, meta); err != nil {
return err return err
} }

View File

@ -22,6 +22,7 @@ func TestAccProjectOrganizationPolicy(t *testing.T) {
"list_denySome": testAccProjectOrganizationPolicy_list_denySome, "list_denySome": testAccProjectOrganizationPolicy_list_denySome,
"list_update": testAccProjectOrganizationPolicy_list_update, "list_update": testAccProjectOrganizationPolicy_list_update,
"restore_policy": testAccProjectOrganizationPolicy_restore_defaultTrue, "restore_policy": testAccProjectOrganizationPolicy_restore_defaultTrue,
"empty_policy": testAccProjectOrganizationPolicy_none,
} }
for name, tc := range testCases { for name, tc := range testCases {
@ -179,6 +180,27 @@ func testAccProjectOrganizationPolicy_restore_defaultTrue(t *testing.T) {
}) })
} }
func testAccProjectOrganizationPolicy_none(t *testing.T) {
projectId := getTestProjectFromEnv()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGoogleProjectOrganizationPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccProjectOrganizationPolicyConfig_none(projectId),
Check: testAccCheckGoogleProjectOrganizationPolicyDestroy,
},
{
ResourceName: "google_project_organization_policy.none",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func testAccCheckGoogleProjectOrganizationPolicyDestroy(s *terraform.State) error { func testAccCheckGoogleProjectOrganizationPolicyDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config) config := testAccProvider.Meta().(*Config)
@ -387,6 +409,15 @@ resource "google_project_organization_policy" "restore" {
`, pid) `, pid)
} }
func testAccProjectOrganizationPolicyConfig_none(pid string) string {
return fmt.Sprintf(`
resource "google_project_organization_policy" "none" {
project = "%s"
constraint = "constraints/serviceuser.services"
}
`, pid)
}
func canonicalProjectId(project string) string { func canonicalProjectId(project string) string {
if strings.HasPrefix(project, "projects/") { if strings.HasPrefix(project, "projects/") {
return project return project

View File

@ -94,6 +94,9 @@ can also be used to allow or deny all values. Structure is documented below.
* `restore_policy` - (Optional) A restore policy is a constraint to restore the default policy. Structure is documented below. * `restore_policy` - (Optional) A restore policy is a constraint to restore the default policy. Structure is documented below.
~> **Note:** If none of [`boolean_policy`, `list_policy`, `restore_policy`] are defined the policy for a given constraint will
effectively be unset. This is represented in the UI as the constraint being 'Inherited'.
- - - - - -
The `boolean_policy` block supports: The `boolean_policy` block supports:

View File

@ -86,11 +86,14 @@ The following arguments are supported:
* `version` - (Optional) Version of the Policy. Default version is 0. * `version` - (Optional) Version of the Policy. Default version is 0.
* `boolean_policy` - (Optional) A boolean policy is a constraint that is either enforced or not. Structure is documented below. * `boolean_policy` - (Optional) A boolean policy is a constraint that is either enforced or not. Structure is documented below.
* `list_policy` - (Optional) A policy that can define specific values that are allowed or denied for the given constraint. It can also be used to allow or deny all values. Structure is documented below. * `list_policy` - (Optional) A policy that can define specific values that are allowed or denied for the given constraint. It can also be used to allow or deny all values. Structure is documented below.
* `restore_policy` - (Optional) A restore policy is a constraint to restore the default policy. Structure is documented below. * `restore_policy` - (Optional) A restore policy is a constraint to restore the default policy. Structure is documented below.
~> **Note:** If none of [`boolean_policy`, `list_policy`, `restore_policy`] are defined the policy for a given constraint will
effectively be unset. This is represented in the UI as the constraint being 'Inherited'.
- - - - - -
@ -122,7 +125,7 @@ The `restore_policy` block supports:
In addition to the arguments listed above, the following computed attributes are In addition to the arguments listed above, the following computed attributes are
exported: exported:
* `etag` - (Computed) The etag of the organization policy. `etag` is used for optimistic concurrency control as a way to help prevent simultaneous updates of a policy from overwriting each other. * `etag` - (Computed) The etag of the organization policy. `etag` is used for optimistic concurrency control as a way to help prevent simultaneous updates of a policy from overwriting each other.
* `update_time` - (Computed) The timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds, representing when the variable was last updated. Example: "2016-10-09T12:33:37.578138407Z". * `update_time` - (Computed) The timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds, representing when the variable was last updated. Example: "2016-10-09T12:33:37.578138407Z".

View File

@ -93,6 +93,9 @@ The following arguments are supported:
* `restore_policy` - (Optional) A restore policy is a constraint to restore the default policy. Structure is documented below. * `restore_policy` - (Optional) A restore policy is a constraint to restore the default policy. Structure is documented below.
~> **Note:** If none of [`boolean_policy`, `list_policy`, `restore_policy`] are defined the policy for a given constraint will
effectively be unset. This is represented in the UI as the constraint being 'Inherited'.
- - - - - -
The `boolean_policy` block supports: The `boolean_policy` block supports: