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