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