github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/terraform/resource_address_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/terraform/config"
     8  )
     9  
    10  func TestParseResourceAddressInternal(t *testing.T) {
    11  	cases := map[string]struct {
    12  		Input    string
    13  		Expected *ResourceAddress
    14  		Output   string
    15  	}{
    16  		"basic resource": {
    17  			"aws_instance.foo",
    18  			&ResourceAddress{
    19  				Mode:         config.ManagedResourceMode,
    20  				Type:         "aws_instance",
    21  				Name:         "foo",
    22  				InstanceType: TypePrimary,
    23  				Index:        -1,
    24  			},
    25  			"aws_instance.foo",
    26  		},
    27  
    28  		"basic resource with count": {
    29  			"aws_instance.foo.1",
    30  			&ResourceAddress{
    31  				Mode:         config.ManagedResourceMode,
    32  				Type:         "aws_instance",
    33  				Name:         "foo",
    34  				InstanceType: TypePrimary,
    35  				Index:        1,
    36  			},
    37  			"aws_instance.foo[1]",
    38  		},
    39  
    40  		"data resource": {
    41  			"data.aws_ami.foo",
    42  			&ResourceAddress{
    43  				Mode:         config.DataResourceMode,
    44  				Type:         "aws_ami",
    45  				Name:         "foo",
    46  				InstanceType: TypePrimary,
    47  				Index:        -1,
    48  			},
    49  			"data.aws_ami.foo",
    50  		},
    51  
    52  		"data resource with count": {
    53  			"data.aws_ami.foo.1",
    54  			&ResourceAddress{
    55  				Mode:         config.DataResourceMode,
    56  				Type:         "aws_ami",
    57  				Name:         "foo",
    58  				InstanceType: TypePrimary,
    59  				Index:        1,
    60  			},
    61  			"data.aws_ami.foo[1]",
    62  		},
    63  
    64  		"non-data resource with 4 elements": {
    65  			"aws_instance.foo.bar.1",
    66  			nil,
    67  			"",
    68  		},
    69  	}
    70  
    71  	for tn, tc := range cases {
    72  		t.Run(tc.Input, func(t *testing.T) {
    73  			out, err := parseResourceAddressInternal(tc.Input)
    74  			if (err != nil) != (tc.Expected == nil) {
    75  				t.Fatalf("%s: unexpected err: %#v", tn, err)
    76  			}
    77  			if err != nil {
    78  				return
    79  			}
    80  
    81  			if !reflect.DeepEqual(out, tc.Expected) {
    82  				t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out)
    83  			}
    84  
    85  			// Compare outputs if those exist
    86  			expected := tc.Input
    87  			if tc.Output != "" {
    88  				expected = tc.Output
    89  			}
    90  			if out.String() != expected {
    91  				t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out)
    92  			}
    93  
    94  			// Compare equality because the internal parse is used
    95  			// to compare equality to equal inputs.
    96  			if !out.Equals(tc.Expected) {
    97  				t.Fatalf("expected equality:\n\n%#v\n\n%#v", out, tc.Expected)
    98  			}
    99  		})
   100  	}
   101  }
   102  
   103  func TestParseResourceAddress(t *testing.T) {
   104  	cases := map[string]struct {
   105  		Input    string
   106  		Expected *ResourceAddress
   107  		Output   string
   108  		Err      bool
   109  	}{
   110  		"implicit primary managed instance, no specific index": {
   111  			"aws_instance.foo",
   112  			&ResourceAddress{
   113  				Mode:         config.ManagedResourceMode,
   114  				Type:         "aws_instance",
   115  				Name:         "foo",
   116  				InstanceType: TypePrimary,
   117  				Index:        -1,
   118  			},
   119  			"",
   120  			false,
   121  		},
   122  		"implicit primary data instance, no specific index": {
   123  			"data.aws_instance.foo",
   124  			&ResourceAddress{
   125  				Mode:         config.DataResourceMode,
   126  				Type:         "aws_instance",
   127  				Name:         "foo",
   128  				InstanceType: TypePrimary,
   129  				Index:        -1,
   130  			},
   131  			"",
   132  			false,
   133  		},
   134  		"implicit primary, explicit index": {
   135  			"aws_instance.foo[2]",
   136  			&ResourceAddress{
   137  				Mode:         config.ManagedResourceMode,
   138  				Type:         "aws_instance",
   139  				Name:         "foo",
   140  				InstanceType: TypePrimary,
   141  				Index:        2,
   142  			},
   143  			"",
   144  			false,
   145  		},
   146  		"implicit primary, explicit index over ten": {
   147  			"aws_instance.foo[12]",
   148  			&ResourceAddress{
   149  				Mode:         config.ManagedResourceMode,
   150  				Type:         "aws_instance",
   151  				Name:         "foo",
   152  				InstanceType: TypePrimary,
   153  				Index:        12,
   154  			},
   155  			"",
   156  			false,
   157  		},
   158  		"explicit primary, explicit index": {
   159  			"aws_instance.foo.primary[2]",
   160  			&ResourceAddress{
   161  				Mode:            config.ManagedResourceMode,
   162  				Type:            "aws_instance",
   163  				Name:            "foo",
   164  				InstanceType:    TypePrimary,
   165  				InstanceTypeSet: true,
   166  				Index:           2,
   167  			},
   168  			"",
   169  			false,
   170  		},
   171  		"tainted": {
   172  			"aws_instance.foo.tainted",
   173  			&ResourceAddress{
   174  				Mode:            config.ManagedResourceMode,
   175  				Type:            "aws_instance",
   176  				Name:            "foo",
   177  				InstanceType:    TypeTainted,
   178  				InstanceTypeSet: true,
   179  				Index:           -1,
   180  			},
   181  			"",
   182  			false,
   183  		},
   184  		"deposed": {
   185  			"aws_instance.foo.deposed",
   186  			&ResourceAddress{
   187  				Mode:            config.ManagedResourceMode,
   188  				Type:            "aws_instance",
   189  				Name:            "foo",
   190  				InstanceType:    TypeDeposed,
   191  				InstanceTypeSet: true,
   192  				Index:           -1,
   193  			},
   194  			"",
   195  			false,
   196  		},
   197  		"with a hyphen": {
   198  			"aws_instance.foo-bar",
   199  			&ResourceAddress{
   200  				Mode:         config.ManagedResourceMode,
   201  				Type:         "aws_instance",
   202  				Name:         "foo-bar",
   203  				InstanceType: TypePrimary,
   204  				Index:        -1,
   205  			},
   206  			"",
   207  			false,
   208  		},
   209  		"managed in a module": {
   210  			"module.child.aws_instance.foo",
   211  			&ResourceAddress{
   212  				Path:         []string{"child"},
   213  				Mode:         config.ManagedResourceMode,
   214  				Type:         "aws_instance",
   215  				Name:         "foo",
   216  				InstanceType: TypePrimary,
   217  				Index:        -1,
   218  			},
   219  			"",
   220  			false,
   221  		},
   222  		"data in a module": {
   223  			"module.child.data.aws_instance.foo",
   224  			&ResourceAddress{
   225  				Path:         []string{"child"},
   226  				Mode:         config.DataResourceMode,
   227  				Type:         "aws_instance",
   228  				Name:         "foo",
   229  				InstanceType: TypePrimary,
   230  				Index:        -1,
   231  			},
   232  			"",
   233  			false,
   234  		},
   235  		"nested modules": {
   236  			"module.a.module.b.module.forever.aws_instance.foo",
   237  			&ResourceAddress{
   238  				Path:         []string{"a", "b", "forever"},
   239  				Mode:         config.ManagedResourceMode,
   240  				Type:         "aws_instance",
   241  				Name:         "foo",
   242  				InstanceType: TypePrimary,
   243  				Index:        -1,
   244  			},
   245  			"",
   246  			false,
   247  		},
   248  		"just a module": {
   249  			"module.a",
   250  			&ResourceAddress{
   251  				Path:         []string{"a"},
   252  				Type:         "",
   253  				Name:         "",
   254  				InstanceType: TypePrimary,
   255  				Index:        -1,
   256  			},
   257  			"",
   258  			false,
   259  		},
   260  		"just a nested module": {
   261  			"module.a.module.b",
   262  			&ResourceAddress{
   263  				Path:         []string{"a", "b"},
   264  				Type:         "",
   265  				Name:         "",
   266  				InstanceType: TypePrimary,
   267  				Index:        -1,
   268  			},
   269  			"",
   270  			false,
   271  		},
   272  		"module missing resource type": {
   273  			"module.name.foo",
   274  			nil,
   275  			"",
   276  			true,
   277  		},
   278  	}
   279  
   280  	for tn, tc := range cases {
   281  		t.Run(tn, func(t *testing.T) {
   282  			out, err := ParseResourceAddress(tc.Input)
   283  			if (err != nil) != tc.Err {
   284  				t.Fatalf("%s: unexpected err: %#v", tn, err)
   285  			}
   286  			if tc.Err {
   287  				return
   288  			}
   289  
   290  			if !reflect.DeepEqual(out, tc.Expected) {
   291  				t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out)
   292  			}
   293  
   294  			expected := tc.Input
   295  			if tc.Output != "" {
   296  				expected = tc.Output
   297  			}
   298  			if out.String() != expected {
   299  				t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out)
   300  			}
   301  		})
   302  	}
   303  }
   304  
   305  func TestResourceAddressEquals(t *testing.T) {
   306  	cases := map[string]struct {
   307  		Address *ResourceAddress
   308  		Other   interface{}
   309  		Expect  bool
   310  	}{
   311  		"basic match": {
   312  			Address: &ResourceAddress{
   313  				Mode:         config.ManagedResourceMode,
   314  				Type:         "aws_instance",
   315  				Name:         "foo",
   316  				InstanceType: TypePrimary,
   317  				Index:        0,
   318  			},
   319  			Other: &ResourceAddress{
   320  				Mode:         config.ManagedResourceMode,
   321  				Type:         "aws_instance",
   322  				Name:         "foo",
   323  				InstanceType: TypePrimary,
   324  				Index:        0,
   325  			},
   326  			Expect: true,
   327  		},
   328  		"address does not set index": {
   329  			Address: &ResourceAddress{
   330  				Mode:         config.ManagedResourceMode,
   331  				Type:         "aws_instance",
   332  				Name:         "foo",
   333  				InstanceType: TypePrimary,
   334  				Index:        -1,
   335  			},
   336  			Other: &ResourceAddress{
   337  				Mode:         config.ManagedResourceMode,
   338  				Type:         "aws_instance",
   339  				Name:         "foo",
   340  				InstanceType: TypePrimary,
   341  				Index:        3,
   342  			},
   343  			Expect: true,
   344  		},
   345  		"other does not set index": {
   346  			Address: &ResourceAddress{
   347  				Mode:         config.ManagedResourceMode,
   348  				Type:         "aws_instance",
   349  				Name:         "foo",
   350  				InstanceType: TypePrimary,
   351  				Index:        3,
   352  			},
   353  			Other: &ResourceAddress{
   354  				Mode:         config.ManagedResourceMode,
   355  				Type:         "aws_instance",
   356  				Name:         "foo",
   357  				InstanceType: TypePrimary,
   358  				Index:        -1,
   359  			},
   360  			Expect: true,
   361  		},
   362  		"neither sets index": {
   363  			Address: &ResourceAddress{
   364  				Mode:         config.ManagedResourceMode,
   365  				Type:         "aws_instance",
   366  				Name:         "foo",
   367  				InstanceType: TypePrimary,
   368  				Index:        -1,
   369  			},
   370  			Other: &ResourceAddress{
   371  				Mode:         config.ManagedResourceMode,
   372  				Type:         "aws_instance",
   373  				Name:         "foo",
   374  				InstanceType: TypePrimary,
   375  				Index:        -1,
   376  			},
   377  			Expect: true,
   378  		},
   379  		"index over ten": {
   380  			Address: &ResourceAddress{
   381  				Mode:         config.ManagedResourceMode,
   382  				Type:         "aws_instance",
   383  				Name:         "foo",
   384  				InstanceType: TypePrimary,
   385  				Index:        1,
   386  			},
   387  			Other: &ResourceAddress{
   388  				Mode:         config.ManagedResourceMode,
   389  				Type:         "aws_instance",
   390  				Name:         "foo",
   391  				InstanceType: TypePrimary,
   392  				Index:        13,
   393  			},
   394  			Expect: false,
   395  		},
   396  		"different type": {
   397  			Address: &ResourceAddress{
   398  				Mode:         config.ManagedResourceMode,
   399  				Type:         "aws_instance",
   400  				Name:         "foo",
   401  				InstanceType: TypePrimary,
   402  				Index:        0,
   403  			},
   404  			Other: &ResourceAddress{
   405  				Mode:         config.ManagedResourceMode,
   406  				Type:         "aws_vpc",
   407  				Name:         "foo",
   408  				InstanceType: TypePrimary,
   409  				Index:        0,
   410  			},
   411  			Expect: false,
   412  		},
   413  		"different mode": {
   414  			Address: &ResourceAddress{
   415  				Mode:         config.ManagedResourceMode,
   416  				Type:         "aws_instance",
   417  				Name:         "foo",
   418  				InstanceType: TypePrimary,
   419  				Index:        0,
   420  			},
   421  			Other: &ResourceAddress{
   422  				Mode:         config.DataResourceMode,
   423  				Type:         "aws_instance",
   424  				Name:         "foo",
   425  				InstanceType: TypePrimary,
   426  				Index:        0,
   427  			},
   428  			Expect: false,
   429  		},
   430  		"different name": {
   431  			Address: &ResourceAddress{
   432  				Mode:         config.ManagedResourceMode,
   433  				Type:         "aws_instance",
   434  				Name:         "foo",
   435  				InstanceType: TypePrimary,
   436  				Index:        0,
   437  			},
   438  			Other: &ResourceAddress{
   439  				Mode:         config.ManagedResourceMode,
   440  				Type:         "aws_instance",
   441  				Name:         "bar",
   442  				InstanceType: TypePrimary,
   443  				Index:        0,
   444  			},
   445  			Expect: false,
   446  		},
   447  		"different instance type": {
   448  			Address: &ResourceAddress{
   449  				Mode:         config.ManagedResourceMode,
   450  				Type:         "aws_instance",
   451  				Name:         "foo",
   452  				InstanceType: TypePrimary,
   453  				Index:        0,
   454  			},
   455  			Other: &ResourceAddress{
   456  				Mode:         config.ManagedResourceMode,
   457  				Type:         "aws_instance",
   458  				Name:         "foo",
   459  				InstanceType: TypeTainted,
   460  				Index:        0,
   461  			},
   462  			Expect: false,
   463  		},
   464  		"different index": {
   465  			Address: &ResourceAddress{
   466  				Mode:         config.ManagedResourceMode,
   467  				Type:         "aws_instance",
   468  				Name:         "foo",
   469  				InstanceType: TypePrimary,
   470  				Index:        0,
   471  			},
   472  			Other: &ResourceAddress{
   473  				Mode:         config.ManagedResourceMode,
   474  				Type:         "aws_instance",
   475  				Name:         "foo",
   476  				InstanceType: TypePrimary,
   477  				Index:        1,
   478  			},
   479  			Expect: false,
   480  		},
   481  		"module address matches address of managed resource inside module": {
   482  			Address: &ResourceAddress{
   483  				Path:         []string{"a", "b"},
   484  				Type:         "",
   485  				Name:         "",
   486  				InstanceType: TypePrimary,
   487  				Index:        -1,
   488  			},
   489  			Other: &ResourceAddress{
   490  				Path:         []string{"a", "b"},
   491  				Mode:         config.ManagedResourceMode,
   492  				Type:         "aws_instance",
   493  				Name:         "foo",
   494  				InstanceType: TypePrimary,
   495  				Index:        0,
   496  			},
   497  			Expect: true,
   498  		},
   499  		"module address matches address of data resource inside module": {
   500  			Address: &ResourceAddress{
   501  				Path:         []string{"a", "b"},
   502  				Type:         "",
   503  				Name:         "",
   504  				InstanceType: TypePrimary,
   505  				Index:        -1,
   506  			},
   507  			Other: &ResourceAddress{
   508  				Path:         []string{"a", "b"},
   509  				Mode:         config.DataResourceMode,
   510  				Type:         "aws_instance",
   511  				Name:         "foo",
   512  				InstanceType: TypePrimary,
   513  				Index:        0,
   514  			},
   515  			Expect: true,
   516  		},
   517  		"module address doesn't match managed resource outside module": {
   518  			Address: &ResourceAddress{
   519  				Path:         []string{"a", "b"},
   520  				Type:         "",
   521  				Name:         "",
   522  				InstanceType: TypePrimary,
   523  				Index:        -1,
   524  			},
   525  			Other: &ResourceAddress{
   526  				Path:         []string{"a"},
   527  				Mode:         config.ManagedResourceMode,
   528  				Type:         "aws_instance",
   529  				Name:         "foo",
   530  				InstanceType: TypePrimary,
   531  				Index:        0,
   532  			},
   533  			Expect: false,
   534  		},
   535  		"module address doesn't match data resource outside module": {
   536  			Address: &ResourceAddress{
   537  				Path:         []string{"a", "b"},
   538  				Type:         "",
   539  				Name:         "",
   540  				InstanceType: TypePrimary,
   541  				Index:        -1,
   542  			},
   543  			Other: &ResourceAddress{
   544  				Path:         []string{"a"},
   545  				Mode:         config.DataResourceMode,
   546  				Type:         "aws_instance",
   547  				Name:         "foo",
   548  				InstanceType: TypePrimary,
   549  				Index:        0,
   550  			},
   551  			Expect: false,
   552  		},
   553  		"nil path vs empty path should match": {
   554  			Address: &ResourceAddress{
   555  				Path:         []string{},
   556  				Mode:         config.ManagedResourceMode,
   557  				Type:         "aws_instance",
   558  				Name:         "foo",
   559  				InstanceType: TypePrimary,
   560  				Index:        -1,
   561  			},
   562  			Other: &ResourceAddress{
   563  				Path:         nil,
   564  				Mode:         config.ManagedResourceMode,
   565  				Type:         "aws_instance",
   566  				Name:         "foo",
   567  				InstanceType: TypePrimary,
   568  				Index:        0,
   569  			},
   570  			Expect: true,
   571  		},
   572  	}
   573  
   574  	for tn, tc := range cases {
   575  		actual := tc.Address.Equals(tc.Other)
   576  		if actual != tc.Expect {
   577  			t.Fatalf("%q: expected equals: %t, got %t for:\n%#v\n%#v",
   578  				tn, tc.Expect, actual, tc.Address, tc.Other)
   579  		}
   580  	}
   581  }
   582  
   583  func TestResourceAddressStateId(t *testing.T) {
   584  	cases := map[string]struct {
   585  		Input    *ResourceAddress
   586  		Expected string
   587  	}{
   588  		"basic resource": {
   589  			&ResourceAddress{
   590  				Mode:         config.ManagedResourceMode,
   591  				Type:         "aws_instance",
   592  				Name:         "foo",
   593  				InstanceType: TypePrimary,
   594  				Index:        -1,
   595  			},
   596  			"aws_instance.foo",
   597  		},
   598  
   599  		"basic resource with index": {
   600  			&ResourceAddress{
   601  				Mode:         config.ManagedResourceMode,
   602  				Type:         "aws_instance",
   603  				Name:         "foo",
   604  				InstanceType: TypePrimary,
   605  				Index:        2,
   606  			},
   607  			"aws_instance.foo.2",
   608  		},
   609  
   610  		"data resource": {
   611  			&ResourceAddress{
   612  				Mode:         config.DataResourceMode,
   613  				Type:         "aws_instance",
   614  				Name:         "foo",
   615  				InstanceType: TypePrimary,
   616  				Index:        -1,
   617  			},
   618  			"data.aws_instance.foo",
   619  		},
   620  	}
   621  
   622  	for tn, tc := range cases {
   623  		t.Run(tn, func(t *testing.T) {
   624  			actual := tc.Input.stateId()
   625  			if actual != tc.Expected {
   626  				t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, tc.Expected, actual)
   627  			}
   628  		})
   629  	}
   630  }