github.com/IBM-Cloud/terraform@v0.6.4-0.20170726051544-8872b87621df/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  }