Fix the perma-diff in storage bucket ACLs.

Add a CustomDiff function to storage bucket ACLs that will ignore a diff
if the config and state have the same role_entities, even if they're in
a different order.

Fixes #1525.
This commit is contained in:
Paddy Carver 2018-06-21 23:42:25 -07:00
parent a2b95e35e6
commit 1c8d56eca2
2 changed files with 64 additions and 4 deletions

View File

@ -13,10 +13,11 @@ import (
func resourceStorageBucketAcl() *schema.Resource {
return &schema.Resource{
Create: resourceStorageBucketAclCreate,
Read: resourceStorageBucketAclRead,
Update: resourceStorageBucketAclUpdate,
Delete: resourceStorageBucketAclDelete,
Create: resourceStorageBucketAclCreate,
Read: resourceStorageBucketAclRead,
Update: resourceStorageBucketAclUpdate,
Delete: resourceStorageBucketAclDelete,
CustomizeDiff: resourceStorageBucketAclCustomizeDiff,
Schema: map[string]*schema.Schema{
"bucket": &schema.Schema{
@ -40,6 +41,7 @@ func resourceStorageBucketAcl() *schema.Resource {
"role_entity": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
ConflictsWith: []string{"predefined_acl"},
},
@ -47,6 +49,33 @@ func resourceStorageBucketAcl() *schema.Resource {
}
}
func resourceStorageBucketAclCustomizeDiff(diff *schema.ResourceDiff, meta interface{}) error {
keys := diff.GetChangedKeysPrefix("role_entity")
if len(keys) < 1 {
return nil
}
count := diff.Get("role_entity.#").(int)
if count < 1 {
return nil
}
state := map[string]struct{}{}
conf := map[string]struct{}{}
for i := 0; i < count; i++ {
old, new := diff.GetChange(fmt.Sprintf("role_entity.%d", i))
state[old.(string)] = struct{}{}
conf[new.(string)] = struct{}{}
}
if len(state) != len(conf) {
return nil
}
for k, _ := range state {
if _, ok := conf[k]; !ok {
return nil
}
}
return diff.Clear("role_entity")
}
type RoleEntity struct {
Role string
Entity string

View File

@ -138,6 +138,24 @@ func TestAccStorageBucketAcl_predefined(t *testing.T) {
})
}
// Test that we allow the API to reorder our role entities without perma-diffing.
func TestAccStorageBucketAcl_unordered(t *testing.T) {
t.Parallel()
bucketName := testBucketName()
skipIfEnvNotSet(t, "GOOGLE_PROJECT_NUMBER")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccStorageBucketAclDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testGoogleStorageBucketsAclUnordered(bucketName),
},
},
})
}
func testAccCheckGoogleStorageBucketAclDelete(bucket, roleEntityS string) resource.TestCheckFunc {
return func(s *terraform.State) error {
roleEntity, _ := getRoleEntityPair(roleEntityS)
@ -244,6 +262,19 @@ resource "google_storage_bucket_acl" "acl" {
`, bucketName, roleEntityOwners, roleEntityEditors, roleEntityViewers, roleEntityBasic2, roleEntityBasic3_reader)
}
func testGoogleStorageBucketsAclUnordered(bucketName string) string {
return fmt.Sprintf(`
resource "google_storage_bucket" "bucket" {
name = "%s"
}
resource "google_storage_bucket_acl" "acl" {
bucket = "${google_storage_bucket.bucket.name}"
role_entity = ["%s", "%s", "%s", "%s", "%s"]
}
`, bucketName, roleEntityBasic1, roleEntityViewers, roleEntityOwners, roleEntityBasic2, roleEntityEditors)
}
func testGoogleStorageBucketsAclPredefined(bucketName string) string {
return fmt.Sprintf(`
resource "google_storage_bucket" "bucket" {