github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 := v.Role 154 entity := v.Entity 155 if _, in := re_local_map[entity]; in { 156 role_entity = append(role_entity, fmt.Sprintf("%s:%s", role, entity)) 157 log.Printf("[DEBUG]: saving re %s-%s", role, entity) 158 } 159 } 160 161 d.Set("role_entity", role_entity) 162 } 163 164 d.SetId(getObjectAclId(object)) 165 return nil 166 } 167 168 func resourceStorageObjectAclUpdate(d *schema.ResourceData, meta interface{}) error { 169 config := meta.(*Config) 170 171 bucket := d.Get("bucket").(string) 172 object := d.Get("object").(string) 173 174 if d.HasChange("role_entity") { 175 o, n := d.GetChange("role_entity") 176 old_re, new_re := o.([]interface{}), n.([]interface{}) 177 178 old_re_map := make(map[string]string) 179 for _, v := range old_re { 180 res, err := getRoleEntityPair(v.(string)) 181 182 if err != nil { 183 return fmt.Errorf( 184 "Old state has malformed Role/Entity pair: %v", err) 185 } 186 187 old_re_map[res.Entity] = res.Role 188 } 189 190 for _, v := range new_re { 191 pair, err := getRoleEntityPair(v.(string)) 192 193 objectAccessControl := &storage.ObjectAccessControl{ 194 Role: pair.Role, 195 Entity: pair.Entity, 196 } 197 198 // If the old state is missing this entity, it needs to 199 // be created. Otherwise it is updated 200 if _, ok := old_re_map[pair.Entity]; ok { 201 _, err = config.clientStorage.ObjectAccessControls.Update( 202 bucket, object, pair.Entity, objectAccessControl).Do() 203 } else { 204 _, err = config.clientStorage.ObjectAccessControls.Insert( 205 bucket, object, objectAccessControl).Do() 206 } 207 208 // Now we only store the keys that have to be removed 209 delete(old_re_map, pair.Entity) 210 211 if err != nil { 212 return fmt.Errorf("Error updating ACL for object %s: %v", bucket, err) 213 } 214 } 215 216 for entity, _ := range old_re_map { 217 log.Printf("[DEBUG]: removing entity %s", entity) 218 err := config.clientStorage.ObjectAccessControls.Delete(bucket, object, entity).Do() 219 220 if err != nil { 221 return fmt.Errorf("Error updating ACL for object %s: %v", bucket, err) 222 } 223 } 224 225 return resourceStorageObjectAclRead(d, meta) 226 } 227 228 return nil 229 } 230 231 func resourceStorageObjectAclDelete(d *schema.ResourceData, meta interface{}) error { 232 config := meta.(*Config) 233 234 bucket := d.Get("bucket").(string) 235 object := d.Get("object").(string) 236 237 re_local := d.Get("role_entity").([]interface{}) 238 for _, v := range re_local { 239 res, err := getRoleEntityPair(v.(string)) 240 if err != nil { 241 return err 242 } 243 244 entity := res.Entity 245 246 log.Printf("[DEBUG]: removing entity %s", entity) 247 248 err = config.clientStorage.ObjectAccessControls.Delete(bucket, object, 249 entity).Do() 250 251 if err != nil { 252 return fmt.Errorf("Error deleting entity %s ACL: %s", 253 entity, err) 254 } 255 } 256 257 return nil 258 }