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  }