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