github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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  func TestExpandStringListEmptyItems(t *testing.T) {
   453  	initialList := []string{"foo", "bar", "", "baz"}
   454  	l := make([]interface{}, len(initialList))
   455  	for i, v := range initialList {
   456  		l[i] = v
   457  	}
   458  	stringList := expandStringList(l)
   459  	expected := []*string{
   460  		aws.String("foo"),
   461  		aws.String("bar"),
   462  		aws.String("baz"),
   463  	}
   464  
   465  	if !reflect.DeepEqual(stringList, expected) {
   466  		t.Fatalf(
   467  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   468  			stringList,
   469  			expected)
   470  	}
   471  }
   472  
   473  func TestExpandParameters(t *testing.T) {
   474  	expanded := []interface{}{
   475  		map[string]interface{}{
   476  			"name":         "character_set_client",
   477  			"value":        "utf8",
   478  			"apply_method": "immediate",
   479  		},
   480  	}
   481  	parameters, err := expandParameters(expanded)
   482  	if err != nil {
   483  		t.Fatalf("bad: %#v", err)
   484  	}
   485  
   486  	expected := &rds.Parameter{
   487  		ParameterName:  aws.String("character_set_client"),
   488  		ParameterValue: aws.String("utf8"),
   489  		ApplyMethod:    aws.String("immediate"),
   490  	}
   491  
   492  	if !reflect.DeepEqual(parameters[0], expected) {
   493  		t.Fatalf(
   494  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   495  			parameters[0],
   496  			expected)
   497  	}
   498  }
   499  
   500  func TestExpandRedshiftParameters(t *testing.T) {
   501  	expanded := []interface{}{
   502  		map[string]interface{}{
   503  			"name":  "character_set_client",
   504  			"value": "utf8",
   505  		},
   506  	}
   507  	parameters, err := expandRedshiftParameters(expanded)
   508  	if err != nil {
   509  		t.Fatalf("bad: %#v", err)
   510  	}
   511  
   512  	expected := &redshift.Parameter{
   513  		ParameterName:  aws.String("character_set_client"),
   514  		ParameterValue: aws.String("utf8"),
   515  	}
   516  
   517  	if !reflect.DeepEqual(parameters[0], expected) {
   518  		t.Fatalf(
   519  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   520  			parameters[0],
   521  			expected)
   522  	}
   523  }
   524  
   525  func TestExpandElasticacheParameters(t *testing.T) {
   526  	expanded := []interface{}{
   527  		map[string]interface{}{
   528  			"name":         "activerehashing",
   529  			"value":        "yes",
   530  			"apply_method": "immediate",
   531  		},
   532  	}
   533  	parameters, err := expandElastiCacheParameters(expanded)
   534  	if err != nil {
   535  		t.Fatalf("bad: %#v", err)
   536  	}
   537  
   538  	expected := &elasticache.ParameterNameValue{
   539  		ParameterName:  aws.String("activerehashing"),
   540  		ParameterValue: aws.String("yes"),
   541  	}
   542  
   543  	if !reflect.DeepEqual(parameters[0], expected) {
   544  		t.Fatalf(
   545  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   546  			parameters[0],
   547  			expected)
   548  	}
   549  }
   550  
   551  func TestExpandStepAdjustments(t *testing.T) {
   552  	expanded := []interface{}{
   553  		map[string]interface{}{
   554  			"metric_interval_lower_bound": "1.0",
   555  			"metric_interval_upper_bound": "2.0",
   556  			"scaling_adjustment":          1,
   557  		},
   558  	}
   559  	parameters, err := expandStepAdjustments(expanded)
   560  	if err != nil {
   561  		t.Fatalf("bad: %#v", err)
   562  	}
   563  
   564  	expected := &autoscaling.StepAdjustment{
   565  		MetricIntervalLowerBound: aws.Float64(1.0),
   566  		MetricIntervalUpperBound: aws.Float64(2.0),
   567  		ScalingAdjustment:        aws.Int64(int64(1)),
   568  	}
   569  
   570  	if !reflect.DeepEqual(parameters[0], expected) {
   571  		t.Fatalf(
   572  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
   573  			parameters[0],
   574  			expected)
   575  	}
   576  }
   577  
   578  func TestFlattenParameters(t *testing.T) {
   579  	cases := []struct {
   580  		Input  []*rds.Parameter
   581  		Output []map[string]interface{}
   582  	}{
   583  		{
   584  			Input: []*rds.Parameter{
   585  				&rds.Parameter{
   586  					ParameterName:  aws.String("character_set_client"),
   587  					ParameterValue: aws.String("utf8"),
   588  				},
   589  			},
   590  			Output: []map[string]interface{}{
   591  				map[string]interface{}{
   592  					"name":  "character_set_client",
   593  					"value": "utf8",
   594  				},
   595  			},
   596  		},
   597  	}
   598  
   599  	for _, tc := range cases {
   600  		output := flattenParameters(tc.Input)
   601  		if !reflect.DeepEqual(output, tc.Output) {
   602  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
   603  		}
   604  	}
   605  }
   606  
   607  func TestFlattenRedshiftParameters(t *testing.T) {
   608  	cases := []struct {
   609  		Input  []*redshift.Parameter
   610  		Output []map[string]interface{}
   611  	}{
   612  		{
   613  			Input: []*redshift.Parameter{
   614  				&redshift.Parameter{
   615  					ParameterName:  aws.String("character_set_client"),
   616  					ParameterValue: aws.String("utf8"),
   617  				},
   618  			},
   619  			Output: []map[string]interface{}{
   620  				map[string]interface{}{
   621  					"name":  "character_set_client",
   622  					"value": "utf8",
   623  				},
   624  			},
   625  		},
   626  	}
   627  
   628  	for _, tc := range cases {
   629  		output := flattenRedshiftParameters(tc.Input)
   630  		if !reflect.DeepEqual(output, tc.Output) {
   631  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
   632  		}
   633  	}
   634  }
   635  
   636  func TestFlattenElasticacheParameters(t *testing.T) {
   637  	cases := []struct {
   638  		Input  []*elasticache.Parameter
   639  		Output []map[string]interface{}
   640  	}{
   641  		{
   642  			Input: []*elasticache.Parameter{
   643  				&elasticache.Parameter{
   644  					ParameterName:  aws.String("activerehashing"),
   645  					ParameterValue: aws.String("yes"),
   646  				},
   647  			},
   648  			Output: []map[string]interface{}{
   649  				map[string]interface{}{
   650  					"name":  "activerehashing",
   651  					"value": "yes",
   652  				},
   653  			},
   654  		},
   655  	}
   656  
   657  	for _, tc := range cases {
   658  		output := flattenElastiCacheParameters(tc.Input)
   659  		if !reflect.DeepEqual(output, tc.Output) {
   660  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
   661  		}
   662  	}
   663  }
   664  
   665  func TestExpandInstanceString(t *testing.T) {
   666  
   667  	expected := []*elb.Instance{
   668  		&elb.Instance{InstanceId: aws.String("test-one")},
   669  		&elb.Instance{InstanceId: aws.String("test-two")},
   670  	}
   671  
   672  	ids := []interface{}{
   673  		"test-one",
   674  		"test-two",
   675  	}
   676  
   677  	expanded := expandInstanceString(ids)
   678  
   679  	if !reflect.DeepEqual(expanded, expected) {
   680  		t.Fatalf("Expand Instance String output did not match.\nGot:\n%#v\n\nexpected:\n%#v", expanded, expected)
   681  	}
   682  }
   683  
   684  func TestFlattenNetworkInterfacesPrivateIPAddresses(t *testing.T) {
   685  	expanded := []*ec2.NetworkInterfacePrivateIpAddress{
   686  		&ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.1")},
   687  		&ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.2")},
   688  	}
   689  
   690  	result := flattenNetworkInterfacesPrivateIPAddresses(expanded)
   691  
   692  	if result == nil {
   693  		t.Fatal("result was nil")
   694  	}
   695  
   696  	if len(result) != 2 {
   697  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   698  	}
   699  
   700  	if result[0] != "192.168.0.1" {
   701  		t.Fatalf("expected ip to be 192.168.0.1, but was %s", result[0])
   702  	}
   703  
   704  	if result[1] != "192.168.0.2" {
   705  		t.Fatalf("expected ip to be 192.168.0.2, but was %s", result[1])
   706  	}
   707  }
   708  
   709  func TestFlattenGroupIdentifiers(t *testing.T) {
   710  	expanded := []*ec2.GroupIdentifier{
   711  		&ec2.GroupIdentifier{GroupId: aws.String("sg-001")},
   712  		&ec2.GroupIdentifier{GroupId: aws.String("sg-002")},
   713  	}
   714  
   715  	result := flattenGroupIdentifiers(expanded)
   716  
   717  	if len(result) != 2 {
   718  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   719  	}
   720  
   721  	if result[0] != "sg-001" {
   722  		t.Fatalf("expected id to be sg-001, but was %s", result[0])
   723  	}
   724  
   725  	if result[1] != "sg-002" {
   726  		t.Fatalf("expected id to be sg-002, but was %s", result[1])
   727  	}
   728  }
   729  
   730  func TestExpandPrivateIPAddresses(t *testing.T) {
   731  
   732  	ip1 := "192.168.0.1"
   733  	ip2 := "192.168.0.2"
   734  	flattened := []interface{}{
   735  		ip1,
   736  		ip2,
   737  	}
   738  
   739  	result := expandPrivateIPAddresses(flattened)
   740  
   741  	if len(result) != 2 {
   742  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   743  	}
   744  
   745  	if *result[0].PrivateIpAddress != "192.168.0.1" || !*result[0].Primary {
   746  		t.Fatalf("expected ip to be 192.168.0.1 and Primary, but got %v, %t", *result[0].PrivateIpAddress, *result[0].Primary)
   747  	}
   748  
   749  	if *result[1].PrivateIpAddress != "192.168.0.2" || *result[1].Primary {
   750  		t.Fatalf("expected ip to be 192.168.0.2 and not Primary, but got %v, %t", *result[1].PrivateIpAddress, *result[1].Primary)
   751  	}
   752  }
   753  
   754  func TestFlattenAttachment(t *testing.T) {
   755  	expanded := &ec2.NetworkInterfaceAttachment{
   756  		InstanceId:   aws.String("i-00001"),
   757  		DeviceIndex:  aws.Int64(int64(1)),
   758  		AttachmentId: aws.String("at-002"),
   759  	}
   760  
   761  	result := flattenAttachment(expanded)
   762  
   763  	if result == nil {
   764  		t.Fatal("expected result to have value, but got nil")
   765  	}
   766  
   767  	if result["instance"] != "i-00001" {
   768  		t.Fatalf("expected instance to be i-00001, but got %s", result["instance"])
   769  	}
   770  
   771  	if result["device_index"] != int64(1) {
   772  		t.Fatalf("expected device_index to be 1, but got %d", result["device_index"])
   773  	}
   774  
   775  	if result["attachment_id"] != "at-002" {
   776  		t.Fatalf("expected attachment_id to be at-002, but got %s", result["attachment_id"])
   777  	}
   778  }
   779  
   780  func TestFlattenAttachmentWhenNoInstanceId(t *testing.T) {
   781  	expanded := &ec2.NetworkInterfaceAttachment{
   782  		DeviceIndex:  aws.Int64(int64(1)),
   783  		AttachmentId: aws.String("at-002"),
   784  	}
   785  
   786  	result := flattenAttachment(expanded)
   787  
   788  	if result == nil {
   789  		t.Fatal("expected result to have value, but got nil")
   790  	}
   791  
   792  	if result["instance"] != nil {
   793  		t.Fatalf("expected instance to be nil, but got %s", result["instance"])
   794  	}
   795  }
   796  
   797  func TestFlattenStepAdjustments(t *testing.T) {
   798  	expanded := []*autoscaling.StepAdjustment{
   799  		&autoscaling.StepAdjustment{
   800  			MetricIntervalLowerBound: aws.Float64(1.0),
   801  			MetricIntervalUpperBound: aws.Float64(2.0),
   802  			ScalingAdjustment:        aws.Int64(int64(1)),
   803  		},
   804  	}
   805  
   806  	result := flattenStepAdjustments(expanded)[0]
   807  	if result == nil {
   808  		t.Fatal("expected result to have value, but got nil")
   809  	}
   810  	if result["metric_interval_lower_bound"] != float64(1.0) {
   811  		t.Fatalf("expected metric_interval_lower_bound to be 1.0, but got %d", result["metric_interval_lower_bound"])
   812  	}
   813  	if result["metric_interval_upper_bound"] != float64(2.0) {
   814  		t.Fatalf("expected metric_interval_upper_bound to be 1.0, but got %d", result["metric_interval_upper_bound"])
   815  	}
   816  	if result["scaling_adjustment"] != int64(1) {
   817  		t.Fatalf("expected scaling_adjustment to be 1, but got %d", result["scaling_adjustment"])
   818  	}
   819  }
   820  
   821  func TestFlattenResourceRecords(t *testing.T) {
   822  	expanded := []*route53.ResourceRecord{
   823  		&route53.ResourceRecord{
   824  			Value: aws.String("127.0.0.1"),
   825  		},
   826  		&route53.ResourceRecord{
   827  			Value: aws.String("127.0.0.3"),
   828  		},
   829  	}
   830  
   831  	result := flattenResourceRecords(expanded)
   832  
   833  	if result == nil {
   834  		t.Fatal("expected result to have value, but got nil")
   835  	}
   836  
   837  	if len(result) != 2 {
   838  		t.Fatal("expected result to have value, but got nil")
   839  	}
   840  }
   841  
   842  func TestFlattenAsgEnabledMetrics(t *testing.T) {
   843  	expanded := []*autoscaling.EnabledMetric{
   844  		&autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupTotalInstances")},
   845  		&autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupMaxSize")},
   846  	}
   847  
   848  	result := flattenAsgEnabledMetrics(expanded)
   849  
   850  	if len(result) != 2 {
   851  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   852  	}
   853  
   854  	if result[0] != "GroupTotalInstances" {
   855  		t.Fatalf("expected id to be GroupTotalInstances, but was %s", result[0])
   856  	}
   857  
   858  	if result[1] != "GroupMaxSize" {
   859  		t.Fatalf("expected id to be GroupMaxSize, but was %s", result[1])
   860  	}
   861  }
   862  
   863  func TestFlattenKinesisShardLevelMetrics(t *testing.T) {
   864  	expanded := []*kinesis.EnhancedMetrics{
   865  		&kinesis.EnhancedMetrics{
   866  			ShardLevelMetrics: []*string{
   867  				aws.String("IncomingBytes"),
   868  				aws.String("IncomingRecords"),
   869  			},
   870  		},
   871  	}
   872  	result := flattenKinesisShardLevelMetrics(expanded)
   873  	if len(result) != 2 {
   874  		t.Fatalf("expected result had %d elements, but got %d", 2, len(result))
   875  	}
   876  	if result[0] != "IncomingBytes" {
   877  		t.Fatalf("expected element 0 to be IncomingBytes, but was %s", result[0])
   878  	}
   879  	if result[1] != "IncomingRecords" {
   880  		t.Fatalf("expected element 0 to be IncomingRecords, but was %s", result[1])
   881  	}
   882  }
   883  
   884  func TestFlattenSecurityGroups(t *testing.T) {
   885  	cases := []struct {
   886  		ownerId  *string
   887  		pairs    []*ec2.UserIdGroupPair
   888  		expected []*ec2.GroupIdentifier
   889  	}{
   890  		// simple, no user id included (we ignore it mostly)
   891  		{
   892  			ownerId: aws.String("user1234"),
   893  			pairs: []*ec2.UserIdGroupPair{
   894  				&ec2.UserIdGroupPair{
   895  					GroupId: aws.String("sg-12345"),
   896  				},
   897  			},
   898  			expected: []*ec2.GroupIdentifier{
   899  				&ec2.GroupIdentifier{
   900  					GroupId: aws.String("sg-12345"),
   901  				},
   902  			},
   903  		},
   904  		// include the owner id, but keep it consitent with the same account. Tests
   905  		// EC2 classic situation
   906  		{
   907  			ownerId: aws.String("user1234"),
   908  			pairs: []*ec2.UserIdGroupPair{
   909  				&ec2.UserIdGroupPair{
   910  					GroupId: aws.String("sg-12345"),
   911  					UserId:  aws.String("user1234"),
   912  				},
   913  			},
   914  			expected: []*ec2.GroupIdentifier{
   915  				&ec2.GroupIdentifier{
   916  					GroupId: aws.String("sg-12345"),
   917  				},
   918  			},
   919  		},
   920  
   921  		// include the owner id, but from a different account. This is reflects
   922  		// EC2 Classic when referring to groups by name
   923  		{
   924  			ownerId: aws.String("user1234"),
   925  			pairs: []*ec2.UserIdGroupPair{
   926  				&ec2.UserIdGroupPair{
   927  					GroupId:   aws.String("sg-12345"),
   928  					GroupName: aws.String("somegroup"), // GroupName is only included in Classic
   929  					UserId:    aws.String("user4321"),
   930  				},
   931  			},
   932  			expected: []*ec2.GroupIdentifier{
   933  				&ec2.GroupIdentifier{
   934  					GroupId:   aws.String("sg-12345"),
   935  					GroupName: aws.String("user4321/somegroup"),
   936  				},
   937  			},
   938  		},
   939  
   940  		// include the owner id, but from a different account. This reflects in
   941  		// EC2 VPC when referring to groups by id
   942  		{
   943  			ownerId: aws.String("user1234"),
   944  			pairs: []*ec2.UserIdGroupPair{
   945  				&ec2.UserIdGroupPair{
   946  					GroupId: aws.String("sg-12345"),
   947  					UserId:  aws.String("user4321"),
   948  				},
   949  			},
   950  			expected: []*ec2.GroupIdentifier{
   951  				&ec2.GroupIdentifier{
   952  					GroupId: aws.String("user4321/sg-12345"),
   953  				},
   954  			},
   955  		},
   956  	}
   957  
   958  	for _, c := range cases {
   959  		out := flattenSecurityGroups(c.pairs, c.ownerId)
   960  		if !reflect.DeepEqual(out, c.expected) {
   961  			t.Fatalf("Error matching output and expected: %#v vs %#v", out, c.expected)
   962  		}
   963  	}
   964  }
   965  
   966  func TestFlattenApiGatewayThrottleSettings(t *testing.T) {
   967  	expectedBurstLimit := int64(140)
   968  	expectedRateLimit := 120.0
   969  
   970  	ts := &apigateway.ThrottleSettings{
   971  		BurstLimit: aws.Int64(expectedBurstLimit),
   972  		RateLimit:  aws.Float64(expectedRateLimit),
   973  	}
   974  	result := flattenApiGatewayThrottleSettings(ts)
   975  
   976  	if len(result) != 1 {
   977  		t.Fatalf("Expected map to have exactly 1 element, got %d", len(result))
   978  	}
   979  
   980  	burstLimit, ok := result[0]["burst_limit"]
   981  	if !ok {
   982  		t.Fatal("Expected 'burst_limit' key in the map")
   983  	}
   984  	burstLimitInt, ok := burstLimit.(int64)
   985  	if !ok {
   986  		t.Fatal("Expected 'burst_limit' to be int")
   987  	}
   988  	if burstLimitInt != expectedBurstLimit {
   989  		t.Fatalf("Expected 'burst_limit' to equal %d, got %d", expectedBurstLimit, burstLimitInt)
   990  	}
   991  
   992  	rateLimit, ok := result[0]["rate_limit"]
   993  	if !ok {
   994  		t.Fatal("Expected 'rate_limit' key in the map")
   995  	}
   996  	rateLimitFloat, ok := rateLimit.(float64)
   997  	if !ok {
   998  		t.Fatal("Expected 'rate_limit' to be float64")
   999  	}
  1000  	if rateLimitFloat != expectedRateLimit {
  1001  		t.Fatalf("Expected 'rate_limit' to equal %f, got %f", expectedRateLimit, rateLimitFloat)
  1002  	}
  1003  }
  1004  
  1005  func TestFlattenApiGatewayStageKeys(t *testing.T) {
  1006  	cases := []struct {
  1007  		Input  []*string
  1008  		Output []map[string]interface{}
  1009  	}{
  1010  		{
  1011  			Input: []*string{
  1012  				aws.String("a1b2c3d4e5/dev"),
  1013  				aws.String("e5d4c3b2a1/test"),
  1014  			},
  1015  			Output: []map[string]interface{}{
  1016  				map[string]interface{}{
  1017  					"stage_name":  "dev",
  1018  					"rest_api_id": "a1b2c3d4e5",
  1019  				},
  1020  				map[string]interface{}{
  1021  					"stage_name":  "test",
  1022  					"rest_api_id": "e5d4c3b2a1",
  1023  				},
  1024  			},
  1025  		},
  1026  	}
  1027  
  1028  	for _, tc := range cases {
  1029  		output := flattenApiGatewayStageKeys(tc.Input)
  1030  		if !reflect.DeepEqual(output, tc.Output) {
  1031  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
  1032  		}
  1033  	}
  1034  }
  1035  
  1036  func TestExpandPolicyAttributes(t *testing.T) {
  1037  	expanded := []interface{}{
  1038  		map[string]interface{}{
  1039  			"name":  "Protocol-TLSv1",
  1040  			"value": "false",
  1041  		},
  1042  		map[string]interface{}{
  1043  			"name":  "Protocol-TLSv1.1",
  1044  			"value": "false",
  1045  		},
  1046  		map[string]interface{}{
  1047  			"name":  "Protocol-TLSv1.2",
  1048  			"value": "true",
  1049  		},
  1050  	}
  1051  	attributes, err := expandPolicyAttributes(expanded)
  1052  	if err != nil {
  1053  		t.Fatalf("bad: %#v", err)
  1054  	}
  1055  
  1056  	if len(attributes) != 3 {
  1057  		t.Fatalf("expected number of attributes to be 3, but got %d", len(attributes))
  1058  	}
  1059  
  1060  	expected := &elb.PolicyAttribute{
  1061  		AttributeName:  aws.String("Protocol-TLSv1.2"),
  1062  		AttributeValue: aws.String("true"),
  1063  	}
  1064  
  1065  	if !reflect.DeepEqual(attributes[2], expected) {
  1066  		t.Fatalf(
  1067  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
  1068  			attributes[2],
  1069  			expected)
  1070  	}
  1071  }
  1072  
  1073  func TestExpandPolicyAttributes_invalid(t *testing.T) {
  1074  	expanded := []interface{}{
  1075  		map[string]interface{}{
  1076  			"name":  "Protocol-TLSv1.2",
  1077  			"value": "true",
  1078  		},
  1079  	}
  1080  	attributes, err := expandPolicyAttributes(expanded)
  1081  	if err != nil {
  1082  		t.Fatalf("bad: %#v", err)
  1083  	}
  1084  
  1085  	expected := &elb.PolicyAttribute{
  1086  		AttributeName:  aws.String("Protocol-TLSv1.2"),
  1087  		AttributeValue: aws.String("false"),
  1088  	}
  1089  
  1090  	if reflect.DeepEqual(attributes[0], expected) {
  1091  		t.Fatalf(
  1092  			"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
  1093  			attributes[0],
  1094  			expected)
  1095  	}
  1096  }
  1097  
  1098  func TestExpandPolicyAttributes_empty(t *testing.T) {
  1099  	var expanded []interface{}
  1100  
  1101  	attributes, err := expandPolicyAttributes(expanded)
  1102  	if err != nil {
  1103  		t.Fatalf("bad: %#v", err)
  1104  	}
  1105  
  1106  	if len(attributes) != 0 {
  1107  		t.Fatalf("expected number of attributes to be 0, but got %d", len(attributes))
  1108  	}
  1109  }
  1110  
  1111  func TestFlattenPolicyAttributes(t *testing.T) {
  1112  	cases := []struct {
  1113  		Input  []*elb.PolicyAttributeDescription
  1114  		Output []interface{}
  1115  	}{
  1116  		{
  1117  			Input: []*elb.PolicyAttributeDescription{
  1118  				&elb.PolicyAttributeDescription{
  1119  					AttributeName:  aws.String("Protocol-TLSv1.2"),
  1120  					AttributeValue: aws.String("true"),
  1121  				},
  1122  			},
  1123  			Output: []interface{}{
  1124  				map[string]string{
  1125  					"name":  "Protocol-TLSv1.2",
  1126  					"value": "true",
  1127  				},
  1128  			},
  1129  		},
  1130  	}
  1131  
  1132  	for _, tc := range cases {
  1133  		output := flattenPolicyAttributes(tc.Input)
  1134  		if !reflect.DeepEqual(output, tc.Output) {
  1135  			t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output)
  1136  		}
  1137  	}
  1138  }
  1139  
  1140  func TestNormalizeJsonString(t *testing.T) {
  1141  	var err error
  1142  	var actual string
  1143  
  1144  	// Well formatted and valid.
  1145  	validJson := `{
  1146     "abc": {
  1147        "def": 123,
  1148        "xyz": [
  1149           {
  1150              "a": "ホリネズミ"
  1151           },
  1152           {
  1153              "b": "1\\n2"
  1154           }
  1155        ]
  1156     }
  1157  }`
  1158  	expected := `{"abc":{"def":123,"xyz":[{"a":"ホリネズミ"},{"b":"1\\n2"}]}}`
  1159  
  1160  	actual, err = normalizeJsonString(validJson)
  1161  	if err != nil {
  1162  		t.Fatalf("Expected not to throw an error while parsing JSON, but got: %s", err)
  1163  	}
  1164  
  1165  	if actual != expected {
  1166  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, expected)
  1167  	}
  1168  
  1169  	// Well formatted but not valid,
  1170  	// missing closing squre bracket.
  1171  	invalidJson := `{
  1172     "abc": {
  1173        "def": 123,
  1174        "xyz": [
  1175           {
  1176              "a": "1"
  1177           }
  1178        }
  1179     }
  1180  }`
  1181  	actual, err = normalizeJsonString(invalidJson)
  1182  	if err == nil {
  1183  		t.Fatalf("Expected to throw an error while parsing JSON, but got: %s", err)
  1184  	}
  1185  
  1186  	// We expect the invalid JSON to be shown back to us again.
  1187  	if actual != invalidJson {
  1188  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", expected, invalidJson)
  1189  	}
  1190  }
  1191  
  1192  func TestCheckYamlString(t *testing.T) {
  1193  	var err error
  1194  	var actual string
  1195  
  1196  	validYaml := `---
  1197  abc:
  1198    def: 123
  1199    xyz:
  1200      -
  1201        a: "ホリネズミ"
  1202        b: "1"
  1203  `
  1204  
  1205  	actual, err = checkYamlString(validYaml)
  1206  	if err != nil {
  1207  		t.Fatalf("Expected not to throw an error while parsing YAML, but got: %s", err)
  1208  	}
  1209  
  1210  	// We expect the same YAML string back
  1211  	if actual != validYaml {
  1212  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, validYaml)
  1213  	}
  1214  
  1215  	invalidYaml := `abc: [`
  1216  
  1217  	actual, err = checkYamlString(invalidYaml)
  1218  	if err == nil {
  1219  		t.Fatalf("Expected to throw an error while parsing YAML, but got: %s", err)
  1220  	}
  1221  
  1222  	// We expect the invalid YAML to be shown back to us again.
  1223  	if actual != invalidYaml {
  1224  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, invalidYaml)
  1225  	}
  1226  }
  1227  
  1228  func TestNormalizeCloudFormationTemplate(t *testing.T) {
  1229  	var err error
  1230  	var actual string
  1231  
  1232  	validNormalizedJson := `{"abc":"1"}`
  1233  	actual, err = normalizeCloudFormationTemplate(validNormalizedJson)
  1234  	if err != nil {
  1235  		t.Fatalf("Expected not to throw an error while parsing template, but got: %s", err)
  1236  	}
  1237  	if actual != validNormalizedJson {
  1238  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, validNormalizedJson)
  1239  	}
  1240  
  1241  	validNormalizedYaml := `abc: 1
  1242  `
  1243  	actual, err = normalizeCloudFormationTemplate(validNormalizedYaml)
  1244  	if err != nil {
  1245  		t.Fatalf("Expected not to throw an error while parsing template, but got: %s", err)
  1246  	}
  1247  	if actual != validNormalizedYaml {
  1248  		t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, validNormalizedYaml)
  1249  	}
  1250  }