github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/builtin/providers/google/resource_storage_object_acl.go (about) 1 package google 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/hashicorp/terraform/helper/schema" 8 9 "google.golang.org/api/googleapi" 10 "google.golang.org/api/storage/v1" 11 ) 12 13 func resourceStorageObjectAcl() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceStorageObjectAclCreate, 16 Read: resourceStorageObjectAclRead, 17 Update: resourceStorageObjectAclUpdate, 18 Delete: resourceStorageObjectAclDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "bucket": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 ForceNew: true, 25 }, 26 "object": &schema.Schema{ 27 Type: schema.TypeString, 28 Required: 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 "predefined_acl": &schema.Schema{ 37 Type: schema.TypeString, 38 Optional: true, 39 ForceNew: true, 40 }, 41 }, 42 } 43 } 44 45 func getObjectAclId(object string) string { 46 return object + "-acl" 47 } 48 49 func resourceStorageObjectAclCreate(d *schema.ResourceData, meta interface{}) error { 50 config := meta.(*Config) 51 52 bucket := d.Get("bucket").(string) 53 object := d.Get("object").(string) 54 55 predefined_acl := "" 56 role_entity := make([]interface{}, 0) 57 58 if v, ok := d.GetOk("predefined_acl"); ok { 59 predefined_acl = v.(string) 60 } 61 62 if v, ok := d.GetOk("role_entity"); ok { 63 role_entity = v.([]interface{}) 64 } 65 66 if len(predefined_acl) > 0 { 67 if len(role_entity) > 0 { 68 return fmt.Errorf("Error, you cannot specify both " + 69 "\"predefined_acl\" and \"role_entity\"") 70 } 71 72 res, err := config.clientStorage.Objects.Get(bucket, object).Do() 73 74 if err != nil { 75 return fmt.Errorf("Error reading object %s: %v", bucket, err) 76 } 77 78 res, err = config.clientStorage.Objects.Update(bucket, object, 79 res).PredefinedAcl(predefined_acl).Do() 80 81 if err != nil { 82 return fmt.Errorf("Error updating object %s: %v", bucket, err) 83 } 84 85 return resourceStorageBucketAclRead(d, meta) 86 } else if len(role_entity) > 0 { 87 for _, v := range role_entity { 88 pair, err := getRoleEntityPair(v.(string)) 89 90 objectAccessControl := &storage.ObjectAccessControl{ 91 Role: pair.Role, 92 Entity: pair.Entity, 93 } 94 95 log.Printf("[DEBUG]: setting role = %s, entity = %s", pair.Role, pair.Entity) 96 97 _, err = config.clientStorage.ObjectAccessControls.Insert(bucket, 98 object, objectAccessControl).Do() 99 100 if err != nil { 101 return fmt.Errorf("Error setting ACL for %s on object %s: %v", pair.Entity, object, err) 102 } 103 } 104 105 return resourceStorageObjectAclRead(d, meta) 106 } 107 108 return fmt.Errorf("Error, you must specify either " + 109 "\"predefined_acl\" or \"role_entity\"") 110 } 111 112 func resourceStorageObjectAclRead(d *schema.ResourceData, meta interface{}) error { 113 config := meta.(*Config) 114 115 bucket := d.Get("bucket").(string) 116 object := d.Get("object").(string) 117 118 // Predefined ACLs cannot easily be parsed once they have been processed 119 // by the GCP server 120 if _, ok := d.GetOk("predefined_acl"); !ok { 121 role_entity := make([]interface{}, 0) 122 re_local := d.Get("role_entity").([]interface{}) 123 re_local_map := make(map[string]string) 124 for _, v := range re_local { 125 res, err := getRoleEntityPair(v.(string)) 126 127 if err != nil { 128 return fmt.Errorf( 129 "Old state has malformed Role/Entity pair: %v", err) 130 } 131 132 re_local_map[res.Entity] = res.Role 133 } 134 135 res, err := config.clientStorage.ObjectAccessControls.List(bucket, object).Do() 136 137 if err != nil { 138 if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 { 139 log.Printf("[WARN] Removing Storage Object ACL for Bucket %q because it's gone", d.Get("bucket").(string)) 140 // The resource doesn't exist anymore 141 d.SetId("") 142 143 return nil 144 } 145 146 return err 147 } 148 149 for _, v := range res.Items { 150 role := "" 151 entity := "" 152 for key, val := range v.(map[string]interface{}) { 153 if key == "role" { 154 role = val.(string) 155 } else if key == "entity" { 156 entity = val.(string) 157 } 158 } 159 if _, in := re_local_map[entity]; in { 160 role_entity = append(role_entity, fmt.Sprintf("%s:%s", role, entity)) 161 log.Printf("[DEBUG]: saving re %s-%s", role, entity) 162 } 163 } 164 165 d.Set("role_entity", role_entity) 166 } 167 168 d.SetId(getObjectAclId(object)) 169 return nil 170 } 171 172 func resourceStorageObjectAclUpdate(d *schema.ResourceData, meta interface{}) error { 173 config := meta.(*Config) 174 175 bucket := d.Get("bucket").(string) 176 object := d.Get("object").(string) 177 178 if d.HasChange("role_entity") { 179 o, n := d.GetChange("role_entity") 180 old_re, new_re := o.([]interface{}), n.([]interface{}) 181 182 old_re_map := make(map[string]string) 183 for _, v := range old_re { 184 res, err := getRoleEntityPair(v.(string)) 185 186 if err != nil { 187 return fmt.Errorf( 188 "Old state has malformed Role/Entity pair: %v", err) 189 } 190 191 old_re_map[res.Entity] = res.Role 192 } 193 194 for _, v := range new_re { 195 pair, err := getRoleEntityPair(v.(string)) 196 197 objectAccessControl := &storage.ObjectAccessControl{ 198 Role: pair.Role, 199 Entity: pair.Entity, 200 } 201 202 // If the old state is missing this entity, it needs to 203 // be created. Otherwise it is updated 204 if _, ok := old_re_map[pair.Entity]; ok { 205 _, err = config.clientStorage.ObjectAccessControls.Update( 206 bucket, object, pair.Entity, objectAccessControl).Do() 207 } else { 208 _, err = config.clientStorage.ObjectAccessControls.Insert( 209 bucket, object, objectAccessControl).Do() 210 } 211 212 // Now we only store the keys that have to be removed 213 delete(old_re_map, pair.Entity) 214 215 if err != nil { 216 return fmt.Errorf("Error updating ACL for object %s: %v", bucket, err) 217 } 218 } 219 220 for entity, _ := range old_re_map { 221 log.Printf("[DEBUG]: removing entity %s", entity) 222 err := config.clientStorage.ObjectAccessControls.Delete(bucket, object, entity).Do() 223 224 if err != nil { 225 return fmt.Errorf("Error updating ACL for object %s: %v", bucket, err) 226 } 227 } 228 229 return resourceStorageObjectAclRead(d, meta) 230 } 231 232 return nil 233 } 234 235 func resourceStorageObjectAclDelete(d *schema.ResourceData, meta interface{}) error { 236 config := meta.(*Config) 237 238 bucket := d.Get("bucket").(string) 239 object := d.Get("object").(string) 240 241 re_local := d.Get("role_entity").([]interface{}) 242 for _, v := range re_local { 243 res, err := getRoleEntityPair(v.(string)) 244 if err != nil { 245 return err 246 } 247 248 entity := res.Entity 249 250 log.Printf("[DEBUG]: removing entity %s", entity) 251 252 err = config.clientStorage.ObjectAccessControls.Delete(bucket, object, 253 entity).Do() 254 255 if err != nil { 256 return fmt.Errorf("Error deleting entity %s ACL: %s", 257 entity, err) 258 } 259 } 260 261 return nil 262 }