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