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