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  }