github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 }