github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/structure_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"reflect"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	"github.com/aws/aws-sdk-go/service/apigateway"
    10  	"github.com/aws/aws-sdk-go/service/autoscaling"
    11  	"github.com/aws/aws-sdk-go/service/ec2"
    12  	"github.com/aws/aws-sdk-go/service/elasticache"
    13  	"github.com/aws/aws-sdk-go/service/elb"
    14  	"github.com/aws/aws-sdk-go/service/kinesis"
    15  	"github.com/aws/aws-sdk-go/service/rds"
    16  	"github.com/aws/aws-sdk-go/service/redshift"
    17  	"github.com/aws/aws-sdk-go/service/route53"
    18  	"github.com/hashicorp/terraform/flatmap"
    19  	"github.com/hashicorp/terraform/helper/schema"
    20  )
    21  
    22  // Returns test configuration
    23  func testConf() map[string]string {
    24  	return map[string]string{
    25  		"listener.#":                   "1",
    26  		"listener.0.lb_port":           "80",
    27  		"listener.0.lb_protocol":       "http",
    28  		"listener.0.instance_port":     "8000",
    29  		"listener.0.instance_protocol": "http",
    30  		"availability_zones.#":         "2",
    31  		"availability_zones.0":         "us-east-1a",
    32  		"availability_zones.1":         "us-east-1b",
    33  		"ingress.#":                    "1",
    34  		"ingress.0.protocol":           "icmp",
    35  		"ingress.0.from_port":          "1",
    36  		"ingress.0.to_port":            "-1",
    37  		"ingress.0.cidr_blocks.#":      "1",
    38  		"ingress.0.cidr_blocks.0":      "0.0.0.0/0",
    39  		"ingress.0.security_groups.#":  "2",
    40  		"ingress.0.security_groups.0":  "sg-11111",
    41  		"ingress.0.security_groups.1":  "foo/sg-22222",
    42  	}
    43  }
    44  
    45  func TestExpandIPPerms(t *testing.T) {
    46  	hash := schema.HashString
    47  
    48  	expanded := []interface{}{
    49  		map[string]interface{}{
    50  			"protocol":    "icmp",
    51  			"from_port":   1,
    52  			"to_port":     -1,
    53  			"cidr_blocks": []interface{}{"0.0.0.0/0"},
    54  			"security_groups": schema.NewSet(hash, []interface{}{
    55  				"sg-11111",
    56  				"foo/sg-22222",
    57  			}),
    58  		},
    59  		map[string]interface{}{
    60  			"protocol":  "icmp",
    61  			"from_port": 1,
    62  			"to_port":   -1,
    63  			"self":      true,
    64  		},
    65  	}
    66  	group := &ec2.SecurityGroup{
    67  		GroupId: aws.String("foo"),
    68  		VpcId:   aws.String("bar"),
    69  	}
    70  	perms, err := expandIPPerms(group, expanded)
    71  	if err != nil {
    72  		t.Fatalf("error expanding perms: %v", err)
    73  	}
    74  
    75  	expected := []ec2.IpPermission{
    76  		ec2.IpPermission{
    77  			IpProtocol: aws.String("icmp"),
    78  			FromPort:   aws.Int64(int64(1)),
    79  			ToPort:     aws.Int64(int64(-1)),
    80  			IpRanges:   []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}},
    81  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
    82  				&ec2.UserIdGroupPair{
    83  					UserId:  aws.String("foo"),
    84  					GroupId: aws.String("sg-22222"),
    85  				},
    86  				&ec2.UserIdGroupPair{
    87  					GroupId: aws.String("sg-11111"),
    88  				},
    89  			},
    90  		},
    91  		ec2.IpPermission{
    92  			IpProtocol: aws.String("icmp"),
    93  			FromPort:   aws.Int64(int64(1)),
    94  			ToPort:     aws.Int64(int64(-1)),
    95  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
    96  				&ec2.UserIdGroupPair{
    97  					GroupId: aws.String("foo"),
    98  				},
    99  			},
   100  		},
   101  	}
   102  
   103  	exp := expected[0]
   104  	perm := perms[0]
   105  
   106  	if *exp.FromPort != *perm.FromPort {
   107  		t.Fatalf(
   108  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   109  			*perm.FromPort,
   110  			*exp.FromPort)
   111  	}
   112  
   113  	if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp {
   114  		t.Fatalf(
   115  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   116  			*perm.IpRanges[0].CidrIp,
   117  			*exp.IpRanges[0].CidrIp)
   118  	}
   119  
   120  	if *exp.UserIdGroupPairs[0].UserId != *perm.UserIdGroupPairs[0].UserId {
   121  		t.Fatalf(
   122  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   123  			*perm.UserIdGroupPairs[0].UserId,
   124  			*exp.UserIdGroupPairs[0].UserId)
   125  	}
   126  
   127  	if *exp.UserIdGroupPairs[0].GroupId != *perm.UserIdGroupPairs[0].GroupId {
   128  		t.Fatalf(
   129  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   130  			*perm.UserIdGroupPairs[0].GroupId,
   131  			*exp.UserIdGroupPairs[0].GroupId)
   132  	}
   133  
   134  	if *exp.UserIdGroupPairs[1].GroupId != *perm.UserIdGroupPairs[1].GroupId {
   135  		t.Fatalf(
   136  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   137  			*perm.UserIdGroupPairs[1].GroupId,
   138  			*exp.UserIdGroupPairs[1].GroupId)
   139  	}
   140  
   141  	exp = expected[1]
   142  	perm = perms[1]
   143  
   144  	if *exp.UserIdGroupPairs[0].GroupId != *perm.UserIdGroupPairs[0].GroupId {
   145  		t.Fatalf(
   146  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   147  			*perm.UserIdGroupPairs[0].GroupId,
   148  			*exp.UserIdGroupPairs[0].GroupId)
   149  	}
   150  }
   151  
   152  func TestExpandIPPerms_NegOneProtocol(t *testing.T) {
   153  	hash := schema.HashString
   154  
   155  	expanded := []interface{}{
   156  		map[string]interface{}{
   157  			"protocol":    "-1",
   158  			"from_port":   0,
   159  			"to_port":     0,
   160  			"cidr_blocks": []interface{}{"0.0.0.0/0"},
   161  			"security_groups": schema.NewSet(hash, []interface{}{
   162  				"sg-11111",
   163  				"foo/sg-22222",
   164  			}),
   165  		},
   166  	}
   167  	group := &ec2.SecurityGroup{
   168  		GroupId: aws.String("foo"),
   169  		VpcId:   aws.String("bar"),
   170  	}
   171  
   172  	perms, err := expandIPPerms(group, expanded)
   173  	if err != nil {
   174  		t.Fatalf("error expanding perms: %v", err)
   175  	}
   176  
   177  	expected := []ec2.IpPermission{
   178  		ec2.IpPermission{
   179  			IpProtocol: aws.String("-1"),
   180  			FromPort:   aws.Int64(int64(0)),
   181  			ToPort:     aws.Int64(int64(0)),
   182  			IpRanges:   []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}},
   183  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
   184  				&ec2.UserIdGroupPair{
   185  					UserId:  aws.String("foo"),
   186  					GroupId: aws.String("sg-22222"),
   187  				},
   188  				&ec2.UserIdGroupPair{
   189  					GroupId: aws.String("sg-11111"),
   190  				},
   191  			},
   192  		},
   193  	}
   194  
   195  	exp := expected[0]
   196  	perm := perms[0]
   197  
   198  	if *exp.FromPort != *perm.FromPort {
   199  		t.Fatalf(
   200  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   201  			*perm.FromPort,
   202  			*exp.FromPort)
   203  	}
   204  
   205  	if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp {
   206  		t.Fatalf(
   207  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   208  			*perm.IpRanges[0].CidrIp,
   209  			*exp.IpRanges[0].CidrIp)
   210  	}
   211  
   212  	if *exp.UserIdGroupPairs[0].UserId != *perm.UserIdGroupPairs[0].UserId {
   213  		t.Fatalf(
   214  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   215  			*perm.UserIdGroupPairs[0].UserId,
   216  			*exp.UserIdGroupPairs[0].UserId)
   217  	}
   218  
   219  	// Now test the error case. This *should* error when either from_port
   220  	// or to_port is not zero, but protocol is "-1".
   221  	errorCase := []interface{}{
   222  		map[string]interface{}{
   223  			"protocol":    "-1",
   224  			"from_port":   0,
   225  			"to_port":     65535,
   226  			"cidr_blocks": []interface{}{"0.0.0.0/0"},
   227  			"security_groups": schema.NewSet(hash, []interface{}{
   228  				"sg-11111",
   229  				"foo/sg-22222",
   230  			}),
   231  		},
   232  	}
   233  	securityGroups := &ec2.SecurityGroup{
   234  		GroupId: aws.String("foo"),
   235  		VpcId:   aws.String("bar"),
   236  	}
   237  
   238  	_, expandErr := expandIPPerms(securityGroups, errorCase)
   239  	if expandErr == nil {
   240  		t.Fatal("expandIPPerms should have errored!")
   241  	}
   242  }
   243  
   244  func TestExpandIPPerms_nonVPC(t *testing.T) {
   245  	hash := schema.HashString
   246  
   247  	expanded := []interface{}{
   248  		map[string]interface{}{
   249  			"protocol":    "icmp",
   250  			"from_port":   1,
   251  			"to_port":     -1,
   252  			"cidr_blocks": []interface{}{"0.0.0.0/0"},
   253  			"security_groups": schema.NewSet(hash, []interface{}{
   254  				"sg-11111",
   255  				"foo/sg-22222",
   256  			}),
   257  		},
   258  		map[string]interface{}{
   259  			"protocol":  "icmp",
   260  			"from_port": 1,
   261  			"to_port":   -1,
   262  			"self":      true,
   263  		},
   264  	}
   265  	group := &ec2.SecurityGroup{
   266  		GroupName: aws.String("foo"),
   267  	}
   268  	perms, err := expandIPPerms(group, expanded)
   269  	if err != nil {
   270  		t.Fatalf("error expanding perms: %v", err)
   271  	}
   272  
   273  	expected := []ec2.IpPermission{
   274  		ec2.IpPermission{
   275  			IpProtocol: aws.String("icmp"),
   276  			FromPort:   aws.Int64(int64(1)),
   277  			ToPort:     aws.Int64(int64(-1)),
   278  			IpRanges:   []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}},
   279  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
   280  				&ec2.UserIdGroupPair{
   281  					GroupName: aws.String("sg-22222"),
   282  				},
   283  				&ec2.UserIdGroupPair{
   284  					GroupName: aws.String("sg-11111"),
   285  				},
   286  			},
   287  		},
   288  		ec2.IpPermission{
   289  			IpProtocol: aws.String("icmp"),
   290  			FromPort:   aws.Int64(int64(1)),
   291  			ToPort:     aws.Int64(int64(-1)),
   292  			UserIdGroupPairs: []*ec2.UserIdGroupPair{
   293  				&ec2.UserIdGroupPair{
   294  					GroupName: aws.String("foo"),
   295  				},
   296  			},
   297  		},
   298  	}
   299  
   300  	exp := expected[0]
   301  	perm := perms[0]
   302  
   303  	if *exp.FromPort != *perm.FromPort {
   304  		t.Fatalf(
   305  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   306  			*perm.FromPort,
   307  			*exp.FromPort)
   308  	}
   309  
   310  	if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp {
   311  		t.Fatalf(
   312  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   313  			*perm.IpRanges[0].CidrIp,
   314  			*exp.IpRanges[0].CidrIp)
   315  	}
   316  
   317  	if *exp.UserIdGroupPairs[0].GroupName != *perm.UserIdGroupPairs[0].GroupName {
   318  		t.Fatalf(
   319  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   320  			*perm.UserIdGroupPairs[0].GroupName,
   321  			*exp.UserIdGroupPairs[0].GroupName)
   322  	}
   323  
   324  	if *exp.UserIdGroupPairs[1].GroupName != *perm.UserIdGroupPairs[1].GroupName {
   325  		t.Fatalf(
   326  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   327  			*perm.UserIdGroupPairs[1].GroupName,
   328  			*exp.UserIdGroupPairs[1].GroupName)
   329  	}
   330  
   331  	exp = expected[1]
   332  	perm = perms[1]
   333  
   334  	if *exp.UserIdGroupPairs[0].GroupName != *perm.UserIdGroupPairs[0].GroupName {
   335  		t.Fatalf(
   336  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   337  			*perm.UserIdGroupPairs[0].GroupName,
   338  			*exp.UserIdGroupPairs[0].GroupName)
   339  	}
   340  }
   341  
   342  func TestExpandListeners(t *testing.T) {
   343  	expanded := []interface{}{
   344  		map[string]interface{}{
   345  			"instance_port":     8000,
   346  			"lb_port":           80,
   347  			"instance_protocol": "http",
   348  			"lb_protocol":       "http",
   349  		},
   350  		map[string]interface{}{
   351  			"instance_port":      8000,
   352  			"lb_port":            80,
   353  			"instance_protocol":  "https",
   354  			"lb_protocol":        "https",
   355  			"ssl_certificate_id": "something",
   356  		},
   357  	}
   358  	listeners, err := expandListeners(expanded)
   359  	if err != nil {
   360  		t.Fatalf("bad: %#v", err)
   361  	}
   362  
   363  	expected := &elb.Listener{
   364  		InstancePort:     aws.Int64(int64(8000)),
   365  		LoadBalancerPort: aws.Int64(int64(80)),
   366  		InstanceProtocol: aws.String("http"),
   367  		Protocol:         aws.String("http"),
   368  	}
   369  
   370  	if !reflect.DeepEqual(listeners[0], expected) {
   371  		t.Fatalf(
   372  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   373  			listeners[0],
   374  			expected)
   375  	}
   376  }
   377  
   378  // this test should produce an error from expandlisteners on an invalid
   379  // combination
   380  func TestExpandListeners_invalid(t *testing.T) {
   381  	expanded := []interface{}{
   382  		map[string]interface{}{
   383  			"instance_port":      8000,
   384  			"lb_port":            80,
   385  			"instance_protocol":  "http",
   386  			"lb_protocol":        "http",
   387  			"ssl_certificate_id": "something",
   388  		},
   389  	}
   390  	_, err := expandListeners(expanded)
   391  	if err != nil {
   392  		// Check the error we got
   393  		if !strings.Contains(err.Error(), "ssl_certificate_id may be set only when protocol") {
   394  			t.Fatalf("Got error in TestExpandListeners_invalid, but not what we expected: %s", err)
   395  		}
   396  	}
   397  
   398  	if err == nil {
   399  		t.Fatalf("Expected TestExpandListeners_invalid to fail, but passed")
   400  	}
   401  }
   402  
   403  func TestFlattenHealthCheck(t *testing.T) {
   404  	cases := []struct {
   405  		Input  *elb.HealthCheck
   406  		Output []map[string]interface{}
   407  	}{
   408  		{
   409  			Input: &elb.HealthCheck{
   410  				UnhealthyThreshold: aws.Int64(int64(10)),
   411  				HealthyThreshold:   aws.Int64(int64(10)),
   412  				Target:             aws.String("HTTP:80/"),
   413  				Timeout:            aws.Int64(int64(30)),
   414  				Interval:           aws.Int64(int64(30)),
   415  			},
   416  			Output: []map[string]interface{}{
   417  				map[string]interface{}{
   418  					"unhealthy_threshold": int64(10),
   419  					"healthy_threshold":   int64(10),
   420  					"target":              "HTTP:80/",
   421  					"timeout":             int64(30),
   422  					"interval":            int64(30),
   423  				},
   424  			},
   425  		},
   426  	}
   427  
   428  	for _, tc := range cases {
   429  		output := flattenHealthCheck(tc.Input)
   430  		if !reflect.DeepEqual(output, tc.Output) {
   431  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
   432  		}
   433  	}
   434  }
   435  
   436  func TestExpandStringList(t *testing.T) {
   437  	expanded := flatmap.Expand(testConf(), "availability_zones").([]interface{})
   438  	stringList := expandStringList(expanded)
   439  	expected := []*string{
   440  		aws.String("us-east-1a"),
   441  		aws.String("us-east-1b"),
   442  	}
   443  
   444  	if !reflect.DeepEqual(stringList, expected) {
   445  		t.Fatalf(
   446  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   447  			stringList,
   448  			expected)
   449  	}
   450  
   451  }
   452  
   453  func TestExpandParameters(t *testing.T) {
   454  	expanded := []interface{}{
   455  		map[string]interface{}{
   456  			"name":         "character_set_client",
   457  			"value":        "utf8",
   458  			"apply_method": "immediate",
   459  		},
   460  	}
   461  	parameters, err := expandParameters(expanded)
   462  	if err != nil {
   463  		t.Fatalf("bad: %#v", err)
   464  	}
   465  
   466  	expected := &rds.Parameter{
   467  		ParameterName:  aws.String("character_set_client"),
   468  		ParameterValue: aws.String("utf8"),
   469  		ApplyMethod:    aws.String("immediate"),
   470  	}
   471  
   472  	if !reflect.DeepEqual(parameters[0], expected) {
   473  		t.Fatalf(
   474  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   475  			parameters[0],
   476  			expected)
   477  	}
   478  }
   479  
   480  func TestExpandRedshiftParameters(t *testing.T) {
   481  	expanded := []interface{}{
   482  		map[string]interface{}{
   483  			"name":  "character_set_client",
   484  			"value": "utf8",
   485  		},
   486  	}
   487  	parameters, err := expandRedshiftParameters(expanded)
   488  	if err != nil {
   489  		t.Fatalf("bad: %#v", err)
   490  	}
   491  
   492  	expected := &redshift.Parameter{
   493  		ParameterName:  aws.String("character_set_client"),
   494  		ParameterValue: aws.String("utf8"),
   495  	}
   496  
   497  	if !reflect.DeepEqual(parameters[0], expected) {
   498  		t.Fatalf(
   499  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   500  			parameters[0],
   501  			expected)
   502  	}
   503  }
   504  
   505  func TestExpandElasticacheParameters(t *testing.T) {
   506  	expanded := []interface{}{
   507  		map[string]interface{}{
   508  			"name":         "activerehashing",
   509  			"value":        "yes",
   510  			"apply_method": "immediate",
   511  		},
   512  	}
   513  	parameters, err := expandElastiCacheParameters(expanded)
   514  	if err != nil {
   515  		t.Fatalf("bad: %#v", err)
   516  	}
   517  
   518  	expected := &elasticache.ParameterNameValue{
   519  		ParameterName:  aws.String("activerehashing"),
   520  		ParameterValue: aws.String("yes"),
   521  	}
   522  
   523  	if !reflect.DeepEqual(parameters[0], expected) {
   524  		t.Fatalf(
   525  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   526  			parameters[0],
   527  			expected)
   528  	}
   529  }
   530  
   531  func TestExpandStepAdjustments(t *testing.T) {
   532  	expanded := []interface{}{
   533  		map[string]interface{}{
   534  			"metric_interval_lower_bound": "1.0",
   535  			"metric_interval_upper_bound": "2.0",
   536  			"scaling_adjustment":          1,
   537  		},
   538  	}
   539  	parameters, err := expandStepAdjustments(expanded)
   540  	if err != nil {
   541  		t.Fatalf("bad: %#v", err)
   542  	}
   543  
   544  	expected := &autoscaling.StepAdjustment{
   545  		MetricIntervalLowerBound: aws.Float64(1.0),
   546  		MetricIntervalUpperBound: aws.Float64(2.0),
   547  		ScalingAdjustment:        aws.Int64(int64(1)),
   548  	}
   549  
   550  	if !reflect.DeepEqual(parameters[0], expected) {
   551  		t.Fatalf(
   552  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   553  			parameters[0],
   554  			expected)
   555  	}
   556  }
   557  
   558  func TestFlattenParameters(t *testing.T) {
   559  	cases := []struct {
   560  		Input  []*rds.Parameter
   561  		Output []map[string]interface{}
   562  	}{
   563  		{
   564  			Input: []*rds.Parameter{
   565  				&rds.Parameter{
   566  					ParameterName:  aws.String("character_set_client"),
   567  					ParameterValue: aws.String("utf8"),
   568  				},
   569  			},
   570  			Output: []map[string]interface{}{
   571  				map[string]interface{}{
   572  					"name":  "character_set_client",
   573  					"value": "utf8",
   574  				},
   575  			},
   576  		},
   577  	}
   578  
   579  	for _, tc := range cases {
   580  		output := flattenParameters(tc.Input)
   581  		if !reflect.DeepEqual(output, tc.Output) {
   582  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
   583  		}
   584  	}
   585  }
   586  
   587  func TestFlattenRedshiftParameters(t *testing.T) {
   588  	cases := []struct {
   589  		Input  []*redshift.Parameter
   590  		Output []map[string]interface{}
   591  	}{
   592  		{
   593  			Input: []*redshift.Parameter{
   594  				&redshift.Parameter{
   595  					ParameterName:  aws.String("character_set_client"),
   596  					ParameterValue: aws.String("utf8"),
   597  				},
   598  			},
   599  			Output: []map[string]interface{}{
   600  				map[string]interface{}{
   601  					"name":  "character_set_client",
   602  					"value": "utf8",
   603  				},
   604  			},
   605  		},
   606  	}
   607  
   608  	for _, tc := range cases {
   609  		output := flattenRedshiftParameters(tc.Input)
   610  		if !reflect.DeepEqual(output, tc.Output) {
   611  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
   612  		}
   613  	}
   614  }
   615  
   616  func TestFlattenElasticacheParameters(t *testing.T) {
   617  	cases := []struct {
   618  		Input  []*elasticache.Parameter
   619  		Output []map[string]interface{}
   620  	}{
   621  		{
   622  			Input: []*elasticache.Parameter{
   623  				&elasticache.Parameter{
   624  					ParameterName:  aws.String("activerehashing"),
   625  					ParameterValue: aws.String("yes"),
   626  				},
   627  			},
   628  			Output: []map[string]interface{}{
   629  				map[string]interface{}{
   630  					"name":  "activerehashing",
   631  					"value": "yes",
   632  				},
   633  			},
   634  		},
   635  	}
   636  
   637  	for _, tc := range cases {
   638  		output := flattenElastiCacheParameters(tc.Input)
   639  		if !reflect.DeepEqual(output, tc.Output) {
   640  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
   641  		}
   642  	}
   643  }
   644  
   645  func TestExpandInstanceString(t *testing.T) {
   646  
   647  	expected := []*elb.Instance{
   648  		&elb.Instance{InstanceId: aws.String("test-one")},
   649  		&elb.Instance{InstanceId: aws.String("test-two")},
   650  	}
   651  
   652  	ids := []interface{}{
   653  		"test-one",
   654  		"test-two",
   655  	}
   656  
   657  	expanded := expandInstanceString(ids)
   658  
   659  	if !reflect.DeepEqual(expanded, expected) {
   660  		t.Fatalf("Expand Instance String output did not match.\nGot:\n%#v\n\nexpected:\n%#v", expanded, expected)
   661  	}
   662  }
   663  
   664  func TestFlattenNetworkInterfacesPrivateIPAddresses(t *testing.T) {
   665  	expanded := []*ec2.NetworkInterfacePrivateIpAddress{
   666  		&ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.1")},
   667  		&ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.2")},
   668  	}
   669  
   670  	result := flattenNetworkInterfacesPrivateIPAddresses(expanded)
   671  
   672  	if result == nil {
   673  		t.Fatal("result was nil")
   674  	}
   675  
   676  	if len(result) != 2 {
   677  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   678  	}
   679  
   680  	if result[0] != "192.168.0.1" {
   681  		t.Fatalf("expected ip to be 192.168.0.1, but was %s", result[0])
   682  	}
   683  
   684  	if result[1] != "192.168.0.2" {
   685  		t.Fatalf("expected ip to be 192.168.0.2, but was %s", result[1])
   686  	}
   687  }
   688  
   689  func TestFlattenGroupIdentifiers(t *testing.T) {
   690  	expanded := []*ec2.GroupIdentifier{
   691  		&ec2.GroupIdentifier{GroupId: aws.String("sg-001")},
   692  		&ec2.GroupIdentifier{GroupId: aws.String("sg-002")},
   693  	}
   694  
   695  	result := flattenGroupIdentifiers(expanded)
   696  
   697  	if len(result) != 2 {
   698  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   699  	}
   700  
   701  	if result[0] != "sg-001" {
   702  		t.Fatalf("expected id to be sg-001, but was %s", result[0])
   703  	}
   704  
   705  	if result[1] != "sg-002" {
   706  		t.Fatalf("expected id to be sg-002, but was %s", result[1])
   707  	}
   708  }
   709  
   710  func TestExpandPrivateIPAddresses(t *testing.T) {
   711  
   712  	ip1 := "192.168.0.1"
   713  	ip2 := "192.168.0.2"
   714  	flattened := []interface{}{
   715  		ip1,
   716  		ip2,
   717  	}
   718  
   719  	result := expandPrivateIPAddresses(flattened)
   720  
   721  	if len(result) != 2 {
   722  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   723  	}
   724  
   725  	if *result[0].PrivateIpAddress != "192.168.0.1" || !*result[0].Primary {
   726  		t.Fatalf("expected ip to be 192.168.0.1 and Primary, but got %v, %t", *result[0].PrivateIpAddress, *result[0].Primary)
   727  	}
   728  
   729  	if *result[1].PrivateIpAddress != "192.168.0.2" || *result[1].Primary {
   730  		t.Fatalf("expected ip to be 192.168.0.2 and not Primary, but got %v, %t", *result[1].PrivateIpAddress, *result[1].Primary)
   731  	}
   732  }
   733  
   734  func TestFlattenAttachment(t *testing.T) {
   735  	expanded := &ec2.NetworkInterfaceAttachment{
   736  		InstanceId:   aws.String("i-00001"),
   737  		DeviceIndex:  aws.Int64(int64(1)),
   738  		AttachmentId: aws.String("at-002"),
   739  	}
   740  
   741  	result := flattenAttachment(expanded)
   742  
   743  	if result == nil {
   744  		t.Fatal("expected result to have value, but got nil")
   745  	}
   746  
   747  	if result["instance"] != "i-00001" {
   748  		t.Fatalf("expected instance to be i-00001, but got %s", result["instance"])
   749  	}
   750  
   751  	if result["device_index"] != int64(1) {
   752  		t.Fatalf("expected device_index to be 1, but got %d", result["device_index"])
   753  	}
   754  
   755  	if result["attachment_id"] != "at-002" {
   756  		t.Fatalf("expected attachment_id to be at-002, but got %s", result["attachment_id"])
   757  	}
   758  }
   759  
   760  func TestFlattenAttachmentWhenNoInstanceId(t *testing.T) {
   761  	expanded := &ec2.NetworkInterfaceAttachment{
   762  		DeviceIndex:  aws.Int64(int64(1)),
   763  		AttachmentId: aws.String("at-002"),
   764  	}
   765  
   766  	result := flattenAttachment(expanded)
   767  
   768  	if result == nil {
   769  		t.Fatal("expected result to have value, but got nil")
   770  	}
   771  
   772  	if result["instance"] != nil {
   773  		t.Fatalf("expected instance to be nil, but got %s", result["instance"])
   774  	}
   775  }
   776  
   777  func TestFlattenStepAdjustments(t *testing.T) {
   778  	expanded := []*autoscaling.StepAdjustment{
   779  		&autoscaling.StepAdjustment{
   780  			MetricIntervalLowerBound: aws.Float64(1.0),
   781  			MetricIntervalUpperBound: aws.Float64(2.0),
   782  			ScalingAdjustment:        aws.Int64(int64(1)),
   783  		},
   784  	}
   785  
   786  	result := flattenStepAdjustments(expanded)[0]
   787  	if result == nil {
   788  		t.Fatal("expected result to have value, but got nil")
   789  	}
   790  	if result["metric_interval_lower_bound"] != float64(1.0) {
   791  		t.Fatalf("expected metric_interval_lower_bound to be 1.0, but got %d", result["metric_interval_lower_bound"])
   792  	}
   793  	if result["metric_interval_upper_bound"] != float64(2.0) {
   794  		t.Fatalf("expected metric_interval_upper_bound to be 1.0, but got %d", result["metric_interval_upper_bound"])
   795  	}
   796  	if result["scaling_adjustment"] != int64(1) {
   797  		t.Fatalf("expected scaling_adjustment to be 1, but got %d", result["scaling_adjustment"])
   798  	}
   799  }
   800  
   801  func TestFlattenResourceRecords(t *testing.T) {
   802  	expanded := []*route53.ResourceRecord{
   803  		&route53.ResourceRecord{
   804  			Value: aws.String("127.0.0.1"),
   805  		},
   806  		&route53.ResourceRecord{
   807  			Value: aws.String("127.0.0.3"),
   808  		},
   809  	}
   810  
   811  	result := flattenResourceRecords(expanded)
   812  
   813  	if result == nil {
   814  		t.Fatal("expected result to have value, but got nil")
   815  	}
   816  
   817  	if len(result) != 2 {
   818  		t.Fatal("expected result to have value, but got nil")
   819  	}
   820  }
   821  
   822  func TestFlattenAsgEnabledMetrics(t *testing.T) {
   823  	expanded := []*autoscaling.EnabledMetric{
   824  		&autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupTotalInstances")},
   825  		&autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupMaxSize")},
   826  	}
   827  
   828  	result := flattenAsgEnabledMetrics(expanded)
   829  
   830  	if len(result) != 2 {
   831  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   832  	}
   833  
   834  	if result[0] != "GroupTotalInstances" {
   835  		t.Fatalf("expected id to be GroupTotalInstances, but was %s", result[0])
   836  	}
   837  
   838  	if result[1] != "GroupMaxSize" {
   839  		t.Fatalf("expected id to be GroupMaxSize, but was %s", result[1])
   840  	}
   841  }
   842  
   843  func TestFlattenKinesisShardLevelMetrics(t *testing.T) {
   844  	expanded := []*kinesis.EnhancedMetrics{
   845  		&kinesis.EnhancedMetrics{
   846  			ShardLevelMetrics: []*string{
   847  				aws.String("IncomingBytes"),
   848  				aws.String("IncomingRecords"),
   849  			},
   850  		},
   851  	}
   852  	result := flattenKinesisShardLevelMetrics(expanded)
   853  	if len(result) != 2 {
   854  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   855  	}
   856  	if result[0] != "IncomingBytes" {
   857  		t.Fatalf("expected element 0 to be IncomingBytes, but was %s", result[0])
   858  	}
   859  	if result[1] != "IncomingRecords" {
   860  		t.Fatalf("expected element 0 to be IncomingRecords, but was %s", result[1])
   861  	}
   862  }
   863  
   864  func TestFlattenSecurityGroups(t *testing.T) {
   865  	cases := []struct {
   866  		ownerId  *string
   867  		pairs    []*ec2.UserIdGroupPair
   868  		expected []*ec2.GroupIdentifier
   869  	}{
   870  		// simple, no user id included (we ignore it mostly)
   871  		{
   872  			ownerId: aws.String("user1234"),
   873  			pairs: []*ec2.UserIdGroupPair{
   874  				&ec2.UserIdGroupPair{
   875  					GroupId: aws.String("sg-12345"),
   876  				},
   877  			},
   878  			expected: []*ec2.GroupIdentifier{
   879  				&ec2.GroupIdentifier{
   880  					GroupId: aws.String("sg-12345"),
   881  				},
   882  			},
   883  		},
   884  		// include the owner id, but keep it consitent with the same account. Tests
   885  		// EC2 classic situation
   886  		{
   887  			ownerId: aws.String("user1234"),
   888  			pairs: []*ec2.UserIdGroupPair{
   889  				&ec2.UserIdGroupPair{
   890  					GroupId: aws.String("sg-12345"),
   891  					UserId:  aws.String("user1234"),
   892  				},
   893  			},
   894  			expected: []*ec2.GroupIdentifier{
   895  				&ec2.GroupIdentifier{
   896  					GroupId: aws.String("sg-12345"),
   897  				},
   898  			},
   899  		},
   900  
   901  		// include the owner id, but from a different account. This is reflects
   902  		// EC2 Classic when referring to groups by name
   903  		{
   904  			ownerId: aws.String("user1234"),
   905  			pairs: []*ec2.UserIdGroupPair{
   906  				&ec2.UserIdGroupPair{
   907  					GroupId:   aws.String("sg-12345"),
   908  					GroupName: aws.String("somegroup"), // GroupName is only included in Classic
   909  					UserId:    aws.String("user4321"),
   910  				},
   911  			},
   912  			expected: []*ec2.GroupIdentifier{
   913  				&ec2.GroupIdentifier{
   914  					GroupId:   aws.String("sg-12345"),
   915  					GroupName: aws.String("user4321/somegroup"),
   916  				},
   917  			},
   918  		},
   919  
   920  		// include the owner id, but from a different account. This reflects in
   921  		// EC2 VPC when referring to groups by id
   922  		{
   923  			ownerId: aws.String("user1234"),
   924  			pairs: []*ec2.UserIdGroupPair{
   925  				&ec2.UserIdGroupPair{
   926  					GroupId: aws.String("sg-12345"),
   927  					UserId:  aws.String("user4321"),
   928  				},
   929  			},
   930  			expected: []*ec2.GroupIdentifier{
   931  				&ec2.GroupIdentifier{
   932  					GroupId: aws.String("user4321/sg-12345"),
   933  				},
   934  			},
   935  		},
   936  	}
   937  
   938  	for _, c := range cases {
   939  		out := flattenSecurityGroups(c.pairs, c.ownerId)
   940  		if !reflect.DeepEqual(out, c.expected) {
   941  			t.Fatalf("Error matching output and expected: %#v vs %#v", out, c.expected)
   942  		}
   943  	}
   944  }
   945  
   946  func TestFlattenApiGatewayThrottleSettings(t *testing.T) {
   947  	expectedBurstLimit := int64(140)
   948  	expectedRateLimit := 120.0
   949  
   950  	ts := &apigateway.ThrottleSettings{
   951  		BurstLimit: aws.Int64(expectedBurstLimit),
   952  		RateLimit:  aws.Float64(expectedRateLimit),
   953  	}
   954  	result := flattenApiGatewayThrottleSettings(ts)
   955  
   956  	if len(result) != 1 {
   957  		t.Fatalf("Expected map to have exactly 1 element, got %d", len(result))
   958  	}
   959  
   960  	burstLimit, ok := result[0]["burst_limit"]
   961  	if !ok {
   962  		t.Fatal("Expected 'burst_limit' key in the map")
   963  	}
   964  	burstLimitInt, ok := burstLimit.(int64)
   965  	if !ok {
   966  		t.Fatal("Expected 'burst_limit' to be int")
   967  	}
   968  	if burstLimitInt != expectedBurstLimit {
   969  		t.Fatalf("Expected 'burst_limit' to equal %d, got %d", expectedBurstLimit, burstLimitInt)
   970  	}
   971  
   972  	rateLimit, ok := result[0]["rate_limit"]
   973  	if !ok {
   974  		t.Fatal("Expected 'rate_limit' key in the map")
   975  	}
   976  	rateLimitFloat, ok := rateLimit.(float64)
   977  	if !ok {
   978  		t.Fatal("Expected 'rate_limit' to be float64")
   979  	}
   980  	if rateLimitFloat != expectedRateLimit {
   981  		t.Fatalf("Expected 'rate_limit' to equal %f, got %f", expectedRateLimit, rateLimitFloat)
   982  	}
   983  }
   984  
   985  func TestFlattenApiGatewayStageKeys(t *testing.T) {
   986  	cases := []struct {
   987  		Input  []*string
   988  		Output []map[string]interface{}
   989  	}{
   990  		{
   991  			Input: []*string{
   992  				aws.String("a1b2c3d4e5/dev"),
   993  				aws.String("e5d4c3b2a1/test"),
   994  			},
   995  			Output: []map[string]interface{}{
   996  				map[string]interface{}{
   997  					"stage_name":  "dev",
   998  					"rest_api_id": "a1b2c3d4e5",
   999  				},
  1000  				map[string]interface{}{
  1001  					"stage_name":  "test",
  1002  					"rest_api_id": "e5d4c3b2a1",
  1003  				},
  1004  			},
  1005  		},
  1006  	}
  1007  
  1008  	for _, tc := range cases {
  1009  		output := flattenApiGatewayStageKeys(tc.Input)
  1010  		if !reflect.DeepEqual(output, tc.Output) {
  1011  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
  1012  		}
  1013  	}
  1014  }
  1015  
  1016  func TestExpandPolicyAttributes(t *testing.T) {
  1017  	expanded := []interface{}{
  1018  		map[string]interface{}{
  1019  			"name":  "Protocol-TLSv1",
  1020  			"value": "false",
  1021  		},
  1022  		map[string]interface{}{
  1023  			"name":  "Protocol-TLSv1.1",
  1024  			"value": "false",
  1025  		},
  1026  		map[string]interface{}{
  1027  			"name":  "Protocol-TLSv1.2",
  1028  			"value": "true",
  1029  		},
  1030  	}
  1031  	attributes, err := expandPolicyAttributes(expanded)
  1032  	if err != nil {
  1033  		t.Fatalf("bad: %#v", err)
  1034  	}
  1035  
  1036  	if len(attributes) != 3 {
  1037  		t.Fatalf("expected number of attributes to be 3, but got %d", len(attributes))
  1038  	}
  1039  
  1040  	expected := &elb.PolicyAttribute{
  1041  		AttributeName:  aws.String("Protocol-TLSv1.2"),
  1042  		AttributeValue: aws.String("true"),
  1043  	}
  1044  
  1045  	if !reflect.DeepEqual(attributes[2], expected) {
  1046  		t.Fatalf(
  1047  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
  1048  			attributes[2],
  1049  			expected)
  1050  	}
  1051  }
  1052  
  1053  func TestExpandPolicyAttributes_invalid(t *testing.T) {
  1054  	expanded := []interface{}{
  1055  		map[string]interface{}{
  1056  			"name":  "Protocol-TLSv1.2",
  1057  			"value": "true",
  1058  		},
  1059  	}
  1060  	attributes, err := expandPolicyAttributes(expanded)
  1061  	if err != nil {
  1062  		t.Fatalf("bad: %#v", err)
  1063  	}
  1064  
  1065  	expected := &elb.PolicyAttribute{
  1066  		AttributeName:  aws.String("Protocol-TLSv1.2"),
  1067  		AttributeValue: aws.String("false"),
  1068  	}
  1069  
  1070  	if reflect.DeepEqual(attributes[0], expected) {
  1071  		t.Fatalf(
  1072  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
  1073  			attributes[0],
  1074  			expected)
  1075  	}
  1076  }
  1077  
  1078  func TestExpandPolicyAttributes_empty(t *testing.T) {
  1079  	var expanded []interface{}
  1080  
  1081  	attributes, err := expandPolicyAttributes(expanded)
  1082  	if err != nil {
  1083  		t.Fatalf("bad: %#v", err)
  1084  	}
  1085  
  1086  	if len(attributes) != 0 {
  1087  		t.Fatalf("expected number of attributes to be 0, but got %d", len(attributes))
  1088  	}
  1089  }
  1090  
  1091  func TestFlattenPolicyAttributes(t *testing.T) {
  1092  	cases := []struct {
  1093  		Input  []*elb.PolicyAttributeDescription
  1094  		Output []interface{}
  1095  	}{
  1096  		{
  1097  			Input: []*elb.PolicyAttributeDescription{
  1098  				&elb.PolicyAttributeDescription{
  1099  					AttributeName:  aws.String("Protocol-TLSv1.2"),
  1100  					AttributeValue: aws.String("true"),
  1101  				},
  1102  			},
  1103  			Output: []interface{}{
  1104  				map[string]string{
  1105  					"name":  "Protocol-TLSv1.2",
  1106  					"value": "true",
  1107  				},
  1108  			},
  1109  		},
  1110  	}
  1111  
  1112  	for _, tc := range cases {
  1113  		output := flattenPolicyAttributes(tc.Input)
  1114  		if !reflect.DeepEqual(output, tc.Output) {
  1115  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
  1116  		}
  1117  	}
  1118  }
  1119  
  1120  func TestNormalizeJsonString(t *testing.T) {
  1121  	var err error
  1122  	var actual string
  1123  
  1124  	// Well formatted and valid.
  1125  	validJson := `{
  1126     "abc": {
  1127        "def": 123,
  1128        "xyz": [
  1129           {
  1130              "a": "ホリネズミ"
  1131           },
  1132           {
  1133              "b": "1\\n2"
  1134           }
  1135        ]
  1136     }
  1137  }`
  1138  	expected := `{"abc":{"def":123,"xyz":[{"a":"ホリネズミ"},{"b":"1\\n2"}]}}`
  1139  
  1140  	actual, err = normalizeJsonString(validJson)
  1141  	if err != nil {
  1142  		t.Fatalf("Expected not to throw an error while parsing JSON, but got: %s", err)
  1143  	}
  1144  
  1145  	if actual != expected {
  1146  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, expected)
  1147  	}
  1148  
  1149  	// Well formatted but not valid,
  1150  	// missing closing squre bracket.
  1151  	invalidJson := `{
  1152     "abc": {
  1153        "def": 123,
  1154        "xyz": [
  1155           {
  1156              "a": "1"
  1157           }
  1158        }
  1159     }
  1160  }`
  1161  	actual, err = normalizeJsonString(invalidJson)
  1162  	if err == nil {
  1163  		t.Fatalf("Expected to throw an error while parsing JSON, but got: %s", err)
  1164  	}
  1165  
  1166  	// We expect the invalid JSON to be shown back to us again.
  1167  	if actual != invalidJson {
  1168  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", expected, invalidJson)
  1169  	}
  1170  }