github.com/joshgarnett/terraform@v0.5.4-0.20160219181435-92dc20bb3594/builtin/providers/aws/structure.go (about)

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