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