github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/google/resource_storage_bucket_acl.go (about) 1 package google 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "github.com/hashicorp/terraform/helper/schema" 9 10 "google.golang.org/api/storage/v1" 11 ) 12 13 func resourceStorageBucketAcl() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceStorageBucketAclCreate, 16 Read: resourceStorageBucketAclRead, 17 Update: resourceStorageBucketAclUpdate, 18 Delete: resourceStorageBucketAclDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "bucket": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 ForceNew: true, 25 }, 26 "predefined_acl": &schema.Schema{ 27 Type: schema.TypeString, 28 Optional: true, 29 ForceNew: true, 30 }, 31 "role_entity": &schema.Schema{ 32 Type: schema.TypeList, 33 Optional: true, 34 Elem: &schema.Schema{Type: schema.TypeString}, 35 }, 36 "default_acl": &schema.Schema{ 37 Type: schema.TypeString, 38 Optional: true, 39 }, 40 }, 41 } 42 } 43 44 type RoleEntity struct { 45 Role string 46 Entity string 47 } 48 49 func getBucketAclId(bucket string) string { 50 return bucket + "-acl" 51 } 52 53 func getRoleEntityPair(role_entity string) (*RoleEntity, error) { 54 split := strings.Split(role_entity, ":") 55 if len(split) != 2 { 56 return nil, fmt.Errorf("Error, each role entity pair must be " + 57 "formatted as ROLE:entity") 58 } 59 60 return &RoleEntity{Role: split[0], Entity: split[1]}, nil 61 } 62 63 func resourceStorageBucketAclCreate(d *schema.ResourceData, meta interface{}) error { 64 config := meta.(*Config) 65 66 bucket := d.Get("bucket").(string) 67 predefined_acl := "" 68 default_acl := "" 69 role_entity := make([]interface{}, 0) 70 71 if v, ok := d.GetOk("predefined_acl"); ok { 72 predefined_acl = v.(string) 73 } 74 75 if v, ok := d.GetOk("role_entity"); ok { 76 role_entity = v.([]interface{}) 77 } 78 79 if v, ok := d.GetOk("default_acl"); ok { 80 default_acl = v.(string) 81 } 82 83 if len(predefined_acl) > 0 { 84 if len(role_entity) > 0 { 85 return fmt.Errorf("Error, you cannot specify both " + 86 "\"predefined_acl\" and \"role_entity\"") 87 } 88 89 res, err := config.clientStorage.Buckets.Get(bucket).Do() 90 91 if err != nil { 92 return fmt.Errorf("Error reading bucket %s: %v", bucket, err) 93 } 94 95 res, err = config.clientStorage.Buckets.Update(bucket, 96 res).PredefinedAcl(predefined_acl).Do() 97 98 if err != nil { 99 return fmt.Errorf("Error updating bucket %s: %v", bucket, err) 100 } 101 102 return resourceStorageBucketAclRead(d, meta) 103 } else if len(role_entity) > 0 { 104 for _, v := range role_entity { 105 pair, err := getRoleEntityPair(v.(string)) 106 107 bucketAccessControl := &storage.BucketAccessControl{ 108 Role: pair.Role, 109 Entity: pair.Entity, 110 } 111 112 log.Printf("[DEBUG]: storing re %s-%s", pair.Role, pair.Entity) 113 114 _, err = config.clientStorage.BucketAccessControls.Insert(bucket, bucketAccessControl).Do() 115 116 if err != nil { 117 return fmt.Errorf("Error updating ACL for bucket %s: %v", bucket, err) 118 } 119 } 120 121 return resourceStorageBucketAclRead(d, meta) 122 } 123 124 if len(default_acl) > 0 { 125 res, err := config.clientStorage.Buckets.Get(bucket).Do() 126 127 if err != nil { 128 return fmt.Errorf("Error reading bucket %s: %v", bucket, err) 129 } 130 131 res, err = config.clientStorage.Buckets.Update(bucket, 132 res).PredefinedDefaultObjectAcl(default_acl).Do() 133 134 if err != nil { 135 return fmt.Errorf("Error updating bucket %s: %v", bucket, err) 136 } 137 138 return resourceStorageBucketAclRead(d, meta) 139 } 140 141 return nil 142 } 143 144 func resourceStorageBucketAclRead(d *schema.ResourceData, meta interface{}) error { 145 config := meta.(*Config) 146 147 bucket := d.Get("bucket").(string) 148 149 // Predefined ACLs cannot easily be parsed once they have been processed 150 // by the GCP server 151 if _, ok := d.GetOk("predefined_acl"); !ok { 152 role_entity := make([]interface{}, 0) 153 re_local := d.Get("role_entity").([]interface{}) 154 re_local_map := make(map[string]string) 155 for _, v := range re_local { 156 res, err := getRoleEntityPair(v.(string)) 157 158 if err != nil { 159 return fmt.Errorf( 160 "Old state has malformed Role/Entity pair: %v", err) 161 } 162 163 re_local_map[res.Entity] = res.Role 164 } 165 166 res, err := config.clientStorage.BucketAccessControls.List(bucket).Do() 167 168 if err != nil { 169 return err 170 } 171 172 for _, v := range res.Items { 173 log.Printf("[DEBUG]: examining re %s-%s", v.Role, v.Entity) 174 // We only store updates to the locally defined access controls 175 if _, in := re_local_map[v.Entity]; in { 176 role_entity = append(role_entity, fmt.Sprintf("%s:%s", v.Role, v.Entity)) 177 log.Printf("[DEBUG]: saving re %s-%s", v.Role, v.Entity) 178 } 179 } 180 181 d.Set("role_entity", role_entity) 182 } 183 184 d.SetId(getBucketAclId(bucket)) 185 return nil 186 } 187 188 func resourceStorageBucketAclUpdate(d *schema.ResourceData, meta interface{}) error { 189 config := meta.(*Config) 190 191 bucket := d.Get("bucket").(string) 192 193 if d.HasChange("role_entity") { 194 o, n := d.GetChange("role_entity") 195 old_re, new_re := o.([]interface{}), n.([]interface{}) 196 197 old_re_map := make(map[string]string) 198 for _, v := range old_re { 199 res, err := getRoleEntityPair(v.(string)) 200 201 if err != nil { 202 return fmt.Errorf( 203 "Old state has malformed Role/Entity pair: %v", err) 204 } 205 206 old_re_map[res.Entity] = res.Role 207 } 208 209 for _, v := range new_re { 210 pair, err := getRoleEntityPair(v.(string)) 211 212 bucketAccessControl := &storage.BucketAccessControl{ 213 Role: pair.Role, 214 Entity: pair.Entity, 215 } 216 217 // If the old state is missing this entity, it needs to 218 // be created. Otherwise it is updated 219 if _, ok := old_re_map[pair.Entity]; ok { 220 _, err = config.clientStorage.BucketAccessControls.Update( 221 bucket, pair.Entity, bucketAccessControl).Do() 222 } else { 223 _, err = config.clientStorage.BucketAccessControls.Insert( 224 bucket, bucketAccessControl).Do() 225 } 226 227 // Now we only store the keys that have to be removed 228 delete(old_re_map, pair.Entity) 229 230 if err != nil { 231 return fmt.Errorf("Error updating ACL for bucket %s: %v", bucket, err) 232 } 233 } 234 235 for entity, _ := range old_re_map { 236 log.Printf("[DEBUG]: removing entity %s", entity) 237 err := config.clientStorage.BucketAccessControls.Delete(bucket, entity).Do() 238 239 if err != nil { 240 return fmt.Errorf("Error updating ACL for bucket %s: %v", bucket, err) 241 } 242 } 243 244 return resourceStorageBucketAclRead(d, meta) 245 } 246 247 if d.HasChange("default_acl") { 248 default_acl := d.Get("default_acl").(string) 249 250 res, err := config.clientStorage.Buckets.Get(bucket).Do() 251 252 if err != nil { 253 return fmt.Errorf("Error reading bucket %s: %v", bucket, err) 254 } 255 256 res, err = config.clientStorage.Buckets.Update(bucket, 257 res).PredefinedDefaultObjectAcl(default_acl).Do() 258 259 if err != nil { 260 return fmt.Errorf("Error updating bucket %s: %v", bucket, err) 261 } 262 263 return resourceStorageBucketAclRead(d, meta) 264 } 265 266 return nil 267 } 268 269 func resourceStorageBucketAclDelete(d *schema.ResourceData, meta interface{}) error { 270 config := meta.(*Config) 271 272 bucket := d.Get("bucket").(string) 273 274 re_local := d.Get("role_entity").([]interface{}) 275 for _, v := range re_local { 276 res, err := getRoleEntityPair(v.(string)) 277 if err != nil { 278 return err 279 } 280 281 log.Printf("[DEBUG]: removing entity %s", res.Entity) 282 283 err = config.clientStorage.BucketAccessControls.Delete(bucket, res.Entity).Do() 284 285 if err != nil { 286 return fmt.Errorf("Error deleting entity %s ACL: %s", res.Entity, err) 287 } 288 } 289 290 return nil 291 }