github.com/atsaki/terraform@v0.4.3-0.20150919165407-25bba5967654/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 Update: resourceAwsDbSubnetGroupUpdate, 22 Delete: resourceAwsDbSubnetGroupDelete, 23 24 Schema: map[string]*schema.Schema{ 25 "name": &schema.Schema{ 26 Type: schema.TypeString, 27 ForceNew: true, 28 Required: true, 29 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 30 value := v.(string) 31 if !regexp.MustCompile(`^[.0-9A-Za-z-_]+$`).MatchString(value) { 32 errors = append(errors, fmt.Errorf( 33 "only alphanumeric characters, hyphens, underscores, and periods allowed in %q", k)) 34 } 35 if len(value) > 255 { 36 errors = append(errors, fmt.Errorf( 37 "%q cannot be longer than 255 characters", k)) 38 } 39 if regexp.MustCompile(`(?i)^default$`).MatchString(value) { 40 errors = append(errors, fmt.Errorf( 41 "%q is not allowed as %q", "Default", k)) 42 } 43 return 44 }, 45 }, 46 47 "description": &schema.Schema{ 48 Type: schema.TypeString, 49 Required: true, 50 ForceNew: true, 51 }, 52 53 "subnet_ids": &schema.Schema{ 54 Type: schema.TypeSet, 55 Required: 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 resourceAwsDbSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error { 137 conn := meta.(*AWSClient).rdsconn 138 if d.HasChange("subnet_ids") { 139 _, n := d.GetChange("subnet_ids") 140 if n == nil { 141 n = new(schema.Set) 142 } 143 ns := n.(*schema.Set) 144 145 var sIds []*string 146 for _, s := range ns.List() { 147 sIds = append(sIds, aws.String(s.(string))) 148 } 149 150 _, err := conn.ModifyDBSubnetGroup(&rds.ModifyDBSubnetGroupInput{ 151 DBSubnetGroupName: aws.String(d.Id()), 152 SubnetIds: sIds, 153 }) 154 155 if err != nil { 156 return err 157 } 158 } 159 return resourceAwsDbSubnetGroupRead(d, meta) 160 } 161 162 func resourceAwsDbSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error { 163 stateConf := &resource.StateChangeConf{ 164 Pending: []string{"pending"}, 165 Target: "destroyed", 166 Refresh: resourceAwsDbSubnetGroupDeleteRefreshFunc(d, meta), 167 Timeout: 3 * time.Minute, 168 MinTimeout: 1 * time.Second, 169 } 170 _, err := stateConf.WaitForState() 171 return err 172 } 173 174 func resourceAwsDbSubnetGroupDeleteRefreshFunc( 175 d *schema.ResourceData, 176 meta interface{}) resource.StateRefreshFunc { 177 rdsconn := meta.(*AWSClient).rdsconn 178 179 return func() (interface{}, string, error) { 180 181 deleteOpts := rds.DeleteDBSubnetGroupInput{ 182 DBSubnetGroupName: aws.String(d.Id()), 183 } 184 185 if _, err := rdsconn.DeleteDBSubnetGroup(&deleteOpts); err != nil { 186 rdserr, ok := err.(awserr.Error) 187 if !ok { 188 return d, "error", err 189 } 190 191 if rdserr.Code() != "DBSubnetGroupNotFoundFault" { 192 return d, "error", err 193 } 194 } 195 196 return d, "destroyed", nil 197 } 198 }