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