github.com/acm1/terraform@v0.6.2-0.20150729164239-1f314444f45c/builtin/providers/aws/resource_aws_db_subnet_group.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "regexp" 7 "strings" 8 "time" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/awserr" 12 "github.com/aws/aws-sdk-go/service/rds" 13 "github.com/hashicorp/terraform/helper/resource" 14 "github.com/hashicorp/terraform/helper/schema" 15 ) 16 17 func resourceAwsDbSubnetGroup() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceAwsDbSubnetGroupCreate, 20 Read: resourceAwsDbSubnetGroupRead, 21 Delete: resourceAwsDbSubnetGroupDelete, 22 23 Schema: map[string]*schema.Schema{ 24 "name": &schema.Schema{ 25 Type: schema.TypeString, 26 ForceNew: true, 27 Required: true, 28 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 29 value := v.(string) 30 if !regexp.MustCompile(`^[.0-9A-Za-z-_]+$`).MatchString(value) { 31 errors = append(errors, fmt.Errorf( 32 "only alphanumeric characters, hyphens, underscores, and periods allowed in %q", k)) 33 } 34 if len(value) > 255 { 35 errors = append(errors, fmt.Errorf( 36 "%q cannot be longer than 255 characters", k)) 37 } 38 if regexp.MustCompile(`(?i)^default$`).MatchString(value) { 39 errors = append(errors, fmt.Errorf( 40 "%q is not allowed as %q", "Default", k)) 41 } 42 return 43 }, 44 }, 45 46 "description": &schema.Schema{ 47 Type: schema.TypeString, 48 Required: true, 49 ForceNew: true, 50 }, 51 52 "subnet_ids": &schema.Schema{ 53 Type: schema.TypeSet, 54 Required: true, 55 ForceNew: true, 56 Elem: &schema.Schema{Type: schema.TypeString}, 57 Set: schema.HashString, 58 }, 59 }, 60 } 61 } 62 63 func resourceAwsDbSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error { 64 rdsconn := meta.(*AWSClient).rdsconn 65 66 subnetIdsSet := d.Get("subnet_ids").(*schema.Set) 67 subnetIds := make([]*string, subnetIdsSet.Len()) 68 for i, subnetId := range subnetIdsSet.List() { 69 subnetIds[i] = aws.String(subnetId.(string)) 70 } 71 72 createOpts := rds.CreateDBSubnetGroupInput{ 73 DBSubnetGroupName: aws.String(d.Get("name").(string)), 74 DBSubnetGroupDescription: aws.String(d.Get("description").(string)), 75 SubnetIDs: subnetIds, 76 } 77 78 log.Printf("[DEBUG] Create DB Subnet Group: %#v", createOpts) 79 _, err := rdsconn.CreateDBSubnetGroup(&createOpts) 80 if err != nil { 81 return fmt.Errorf("Error creating DB Subnet Group: %s", err) 82 } 83 84 d.SetId(*createOpts.DBSubnetGroupName) 85 log.Printf("[INFO] DB Subnet Group ID: %s", d.Id()) 86 return resourceAwsDbSubnetGroupRead(d, meta) 87 } 88 89 func resourceAwsDbSubnetGroupRead(d *schema.ResourceData, meta interface{}) error { 90 rdsconn := meta.(*AWSClient).rdsconn 91 92 describeOpts := rds.DescribeDBSubnetGroupsInput{ 93 DBSubnetGroupName: aws.String(d.Id()), 94 } 95 96 describeResp, err := rdsconn.DescribeDBSubnetGroups(&describeOpts) 97 if err != nil { 98 if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "DBSubnetGroupNotFoundFault" { 99 // Update state to indicate the db subnet no longer exists. 100 d.SetId("") 101 return nil 102 } 103 return err 104 } 105 106 if len(describeResp.DBSubnetGroups) == 0 { 107 return fmt.Errorf("Unable to find DB Subnet Group: %#v", describeResp.DBSubnetGroups) 108 } 109 110 var subnetGroup *rds.DBSubnetGroup 111 for _, s := range describeResp.DBSubnetGroups { 112 // AWS is down casing the name provided, so we compare lower case versions 113 // of the names. We lower case both our name and their name in the check, 114 // incase they change that someday. 115 if strings.ToLower(d.Id()) == strings.ToLower(*s.DBSubnetGroupName) { 116 subnetGroup = describeResp.DBSubnetGroups[0] 117 } 118 } 119 120 if subnetGroup.DBSubnetGroupName == nil { 121 return fmt.Errorf("Unable to find DB Subnet Group: %#v", describeResp.DBSubnetGroups) 122 } 123 124 d.Set("name", d.Id()) 125 d.Set("description", *subnetGroup.DBSubnetGroupDescription) 126 127 subnets := make([]string, 0, len(subnetGroup.Subnets)) 128 for _, s := range subnetGroup.Subnets { 129 subnets = append(subnets, *s.SubnetIdentifier) 130 } 131 d.Set("subnet_ids", subnets) 132 133 return nil 134 } 135 136 func resourceAwsDbSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error { 137 stateConf := &resource.StateChangeConf{ 138 Pending: []string{"pending"}, 139 Target: "destroyed", 140 Refresh: resourceAwsDbSubnetGroupDeleteRefreshFunc(d, meta), 141 Timeout: 3 * time.Minute, 142 MinTimeout: 1 * time.Second, 143 } 144 _, err := stateConf.WaitForState() 145 return err 146 } 147 148 func resourceAwsDbSubnetGroupDeleteRefreshFunc( 149 d *schema.ResourceData, 150 meta interface{}) resource.StateRefreshFunc { 151 rdsconn := meta.(*AWSClient).rdsconn 152 153 return func() (interface{}, string, error) { 154 155 deleteOpts := rds.DeleteDBSubnetGroupInput{ 156 DBSubnetGroupName: aws.String(d.Id()), 157 } 158 159 if _, err := rdsconn.DeleteDBSubnetGroup(&deleteOpts); err != nil { 160 rdserr, ok := err.(awserr.Error) 161 if !ok { 162 return d, "error", err 163 } 164 165 if rdserr.Code() != "DBSubnetGroupNotFoundFault" { 166 return d, "error", err 167 } 168 } 169 170 return d, "destroyed", nil 171 } 172 }