github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/resource_aws_redshift_subnet_group.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"regexp"
     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/redshift"
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  )
    15  
    16  func resourceAwsRedshiftSubnetGroup() *schema.Resource {
    17  	return &schema.Resource{
    18  		Create: resourceAwsRedshiftSubnetGroupCreate,
    19  		Read:   resourceAwsRedshiftSubnetGroupRead,
    20  		Update: resourceAwsRedshiftSubnetGroupUpdate,
    21  		Delete: resourceAwsRedshiftSubnetGroupDelete,
    22  		Importer: &schema.ResourceImporter{
    23  			State: schema.ImportStatePassthrough,
    24  		},
    25  
    26  		Schema: map[string]*schema.Schema{
    27  			"name": {
    28  				Type:         schema.TypeString,
    29  				ForceNew:     true,
    30  				Required:     true,
    31  				ValidateFunc: validateRedshiftSubnetGroupName,
    32  			},
    33  
    34  			"description": {
    35  				Type:     schema.TypeString,
    36  				Optional: true,
    37  				Default:  "Managed by Terraform",
    38  			},
    39  
    40  			"subnet_ids": {
    41  				Type:     schema.TypeSet,
    42  				Required: true,
    43  				Elem:     &schema.Schema{Type: schema.TypeString},
    44  				Set:      schema.HashString,
    45  			},
    46  
    47  			"tags": tagsSchema(),
    48  		},
    49  	}
    50  }
    51  
    52  func resourceAwsRedshiftSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error {
    53  	conn := meta.(*AWSClient).redshiftconn
    54  
    55  	subnetIdsSet := d.Get("subnet_ids").(*schema.Set)
    56  	subnetIds := make([]*string, subnetIdsSet.Len())
    57  	for i, subnetId := range subnetIdsSet.List() {
    58  		subnetIds[i] = aws.String(subnetId.(string))
    59  	}
    60  	tags := tagsFromMapRedshift(d.Get("tags").(map[string]interface{}))
    61  
    62  	createOpts := redshift.CreateClusterSubnetGroupInput{
    63  		ClusterSubnetGroupName: aws.String(d.Get("name").(string)),
    64  		Description:            aws.String(d.Get("description").(string)),
    65  		SubnetIds:              subnetIds,
    66  		Tags:                   tags,
    67  	}
    68  
    69  	log.Printf("[DEBUG] Create Redshift Subnet Group: %#v", createOpts)
    70  	_, err := conn.CreateClusterSubnetGroup(&createOpts)
    71  	if err != nil {
    72  		return fmt.Errorf("Error creating Redshift Subnet Group: %s", err)
    73  	}
    74  
    75  	d.SetId(*createOpts.ClusterSubnetGroupName)
    76  	log.Printf("[INFO] Redshift Subnet Group ID: %s", d.Id())
    77  	return resourceAwsRedshiftSubnetGroupRead(d, meta)
    78  }
    79  
    80  func resourceAwsRedshiftSubnetGroupRead(d *schema.ResourceData, meta interface{}) error {
    81  	conn := meta.(*AWSClient).redshiftconn
    82  
    83  	describeOpts := redshift.DescribeClusterSubnetGroupsInput{
    84  		ClusterSubnetGroupName: aws.String(d.Id()),
    85  	}
    86  
    87  	describeResp, err := conn.DescribeClusterSubnetGroups(&describeOpts)
    88  	if err != nil {
    89  		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "ClusterSubnetGroupNotFoundFault" {
    90  			log.Printf("[INFO] Redshift Subnet Group: %s was not found", d.Id())
    91  			d.SetId("")
    92  			return nil
    93  		}
    94  		return err
    95  	}
    96  
    97  	if len(describeResp.ClusterSubnetGroups) == 0 {
    98  		return fmt.Errorf("Unable to find Redshift Subnet Group: %#v", describeResp.ClusterSubnetGroups)
    99  	}
   100  
   101  	d.Set("name", d.Id())
   102  	d.Set("description", describeResp.ClusterSubnetGroups[0].Description)
   103  	d.Set("subnet_ids", subnetIdsToSlice(describeResp.ClusterSubnetGroups[0].Subnets))
   104  	if err := d.Set("tags", tagsToMapRedshift(describeResp.ClusterSubnetGroups[0].Tags)); err != nil {
   105  		return fmt.Errorf("[DEBUG] Error setting Redshift Subnet Group Tags: %#v", err)
   106  	}
   107  
   108  	return nil
   109  }
   110  
   111  func resourceAwsRedshiftSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
   112  	conn := meta.(*AWSClient).redshiftconn
   113  
   114  	arn, tagErr := buildRedshiftSubnetGroupARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region)
   115  	if tagErr != nil {
   116  		return fmt.Errorf("Error building ARN for Redshift Subnet Group, not updating Tags for Subnet Group %s", d.Id())
   117  	} else {
   118  		if tagErr := setTagsRedshift(conn, d, arn); tagErr != nil {
   119  			return tagErr
   120  		}
   121  	}
   122  
   123  	if d.HasChange("subnet_ids") || d.HasChange("description") {
   124  		_, n := d.GetChange("subnet_ids")
   125  		if n == nil {
   126  			n = new(schema.Set)
   127  		}
   128  		ns := n.(*schema.Set)
   129  
   130  		var sIds []*string
   131  		for _, s := range ns.List() {
   132  			sIds = append(sIds, aws.String(s.(string)))
   133  		}
   134  
   135  		_, err := conn.ModifyClusterSubnetGroup(&redshift.ModifyClusterSubnetGroupInput{
   136  			ClusterSubnetGroupName: aws.String(d.Id()),
   137  			Description:            aws.String(d.Get("description").(string)),
   138  			SubnetIds:              sIds,
   139  		})
   140  
   141  		if err != nil {
   142  			return err
   143  		}
   144  	}
   145  
   146  	return nil
   147  }
   148  
   149  func resourceAwsRedshiftSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
   150  	stateConf := &resource.StateChangeConf{
   151  		Pending:    []string{"pending"},
   152  		Target:     []string{"destroyed"},
   153  		Refresh:    resourceAwsRedshiftSubnetGroupDeleteRefreshFunc(d, meta),
   154  		Timeout:    3 * time.Minute,
   155  		MinTimeout: 1 * time.Second,
   156  	}
   157  	_, err := stateConf.WaitForState()
   158  	return err
   159  }
   160  
   161  func resourceAwsRedshiftSubnetGroupDeleteRefreshFunc(d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
   162  	conn := meta.(*AWSClient).redshiftconn
   163  
   164  	return func() (interface{}, string, error) {
   165  
   166  		deleteOpts := redshift.DeleteClusterSubnetGroupInput{
   167  			ClusterSubnetGroupName: aws.String(d.Id()),
   168  		}
   169  
   170  		if _, err := conn.DeleteClusterSubnetGroup(&deleteOpts); err != nil {
   171  			redshiftErr, ok := err.(awserr.Error)
   172  			if !ok {
   173  				return d, "error", err
   174  			}
   175  
   176  			if redshiftErr.Code() != "ClusterSubnetGroupNotFoundFault" {
   177  				return d, "error", err
   178  			}
   179  		}
   180  
   181  		return d, "destroyed", nil
   182  	}
   183  }
   184  
   185  func subnetIdsToSlice(subnetIds []*redshift.Subnet) []string {
   186  	subnetsSlice := make([]string, 0, len(subnetIds))
   187  	for _, s := range subnetIds {
   188  		subnetsSlice = append(subnetsSlice, *s.SubnetIdentifier)
   189  	}
   190  	return subnetsSlice
   191  }
   192  
   193  func validateRedshiftSubnetGroupName(v interface{}, k string) (ws []string, errors []error) {
   194  	value := v.(string)
   195  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
   196  		errors = append(errors, fmt.Errorf(
   197  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
   198  	}
   199  	if len(value) > 255 {
   200  		errors = append(errors, fmt.Errorf(
   201  			"%q cannot be longer than 255 characters", k))
   202  	}
   203  	if regexp.MustCompile(`(?i)^default$`).MatchString(value) {
   204  		errors = append(errors, fmt.Errorf(
   205  			"%q is not allowed as %q", "Default", k))
   206  	}
   207  	return
   208  }
   209  
   210  func buildRedshiftSubnetGroupARN(identifier, partition, accountid, region string) (string, error) {
   211  	if partition == "" {
   212  		return "", fmt.Errorf("Unable to construct Subnet Group ARN because of missing AWS partition")
   213  	}
   214  	if accountid == "" {
   215  		return "", fmt.Errorf("Unable to construct Subnet Group ARN because of missing AWS Account ID")
   216  	}
   217  	arn := fmt.Sprintf("arn:%s:redshift:%s:%s:subnetgroup:%s", partition, region, accountid, identifier)
   218  	return arn, nil
   219  
   220  }