github.com/ricardclau/terraform@v0.6.17-0.20160519222547-283e3ae6b5a9/builtin/providers/aws/structure.go (about)

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