github.com/ezbercih/terraform@v0.1.1-0.20140729011846-3c33865e0839/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.ResourceState, 19 d *terraform.ResourceDiff, 20 meta interface{}) (*terraform.ResourceState, 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.ResourceState, 89 d *terraform.ResourceDiff, 90 meta interface{}) (*terraform.ResourceState, error) { 91 92 panic("Cannot update DB") 93 94 return nil, nil 95 } 96 97 func resource_aws_db_security_group_destroy( 98 s *terraform.ResourceState, 99 meta interface{}) error { 100 p := meta.(*ResourceProvider) 101 conn := p.rdsconn 102 103 log.Printf("[DEBUG] DB Security Group destroy: %v", s.ID) 104 105 opts := rds.DeleteDBSecurityGroup{DBSecurityGroupName: s.ID} 106 107 log.Printf("[DEBUG] DB Security Group destroy configuration: %v", opts) 108 _, err := conn.DeleteDBSecurityGroup(&opts) 109 110 if err != nil { 111 newerr, ok := err.(*rds.Error) 112 if ok && newerr.Code == "InvalidDBSecurityGroup.NotFound" { 113 return nil 114 } 115 return err 116 } 117 118 return nil 119 } 120 121 func resource_aws_db_security_group_refresh( 122 s *terraform.ResourceState, 123 meta interface{}) (*terraform.ResourceState, error) { 124 p := meta.(*ResourceProvider) 125 conn := p.rdsconn 126 127 v, err := resource_aws_db_security_group_retrieve(s.ID, conn) 128 129 if err != nil { 130 return s, err 131 } 132 133 return resource_aws_db_security_group_update_state(s, v) 134 } 135 136 func resource_aws_db_security_group_diff( 137 s *terraform.ResourceState, 138 c *terraform.ResourceConfig, 139 meta interface{}) (*terraform.ResourceDiff, error) { 140 141 b := &diff.ResourceBuilder{ 142 Attrs: map[string]diff.AttrType{ 143 "name": diff.AttrTypeCreate, 144 "description": diff.AttrTypeCreate, 145 "ingress": diff.AttrTypeCreate, 146 }, 147 148 ComputedAttrs: []string{ 149 "ingress_cidr", 150 "ingress_security_groups", 151 }, 152 } 153 154 return b.Diff(s, c) 155 } 156 157 func resource_aws_db_security_group_update_state( 158 s *terraform.ResourceState, 159 v *rds.DBSecurityGroup) (*terraform.ResourceState, error) { 160 161 s.Attributes["name"] = v.Name 162 s.Attributes["description"] = v.Description 163 164 // Flatten our group values 165 toFlatten := make(map[string]interface{}) 166 167 if len(v.EC2SecurityGroupOwnerIds) > 0 && v.EC2SecurityGroupOwnerIds[0] != "" { 168 toFlatten["ingress_security_groups"] = v.EC2SecurityGroupOwnerIds 169 } 170 171 if len(v.CidrIps) > 0 && v.CidrIps[0] != "" { 172 toFlatten["ingress_cidr"] = v.CidrIps 173 } 174 175 for k, v := range flatmap.Flatten(toFlatten) { 176 s.Attributes[k] = v 177 } 178 179 return s, nil 180 } 181 182 func resource_aws_db_security_group_retrieve(id string, conn *rds.Rds) (*rds.DBSecurityGroup, error) { 183 opts := rds.DescribeDBSecurityGroups{ 184 DBSecurityGroupName: id, 185 } 186 187 log.Printf("[DEBUG] DB Security Group describe configuration: %#v", opts) 188 189 resp, err := conn.DescribeDBSecurityGroups(&opts) 190 191 if err != nil { 192 return nil, fmt.Errorf("Error retrieving DB Security Groups: %s", err) 193 } 194 195 if len(resp.DBSecurityGroups) != 1 || 196 resp.DBSecurityGroups[0].Name != id { 197 if err != nil { 198 return nil, fmt.Errorf("Unable to find DB Security Group: %#v", resp.DBSecurityGroups) 199 } 200 } 201 202 v := resp.DBSecurityGroups[0] 203 204 return &v, nil 205 } 206 207 // Authorizes the ingress rule on the db security group 208 func authorize_ingress_rule(ingress interface{}, dbSecurityGroupName string, conn *rds.Rds) error { 209 ing := ingress.(map[string]interface{}) 210 211 opts := rds.AuthorizeDBSecurityGroupIngress{ 212 DBSecurityGroupName: dbSecurityGroupName, 213 } 214 215 if attr, ok := ing["cidr"].(string); ok && attr != "" { 216 opts.Cidr = attr 217 } 218 219 if attr, ok := ing["security_group_name"].(string); ok && attr != "" { 220 opts.EC2SecurityGroupName = attr 221 } 222 223 if attr, ok := ing["security_group_id"].(string); ok && attr != "" { 224 opts.EC2SecurityGroupId = attr 225 } 226 227 if attr, ok := ing["security_group_owner_id"].(string); ok && attr != "" { 228 opts.EC2SecurityGroupOwnerId = attr 229 } 230 231 log.Printf("[DEBUG] Authorize ingress rule configuration: %#v", opts) 232 233 _, err := conn.AuthorizeDBSecurityGroupIngress(&opts) 234 235 if err != nil { 236 return fmt.Errorf("Error authorizing security group ingress: %s", err) 237 } 238 239 return nil 240 } 241 242 func resource_aws_db_security_group_validation() *config.Validator { 243 return &config.Validator{ 244 Required: []string{ 245 "name", 246 "description", 247 }, 248 Optional: []string{ 249 "ingress.*", 250 "ingress.*.cidr", 251 "ingress.*.security_group_name", 252 "ingress.*.security_group_id", 253 "ingress.*.security_group_owner_id", 254 }, 255 } 256 } 257 258 func DBSecurityGroupStateRefreshFunc(id string, conn *rds.Rds) resource.StateRefreshFunc { 259 return func() (interface{}, string, error) { 260 v, err := resource_aws_db_security_group_retrieve(id, conn) 261 262 if err != nil { 263 log.Printf("Error on retrieving DB Security Group when waiting: %s", err) 264 return nil, "", err 265 } 266 267 statuses := append(v.EC2SecurityGroupStatuses, v.CidrStatuses...) 268 269 for _, stat := range statuses { 270 // Not done 271 if stat != "authorized" { 272 return nil, "authorizing", nil 273 } 274 } 275 276 return v, "authorized", nil 277 } 278 }