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