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