Skip to content

Commit

Permalink
Merge pull request hashicorp#6 from pdecat/f-google-storage-bucket-li…
Browse files Browse the repository at this point in the history
…fecycle

Add provider/google/google_storage_bucket lifecycle interface
  • Loading branch information
paddycarver authored Jul 25, 2017
2 parents 83b2974 + 1bb145b commit 66f8d8f
Show file tree
Hide file tree
Showing 3 changed files with 431 additions and 0 deletions.
200 changes: 200 additions & 0 deletions google/resource_storage_bucket.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package google

import (
"bytes"
"errors"
"fmt"
"log"
"strings"
"time"

"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"

Expand Down Expand Up @@ -77,6 +79,68 @@ func resourceStorageBucket() *schema.Resource {
ForceNew: true,
},

"lifecycle_rule": {
Type: schema.TypeList,
Optional: true,
MaxItems: 100,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"action": {
Type: schema.TypeSet,
Required: true,
MinItems: 1,
MaxItems: 1,
Set: resourceGCSBucketLifecycleRuleActionHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
},
"storage_class": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"condition": {
Type: schema.TypeSet,
Required: true,
MinItems: 1,
MaxItems: 1,
Set: resourceGCSBucketLifecycleRuleConditionHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"age": {
Type: schema.TypeInt,
Optional: true,
},
"created_before": {
Type: schema.TypeString,
Optional: true,
},
"is_live": {
Type: schema.TypeBool,
Optional: true,
},
"matches_storage_class": {
Type: schema.TypeList,
Optional: true,
MinItems: 1,
Elem: &schema.Schema{Type: schema.TypeString},
},
"num_newer_versions": {
Type: schema.TypeInt,
Optional: true,
},
},
},
},
},
},
},

"website": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -150,6 +214,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error
sb.StorageClass = v.(string)
}

if err := resourceGCSBucketLifecycleCreateOrUpdate(d, sb); err != nil {
return err
}

if v, ok := d.GetOk("website"); ok {
websites := v.([]interface{})

Expand Down Expand Up @@ -208,6 +276,12 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error

sb := &storage.Bucket{}

if d.HasChange("lifecycle_rule") {
if err := resourceGCSBucketLifecycleCreateOrUpdate(d, sb); err != nil {
return err
}
}

if d.HasChange("website") {
if v, ok := d.GetOk("website"); ok {
websites := v.([]interface{})
Expand Down Expand Up @@ -382,3 +456,129 @@ func flattenCors(corsRules []*storage.BucketCors) []map[string]interface{} {
}
return corsRulesSchema
}

func resourceGCSBucketLifecycleCreateOrUpdate(d *schema.ResourceData, sb *storage.Bucket) error {
if v, ok := d.GetOk("lifecycle_rule"); ok {
lifecycle_rules := v.([]interface{})

sb.Lifecycle = &storage.BucketLifecycle{}
sb.Lifecycle.Rule = make([]*storage.BucketLifecycleRule, 0, len(lifecycle_rules))

for _, raw_lifecycle_rule := range lifecycle_rules {
lifecycle_rule := raw_lifecycle_rule.(map[string]interface{})

target_lifecycle_rule := &storage.BucketLifecycleRule{}

if v, ok := lifecycle_rule["action"]; ok {
if actions := v.(*schema.Set).List(); len(actions) == 1 {
action := actions[0].(map[string]interface{})

target_lifecycle_rule.Action = &storage.BucketLifecycleRuleAction{}

if v, ok := action["type"]; ok {
target_lifecycle_rule.Action.Type = v.(string)
}

if v, ok := action["storage_class"]; ok {
target_lifecycle_rule.Action.StorageClass = v.(string)
}
} else {
return fmt.Errorf("Exactly one action is required")
}
}

if v, ok := lifecycle_rule["condition"]; ok {
if conditions := v.(*schema.Set).List(); len(conditions) == 1 {
condition := conditions[0].(map[string]interface{})

target_lifecycle_rule.Condition = &storage.BucketLifecycleRuleCondition{}

if v, ok := condition["age"]; ok {
target_lifecycle_rule.Condition.Age = int64(v.(int))
}

if v, ok := condition["created_before"]; ok {
target_lifecycle_rule.Condition.CreatedBefore = v.(string)
}

if v, ok := condition["is_live"]; ok {
target_lifecycle_rule.Condition.IsLive = v.(bool)
}

if v, ok := condition["matches_storage_class"]; ok {
matches_storage_classes := v.([]interface{})

target_matches_storage_classes := make([]string, 0, len(matches_storage_classes))

for _, v := range matches_storage_classes {
target_matches_storage_classes = append(target_matches_storage_classes, v.(string))
}

target_lifecycle_rule.Condition.MatchesStorageClass = target_matches_storage_classes
}

if v, ok := condition["num_newer_versions"]; ok {
target_lifecycle_rule.Condition.NumNewerVersions = int64(v.(int))
}
} else {
return fmt.Errorf("Exactly one condition is required")
}
}

sb.Lifecycle.Rule = append(sb.Lifecycle.Rule, target_lifecycle_rule)
}
}

return nil
}

func resourceGCSBucketLifecycleRuleActionHash(v interface{}) int {
if v == nil {
return 0
}

var buf bytes.Buffer
m := v.(map[string]interface{})

buf.WriteString(fmt.Sprintf("%s-", m["type"].(string)))

if v, ok := m["storage_class"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}

return hashcode.String(buf.String())
}

func resourceGCSBucketLifecycleRuleConditionHash(v interface{}) int {
if v == nil {
return 0
}

var buf bytes.Buffer
m := v.(map[string]interface{})

if v, ok := m["age"]; ok {
buf.WriteString(fmt.Sprintf("%d-", v.(int)))
}

if v, ok := m["created_before"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}

if v, ok := m["is_live"]; ok {
buf.WriteString(fmt.Sprintf("%t-", v.(bool)))
}

if v, ok := m["matches_storage_class"]; ok {
matches_storage_classes := v.([]interface{})
for _, matches_storage_class := range matches_storage_classes {
buf.WriteString(fmt.Sprintf("%s-", matches_storage_class))
}
}

if v, ok := m["num_newer_versions"]; ok {
buf.WriteString(fmt.Sprintf("%d-", v.(int)))
}

return hashcode.String(buf.String())
}
Loading

0 comments on commit 66f8d8f

Please sign in to comment.