opentofu/builtin/providers/aws/structure.go
stack72 8dc123fd94 Scaffold the AWS DB Option Group resource
Change the AWS DB Instance to now include the DB Option Group param. Adds a test to prove that it works

Add acceptance tests for the AWS DB Option Group work. This ensures that Options can be added and updated

Documentation for the AWS DB Option resource
2016-05-08 20:18:53 +01:00

1244 lines
35 KiB
Go

package aws
import (
"bytes"
"encoding/json"
"fmt"
"sort"
"strconv"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/apigateway"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
"github.com/aws/aws-sdk-go/service/directoryservice"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/elasticbeanstalk"
elasticsearch "github.com/aws/aws-sdk-go/service/elasticsearchservice"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/aws/aws-sdk-go/service/route53"
"github.com/hashicorp/terraform/helper/schema"
)
// Takes the result of flatmap.Expand for an array of listeners and
// returns ELB API compatible objects
func expandListeners(configured []interface{}) ([]*elb.Listener, error) {
listeners := make([]*elb.Listener, 0, len(configured))
// Loop over our configured listeners and create
// an array of aws-sdk-go compatabile objects
for _, lRaw := range configured {
data := lRaw.(map[string]interface{})
ip := int64(data["instance_port"].(int))
lp := int64(data["lb_port"].(int))
l := &elb.Listener{
InstancePort: &ip,
InstanceProtocol: aws.String(data["instance_protocol"].(string)),
LoadBalancerPort: &lp,
Protocol: aws.String(data["lb_protocol"].(string)),
}
if v, ok := data["ssl_certificate_id"]; ok {
l.SSLCertificateId = aws.String(v.(string))
}
var valid bool
if l.SSLCertificateId != nil && *l.SSLCertificateId != "" {
// validate the protocol is correct
for _, p := range []string{"https", "ssl"} {
if (strings.ToLower(*l.InstanceProtocol) == p) || (strings.ToLower(*l.Protocol) == p) {
valid = true
}
}
} else {
valid = true
}
if valid {
listeners = append(listeners, l)
} else {
return nil, fmt.Errorf("[ERR] ELB Listener: ssl_certificate_id may be set only when protocol is 'https' or 'ssl'")
}
}
return listeners, nil
}
// Takes the result of flatmap. Expand for an array of listeners and
// returns ECS Volume compatible objects
func expandEcsVolumes(configured []interface{}) ([]*ecs.Volume, error) {
volumes := make([]*ecs.Volume, 0, len(configured))
// Loop over our configured volumes and create
// an array of aws-sdk-go compatible objects
for _, lRaw := range configured {
data := lRaw.(map[string]interface{})
l := &ecs.Volume{
Name: aws.String(data["name"].(string)),
}
hostPath := data["host_path"].(string)
if hostPath != "" {
l.Host = &ecs.HostVolumeProperties{
SourcePath: aws.String(hostPath),
}
}
volumes = append(volumes, l)
}
return volumes, nil
}
// Takes JSON in a string. Decodes JSON into
// an array of ecs.ContainerDefinition compatible objects
func expandEcsContainerDefinitions(rawDefinitions string) ([]*ecs.ContainerDefinition, error) {
var definitions []*ecs.ContainerDefinition
err := json.Unmarshal([]byte(rawDefinitions), &definitions)
if err != nil {
return nil, fmt.Errorf("Error decoding JSON: %s", err)
}
return definitions, nil
}
// Takes the result of flatmap. Expand for an array of load balancers and
// returns ecs.LoadBalancer compatible objects
func expandEcsLoadBalancers(configured []interface{}) []*ecs.LoadBalancer {
loadBalancers := make([]*ecs.LoadBalancer, 0, len(configured))
// Loop over our configured load balancers and create
// an array of aws-sdk-go compatible objects
for _, lRaw := range configured {
data := lRaw.(map[string]interface{})
l := &ecs.LoadBalancer{
ContainerName: aws.String(data["container_name"].(string)),
ContainerPort: aws.Int64(int64(data["container_port"].(int))),
LoadBalancerName: aws.String(data["elb_name"].(string)),
}
loadBalancers = append(loadBalancers, l)
}
return loadBalancers
}
// Takes the result of flatmap.Expand for an array of ingress/egress security
// group rules and returns EC2 API compatible objects. This function will error
// if it finds invalid permissions input, namely a protocol of "-1" with either
// to_port or from_port set to a non-zero value.
func expandIPPerms(
group *ec2.SecurityGroup, configured []interface{}) ([]*ec2.IpPermission, error) {
vpc := group.VpcId != nil && *group.VpcId != ""
perms := make([]*ec2.IpPermission, len(configured))
for i, mRaw := range configured {
var perm ec2.IpPermission
m := mRaw.(map[string]interface{})
perm.FromPort = aws.Int64(int64(m["from_port"].(int)))
perm.ToPort = aws.Int64(int64(m["to_port"].(int)))
perm.IpProtocol = aws.String(m["protocol"].(string))
// When protocol is "-1", AWS won't store any ports for the
// rule, but also won't error if the user specifies ports other
// than '0'. Force the user to make a deliberate '0' port
// choice when specifying a "-1" protocol, and tell them about
// AWS's behavior in the error message.
if *perm.IpProtocol == "-1" && (*perm.FromPort != 0 || *perm.ToPort != 0) {
return nil, fmt.Errorf(
"from_port (%d) and to_port (%d) must both be 0 to use the the 'ALL' \"-1\" protocol!",
*perm.FromPort, *perm.ToPort)
}
var groups []string
if raw, ok := m["security_groups"]; ok {
list := raw.(*schema.Set).List()
for _, v := range list {
groups = append(groups, v.(string))
}
}
if v, ok := m["self"]; ok && v.(bool) {
if vpc {
groups = append(groups, *group.GroupId)
} else {
groups = append(groups, *group.GroupName)
}
}
if len(groups) > 0 {
perm.UserIdGroupPairs = make([]*ec2.UserIdGroupPair, len(groups))
for i, name := range groups {
ownerId, id := "", name
if items := strings.Split(id, "/"); len(items) > 1 {
ownerId, id = items[0], items[1]
}
perm.UserIdGroupPairs[i] = &ec2.UserIdGroupPair{
GroupId: aws.String(id),
}
if ownerId != "" {
perm.UserIdGroupPairs[i].UserId = aws.String(ownerId)
}
if !vpc {
perm.UserIdGroupPairs[i].GroupId = nil
perm.UserIdGroupPairs[i].GroupName = aws.String(id)
}
}
}
if raw, ok := m["cidr_blocks"]; ok {
list := raw.([]interface{})
for _, v := range list {
perm.IpRanges = append(perm.IpRanges, &ec2.IpRange{CidrIp: aws.String(v.(string))})
}
}
perms[i] = &perm
}
return perms, nil
}
// Takes the result of flatmap.Expand for an array of parameters and
// returns Parameter API compatible objects
func expandParameters(configured []interface{}) ([]*rds.Parameter, error) {
var parameters []*rds.Parameter
// Loop over our configured parameters and create
// an array of aws-sdk-go compatabile objects
for _, pRaw := range configured {
data := pRaw.(map[string]interface{})
if data["name"].(string) == "" {
continue
}
p := &rds.Parameter{
ApplyMethod: aws.String(data["apply_method"].(string)),
ParameterName: aws.String(data["name"].(string)),
ParameterValue: aws.String(data["value"].(string)),
}
parameters = append(parameters, p)
}
return parameters, nil
}
func expandRedshiftParameters(configured []interface{}) ([]*redshift.Parameter, error) {
var parameters []*redshift.Parameter
// Loop over our configured parameters and create
// an array of aws-sdk-go compatabile objects
for _, pRaw := range configured {
data := pRaw.(map[string]interface{})
if data["name"].(string) == "" {
continue
}
p := &redshift.Parameter{
ParameterName: aws.String(data["name"].(string)),
ParameterValue: aws.String(data["value"].(string)),
}
parameters = append(parameters, p)
}
return parameters, nil
}
func expandOptionConfiguration(configured []interface{}) ([]*rds.OptionConfiguration, error) {
var option []*rds.OptionConfiguration
for _, pRaw := range configured {
data := pRaw.(map[string]interface{})
o := &rds.OptionConfiguration{
OptionName: aws.String(data["option_name"].(string)),
}
if raw, ok := data["port"]; ok {
port := raw.(int)
if port != 0 {
o.Port = aws.Int64(int64(port))
}
}
if raw, ok := data["db_security_group_memberships"]; ok {
memberships := expandStringList(raw.(*schema.Set).List())
if len(memberships) > 0 {
o.DBSecurityGroupMemberships = memberships
}
}
if raw, ok := data["vpc_security_group_memberships"]; ok {
memberships := expandStringList(raw.(*schema.Set).List())
if len(memberships) > 0 {
o.VpcSecurityGroupMemberships = memberships
}
}
option = append(option, o)
}
return option, nil
}
// Takes the result of flatmap.Expand for an array of parameters and
// returns Parameter API compatible objects
func expandElastiCacheParameters(configured []interface{}) ([]*elasticache.ParameterNameValue, error) {
parameters := make([]*elasticache.ParameterNameValue, 0, len(configured))
// Loop over our configured parameters and create
// an array of aws-sdk-go compatabile objects
for _, pRaw := range configured {
data := pRaw.(map[string]interface{})
p := &elasticache.ParameterNameValue{
ParameterName: aws.String(data["name"].(string)),
ParameterValue: aws.String(data["value"].(string)),
}
parameters = append(parameters, p)
}
return parameters, nil
}
// Flattens an access log into something that flatmap.Flatten() can handle
func flattenAccessLog(l *elb.AccessLog) []map[string]interface{} {
result := make([]map[string]interface{}, 0, 1)
if l != nil && *l.Enabled {
r := make(map[string]interface{})
if l.S3BucketName != nil {
r["bucket"] = *l.S3BucketName
}
if l.S3BucketPrefix != nil {
r["bucket_prefix"] = *l.S3BucketPrefix
}
if l.EmitInterval != nil {
r["interval"] = *l.EmitInterval
}
result = append(result, r)
}
return result
}
// Takes the result of flatmap.Expand for an array of step adjustments and
// returns a []*autoscaling.StepAdjustment.
func expandStepAdjustments(configured []interface{}) ([]*autoscaling.StepAdjustment, error) {
var adjustments []*autoscaling.StepAdjustment
// Loop over our configured step adjustments and create an array
// of aws-sdk-go compatible objects. We're forced to convert strings
// to floats here because there's no way to detect whether or not
// an uninitialized, optional schema element is "0.0" deliberately.
// With strings, we can test for "", which is definitely an empty
// struct value.
for _, raw := range configured {
data := raw.(map[string]interface{})
a := &autoscaling.StepAdjustment{
ScalingAdjustment: aws.Int64(int64(data["scaling_adjustment"].(int))),
}
if data["metric_interval_lower_bound"] != "" {
bound := data["metric_interval_lower_bound"]
switch bound := bound.(type) {
case string:
f, err := strconv.ParseFloat(bound, 64)
if err != nil {
return nil, fmt.Errorf(
"metric_interval_lower_bound must be a float value represented as a string")
}
a.MetricIntervalLowerBound = aws.Float64(f)
default:
return nil, fmt.Errorf(
"metric_interval_lower_bound isn't a string. This is a bug. Please file an issue.")
}
}
if data["metric_interval_upper_bound"] != "" {
bound := data["metric_interval_upper_bound"]
switch bound := bound.(type) {
case string:
f, err := strconv.ParseFloat(bound, 64)
if err != nil {
return nil, fmt.Errorf(
"metric_interval_upper_bound must be a float value represented as a string")
}
a.MetricIntervalUpperBound = aws.Float64(f)
default:
return nil, fmt.Errorf(
"metric_interval_upper_bound isn't a string. This is a bug. Please file an issue.")
}
}
adjustments = append(adjustments, a)
}
return adjustments, nil
}
// Flattens a health check into something that flatmap.Flatten()
// can handle
func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} {
result := make([]map[string]interface{}, 0, 1)
chk := make(map[string]interface{})
chk["unhealthy_threshold"] = *check.UnhealthyThreshold
chk["healthy_threshold"] = *check.HealthyThreshold
chk["target"] = *check.Target
chk["timeout"] = *check.Timeout
chk["interval"] = *check.Interval
result = append(result, chk)
return result
}
// Flattens an array of UserSecurityGroups into a []*ec2.GroupIdentifier
func flattenSecurityGroups(list []*ec2.UserIdGroupPair, ownerId *string) []*ec2.GroupIdentifier {
result := make([]*ec2.GroupIdentifier, 0, len(list))
for _, g := range list {
var userId *string
if g.UserId != nil && *g.UserId != "" && (ownerId == nil || *ownerId != *g.UserId) {
userId = g.UserId
}
// userid nil here for same vpc groups
vpc := g.GroupName == nil || *g.GroupName == ""
var id *string
if vpc {
id = g.GroupId
} else {
id = g.GroupName
}
// id is groupid for vpcs
// id is groupname for non vpc (classic)
if userId != nil {
id = aws.String(*userId + "/" + *id)
}
if vpc {
result = append(result, &ec2.GroupIdentifier{
GroupId: id,
})
} else {
result = append(result, &ec2.GroupIdentifier{
GroupId: g.GroupId,
GroupName: id,
})
}
}
return result
}
// Flattens an array of Instances into a []string
func flattenInstances(list []*elb.Instance) []string {
result := make([]string, 0, len(list))
for _, i := range list {
result = append(result, *i.InstanceId)
}
return result
}
// Expands an array of String Instance IDs into a []Instances
func expandInstanceString(list []interface{}) []*elb.Instance {
result := make([]*elb.Instance, 0, len(list))
for _, i := range list {
result = append(result, &elb.Instance{InstanceId: aws.String(i.(string))})
}
return result
}
// Flattens an array of Backend Descriptions into a a map of instance_port to policy names.
func flattenBackendPolicies(backends []*elb.BackendServerDescription) map[int64][]string {
policies := make(map[int64][]string)
for _, i := range backends {
for _, p := range i.PolicyNames {
policies[*i.InstancePort] = append(policies[*i.InstancePort], *p)
}
sort.Strings(policies[*i.InstancePort])
}
return policies
}
// Flattens an array of Listeners into a []map[string]interface{}
func flattenListeners(list []*elb.ListenerDescription) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
l := map[string]interface{}{
"instance_port": *i.Listener.InstancePort,
"instance_protocol": strings.ToLower(*i.Listener.InstanceProtocol),
"lb_port": *i.Listener.LoadBalancerPort,
"lb_protocol": strings.ToLower(*i.Listener.Protocol),
}
// SSLCertificateID is optional, and may be nil
if i.Listener.SSLCertificateId != nil {
l["ssl_certificate_id"] = *i.Listener.SSLCertificateId
}
result = append(result, l)
}
return result
}
// Flattens an array of Volumes into a []map[string]interface{}
func flattenEcsVolumes(list []*ecs.Volume) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, volume := range list {
l := map[string]interface{}{
"name": *volume.Name,
}
if volume.Host.SourcePath != nil {
l["host_path"] = *volume.Host.SourcePath
}
result = append(result, l)
}
return result
}
// Flattens an array of ECS LoadBalancers into a []map[string]interface{}
func flattenEcsLoadBalancers(list []*ecs.LoadBalancer) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, loadBalancer := range list {
l := map[string]interface{}{
"elb_name": *loadBalancer.LoadBalancerName,
"container_name": *loadBalancer.ContainerName,
"container_port": *loadBalancer.ContainerPort,
}
result = append(result, l)
}
return result
}
// Encodes an array of ecs.ContainerDefinitions into a JSON string
func flattenEcsContainerDefinitions(definitions []*ecs.ContainerDefinition) (string, error) {
byteArray, err := json.Marshal(definitions)
if err != nil {
return "", fmt.Errorf("Error encoding to JSON: %s", err)
}
n := bytes.Index(byteArray, []byte{0})
return string(byteArray[:n]), nil
}
func flattenOptions(list []*rds.Option) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
if i.OptionName != nil {
r := make(map[string]interface{})
r["option_name"] = strings.ToLower(*i.OptionName)
// Default empty string, guard against nil parameter values
r["port"] = ""
if i.Port != nil {
r["port"] = int(*i.Port)
}
if i.VpcSecurityGroupMemberships != nil {
vpcs := make([]string, 0, len(i.VpcSecurityGroupMemberships))
for _, vpc := range i.VpcSecurityGroupMemberships {
id := vpc.VpcSecurityGroupId
vpcs = append(vpcs, *id)
}
r["vpc_security_group_memberships"] = vpcs
}
if i.DBSecurityGroupMemberships != nil {
dbs := make([]string, 0, len(i.DBSecurityGroupMemberships))
for _, db := range i.DBSecurityGroupMemberships {
id := db.DBSecurityGroupName
dbs = append(dbs, *id)
}
r["db_security_group_memberships"] = dbs
}
result = append(result, r)
}
}
return result
}
// Flattens an array of Parameters into a []map[string]interface{}
func flattenParameters(list []*rds.Parameter) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
if i.ParameterName != nil {
r := make(map[string]interface{})
r["name"] = strings.ToLower(*i.ParameterName)
// Default empty string, guard against nil parameter values
r["value"] = ""
if i.ParameterValue != nil {
r["value"] = strings.ToLower(*i.ParameterValue)
}
result = append(result, r)
}
}
return result
}
// Flattens an array of Redshift Parameters into a []map[string]interface{}
func flattenRedshiftParameters(list []*redshift.Parameter) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
result = append(result, map[string]interface{}{
"name": strings.ToLower(*i.ParameterName),
"value": strings.ToLower(*i.ParameterValue),
})
}
return result
}
// Flattens an array of Parameters into a []map[string]interface{}
func flattenElastiCacheParameters(list []*elasticache.Parameter) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
result = append(result, map[string]interface{}{
"name": strings.ToLower(*i.ParameterName),
"value": strings.ToLower(*i.ParameterValue),
})
}
return result
}
// Takes the result of flatmap.Expand for an array of strings
// and returns a []*string
func expandStringList(configured []interface{}) []*string {
vs := make([]*string, 0, len(configured))
for _, v := range configured {
vs = append(vs, aws.String(v.(string)))
}
return vs
}
// Takes the result of schema.Set of strings and returns a []*string
func expandStringSet(configured *schema.Set) []*string {
return expandStringList(configured.List())
}
// Takes list of pointers to strings. Expand to an array
// of raw strings and returns a []interface{}
// to keep compatibility w/ schema.NewSetschema.NewSet
func flattenStringList(list []*string) []interface{} {
vs := make([]interface{}, 0, len(list))
for _, v := range list {
vs = append(vs, *v)
}
return vs
}
//Flattens an array of private ip addresses into a []string, where the elements returned are the IP strings e.g. "192.168.0.0"
func flattenNetworkInterfacesPrivateIPAddresses(dtos []*ec2.NetworkInterfacePrivateIpAddress) []string {
ips := make([]string, 0, len(dtos))
for _, v := range dtos {
ip := *v.PrivateIpAddress
ips = append(ips, ip)
}
return ips
}
//Flattens security group identifiers into a []string, where the elements returned are the GroupIDs
func flattenGroupIdentifiers(dtos []*ec2.GroupIdentifier) []string {
ids := make([]string, 0, len(dtos))
for _, v := range dtos {
group_id := *v.GroupId
ids = append(ids, group_id)
}
return ids
}
//Expands an array of IPs into a ec2 Private IP Address Spec
func expandPrivateIPAddresses(ips []interface{}) []*ec2.PrivateIpAddressSpecification {
dtos := make([]*ec2.PrivateIpAddressSpecification, 0, len(ips))
for i, v := range ips {
new_private_ip := &ec2.PrivateIpAddressSpecification{
PrivateIpAddress: aws.String(v.(string)),
}
new_private_ip.Primary = aws.Bool(i == 0)
dtos = append(dtos, new_private_ip)
}
return dtos
}
//Flattens network interface attachment into a map[string]interface
func flattenAttachment(a *ec2.NetworkInterfaceAttachment) map[string]interface{} {
att := make(map[string]interface{})
att["instance"] = *a.InstanceId
att["device_index"] = *a.DeviceIndex
att["attachment_id"] = *a.AttachmentId
return att
}
// Flattens step adjustments into a list of map[string]interface.
func flattenStepAdjustments(adjustments []*autoscaling.StepAdjustment) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(adjustments))
for _, raw := range adjustments {
a := map[string]interface{}{
"scaling_adjustment": *raw.ScalingAdjustment,
}
if raw.MetricIntervalUpperBound != nil {
a["metric_interval_upper_bound"] = *raw.MetricIntervalUpperBound
}
if raw.MetricIntervalLowerBound != nil {
a["metric_interval_lower_bound"] = *raw.MetricIntervalLowerBound
}
result = append(result, a)
}
return result
}
func flattenResourceRecords(recs []*route53.ResourceRecord) []string {
strs := make([]string, 0, len(recs))
for _, r := range recs {
if r.Value != nil {
s := strings.Replace(*r.Value, "\"", "", 2)
strs = append(strs, s)
}
}
return strs
}
func expandResourceRecords(recs []interface{}, typeStr string) []*route53.ResourceRecord {
records := make([]*route53.ResourceRecord, 0, len(recs))
for _, r := range recs {
s := r.(string)
switch typeStr {
case "TXT", "SPF":
str := fmt.Sprintf("\"%s\"", s)
records = append(records, &route53.ResourceRecord{Value: aws.String(str)})
default:
records = append(records, &route53.ResourceRecord{Value: aws.String(s)})
}
}
return records
}
func expandESClusterConfig(m map[string]interface{}) *elasticsearch.ElasticsearchClusterConfig {
config := elasticsearch.ElasticsearchClusterConfig{}
if v, ok := m["dedicated_master_enabled"]; ok {
isEnabled := v.(bool)
config.DedicatedMasterEnabled = aws.Bool(isEnabled)
if isEnabled {
if v, ok := m["dedicated_master_count"]; ok && v.(int) > 0 {
config.DedicatedMasterCount = aws.Int64(int64(v.(int)))
}
if v, ok := m["dedicated_master_type"]; ok && v.(string) != "" {
config.DedicatedMasterType = aws.String(v.(string))
}
}
}
if v, ok := m["instance_count"]; ok {
config.InstanceCount = aws.Int64(int64(v.(int)))
}
if v, ok := m["instance_type"]; ok {
config.InstanceType = aws.String(v.(string))
}
if v, ok := m["zone_awareness_enabled"]; ok {
config.ZoneAwarenessEnabled = aws.Bool(v.(bool))
}
return &config
}
func flattenESClusterConfig(c *elasticsearch.ElasticsearchClusterConfig) []map[string]interface{} {
m := map[string]interface{}{}
if c.DedicatedMasterCount != nil {
m["dedicated_master_count"] = *c.DedicatedMasterCount
}
if c.DedicatedMasterEnabled != nil {
m["dedicated_master_enabled"] = *c.DedicatedMasterEnabled
}
if c.DedicatedMasterType != nil {
m["dedicated_master_type"] = *c.DedicatedMasterType
}
if c.InstanceCount != nil {
m["instance_count"] = *c.InstanceCount
}
if c.InstanceType != nil {
m["instance_type"] = *c.InstanceType
}
if c.ZoneAwarenessEnabled != nil {
m["zone_awareness_enabled"] = *c.ZoneAwarenessEnabled
}
return []map[string]interface{}{m}
}
func flattenESEBSOptions(o *elasticsearch.EBSOptions) []map[string]interface{} {
m := map[string]interface{}{}
if o.EBSEnabled != nil {
m["ebs_enabled"] = *o.EBSEnabled
}
if o.Iops != nil {
m["iops"] = *o.Iops
}
if o.VolumeSize != nil {
m["volume_size"] = *o.VolumeSize
}
if o.VolumeType != nil {
m["volume_type"] = *o.VolumeType
}
return []map[string]interface{}{m}
}
func expandESEBSOptions(m map[string]interface{}) *elasticsearch.EBSOptions {
options := elasticsearch.EBSOptions{}
if v, ok := m["ebs_enabled"]; ok {
options.EBSEnabled = aws.Bool(v.(bool))
}
if v, ok := m["iops"]; ok && v.(int) > 0 {
options.Iops = aws.Int64(int64(v.(int)))
}
if v, ok := m["volume_size"]; ok && v.(int) > 0 {
options.VolumeSize = aws.Int64(int64(v.(int)))
}
if v, ok := m["volume_type"]; ok && v.(string) != "" {
options.VolumeType = aws.String(v.(string))
}
return &options
}
func pointersMapToStringList(pointers map[string]*string) map[string]interface{} {
list := make(map[string]interface{}, len(pointers))
for i, v := range pointers {
list[i] = *v
}
return list
}
func stringMapToPointers(m map[string]interface{}) map[string]*string {
list := make(map[string]*string, len(m))
for i, v := range m {
list[i] = aws.String(v.(string))
}
return list
}
func flattenDSVpcSettings(
s *directoryservice.DirectoryVpcSettingsDescription) []map[string]interface{} {
settings := make(map[string]interface{}, 0)
if s == nil {
return nil
}
settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds))
settings["vpc_id"] = *s.VpcId
return []map[string]interface{}{settings}
}
func flattenLambdaVpcConfigResponse(s *lambda.VpcConfigResponse) []map[string]interface{} {
settings := make(map[string]interface{}, 0)
if s == nil {
return nil
}
if len(s.SubnetIds) == 0 && len(s.SecurityGroupIds) == 0 && s.VpcId == nil {
return nil
}
settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds))
settings["security_group_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SecurityGroupIds))
if s.VpcId != nil {
settings["vpc_id"] = *s.VpcId
}
return []map[string]interface{}{settings}
}
func flattenDSConnectSettings(
customerDnsIps []*string,
s *directoryservice.DirectoryConnectSettingsDescription) []map[string]interface{} {
if s == nil {
return nil
}
settings := make(map[string]interface{}, 0)
settings["customer_dns_ips"] = schema.NewSet(schema.HashString, flattenStringList(customerDnsIps))
settings["connect_ips"] = schema.NewSet(schema.HashString, flattenStringList(s.ConnectIps))
settings["customer_username"] = *s.CustomerUserName
settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds))
settings["vpc_id"] = *s.VpcId
return []map[string]interface{}{settings}
}
func expandCloudFormationParameters(params map[string]interface{}) []*cloudformation.Parameter {
var cfParams []*cloudformation.Parameter
for k, v := range params {
cfParams = append(cfParams, &cloudformation.Parameter{
ParameterKey: aws.String(k),
ParameterValue: aws.String(v.(string)),
})
}
return cfParams
}
// flattenCloudFormationParameters is flattening list of
// *cloudformation.Parameters and only returning existing
// parameters to avoid clash with default values
func flattenCloudFormationParameters(cfParams []*cloudformation.Parameter,
originalParams map[string]interface{}) map[string]interface{} {
params := make(map[string]interface{}, len(cfParams))
for _, p := range cfParams {
_, isConfigured := originalParams[*p.ParameterKey]
if isConfigured {
params[*p.ParameterKey] = *p.ParameterValue
}
}
return params
}
func expandCloudFormationTags(tags map[string]interface{}) []*cloudformation.Tag {
var cfTags []*cloudformation.Tag
for k, v := range tags {
cfTags = append(cfTags, &cloudformation.Tag{
Key: aws.String(k),
Value: aws.String(v.(string)),
})
}
return cfTags
}
func flattenCloudFormationTags(cfTags []*cloudformation.Tag) map[string]string {
tags := make(map[string]string, len(cfTags))
for _, t := range cfTags {
tags[*t.Key] = *t.Value
}
return tags
}
func flattenCloudFormationOutputs(cfOutputs []*cloudformation.Output) map[string]string {
outputs := make(map[string]string, len(cfOutputs))
for _, o := range cfOutputs {
outputs[*o.OutputKey] = *o.OutputValue
}
return outputs
}
func flattenAsgEnabledMetrics(list []*autoscaling.EnabledMetric) []string {
strs := make([]string, 0, len(list))
for _, r := range list {
if r.Metric != nil {
strs = append(strs, *r.Metric)
}
}
return strs
}
func expandApiGatewayStageKeys(d *schema.ResourceData) []*apigateway.StageKey {
var stageKeys []*apigateway.StageKey
if stageKeyData, ok := d.GetOk("stage_key"); ok {
params := stageKeyData.(*schema.Set).List()
for k := range params {
data := params[k].(map[string]interface{})
stageKeys = append(stageKeys, &apigateway.StageKey{
RestApiId: aws.String(data["rest_api_id"].(string)),
StageName: aws.String(data["stage_name"].(string)),
})
}
}
return stageKeys
}
func expandApiGatewayRequestResponseModelOperations(d *schema.ResourceData, key string, prefix string) []*apigateway.PatchOperation {
operations := make([]*apigateway.PatchOperation, 0)
oldModels, newModels := d.GetChange(key)
oldModelMap := oldModels.(map[string]interface{})
newModelMap := newModels.(map[string]interface{})
for k, _ := range oldModelMap {
operation := apigateway.PatchOperation{
Op: aws.String("remove"),
Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))),
}
for nK, nV := range newModelMap {
if nK == k {
operation.Op = aws.String("replace")
operation.Value = aws.String(nV.(string))
}
}
operations = append(operations, &operation)
}
for nK, nV := range newModelMap {
exists := false
for k, _ := range oldModelMap {
if k == nK {
exists = true
}
}
if !exists {
operation := apigateway.PatchOperation{
Op: aws.String("add"),
Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(nK, "/", "~1", -1))),
Value: aws.String(nV.(string)),
}
operations = append(operations, &operation)
}
}
return operations
}
func expandApiGatewayMethodParametersJSONOperations(d *schema.ResourceData, key string, prefix string) ([]*apigateway.PatchOperation, error) {
operations := make([]*apigateway.PatchOperation, 0)
oldParameters, newParameters := d.GetChange(key)
oldParametersMap := make(map[string]interface{})
newParametersMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(oldParameters.(string)), &oldParametersMap); err != nil {
err := fmt.Errorf("Error unmarshaling old %s: %s", key, err)
return operations, err
}
if err := json.Unmarshal([]byte(newParameters.(string)), &newParametersMap); err != nil {
err := fmt.Errorf("Error unmarshaling new %s: %s", key, err)
return operations, err
}
for k, _ := range oldParametersMap {
operation := apigateway.PatchOperation{
Op: aws.String("remove"),
Path: aws.String(fmt.Sprintf("/%s/%s", prefix, k)),
}
for nK, nV := range newParametersMap {
if nK == k {
operation.Op = aws.String("replace")
operation.Value = aws.String(strconv.FormatBool(nV.(bool)))
}
}
operations = append(operations, &operation)
}
for nK, nV := range newParametersMap {
exists := false
for k, _ := range oldParametersMap {
if k == nK {
exists = true
}
}
if !exists {
operation := apigateway.PatchOperation{
Op: aws.String("add"),
Path: aws.String(fmt.Sprintf("/%s/%s", prefix, nK)),
Value: aws.String(strconv.FormatBool(nV.(bool))),
}
operations = append(operations, &operation)
}
}
return operations, nil
}
func expandApiGatewayStageKeyOperations(d *schema.ResourceData) []*apigateway.PatchOperation {
operations := make([]*apigateway.PatchOperation, 0)
prev, curr := d.GetChange("stage_key")
prevList := prev.(*schema.Set).List()
currList := curr.(*schema.Set).List()
for i := range prevList {
p := prevList[i].(map[string]interface{})
exists := false
for j := range currList {
c := currList[j].(map[string]interface{})
if c["rest_api_id"].(string) == p["rest_api_id"].(string) && c["stage_name"].(string) == p["stage_name"].(string) {
exists = true
}
}
if !exists {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("remove"),
Path: aws.String("/stages"),
Value: aws.String(fmt.Sprintf("%s/%s", p["rest_api_id"].(string), p["stage_name"].(string))),
})
}
}
for i := range currList {
c := currList[i].(map[string]interface{})
exists := false
for j := range prevList {
p := prevList[j].(map[string]interface{})
if c["rest_api_id"].(string) == p["rest_api_id"].(string) && c["stage_name"].(string) == p["stage_name"].(string) {
exists = true
}
}
if !exists {
operations = append(operations, &apigateway.PatchOperation{
Op: aws.String("add"),
Path: aws.String("/stages"),
Value: aws.String(fmt.Sprintf("%s/%s", c["rest_api_id"].(string), c["stage_name"].(string))),
})
}
}
return operations
}
func expandCloudWachLogMetricTransformations(m map[string]interface{}) []*cloudwatchlogs.MetricTransformation {
transformation := cloudwatchlogs.MetricTransformation{
MetricName: aws.String(m["name"].(string)),
MetricNamespace: aws.String(m["namespace"].(string)),
MetricValue: aws.String(m["value"].(string)),
}
return []*cloudwatchlogs.MetricTransformation{&transformation}
}
func flattenCloudWachLogMetricTransformations(ts []*cloudwatchlogs.MetricTransformation) map[string]string {
m := make(map[string]string, 0)
m["name"] = *ts[0].MetricName
m["namespace"] = *ts[0].MetricNamespace
m["value"] = *ts[0].MetricValue
return m
}
func flattenBeanstalkAsg(list []*elasticbeanstalk.AutoScalingGroup) []string {
strs := make([]string, 0, len(list))
for _, r := range list {
if r.Name != nil {
strs = append(strs, *r.Name)
}
}
return strs
}
func flattenBeanstalkInstances(list []*elasticbeanstalk.Instance) []string {
strs := make([]string, 0, len(list))
for _, r := range list {
if r.Id != nil {
strs = append(strs, *r.Id)
}
}
return strs
}
func flattenBeanstalkLc(list []*elasticbeanstalk.LaunchConfiguration) []string {
strs := make([]string, 0, len(list))
for _, r := range list {
if r.Name != nil {
strs = append(strs, *r.Name)
}
}
return strs
}
func flattenBeanstalkElb(list []*elasticbeanstalk.LoadBalancer) []string {
strs := make([]string, 0, len(list))
for _, r := range list {
if r.Name != nil {
strs = append(strs, *r.Name)
}
}
return strs
}
func flattenBeanstalkSqs(list []*elasticbeanstalk.Queue) []string {
strs := make([]string, 0, len(list))
for _, r := range list {
if r.URL != nil {
strs = append(strs, *r.URL)
}
}
return strs
}
func flattenBeanstalkTrigger(list []*elasticbeanstalk.Trigger) []string {
strs := make([]string, 0, len(list))
for _, r := range list {
if r.Name != nil {
strs = append(strs, *r.Name)
}
}
return strs
}
// There are several parts of the AWS API that will sort lists of strings,
// causing diffs inbetweeen resources that use lists. This avoids a bit of
// code duplication for pre-sorts that can be used for things like hash
// functions, etc.
func sortInterfaceSlice(in []interface{}) []interface{} {
a := []string{}
b := []interface{}{}
for _, v := range in {
a = append(a, v.(string))
}
sort.Strings(a)
for _, v := range a {
b = append(b, v)
}
return b
}
func flattenApiGatewayThrottleSettings(settings *apigateway.ThrottleSettings) []map[string]interface{} {
result := make([]map[string]interface{}, 0, 1)
if settings != nil {
r := make(map[string]interface{})
if settings.BurstLimit != nil {
r["burst_limit"] = *settings.BurstLimit
}
if settings.RateLimit != nil {
r["rate_limit"] = *settings.RateLimit
}
result = append(result, r)
}
return result
}