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