github.com/IBM-Cloud/terraform@v0.6.4-0.20170726051544-8872b87621df/builtin/providers/google/resource_storage_bucket.go (about)

     1  package google
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  
    12  	"google.golang.org/api/googleapi"
    13  	"google.golang.org/api/storage/v1"
    14  )
    15  
    16  func resourceStorageBucket() *schema.Resource {
    17  	return &schema.Resource{
    18  		Create: resourceStorageBucketCreate,
    19  		Read:   resourceStorageBucketRead,
    20  		Update: resourceStorageBucketUpdate,
    21  		Delete: resourceStorageBucketDelete,
    22  
    23  		Schema: map[string]*schema.Schema{
    24  			"name": &schema.Schema{
    25  				Type:     schema.TypeString,
    26  				Required: true,
    27  				ForceNew: true,
    28  			},
    29  
    30  			"force_destroy": &schema.Schema{
    31  				Type:     schema.TypeBool,
    32  				Optional: true,
    33  				Default:  false,
    34  			},
    35  
    36  			"location": &schema.Schema{
    37  				Type:     schema.TypeString,
    38  				Default:  "US",
    39  				Optional: true,
    40  				ForceNew: true,
    41  			},
    42  
    43  			"predefined_acl": &schema.Schema{
    44  				Type:       schema.TypeString,
    45  				Deprecated: "Please use resource \"storage_bucket_acl.predefined_acl\" instead.",
    46  				Optional:   true,
    47  				ForceNew:   true,
    48  			},
    49  
    50  			"project": &schema.Schema{
    51  				Type:     schema.TypeString,
    52  				Optional: true,
    53  				ForceNew: true,
    54  			},
    55  
    56  			"self_link": &schema.Schema{
    57  				Type:     schema.TypeString,
    58  				Computed: true,
    59  			},
    60  
    61  			"url": &schema.Schema{
    62  				Type:     schema.TypeString,
    63  				Computed: true,
    64  			},
    65  
    66  			"storage_class": &schema.Schema{
    67  				Type:     schema.TypeString,
    68  				Optional: true,
    69  				Default:  "STANDARD",
    70  				ForceNew: true,
    71  			},
    72  
    73  			"website": &schema.Schema{
    74  				Type:     schema.TypeList,
    75  				Optional: true,
    76  				Elem: &schema.Resource{
    77  					Schema: map[string]*schema.Schema{
    78  						"main_page_suffix": &schema.Schema{
    79  							Type:     schema.TypeString,
    80  							Optional: true,
    81  						},
    82  						"not_found_page": &schema.Schema{
    83  							Type:     schema.TypeString,
    84  							Optional: true,
    85  						},
    86  					},
    87  				},
    88  			},
    89  		},
    90  	}
    91  }
    92  
    93  func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error {
    94  	config := meta.(*Config)
    95  
    96  	project, err := getProject(d, config)
    97  	if err != nil {
    98  		return err
    99  	}
   100  
   101  	// Get the bucket and acl
   102  	bucket := d.Get("name").(string)
   103  	location := d.Get("location").(string)
   104  
   105  	// Create a bucket, setting the acl, location and name.
   106  	sb := &storage.Bucket{Name: bucket, Location: location}
   107  
   108  	if v, ok := d.GetOk("storage_class"); ok {
   109  		sb.StorageClass = v.(string)
   110  	}
   111  
   112  	if v, ok := d.GetOk("website"); ok {
   113  		websites := v.([]interface{})
   114  
   115  		if len(websites) > 1 {
   116  			return fmt.Errorf("At most one website block is allowed")
   117  		}
   118  
   119  		sb.Website = &storage.BucketWebsite{}
   120  
   121  		website := websites[0].(map[string]interface{})
   122  
   123  		if v, ok := website["not_found_page"]; ok {
   124  			sb.Website.NotFoundPage = v.(string)
   125  		}
   126  
   127  		if v, ok := website["main_page_suffix"]; ok {
   128  			sb.Website.MainPageSuffix = v.(string)
   129  		}
   130  	}
   131  
   132  	var res *storage.Bucket
   133  
   134  	err = resource.Retry(1*time.Minute, func() *resource.RetryError {
   135  		call := config.clientStorage.Buckets.Insert(project, sb)
   136  		if v, ok := d.GetOk("predefined_acl"); ok {
   137  			call = call.PredefinedAcl(v.(string))
   138  		}
   139  
   140  		res, err = call.Do()
   141  		if err == nil {
   142  			return nil
   143  		}
   144  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 429 {
   145  			return resource.RetryableError(gerr)
   146  		}
   147  		return resource.NonRetryableError(err)
   148  	})
   149  
   150  	if err != nil {
   151  		fmt.Printf("Error creating bucket %s: %v", bucket, err)
   152  		return err
   153  	}
   154  
   155  	log.Printf("[DEBUG] Created bucket %v at location %v\n\n", res.Name, res.SelfLink)
   156  
   157  	// Assign the bucket ID as the resource ID
   158  	d.Set("self_link", res.SelfLink)
   159  	d.Set("url", fmt.Sprintf("gs://%s", bucket))
   160  	d.SetId(res.Id)
   161  
   162  	return nil
   163  }
   164  
   165  func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error {
   166  	config := meta.(*Config)
   167  
   168  	sb := &storage.Bucket{}
   169  
   170  	if d.HasChange("website") {
   171  		if v, ok := d.GetOk("website"); ok {
   172  			websites := v.([]interface{})
   173  
   174  			if len(websites) > 1 {
   175  				return fmt.Errorf("At most one website block is allowed")
   176  			}
   177  
   178  			// Setting fields to "" to be explicit that the PATCH call will
   179  			// delete this field.
   180  			if len(websites) == 0 {
   181  				sb.Website.NotFoundPage = ""
   182  				sb.Website.MainPageSuffix = ""
   183  			} else {
   184  				website := websites[0].(map[string]interface{})
   185  				sb.Website = &storage.BucketWebsite{}
   186  				if v, ok := website["not_found_page"]; ok {
   187  					sb.Website.NotFoundPage = v.(string)
   188  				} else {
   189  					sb.Website.NotFoundPage = ""
   190  				}
   191  
   192  				if v, ok := website["main_page_suffix"]; ok {
   193  					sb.Website.MainPageSuffix = v.(string)
   194  				} else {
   195  					sb.Website.MainPageSuffix = ""
   196  				}
   197  			}
   198  		}
   199  	}
   200  
   201  	res, err := config.clientStorage.Buckets.Patch(d.Get("name").(string), sb).Do()
   202  
   203  	if err != nil {
   204  		return err
   205  	}
   206  
   207  	log.Printf("[DEBUG] Patched bucket %v at location %v\n\n", res.Name, res.SelfLink)
   208  
   209  	// Assign the bucket ID as the resource ID
   210  	d.Set("self_link", res.SelfLink)
   211  	d.SetId(res.Id)
   212  
   213  	return nil
   214  }
   215  
   216  func resourceStorageBucketRead(d *schema.ResourceData, meta interface{}) error {
   217  	config := meta.(*Config)
   218  
   219  	// Get the bucket and acl
   220  	bucket := d.Get("name").(string)
   221  	res, err := config.clientStorage.Buckets.Get(bucket).Do()
   222  
   223  	if err != nil {
   224  		return handleNotFoundError(err, d, fmt.Sprintf("Storage Bucket %q", d.Get("name").(string)))
   225  	}
   226  
   227  	log.Printf("[DEBUG] Read bucket %v at location %v\n\n", res.Name, res.SelfLink)
   228  
   229  	// Update the bucket ID according to the resource ID
   230  	d.Set("self_link", res.SelfLink)
   231  	d.SetId(res.Id)
   232  
   233  	return nil
   234  }
   235  
   236  func resourceStorageBucketDelete(d *schema.ResourceData, meta interface{}) error {
   237  	config := meta.(*Config)
   238  
   239  	// Get the bucket
   240  	bucket := d.Get("name").(string)
   241  
   242  	for {
   243  		res, err := config.clientStorage.Objects.List(bucket).Do()
   244  		if err != nil {
   245  			fmt.Printf("Error Objects.List failed: %v", err)
   246  			return err
   247  		}
   248  
   249  		if len(res.Items) != 0 {
   250  			if d.Get("force_destroy").(bool) {
   251  				// purge the bucket...
   252  				log.Printf("[DEBUG] GCS Bucket attempting to forceDestroy\n\n")
   253  
   254  				for _, object := range res.Items {
   255  					log.Printf("[DEBUG] Found %s", object.Name)
   256  					if err := config.clientStorage.Objects.Delete(bucket, object.Name).Do(); err != nil {
   257  						log.Fatalf("Error trying to delete object: %s %s\n\n", object.Name, err)
   258  					} else {
   259  						log.Printf("Object deleted: %s \n\n", object.Name)
   260  					}
   261  				}
   262  
   263  			} else {
   264  				delete_err := errors.New("Error trying to delete a bucket containing objects without `force_destroy` set to true")
   265  				log.Printf("Error! %s : %s\n\n", bucket, delete_err)
   266  				return delete_err
   267  			}
   268  		} else {
   269  			break // 0 items, bucket empty
   270  		}
   271  	}
   272  
   273  	// remove empty bucket
   274  	err := resource.Retry(1*time.Minute, func() *resource.RetryError {
   275  		err := config.clientStorage.Buckets.Delete(bucket).Do()
   276  		if err == nil {
   277  			return nil
   278  		}
   279  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 429 {
   280  			return resource.RetryableError(gerr)
   281  		}
   282  		return resource.NonRetryableError(err)
   283  	})
   284  	if err != nil {
   285  		fmt.Printf("Error deleting bucket %s: %v\n\n", bucket, err)
   286  		return err
   287  	}
   288  	log.Printf("[DEBUG] Deleted bucket %v\n\n", bucket)
   289  
   290  	return nil
   291  }