github.com/federicobaldo/terraform@v0.6.15-0.20160323222747-b20f680cbf05/builtin/providers/aws/structure.go (about) 1 package aws 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "sort" 8 "strings" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/service/apigateway" 12 "github.com/aws/aws-sdk-go/service/autoscaling" 13 "github.com/aws/aws-sdk-go/service/cloudformation" 14 "github.com/aws/aws-sdk-go/service/cloudwatchlogs" 15 "github.com/aws/aws-sdk-go/service/directoryservice" 16 "github.com/aws/aws-sdk-go/service/ec2" 17 "github.com/aws/aws-sdk-go/service/ecs" 18 "github.com/aws/aws-sdk-go/service/elasticache" 19 elasticsearch "github.com/aws/aws-sdk-go/service/elasticsearchservice" 20 "github.com/aws/aws-sdk-go/service/elb" 21 "github.com/aws/aws-sdk-go/service/lambda" 22 "github.com/aws/aws-sdk-go/service/rds" 23 "github.com/aws/aws-sdk-go/service/redshift" 24 "github.com/aws/aws-sdk-go/service/route53" 25 "github.com/hashicorp/terraform/helper/schema" 26 ) 27 28 // Takes the result of flatmap.Expand for an array of listeners and 29 // returns ELB API compatible objects 30 func expandListeners(configured []interface{}) ([]*elb.Listener, error) { 31 listeners := make([]*elb.Listener, 0, len(configured)) 32 33 // Loop over our configured listeners and create 34 // an array of aws-sdk-go compatabile objects 35 for _, lRaw := range configured { 36 data := lRaw.(map[string]interface{}) 37 38 ip := int64(data["instance_port"].(int)) 39 lp := int64(data["lb_port"].(int)) 40 l := &elb.Listener{ 41 InstancePort: &ip, 42 InstanceProtocol: aws.String(data["instance_protocol"].(string)), 43 LoadBalancerPort: &lp, 44 Protocol: aws.String(data["lb_protocol"].(string)), 45 } 46 47 if v, ok := data["ssl_certificate_id"]; ok { 48 l.SSLCertificateId = aws.String(v.(string)) 49 } 50 51 var valid bool 52 if l.SSLCertificateId != nil && *l.SSLCertificateId != "" { 53 // validate the protocol is correct 54 for _, p := range []string{"https", "ssl"} { 55 if (strings.ToLower(*l.InstanceProtocol) == p) || (strings.ToLower(*l.Protocol) == p) { 56 valid = true 57 } 58 } 59 } else { 60 valid = true 61 } 62 63 if valid { 64 listeners = append(listeners, l) 65 } else { 66 return nil, fmt.Errorf("[ERR] ELB Listener: ssl_certificate_id may be set only when protocol is 'https' or 'ssl'") 67 } 68 } 69 70 return listeners, nil 71 } 72 73 // Takes the result of flatmap. Expand for an array of listeners and 74 // returns ECS Volume compatible objects 75 func expandEcsVolumes(configured []interface{}) ([]*ecs.Volume, error) { 76 volumes := make([]*ecs.Volume, 0, len(configured)) 77 78 // Loop over our configured volumes and create 79 // an array of aws-sdk-go compatible objects 80 for _, lRaw := range configured { 81 data := lRaw.(map[string]interface{}) 82 83 l := &ecs.Volume{ 84 Name: aws.String(data["name"].(string)), 85 } 86 87 hostPath := data["host_path"].(string) 88 if hostPath != "" { 89 l.Host = &ecs.HostVolumeProperties{ 90 SourcePath: aws.String(hostPath), 91 } 92 } 93 94 volumes = append(volumes, l) 95 } 96 97 return volumes, nil 98 } 99 100 // Takes JSON in a string. Decodes JSON into 101 // an array of ecs.ContainerDefinition compatible objects 102 func expandEcsContainerDefinitions(rawDefinitions string) ([]*ecs.ContainerDefinition, error) { 103 var definitions []*ecs.ContainerDefinition 104 105 err := json.Unmarshal([]byte(rawDefinitions), &definitions) 106 if err != nil { 107 return nil, fmt.Errorf("Error decoding JSON: %s", err) 108 } 109 110 return definitions, nil 111 } 112 113 // Takes the result of flatmap. Expand for an array of load balancers and 114 // returns ecs.LoadBalancer compatible objects 115 func expandEcsLoadBalancers(configured []interface{}) []*ecs.LoadBalancer { 116 loadBalancers := make([]*ecs.LoadBalancer, 0, len(configured)) 117 118 // Loop over our configured load balancers and create 119 // an array of aws-sdk-go compatible objects 120 for _, lRaw := range configured { 121 data := lRaw.(map[string]interface{}) 122 123 l := &ecs.LoadBalancer{ 124 ContainerName: aws.String(data["container_name"].(string)), 125 ContainerPort: aws.Int64(int64(data["container_port"].(int))), 126 LoadBalancerName: aws.String(data["elb_name"].(string)), 127 } 128 129 loadBalancers = append(loadBalancers, l) 130 } 131 132 return loadBalancers 133 } 134 135 // Takes the result of flatmap.Expand for an array of ingress/egress security 136 // group rules and returns EC2 API compatible objects. This function will error 137 // if it finds invalid permissions input, namely a protocol of "-1" with either 138 // to_port or from_port set to a non-zero value. 139 func expandIPPerms( 140 group *ec2.SecurityGroup, configured []interface{}) ([]*ec2.IpPermission, error) { 141 vpc := group.VpcId != nil && *group.VpcId != "" 142 143 perms := make([]*ec2.IpPermission, len(configured)) 144 for i, mRaw := range configured { 145 var perm ec2.IpPermission 146 m := mRaw.(map[string]interface{}) 147 148 perm.FromPort = aws.Int64(int64(m["from_port"].(int))) 149 perm.ToPort = aws.Int64(int64(m["to_port"].(int))) 150 perm.IpProtocol = aws.String(m["protocol"].(string)) 151 152 // When protocol is "-1", AWS won't store any ports for the 153 // rule, but also won't error if the user specifies ports other 154 // than '0'. Force the user to make a deliberate '0' port 155 // choice when specifying a "-1" protocol, and tell them about 156 // AWS's behavior in the error message. 157 if *perm.IpProtocol == "-1" && (*perm.FromPort != 0 || *perm.ToPort != 0) { 158 return nil, fmt.Errorf( 159 "from_port (%d) and to_port (%d) must both be 0 to use the the 'ALL' \"-1\" protocol!", 160 *perm.FromPort, *perm.ToPort) 161 } 162 163 var groups []string 164 if raw, ok := m["security_groups"]; ok { 165 list := raw.(*schema.Set).List() 166 for _, v := range list { 167 groups = append(groups, v.(string)) 168 } 169 } 170 if v, ok := m["self"]; ok && v.(bool) { 171 if vpc { 172 groups = append(groups, *group.GroupId) 173 } else { 174 groups = append(groups, *group.GroupName) 175 } 176 } 177 178 if len(groups) > 0 { 179 perm.UserIdGroupPairs = make([]*ec2.UserIdGroupPair, len(groups)) 180 for i, name := range groups { 181 ownerId, id := "", name 182 if items := strings.Split(id, "/"); len(items) > 1 { 183 ownerId, id = items[0], items[1] 184 } 185 186 perm.UserIdGroupPairs[i] = &ec2.UserIdGroupPair{ 187 GroupId: aws.String(id), 188 } 189 190 if ownerId != "" { 191 perm.UserIdGroupPairs[i].UserId = aws.String(ownerId) 192 } 193 194 if !vpc { 195 perm.UserIdGroupPairs[i].GroupId = nil 196 perm.UserIdGroupPairs[i].GroupName = aws.String(id) 197 } 198 } 199 } 200 201 if raw, ok := m["cidr_blocks"]; ok { 202 list := raw.([]interface{}) 203 for _, v := range list { 204 perm.IpRanges = append(perm.IpRanges, &ec2.IpRange{CidrIp: aws.String(v.(string))}) 205 } 206 } 207 208 perms[i] = &perm 209 } 210 211 return perms, nil 212 } 213 214 // Takes the result of flatmap.Expand for an array of parameters and 215 // returns Parameter API compatible objects 216 func expandParameters(configured []interface{}) ([]*rds.Parameter, error) { 217 var parameters []*rds.Parameter 218 219 // Loop over our configured parameters and create 220 // an array of aws-sdk-go compatabile objects 221 for _, pRaw := range configured { 222 data := pRaw.(map[string]interface{}) 223 224 if data["name"].(string) == "" { 225 continue 226 } 227 228 p := &rds.Parameter{ 229 ApplyMethod: aws.String(data["apply_method"].(string)), 230 ParameterName: aws.String(data["name"].(string)), 231 ParameterValue: aws.String(data["value"].(string)), 232 } 233 234 parameters = append(parameters, p) 235 } 236 237 return parameters, nil 238 } 239 240 func expandRedshiftParameters(configured []interface{}) ([]*redshift.Parameter, error) { 241 var parameters []*redshift.Parameter 242 243 // Loop over our configured parameters and create 244 // an array of aws-sdk-go compatabile objects 245 for _, pRaw := range configured { 246 data := pRaw.(map[string]interface{}) 247 248 if data["name"].(string) == "" { 249 continue 250 } 251 252 p := &redshift.Parameter{ 253 ParameterName: aws.String(data["name"].(string)), 254 ParameterValue: aws.String(data["value"].(string)), 255 } 256 257 parameters = append(parameters, p) 258 } 259 260 return parameters, nil 261 } 262 263 // Takes the result of flatmap.Expand for an array of parameters and 264 // returns Parameter API compatible objects 265 func expandElastiCacheParameters(configured []interface{}) ([]*elasticache.ParameterNameValue, error) { 266 parameters := make([]*elasticache.ParameterNameValue, 0, len(configured)) 267 268 // Loop over our configured parameters and create 269 // an array of aws-sdk-go compatabile objects 270 for _, pRaw := range configured { 271 data := pRaw.(map[string]interface{}) 272 273 p := &elasticache.ParameterNameValue{ 274 ParameterName: aws.String(data["name"].(string)), 275 ParameterValue: aws.String(data["value"].(string)), 276 } 277 278 parameters = append(parameters, p) 279 } 280 281 return parameters, nil 282 } 283 284 // Flattens an access log into something that flatmap.Flatten() can handle 285 func flattenAccessLog(l *elb.AccessLog) []map[string]interface{} { 286 result := make([]map[string]interface{}, 0, 1) 287 288 if l != nil && *l.Enabled { 289 r := make(map[string]interface{}) 290 if l.S3BucketName != nil { 291 r["bucket"] = *l.S3BucketName 292 } 293 294 if l.S3BucketPrefix != nil { 295 r["bucket_prefix"] = *l.S3BucketPrefix 296 } 297 298 if l.EmitInterval != nil { 299 r["interval"] = *l.EmitInterval 300 } 301 302 result = append(result, r) 303 } 304 305 return result 306 } 307 308 // Flattens a health check into something that flatmap.Flatten() 309 // can handle 310 func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} { 311 result := make([]map[string]interface{}, 0, 1) 312 313 chk := make(map[string]interface{}) 314 chk["unhealthy_threshold"] = *check.UnhealthyThreshold 315 chk["healthy_threshold"] = *check.HealthyThreshold 316 chk["target"] = *check.Target 317 chk["timeout"] = *check.Timeout 318 chk["interval"] = *check.Interval 319 320 result = append(result, chk) 321 322 return result 323 } 324 325 // Flattens an array of UserSecurityGroups into a []*ec2.GroupIdentifier 326 func flattenSecurityGroups(list []*ec2.UserIdGroupPair, ownerId *string) []*ec2.GroupIdentifier { 327 result := make([]*ec2.GroupIdentifier, 0, len(list)) 328 for _, g := range list { 329 var userId *string 330 if g.UserId != nil && *g.UserId != "" && (ownerId == nil || *ownerId != *g.UserId) { 331 userId = g.UserId 332 } 333 // userid nil here for same vpc groups 334 335 vpc := g.GroupName == nil || *g.GroupName == "" 336 var id *string 337 if vpc { 338 id = g.GroupId 339 } else { 340 id = g.GroupName 341 } 342 343 // id is groupid for vpcs 344 // id is groupname for non vpc (classic) 345 346 if userId != nil { 347 id = aws.String(*userId + "/" + *id) 348 } 349 350 if vpc { 351 result = append(result, &ec2.GroupIdentifier{ 352 GroupId: id, 353 }) 354 } else { 355 result = append(result, &ec2.GroupIdentifier{ 356 GroupId: g.GroupId, 357 GroupName: id, 358 }) 359 } 360 } 361 return result 362 } 363 364 // Flattens an array of Instances into a []string 365 func flattenInstances(list []*elb.Instance) []string { 366 result := make([]string, 0, len(list)) 367 for _, i := range list { 368 result = append(result, *i.InstanceId) 369 } 370 return result 371 } 372 373 // Expands an array of String Instance IDs into a []Instances 374 func expandInstanceString(list []interface{}) []*elb.Instance { 375 result := make([]*elb.Instance, 0, len(list)) 376 for _, i := range list { 377 result = append(result, &elb.Instance{InstanceId: aws.String(i.(string))}) 378 } 379 return result 380 } 381 382 // Flattens an array of Backend Descriptions into a a map of instance_port to policy names. 383 func flattenBackendPolicies(backends []*elb.BackendServerDescription) map[int64][]string { 384 policies := make(map[int64][]string) 385 for _, i := range backends { 386 for _, p := range i.PolicyNames { 387 policies[*i.InstancePort] = append(policies[*i.InstancePort], *p) 388 } 389 sort.Strings(policies[*i.InstancePort]) 390 } 391 return policies 392 } 393 394 // Flattens an array of Listeners into a []map[string]interface{} 395 func flattenListeners(list []*elb.ListenerDescription) []map[string]interface{} { 396 result := make([]map[string]interface{}, 0, len(list)) 397 for _, i := range list { 398 l := map[string]interface{}{ 399 "instance_port": *i.Listener.InstancePort, 400 "instance_protocol": strings.ToLower(*i.Listener.InstanceProtocol), 401 "lb_port": *i.Listener.LoadBalancerPort, 402 "lb_protocol": strings.ToLower(*i.Listener.Protocol), 403 } 404 // SSLCertificateID is optional, and may be nil 405 if i.Listener.SSLCertificateId != nil { 406 l["ssl_certificate_id"] = *i.Listener.SSLCertificateId 407 } 408 result = append(result, l) 409 } 410 return result 411 } 412 413 // Flattens an array of Volumes into a []map[string]interface{} 414 func flattenEcsVolumes(list []*ecs.Volume) []map[string]interface{} { 415 result := make([]map[string]interface{}, 0, len(list)) 416 for _, volume := range list { 417 l := map[string]interface{}{ 418 "name": *volume.Name, 419 } 420 421 if volume.Host.SourcePath != nil { 422 l["host_path"] = *volume.Host.SourcePath 423 } 424 425 result = append(result, l) 426 } 427 return result 428 } 429 430 // Flattens an array of ECS LoadBalancers into a []map[string]interface{} 431 func flattenEcsLoadBalancers(list []*ecs.LoadBalancer) []map[string]interface{} { 432 result := make([]map[string]interface{}, 0, len(list)) 433 for _, loadBalancer := range list { 434 l := map[string]interface{}{ 435 "elb_name": *loadBalancer.LoadBalancerName, 436 "container_name": *loadBalancer.ContainerName, 437 "container_port": *loadBalancer.ContainerPort, 438 } 439 result = append(result, l) 440 } 441 return result 442 } 443 444 // Encodes an array of ecs.ContainerDefinitions into a JSON string 445 func flattenEcsContainerDefinitions(definitions []*ecs.ContainerDefinition) (string, error) { 446 byteArray, err := json.Marshal(definitions) 447 if err != nil { 448 return "", fmt.Errorf("Error encoding to JSON: %s", err) 449 } 450 451 n := bytes.Index(byteArray, []byte{0}) 452 return string(byteArray[:n]), nil 453 } 454 455 // Flattens an array of Parameters into a []map[string]interface{} 456 func flattenParameters(list []*rds.Parameter) []map[string]interface{} { 457 result := make([]map[string]interface{}, 0, len(list)) 458 for _, i := range list { 459 if i.ParameterName != nil { 460 r := make(map[string]interface{}) 461 r["name"] = strings.ToLower(*i.ParameterName) 462 // Default empty string, guard against nil parameter values 463 r["value"] = "" 464 if i.ParameterValue != nil { 465 r["value"] = strings.ToLower(*i.ParameterValue) 466 } 467 result = append(result, r) 468 } 469 } 470 return result 471 } 472 473 // Flattens an array of Redshift Parameters into a []map[string]interface{} 474 func flattenRedshiftParameters(list []*redshift.Parameter) []map[string]interface{} { 475 result := make([]map[string]interface{}, 0, len(list)) 476 for _, i := range list { 477 result = append(result, map[string]interface{}{ 478 "name": strings.ToLower(*i.ParameterName), 479 "value": strings.ToLower(*i.ParameterValue), 480 }) 481 } 482 return result 483 } 484 485 // Flattens an array of Parameters into a []map[string]interface{} 486 func flattenElastiCacheParameters(list []*elasticache.Parameter) []map[string]interface{} { 487 result := make([]map[string]interface{}, 0, len(list)) 488 for _, i := range list { 489 result = append(result, map[string]interface{}{ 490 "name": strings.ToLower(*i.ParameterName), 491 "value": strings.ToLower(*i.ParameterValue), 492 }) 493 } 494 return result 495 } 496 497 // Takes the result of flatmap.Expand for an array of strings 498 // and returns a []*string 499 func expandStringList(configured []interface{}) []*string { 500 vs := make([]*string, 0, len(configured)) 501 for _, v := range configured { 502 vs = append(vs, aws.String(v.(string))) 503 } 504 return vs 505 } 506 507 // Takes the result of schema.Set of strings and returns a []*string 508 func expandStringSet(configured *schema.Set) []*string { 509 return expandStringList(configured.List()) 510 } 511 512 // Takes list of pointers to strings. Expand to an array 513 // of raw strings and returns a []interface{} 514 // to keep compatibility w/ schema.NewSetschema.NewSet 515 func flattenStringList(list []*string) []interface{} { 516 vs := make([]interface{}, 0, len(list)) 517 for _, v := range list { 518 vs = append(vs, *v) 519 } 520 return vs 521 } 522 523 //Flattens an array of private ip addresses into a []string, where the elements returned are the IP strings e.g. "192.168.0.0" 524 func flattenNetworkInterfacesPrivateIPAddresses(dtos []*ec2.NetworkInterfacePrivateIpAddress) []string { 525 ips := make([]string, 0, len(dtos)) 526 for _, v := range dtos { 527 ip := *v.PrivateIpAddress 528 ips = append(ips, ip) 529 } 530 return ips 531 } 532 533 //Flattens security group identifiers into a []string, where the elements returned are the GroupIDs 534 func flattenGroupIdentifiers(dtos []*ec2.GroupIdentifier) []string { 535 ids := make([]string, 0, len(dtos)) 536 for _, v := range dtos { 537 group_id := *v.GroupId 538 ids = append(ids, group_id) 539 } 540 return ids 541 } 542 543 //Expands an array of IPs into a ec2 Private IP Address Spec 544 func expandPrivateIPAddresses(ips []interface{}) []*ec2.PrivateIpAddressSpecification { 545 dtos := make([]*ec2.PrivateIpAddressSpecification, 0, len(ips)) 546 for i, v := range ips { 547 new_private_ip := &ec2.PrivateIpAddressSpecification{ 548 PrivateIpAddress: aws.String(v.(string)), 549 } 550 551 new_private_ip.Primary = aws.Bool(i == 0) 552 553 dtos = append(dtos, new_private_ip) 554 } 555 return dtos 556 } 557 558 //Flattens network interface attachment into a map[string]interface 559 func flattenAttachment(a *ec2.NetworkInterfaceAttachment) map[string]interface{} { 560 att := make(map[string]interface{}) 561 att["instance"] = *a.InstanceId 562 att["device_index"] = *a.DeviceIndex 563 att["attachment_id"] = *a.AttachmentId 564 return att 565 } 566 567 func flattenResourceRecords(recs []*route53.ResourceRecord) []string { 568 strs := make([]string, 0, len(recs)) 569 for _, r := range recs { 570 if r.Value != nil { 571 s := strings.Replace(*r.Value, "\"", "", 2) 572 strs = append(strs, s) 573 } 574 } 575 return strs 576 } 577 578 func expandResourceRecords(recs []interface{}, typeStr string) []*route53.ResourceRecord { 579 records := make([]*route53.ResourceRecord, 0, len(recs)) 580 for _, r := range recs { 581 s := r.(string) 582 switch typeStr { 583 case "TXT", "SPF": 584 str := fmt.Sprintf("\"%s\"", s) 585 records = append(records, &route53.ResourceRecord{Value: aws.String(str)}) 586 default: 587 records = append(records, &route53.ResourceRecord{Value: aws.String(s)}) 588 } 589 } 590 return records 591 } 592 593 func expandESClusterConfig(m map[string]interface{}) *elasticsearch.ElasticsearchClusterConfig { 594 config := elasticsearch.ElasticsearchClusterConfig{} 595 596 if v, ok := m["dedicated_master_enabled"]; ok { 597 isEnabled := v.(bool) 598 config.DedicatedMasterEnabled = aws.Bool(isEnabled) 599 600 if isEnabled { 601 if v, ok := m["dedicated_master_count"]; ok && v.(int) > 0 { 602 config.DedicatedMasterCount = aws.Int64(int64(v.(int))) 603 } 604 if v, ok := m["dedicated_master_type"]; ok && v.(string) != "" { 605 config.DedicatedMasterType = aws.String(v.(string)) 606 } 607 } 608 } 609 610 if v, ok := m["instance_count"]; ok { 611 config.InstanceCount = aws.Int64(int64(v.(int))) 612 } 613 if v, ok := m["instance_type"]; ok { 614 config.InstanceType = aws.String(v.(string)) 615 } 616 617 if v, ok := m["zone_awareness_enabled"]; ok { 618 config.ZoneAwarenessEnabled = aws.Bool(v.(bool)) 619 } 620 621 return &config 622 } 623 624 func flattenESClusterConfig(c *elasticsearch.ElasticsearchClusterConfig) []map[string]interface{} { 625 m := map[string]interface{}{} 626 627 if c.DedicatedMasterCount != nil { 628 m["dedicated_master_count"] = *c.DedicatedMasterCount 629 } 630 if c.DedicatedMasterEnabled != nil { 631 m["dedicated_master_enabled"] = *c.DedicatedMasterEnabled 632 } 633 if c.DedicatedMasterType != nil { 634 m["dedicated_master_type"] = *c.DedicatedMasterType 635 } 636 if c.InstanceCount != nil { 637 m["instance_count"] = *c.InstanceCount 638 } 639 if c.InstanceType != nil { 640 m["instance_type"] = *c.InstanceType 641 } 642 if c.ZoneAwarenessEnabled != nil { 643 m["zone_awareness_enabled"] = *c.ZoneAwarenessEnabled 644 } 645 646 return []map[string]interface{}{m} 647 } 648 649 func flattenESEBSOptions(o *elasticsearch.EBSOptions) []map[string]interface{} { 650 m := map[string]interface{}{} 651 652 if o.EBSEnabled != nil { 653 m["ebs_enabled"] = *o.EBSEnabled 654 } 655 if o.Iops != nil { 656 m["iops"] = *o.Iops 657 } 658 if o.VolumeSize != nil { 659 m["volume_size"] = *o.VolumeSize 660 } 661 if o.VolumeType != nil { 662 m["volume_type"] = *o.VolumeType 663 } 664 665 return []map[string]interface{}{m} 666 } 667 668 func expandESEBSOptions(m map[string]interface{}) *elasticsearch.EBSOptions { 669 options := elasticsearch.EBSOptions{} 670 671 if v, ok := m["ebs_enabled"]; ok { 672 options.EBSEnabled = aws.Bool(v.(bool)) 673 } 674 if v, ok := m["iops"]; ok && v.(int) > 0 { 675 options.Iops = aws.Int64(int64(v.(int))) 676 } 677 if v, ok := m["volume_size"]; ok && v.(int) > 0 { 678 options.VolumeSize = aws.Int64(int64(v.(int))) 679 } 680 if v, ok := m["volume_type"]; ok && v.(string) != "" { 681 options.VolumeType = aws.String(v.(string)) 682 } 683 684 return &options 685 } 686 687 func pointersMapToStringList(pointers map[string]*string) map[string]interface{} { 688 list := make(map[string]interface{}, len(pointers)) 689 for i, v := range pointers { 690 list[i] = *v 691 } 692 return list 693 } 694 695 func stringMapToPointers(m map[string]interface{}) map[string]*string { 696 list := make(map[string]*string, len(m)) 697 for i, v := range m { 698 list[i] = aws.String(v.(string)) 699 } 700 return list 701 } 702 703 func flattenDSVpcSettings( 704 s *directoryservice.DirectoryVpcSettingsDescription) []map[string]interface{} { 705 settings := make(map[string]interface{}, 0) 706 707 if s == nil { 708 return nil 709 } 710 711 settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds)) 712 settings["vpc_id"] = *s.VpcId 713 714 return []map[string]interface{}{settings} 715 } 716 717 func flattenLambdaVpcConfigResponse(s *lambda.VpcConfigResponse) []map[string]interface{} { 718 settings := make(map[string]interface{}, 0) 719 720 if s == nil { 721 return nil 722 } 723 724 if len(s.SubnetIds) == 0 && len(s.SecurityGroupIds) == 0 && s.VpcId == nil { 725 return nil 726 } 727 728 settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds)) 729 settings["security_group_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SecurityGroupIds)) 730 if s.VpcId != nil { 731 settings["vpc_id"] = *s.VpcId 732 } 733 734 return []map[string]interface{}{settings} 735 } 736 737 func flattenDSConnectSettings( 738 customerDnsIps []*string, 739 s *directoryservice.DirectoryConnectSettingsDescription) []map[string]interface{} { 740 if s == nil { 741 return nil 742 } 743 744 settings := make(map[string]interface{}, 0) 745 746 settings["customer_dns_ips"] = schema.NewSet(schema.HashString, flattenStringList(customerDnsIps)) 747 settings["connect_ips"] = schema.NewSet(schema.HashString, flattenStringList(s.ConnectIps)) 748 settings["customer_username"] = *s.CustomerUserName 749 settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds)) 750 settings["vpc_id"] = *s.VpcId 751 752 return []map[string]interface{}{settings} 753 } 754 755 func expandCloudFormationParameters(params map[string]interface{}) []*cloudformation.Parameter { 756 var cfParams []*cloudformation.Parameter 757 for k, v := range params { 758 cfParams = append(cfParams, &cloudformation.Parameter{ 759 ParameterKey: aws.String(k), 760 ParameterValue: aws.String(v.(string)), 761 }) 762 } 763 764 return cfParams 765 } 766 767 // flattenCloudFormationParameters is flattening list of 768 // *cloudformation.Parameters and only returning existing 769 // parameters to avoid clash with default values 770 func flattenCloudFormationParameters(cfParams []*cloudformation.Parameter, 771 originalParams map[string]interface{}) map[string]interface{} { 772 params := make(map[string]interface{}, len(cfParams)) 773 for _, p := range cfParams { 774 _, isConfigured := originalParams[*p.ParameterKey] 775 if isConfigured { 776 params[*p.ParameterKey] = *p.ParameterValue 777 } 778 } 779 return params 780 } 781 782 func expandCloudFormationTags(tags map[string]interface{}) []*cloudformation.Tag { 783 var cfTags []*cloudformation.Tag 784 for k, v := range tags { 785 cfTags = append(cfTags, &cloudformation.Tag{ 786 Key: aws.String(k), 787 Value: aws.String(v.(string)), 788 }) 789 } 790 return cfTags 791 } 792 793 func flattenCloudFormationTags(cfTags []*cloudformation.Tag) map[string]string { 794 tags := make(map[string]string, len(cfTags)) 795 for _, t := range cfTags { 796 tags[*t.Key] = *t.Value 797 } 798 return tags 799 } 800 801 func flattenCloudFormationOutputs(cfOutputs []*cloudformation.Output) map[string]string { 802 outputs := make(map[string]string, len(cfOutputs)) 803 for _, o := range cfOutputs { 804 outputs[*o.OutputKey] = *o.OutputValue 805 } 806 return outputs 807 } 808 809 func flattenAsgEnabledMetrics(list []*autoscaling.EnabledMetric) []string { 810 strs := make([]string, 0, len(list)) 811 for _, r := range list { 812 if r.Metric != nil { 813 strs = append(strs, *r.Metric) 814 } 815 } 816 return strs 817 } 818 819 func expandApiGatewayStageKeys(d *schema.ResourceData) []*apigateway.StageKey { 820 var stageKeys []*apigateway.StageKey 821 822 if stageKeyData, ok := d.GetOk("stage_key"); ok { 823 params := stageKeyData.(*schema.Set).List() 824 for k := range params { 825 data := params[k].(map[string]interface{}) 826 stageKeys = append(stageKeys, &apigateway.StageKey{ 827 RestApiId: aws.String(data["rest_api_id"].(string)), 828 StageName: aws.String(data["stage_name"].(string)), 829 }) 830 } 831 } 832 833 return stageKeys 834 } 835 836 func expandApiGatewayRequestResponseModelOperations(d *schema.ResourceData, key string, prefix string) []*apigateway.PatchOperation { 837 operations := make([]*apigateway.PatchOperation, 0) 838 839 oldModels, newModels := d.GetChange(key) 840 oldModelMap := oldModels.(map[string]interface{}) 841 newModelMap := newModels.(map[string]interface{}) 842 843 for k, _ := range oldModelMap { 844 operation := apigateway.PatchOperation{ 845 Op: aws.String("remove"), 846 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), 847 } 848 849 for nK, nV := range newModelMap { 850 if nK == k { 851 operation.Op = aws.String("replace") 852 operation.Value = aws.String(nV.(string)) 853 } 854 } 855 856 operations = append(operations, &operation) 857 } 858 859 for nK, nV := range newModelMap { 860 exists := false 861 for k, _ := range oldModelMap { 862 if k == nK { 863 exists = true 864 } 865 } 866 if !exists { 867 operation := apigateway.PatchOperation{ 868 Op: aws.String("add"), 869 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(nK, "/", "~1", -1))), 870 Value: aws.String(nV.(string)), 871 } 872 operations = append(operations, &operation) 873 } 874 } 875 876 return operations 877 } 878 879 func expandApiGatewayStageKeyOperations(d *schema.ResourceData) []*apigateway.PatchOperation { 880 operations := make([]*apigateway.PatchOperation, 0) 881 882 prev, curr := d.GetChange("stage_key") 883 prevList := prev.(*schema.Set).List() 884 currList := curr.(*schema.Set).List() 885 886 for i := range prevList { 887 p := prevList[i].(map[string]interface{}) 888 exists := false 889 890 for j := range currList { 891 c := currList[j].(map[string]interface{}) 892 if c["rest_api_id"].(string) == p["rest_api_id"].(string) && c["stage_name"].(string) == p["stage_name"].(string) { 893 exists = true 894 } 895 } 896 897 if !exists { 898 operations = append(operations, &apigateway.PatchOperation{ 899 Op: aws.String("remove"), 900 Path: aws.String("/stages"), 901 Value: aws.String(fmt.Sprintf("%s/%s", p["rest_api_id"].(string), p["stage_name"].(string))), 902 }) 903 } 904 } 905 906 for i := range currList { 907 c := currList[i].(map[string]interface{}) 908 exists := false 909 910 for j := range prevList { 911 p := prevList[j].(map[string]interface{}) 912 if c["rest_api_id"].(string) == p["rest_api_id"].(string) && c["stage_name"].(string) == p["stage_name"].(string) { 913 exists = true 914 } 915 } 916 917 if !exists { 918 operations = append(operations, &apigateway.PatchOperation{ 919 Op: aws.String("add"), 920 Path: aws.String("/stages"), 921 Value: aws.String(fmt.Sprintf("%s/%s", c["rest_api_id"].(string), c["stage_name"].(string))), 922 }) 923 } 924 } 925 926 return operations 927 } 928 929 func expandCloudWachLogMetricTransformations(m map[string]interface{}) []*cloudwatchlogs.MetricTransformation { 930 transformation := cloudwatchlogs.MetricTransformation{ 931 MetricName: aws.String(m["name"].(string)), 932 MetricNamespace: aws.String(m["namespace"].(string)), 933 MetricValue: aws.String(m["value"].(string)), 934 } 935 936 return []*cloudwatchlogs.MetricTransformation{&transformation} 937 } 938 939 func flattenCloudWachLogMetricTransformations(ts []*cloudwatchlogs.MetricTransformation) map[string]string { 940 m := make(map[string]string, 0) 941 942 m["name"] = *ts[0].MetricName 943 m["namespace"] = *ts[0].MetricNamespace 944 m["value"] = *ts[0].MetricValue 945 946 return m 947 }