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