github.com/bengesoff/terraform@v0.3.1-0.20141018223233-b25a53629922/builtin/providers/aws/resource_aws_db_security_group.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/hashicorp/terraform/flatmap" 9 "github.com/hashicorp/terraform/helper/config" 10 "github.com/hashicorp/terraform/helper/diff" 11 "github.com/hashicorp/terraform/helper/multierror" 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/terraform" 14 "github.com/mitchellh/goamz/rds" 15 ) 16 17 func resource_aws_db_security_group_create( 18 s *terraform.InstanceState, 19 d *terraform.InstanceDiff, 20 meta interface{}) (*terraform.InstanceState, error) { 21 p := meta.(*ResourceProvider) 22 conn := p.rdsconn 23 24 // Merge the diff into the state so that we have all the attributes 25 // properly. 26 rs := s.MergeDiff(d) 27 28 var err error 29 var errs []error 30 31 opts := rds.CreateDBSecurityGroup{ 32 DBSecurityGroupName: rs.Attributes["name"], 33 DBSecurityGroupDescription: rs.Attributes["description"], 34 } 35 36 log.Printf("[DEBUG] DB Security Group create configuration: %#v", opts) 37 _, err = conn.CreateDBSecurityGroup(&opts) 38 if err != nil { 39 return nil, fmt.Errorf("Error creating DB Security Group: %s", err) 40 } 41 42 rs.ID = rs.Attributes["name"] 43 44 log.Printf("[INFO] DB Security Group ID: %s", rs.ID) 45 46 v, err := resource_aws_db_security_group_retrieve(rs.ID, conn) 47 if err != nil { 48 return rs, err 49 } 50 51 if _, ok := rs.Attributes["ingress.#"]; ok { 52 ingresses := flatmap.Expand( 53 rs.Attributes, "ingress").([]interface{}) 54 55 for _, ing := range ingresses { 56 err = authorize_ingress_rule(ing, v.Name, conn) 57 58 if err != nil { 59 errs = append(errs, err) 60 } 61 } 62 63 if len(errs) > 0 { 64 return rs, &multierror.Error{Errors: errs} 65 } 66 } 67 68 log.Println( 69 "[INFO] Waiting for Ingress Authorizations to be authorized") 70 71 stateConf := &resource.StateChangeConf{ 72 Pending: []string{"authorizing"}, 73 Target: "authorized", 74 Refresh: DBSecurityGroupStateRefreshFunc(rs.ID, conn), 75 Timeout: 10 * time.Minute, 76 } 77 78 // Wait, catching any errors 79 _, err = stateConf.WaitForState() 80 if err != nil { 81 return rs, err 82 } 83 84 return resource_aws_db_security_group_update_state(rs, v) 85 } 86 87 func resource_aws_db_security_group_update( 88 s *terraform.InstanceState, 89 d *terraform.InstanceDiff, 90 meta interface{}) (*terraform.InstanceState, error) { 91 panic("Cannot update DB security group") 92 } 93 94 func resource_aws_db_security_group_destroy( 95 s *terraform.InstanceState, 96 meta interface{}) error { 97 p := meta.(*ResourceProvider) 98 conn := p.rdsconn 99 100 log.Printf("[DEBUG] DB Security Group destroy: %v", s.ID) 101 102 opts := rds.DeleteDBSecurityGroup{DBSecurityGroupName: s.ID} 103 104 log.Printf("[DEBUG] DB Security Group destroy configuration: %v", opts) 105 _, err := conn.DeleteDBSecurityGroup(&opts) 106 107 if err != nil { 108 newerr, ok := err.(*rds.Error) 109 if ok && newerr.Code == "InvalidDBSecurityGroup.NotFound" { 110 return nil 111 } 112 return err 113 } 114 115 return nil 116 } 117 118 func resource_aws_db_security_group_refresh( 119 s *terraform.InstanceState, 120 meta interface{}) (*terraform.InstanceState, error) { 121 p := meta.(*ResourceProvider) 122 conn := p.rdsconn 123 124 v, err := resource_aws_db_security_group_retrieve(s.ID, conn) 125 126 if err != nil { 127 return s, err 128 } 129 130 return resource_aws_db_security_group_update_state(s, v) 131 } 132 133 func resource_aws_db_security_group_diff( 134 s *terraform.InstanceState, 135 c *terraform.ResourceConfig, 136 meta interface{}) (*terraform.InstanceDiff, error) { 137 138 b := &diff.ResourceBuilder{ 139 Attrs: map[string]diff.AttrType{ 140 "name": diff.AttrTypeCreate, 141 "description": diff.AttrTypeCreate, 142 "ingress": diff.AttrTypeCreate, 143 }, 144 145 ComputedAttrs: []string{ 146 "ingress_cidr", 147 "ingress_security_groups", 148 }, 149 } 150 151 return b.Diff(s, c) 152 } 153 154 func resource_aws_db_security_group_update_state( 155 s *terraform.InstanceState, 156 v *rds.DBSecurityGroup) (*terraform.InstanceState, error) { 157 158 s.Attributes["name"] = v.Name 159 s.Attributes["description"] = v.Description 160 161 // Flatten our group values 162 toFlatten := make(map[string]interface{}) 163 164 if len(v.EC2SecurityGroupOwnerIds) > 0 && v.EC2SecurityGroupOwnerIds[0] != "" { 165 toFlatten["ingress_security_groups"] = v.EC2SecurityGroupOwnerIds 166 } 167 168 if len(v.CidrIps) > 0 && v.CidrIps[0] != "" { 169 toFlatten["ingress_cidr"] = v.CidrIps 170 } 171 172 for k, v := range flatmap.Flatten(toFlatten) { 173 s.Attributes[k] = v 174 } 175 176 return s, nil 177 } 178 179 func resource_aws_db_security_group_retrieve(id string, conn *rds.Rds) (*rds.DBSecurityGroup, error) { 180 opts := rds.DescribeDBSecurityGroups{ 181 DBSecurityGroupName: id, 182 } 183 184 log.Printf("[DEBUG] DB Security Group describe configuration: %#v", opts) 185 186 resp, err := conn.DescribeDBSecurityGroups(&opts) 187 188 if err != nil { 189 return nil, fmt.Errorf("Error retrieving DB Security Groups: %s", err) 190 } 191 192 if len(resp.DBSecurityGroups) != 1 || 193 resp.DBSecurityGroups[0].Name != id { 194 if err != nil { 195 return nil, fmt.Errorf("Unable to find DB Security Group: %#v", resp.DBSecurityGroups) 196 } 197 } 198 199 v := resp.DBSecurityGroups[0] 200 201 return &v, nil 202 } 203 204 // Authorizes the ingress rule on the db security group 205 func authorize_ingress_rule(ingress interface{}, dbSecurityGroupName string, conn *rds.Rds) error { 206 ing := ingress.(map[string]interface{}) 207 208 opts := rds.AuthorizeDBSecurityGroupIngress{ 209 DBSecurityGroupName: dbSecurityGroupName, 210 } 211 212 if attr, ok := ing["cidr"].(string); ok && attr != "" { 213 opts.Cidr = attr 214 } 215 216 if attr, ok := ing["security_group_name"].(string); ok && attr != "" { 217 opts.EC2SecurityGroupName = attr 218 } 219 220 if attr, ok := ing["security_group_id"].(string); ok && attr != "" { 221 opts.EC2SecurityGroupId = attr 222 } 223 224 if attr, ok := ing["security_group_owner_id"].(string); ok && attr != "" { 225 opts.EC2SecurityGroupOwnerId = attr 226 } 227 228 log.Printf("[DEBUG] Authorize ingress rule configuration: %#v", opts) 229 230 _, err := conn.AuthorizeDBSecurityGroupIngress(&opts) 231 232 if err != nil { 233 return fmt.Errorf("Error authorizing security group ingress: %s", err) 234 } 235 236 return nil 237 } 238 239 func resource_aws_db_security_group_validation() *config.Validator { 240 return &config.Validator{ 241 Required: []string{ 242 "name", 243 "description", 244 }, 245 Optional: []string{ 246 "ingress.*", 247 "ingress.*.cidr", 248 "ingress.*.security_group_name", 249 "ingress.*.security_group_id", 250 "ingress.*.security_group_owner_id", 251 }, 252 } 253 } 254 255 func DBSecurityGroupStateRefreshFunc(id string, conn *rds.Rds) resource.StateRefreshFunc { 256 return func() (interface{}, string, error) { 257 v, err := resource_aws_db_security_group_retrieve(id, conn) 258 259 if err != nil { 260 log.Printf("Error on retrieving DB Security Group when waiting: %s", err) 261 return nil, "", err 262 } 263 264 statuses := append(v.EC2SecurityGroupStatuses, v.CidrStatuses...) 265 266 for _, stat := range statuses { 267 // Not done 268 if stat != "authorized" { 269 return nil, "authorizing", nil 270 } 271 } 272 273 return v, "authorized", nil 274 } 275 }