github.com/atsaki/terraform@v0.4.3-0.20150919165407-25bba5967654/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/storage/v1" 11 ) 12 13 func resourceStorageBucket() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceStorageBucketCreate, 16 Read: resourceStorageBucketRead, 17 Update: resourceStorageBucketUpdate, 18 Delete: resourceStorageBucketDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "name": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 ForceNew: true, 25 }, 26 "predefined_acl": &schema.Schema{ 27 Type: schema.TypeString, 28 Default: "projectPrivate", 29 Optional: true, 30 ForceNew: true, 31 }, 32 "location": &schema.Schema{ 33 Type: schema.TypeString, 34 Default: "US", 35 Optional: true, 36 ForceNew: true, 37 }, 38 "force_destroy": &schema.Schema{ 39 Type: schema.TypeBool, 40 Optional: true, 41 Default: false, 42 }, 43 "website": &schema.Schema{ 44 Type: schema.TypeList, 45 Optional: true, 46 Elem: &schema.Resource{ 47 Schema: map[string]*schema.Schema{ 48 "main_page_suffix": &schema.Schema{ 49 Type: schema.TypeString, 50 Optional: true, 51 }, 52 "not_found_page": &schema.Schema{ 53 Type: schema.TypeString, 54 Optional: true, 55 }, 56 }, 57 }, 58 }, 59 "self_link": &schema.Schema{ 60 Type: schema.TypeString, 61 Computed: true, 62 }, 63 }, 64 } 65 } 66 67 func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error { 68 config := meta.(*Config) 69 70 // Get the bucket and acl 71 bucket := d.Get("name").(string) 72 acl := d.Get("predefined_acl").(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 res, err := config.clientStorage.Buckets.Insert(config.Project, sb).PredefinedAcl(acl).Do() 99 100 if err != nil { 101 fmt.Printf("Error creating bucket %s: %v", bucket, err) 102 return err 103 } 104 105 log.Printf("[DEBUG] Created bucket %v at location %v\n\n", res.Name, res.SelfLink) 106 107 // Assign the bucket ID as the resource ID 108 d.Set("self_link", res.SelfLink) 109 d.SetId(res.Id) 110 111 return nil 112 } 113 114 func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error { 115 config := meta.(*Config) 116 117 sb := &storage.Bucket{} 118 119 if d.HasChange("website") { 120 if v, ok := d.GetOk("website"); ok { 121 websites := v.([]interface{}) 122 123 if len(websites) > 1 { 124 return fmt.Errorf("At most one website block is allowed") 125 } 126 127 // Setting fields to "" to be explicit that the PATCH call will 128 // delete this field. 129 if len(websites) == 0 { 130 sb.Website.NotFoundPage = "" 131 sb.Website.MainPageSuffix = "" 132 } else { 133 website := websites[0].(map[string]interface{}) 134 sb.Website = &storage.BucketWebsite{} 135 if v, ok := website["not_found_page"]; ok { 136 sb.Website.NotFoundPage = v.(string) 137 } else { 138 sb.Website.NotFoundPage = "" 139 } 140 141 if v, ok := website["main_page_suffix"]; ok { 142 sb.Website.MainPageSuffix = v.(string) 143 } else { 144 sb.Website.MainPageSuffix = "" 145 } 146 } 147 } 148 } 149 150 res, err := config.clientStorage.Buckets.Patch(d.Get("name").(string), sb).Do() 151 152 if err != nil { 153 return err 154 } 155 156 log.Printf("[DEBUG] Patched bucket %v at location %v\n\n", res.Name, res.SelfLink) 157 158 // Assign the bucket ID as the resource ID 159 d.Set("self_link", res.SelfLink) 160 d.SetId(res.Id) 161 162 return nil 163 } 164 165 func resourceStorageBucketRead(d *schema.ResourceData, meta interface{}) error { 166 config := meta.(*Config) 167 168 // Get the bucket and acl 169 bucket := d.Get("name").(string) 170 res, err := config.clientStorage.Buckets.Get(bucket).Do() 171 172 if err != nil { 173 fmt.Printf("Error reading bucket %s: %v", bucket, err) 174 return err 175 } 176 177 log.Printf("[DEBUG] Read bucket %v at location %v\n\n", res.Name, res.SelfLink) 178 179 // Update the bucket ID according to the resource ID 180 d.Set("self_link", res.SelfLink) 181 d.SetId(res.Id) 182 183 return nil 184 } 185 186 func resourceStorageBucketDelete(d *schema.ResourceData, meta interface{}) error { 187 config := meta.(*Config) 188 189 // Get the bucket 190 bucket := d.Get("name").(string) 191 192 for { 193 res, err := config.clientStorage.Objects.List(bucket).Do() 194 if err != nil { 195 fmt.Printf("Error Objects.List failed: %v", err) 196 return err 197 } 198 199 if len(res.Items) != 0 { 200 if d.Get("force_destroy").(bool) { 201 // purge the bucket... 202 log.Printf("[DEBUG] GCS Bucket attempting to forceDestroy\n\n") 203 204 for _, object := range res.Items { 205 log.Printf("[DEBUG] Found %s", object.Name) 206 if err := config.clientStorage.Objects.Delete(bucket, object.Name).Do(); err != nil { 207 log.Fatalf("Error trying to delete object: %s %s\n\n", object.Name, err) 208 } else { 209 log.Printf("Object deleted: %s \n\n", object.Name) 210 } 211 } 212 213 } else { 214 delete_err := errors.New("Error trying to delete a bucket containing objects without `force_destroy` set to true") 215 log.Printf("Error! %s : %s\n\n", bucket, delete_err) 216 return delete_err 217 } 218 } else { 219 break // 0 items, bucket empty 220 } 221 } 222 223 // remove empty bucket 224 err := config.clientStorage.Buckets.Delete(bucket).Do() 225 if err != nil { 226 fmt.Printf("Error deleting bucket %s: %v\n\n", bucket, err) 227 return err 228 } 229 log.Printf("[DEBUG] Deleted bucket %v\n\n", bucket) 230 231 return nil 232 }