github.com/armen/terraform@v0.5.2-0.20150529052519-caa8117a08f1/builtin/providers/aws/structure.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 8 "github.com/awslabs/aws-sdk-go/aws" 9 "github.com/awslabs/aws-sdk-go/service/ec2" 10 "github.com/awslabs/aws-sdk-go/service/elb" 11 "github.com/awslabs/aws-sdk-go/service/rds" 12 "github.com/awslabs/aws-sdk-go/service/route53" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 // Takes the result of flatmap.Expand for an array of listeners and 17 // returns ELB API compatible objects 18 func expandListeners(configured []interface{}) ([]*elb.Listener, error) { 19 listeners := make([]*elb.Listener, 0, len(configured)) 20 21 // Loop over our configured listeners and create 22 // an array of aws-sdk-go compatabile objects 23 for _, lRaw := range configured { 24 data := lRaw.(map[string]interface{}) 25 26 ip := int64(data["instance_port"].(int)) 27 lp := int64(data["lb_port"].(int)) 28 l := &elb.Listener{ 29 InstancePort: &ip, 30 InstanceProtocol: aws.String(data["instance_protocol"].(string)), 31 LoadBalancerPort: &lp, 32 Protocol: aws.String(data["lb_protocol"].(string)), 33 } 34 35 if v, ok := data["ssl_certificate_id"]; ok { 36 l.SSLCertificateID = aws.String(v.(string)) 37 } 38 39 listeners = append(listeners, l) 40 } 41 42 return listeners, nil 43 } 44 45 // Takes the result of flatmap.Expand for an array of ingress/egress security 46 // group rules and returns EC2 API compatible objects. This function will error 47 // if it finds invalid permissions input, namely a protocol of "-1" with either 48 // to_port or from_port set to a non-zero value. 49 func expandIPPerms( 50 group *ec2.SecurityGroup, configured []interface{}) ([]*ec2.IPPermission, error) { 51 vpc := group.VPCID != nil 52 53 perms := make([]*ec2.IPPermission, len(configured)) 54 for i, mRaw := range configured { 55 var perm ec2.IPPermission 56 m := mRaw.(map[string]interface{}) 57 58 perm.FromPort = aws.Long(int64(m["from_port"].(int))) 59 perm.ToPort = aws.Long(int64(m["to_port"].(int))) 60 perm.IPProtocol = aws.String(m["protocol"].(string)) 61 62 // When protocol is "-1", AWS won't store any ports for the 63 // rule, but also won't error if the user specifies ports other 64 // than '0'. Force the user to make a deliberate '0' port 65 // choice when specifying a "-1" protocol, and tell them about 66 // AWS's behavior in the error message. 67 if *perm.IPProtocol == "-1" && (*perm.FromPort != 0 || *perm.ToPort != 0) { 68 return nil, fmt.Errorf( 69 "from_port (%d) and to_port (%d) must both be 0 to use the the 'ALL' \"-1\" protocol!", 70 *perm.FromPort, *perm.ToPort) 71 } 72 73 var groups []string 74 if raw, ok := m["security_groups"]; ok { 75 list := raw.(*schema.Set).List() 76 for _, v := range list { 77 groups = append(groups, v.(string)) 78 } 79 } 80 if v, ok := m["self"]; ok && v.(bool) { 81 if vpc { 82 groups = append(groups, *group.GroupID) 83 } else { 84 groups = append(groups, *group.GroupName) 85 } 86 } 87 88 if len(groups) > 0 { 89 perm.UserIDGroupPairs = make([]*ec2.UserIDGroupPair, len(groups)) 90 for i, name := range groups { 91 ownerId, id := "", name 92 if items := strings.Split(id, "/"); len(items) > 1 { 93 ownerId, id = items[0], items[1] 94 } 95 96 perm.UserIDGroupPairs[i] = &ec2.UserIDGroupPair{ 97 GroupID: aws.String(id), 98 UserID: aws.String(ownerId), 99 } 100 if !vpc { 101 perm.UserIDGroupPairs[i].GroupID = nil 102 perm.UserIDGroupPairs[i].GroupName = aws.String(id) 103 perm.UserIDGroupPairs[i].UserID = nil 104 } 105 } 106 } 107 108 if raw, ok := m["cidr_blocks"]; ok { 109 list := raw.([]interface{}) 110 for _, v := range list { 111 perm.IPRanges = append(perm.IPRanges, &ec2.IPRange{CIDRIP: aws.String(v.(string))}) 112 } 113 } 114 115 perms[i] = &perm 116 } 117 118 return perms, nil 119 } 120 121 // Takes the result of flatmap.Expand for an array of parameters and 122 // returns Parameter API compatible objects 123 func expandParameters(configured []interface{}) ([]*rds.Parameter, error) { 124 parameters := make([]*rds.Parameter, 0, len(configured)) 125 126 // Loop over our configured parameters and create 127 // an array of aws-sdk-go compatabile objects 128 for _, pRaw := range configured { 129 data := pRaw.(map[string]interface{}) 130 131 p := &rds.Parameter{ 132 ApplyMethod: aws.String(data["apply_method"].(string)), 133 ParameterName: aws.String(data["name"].(string)), 134 ParameterValue: aws.String(data["value"].(string)), 135 } 136 137 parameters = append(parameters, p) 138 } 139 140 return parameters, nil 141 } 142 143 // Flattens a health check into something that flatmap.Flatten() 144 // can handle 145 func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} { 146 result := make([]map[string]interface{}, 0, 1) 147 148 chk := make(map[string]interface{}) 149 chk["unhealthy_threshold"] = *check.UnhealthyThreshold 150 chk["healthy_threshold"] = *check.HealthyThreshold 151 chk["target"] = *check.Target 152 chk["timeout"] = *check.Timeout 153 chk["interval"] = *check.Interval 154 155 result = append(result, chk) 156 157 return result 158 } 159 160 // Flattens an array of UserSecurityGroups into a []string 161 func flattenSecurityGroups(list []*ec2.UserIDGroupPair) []string { 162 result := make([]string, 0, len(list)) 163 for _, g := range list { 164 result = append(result, *g.GroupID) 165 } 166 return result 167 } 168 169 // Flattens an array of Instances into a []string 170 func flattenInstances(list []*elb.Instance) []string { 171 result := make([]string, 0, len(list)) 172 for _, i := range list { 173 result = append(result, *i.InstanceID) 174 } 175 return result 176 } 177 178 // Expands an array of String Instance IDs into a []Instances 179 func expandInstanceString(list []interface{}) []*elb.Instance { 180 result := make([]*elb.Instance, 0, len(list)) 181 for _, i := range list { 182 result = append(result, &elb.Instance{InstanceID: aws.String(i.(string))}) 183 } 184 return result 185 } 186 187 // Flattens an array of Backend Descriptions into a a map of instance_port to policy names. 188 func flattenBackendPolicies(backends []*elb.BackendServerDescription) map[int64][]string { 189 policies := make(map[int64][]string) 190 for _, i := range backends { 191 for _, p := range i.PolicyNames { 192 policies[*i.InstancePort] = append(policies[*i.InstancePort], *p) 193 } 194 sort.Strings(policies[*i.InstancePort]) 195 } 196 return policies 197 } 198 199 // Flattens an array of Listeners into a []map[string]interface{} 200 func flattenListeners(list []*elb.ListenerDescription) []map[string]interface{} { 201 result := make([]map[string]interface{}, 0, len(list)) 202 for _, i := range list { 203 l := map[string]interface{}{ 204 "instance_port": *i.Listener.InstancePort, 205 "instance_protocol": strings.ToLower(*i.Listener.InstanceProtocol), 206 "lb_port": *i.Listener.LoadBalancerPort, 207 "lb_protocol": strings.ToLower(*i.Listener.Protocol), 208 } 209 // SSLCertificateID is optional, and may be nil 210 if i.Listener.SSLCertificateID != nil { 211 l["ssl_certificate_id"] = *i.Listener.SSLCertificateID 212 } 213 result = append(result, l) 214 } 215 return result 216 } 217 218 // Flattens an array of Parameters into a []map[string]interface{} 219 func flattenParameters(list []*rds.Parameter) []map[string]interface{} { 220 result := make([]map[string]interface{}, 0, len(list)) 221 for _, i := range list { 222 result = append(result, map[string]interface{}{ 223 "name": strings.ToLower(*i.ParameterName), 224 "value": strings.ToLower(*i.ParameterValue), 225 }) 226 } 227 return result 228 } 229 230 // Takes the result of flatmap.Expand for an array of strings 231 // and returns a []string 232 func expandStringList(configured []interface{}) []*string { 233 vs := make([]*string, 0, len(configured)) 234 for _, v := range configured { 235 vs = append(vs, aws.String(v.(string))) 236 } 237 return vs 238 } 239 240 //Flattens an array of private ip addresses into a []string, where the elements returned are the IP strings e.g. "192.168.0.0" 241 func flattenNetworkInterfacesPrivateIPAddesses(dtos []*ec2.NetworkInterfacePrivateIPAddress) []string { 242 ips := make([]string, 0, len(dtos)) 243 for _, v := range dtos { 244 ip := *v.PrivateIPAddress 245 ips = append(ips, ip) 246 } 247 return ips 248 } 249 250 //Flattens security group identifiers into a []string, where the elements returned are the GroupIDs 251 func flattenGroupIdentifiers(dtos []*ec2.GroupIdentifier) []string { 252 ids := make([]string, 0, len(dtos)) 253 for _, v := range dtos { 254 group_id := *v.GroupID 255 ids = append(ids, group_id) 256 } 257 return ids 258 } 259 260 //Expands an array of IPs into a ec2 Private IP Address Spec 261 func expandPrivateIPAddesses(ips []interface{}) []*ec2.PrivateIPAddressSpecification { 262 dtos := make([]*ec2.PrivateIPAddressSpecification, 0, len(ips)) 263 for i, v := range ips { 264 new_private_ip := &ec2.PrivateIPAddressSpecification{ 265 PrivateIPAddress: aws.String(v.(string)), 266 } 267 268 new_private_ip.Primary = aws.Boolean(i == 0) 269 270 dtos = append(dtos, new_private_ip) 271 } 272 return dtos 273 } 274 275 //Flattens network interface attachment into a map[string]interface 276 func flattenAttachment(a *ec2.NetworkInterfaceAttachment) map[string]interface{} { 277 att := make(map[string]interface{}) 278 att["instance"] = *a.InstanceID 279 att["device_index"] = *a.DeviceIndex 280 att["attachment_id"] = *a.AttachmentID 281 return att 282 } 283 284 func flattenResourceRecords(recs []*route53.ResourceRecord) []string { 285 strs := make([]string, 0, len(recs)) 286 for _, r := range recs { 287 if r.Value != nil { 288 s := strings.Replace(*r.Value, "\"", "", 2) 289 strs = append(strs, s) 290 } 291 } 292 return strs 293 } 294 295 func expandResourceRecords(recs []interface{}, typeStr string) []*route53.ResourceRecord { 296 records := make([]*route53.ResourceRecord, 0, len(recs)) 297 for _, r := range recs { 298 s := r.(string) 299 switch typeStr { 300 case "TXT": 301 str := fmt.Sprintf("\"%s\"", s) 302 records = append(records, &route53.ResourceRecord{Value: aws.String(str)}) 303 default: 304 records = append(records, &route53.ResourceRecord{Value: aws.String(s)}) 305 } 306 } 307 return records 308 }