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