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