github.com/ljosa/terraform@v0.7.0-rc2.0.20160617205345-fe540b408f59/builtin/providers/aws/resource_aws_elasticache_subnet_group.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 "time" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/service/elasticache" 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 func resourceAwsElasticacheSubnetGroup() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceAwsElasticacheSubnetGroupCreate, 19 Read: resourceAwsElasticacheSubnetGroupRead, 20 Update: resourceAwsElasticacheSubnetGroupUpdate, 21 Delete: resourceAwsElasticacheSubnetGroupDelete, 22 23 Schema: map[string]*schema.Schema{ 24 "description": &schema.Schema{ 25 Type: schema.TypeString, 26 Optional: true, 27 Default: "Managed by Terraform", 28 }, 29 "name": &schema.Schema{ 30 Type: schema.TypeString, 31 Required: true, 32 ForceNew: true, 33 StateFunc: func(val interface{}) string { 34 // Elasticache normalizes subnet names to lowercase, 35 // so we have to do this too or else we can end up 36 // with non-converging diffs. 37 return strings.ToLower(val.(string)) 38 }, 39 }, 40 "subnet_ids": &schema.Schema{ 41 Type: schema.TypeSet, 42 Required: true, 43 Elem: &schema.Schema{Type: schema.TypeString}, 44 Set: schema.HashString, 45 }, 46 }, 47 } 48 } 49 50 func resourceAwsElasticacheSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error { 51 conn := meta.(*AWSClient).elasticacheconn 52 53 // Get the group properties 54 name := d.Get("name").(string) 55 desc := d.Get("description").(string) 56 subnetIdsSet := d.Get("subnet_ids").(*schema.Set) 57 58 log.Printf("[DEBUG] Cache subnet group create: name: %s, description: %s", name, desc) 59 60 subnetIds := expandStringList(subnetIdsSet.List()) 61 62 req := &elasticache.CreateCacheSubnetGroupInput{ 63 CacheSubnetGroupDescription: aws.String(desc), 64 CacheSubnetGroupName: aws.String(name), 65 SubnetIds: subnetIds, 66 } 67 68 _, err := conn.CreateCacheSubnetGroup(req) 69 if err != nil { 70 return fmt.Errorf("Error creating CacheSubnetGroup: %s", err) 71 } 72 73 // Assign the group name as the resource ID 74 // Elasticache always retains the name in lower case, so we have to 75 // mimic that or else we won't be able to refresh a resource whose 76 // name contained uppercase characters. 77 d.SetId(strings.ToLower(name)) 78 79 return nil 80 } 81 82 func resourceAwsElasticacheSubnetGroupRead(d *schema.ResourceData, meta interface{}) error { 83 conn := meta.(*AWSClient).elasticacheconn 84 req := &elasticache.DescribeCacheSubnetGroupsInput{ 85 CacheSubnetGroupName: aws.String(d.Get("name").(string)), 86 } 87 88 res, err := conn.DescribeCacheSubnetGroups(req) 89 if err != nil { 90 if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "CacheSubnetGroupNotFoundFault" { 91 // Update state to indicate the db subnet no longer exists. 92 log.Printf("[WARN] Elasticache Subnet Group (%s) not found, removing from state", d.Id()) 93 d.SetId("") 94 return nil 95 } 96 return err 97 } 98 if len(res.CacheSubnetGroups) == 0 { 99 return fmt.Errorf("Error missing %v", d.Get("name")) 100 } 101 102 var group *elasticache.CacheSubnetGroup 103 for _, g := range res.CacheSubnetGroups { 104 log.Printf("[DEBUG] %v %v", g.CacheSubnetGroupName, d.Id()) 105 if *g.CacheSubnetGroupName == d.Id() { 106 group = g 107 } 108 } 109 if group == nil { 110 return fmt.Errorf("Error retrieving cache subnet group: %v", res) 111 } 112 113 ids := make([]string, len(group.Subnets)) 114 for i, s := range group.Subnets { 115 ids[i] = *s.SubnetIdentifier 116 } 117 118 d.Set("name", group.CacheSubnetGroupName) 119 d.Set("description", group.CacheSubnetGroupDescription) 120 d.Set("subnet_ids", ids) 121 122 return nil 123 } 124 125 func resourceAwsElasticacheSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error { 126 conn := meta.(*AWSClient).elasticacheconn 127 if d.HasChange("subnet_ids") || d.HasChange("description") { 128 var subnets []*string 129 if v := d.Get("subnet_ids"); v != nil { 130 for _, v := range v.(*schema.Set).List() { 131 subnets = append(subnets, aws.String(v.(string))) 132 } 133 } 134 log.Printf("[DEBUG] Updating ElastiCache Subnet Group") 135 136 _, err := conn.ModifyCacheSubnetGroup(&elasticache.ModifyCacheSubnetGroupInput{ 137 CacheSubnetGroupName: aws.String(d.Get("name").(string)), 138 CacheSubnetGroupDescription: aws.String(d.Get("description").(string)), 139 SubnetIds: subnets, 140 }) 141 if err != nil { 142 return err 143 } 144 } 145 146 return resourceAwsElasticacheSubnetGroupRead(d, meta) 147 } 148 func resourceAwsElasticacheSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error { 149 conn := meta.(*AWSClient).elasticacheconn 150 151 log.Printf("[DEBUG] Cache subnet group delete: %s", d.Id()) 152 153 return resource.Retry(5*time.Minute, func() *resource.RetryError { 154 _, err := conn.DeleteCacheSubnetGroup(&elasticache.DeleteCacheSubnetGroupInput{ 155 CacheSubnetGroupName: aws.String(d.Id()), 156 }) 157 if err != nil { 158 apierr, ok := err.(awserr.Error) 159 if !ok { 160 return resource.RetryableError(err) 161 } 162 log.Printf("[DEBUG] APIError.Code: %v", apierr.Code()) 163 switch apierr.Code() { 164 case "DependencyViolation": 165 // If it is a dependency violation, we want to retry 166 return resource.RetryableError(err) 167 default: 168 return resource.NonRetryableError(err) 169 } 170 } 171 return nil 172 }) 173 }