github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/google/resource_storage_bucket.go (about)

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