github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/terraform/resource_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/hil/ast"
     9  	"github.com/hashicorp/terraform/config"
    10  )
    11  
    12  func TestInstanceInfo(t *testing.T) {
    13  	cases := []struct {
    14  		Info   *InstanceInfo
    15  		Result string
    16  	}{
    17  		{
    18  			&InstanceInfo{
    19  				Id: "foo",
    20  			},
    21  			"foo",
    22  		},
    23  		{
    24  			&InstanceInfo{
    25  				Id:         "foo",
    26  				ModulePath: rootModulePath,
    27  			},
    28  			"foo",
    29  		},
    30  		{
    31  			&InstanceInfo{
    32  				Id:         "foo",
    33  				ModulePath: []string{"root", "consul"},
    34  			},
    35  			"module.consul.foo",
    36  		},
    37  	}
    38  
    39  	for i, tc := range cases {
    40  		actual := tc.Info.HumanId()
    41  		if actual != tc.Result {
    42  			t.Fatalf("%d: %s", i, actual)
    43  		}
    44  	}
    45  }
    46  
    47  func TestResourceConfigGet(t *testing.T) {
    48  	cases := []struct {
    49  		Config map[string]interface{}
    50  		Vars   map[string]string
    51  		Key    string
    52  		Value  interface{}
    53  	}{
    54  		{
    55  			Config: nil,
    56  			Key:    "foo",
    57  			Value:  nil,
    58  		},
    59  
    60  		{
    61  			Config: map[string]interface{}{
    62  				"foo": "${var.foo}",
    63  			},
    64  			Key:   "foo",
    65  			Value: "${var.foo}",
    66  		},
    67  
    68  		{
    69  			Config: map[string]interface{}{
    70  				"foo": "${var.foo}",
    71  			},
    72  			Vars:  map[string]string{"foo": "bar"},
    73  			Key:   "foo",
    74  			Value: "bar",
    75  		},
    76  
    77  		{
    78  			Config: map[string]interface{}{
    79  				"foo": []interface{}{1, 2, 5},
    80  			},
    81  			Key:   "foo.0",
    82  			Value: 1,
    83  		},
    84  
    85  		{
    86  			Config: map[string]interface{}{
    87  				"foo": []interface{}{1, 2, 5},
    88  			},
    89  			Key:   "foo.5",
    90  			Value: nil,
    91  		},
    92  
    93  		// get from map
    94  		{
    95  			Config: map[string]interface{}{
    96  				"mapname": []map[string]interface{}{
    97  					map[string]interface{}{"key": 1},
    98  				},
    99  			},
   100  			Key:   "mapname.0.key",
   101  			Value: 1,
   102  		},
   103  
   104  		// get from map with dot in key
   105  		{
   106  			Config: map[string]interface{}{
   107  				"mapname": []map[string]interface{}{
   108  					map[string]interface{}{"key.name": 1},
   109  				},
   110  			},
   111  			Key:   "mapname.0.key.name",
   112  			Value: 1,
   113  		},
   114  
   115  		// get from map with overlapping key names
   116  		{
   117  			Config: map[string]interface{}{
   118  				"mapname": []map[string]interface{}{
   119  					map[string]interface{}{
   120  						"key.name":   1,
   121  						"key.name.2": 2,
   122  					},
   123  				},
   124  			},
   125  			Key:   "mapname.0.key.name.2",
   126  			Value: 2,
   127  		},
   128  		{
   129  			Config: map[string]interface{}{
   130  				"mapname": []map[string]interface{}{
   131  					map[string]interface{}{
   132  						"key.name":     1,
   133  						"key.name.foo": 2,
   134  					},
   135  				},
   136  			},
   137  			Key:   "mapname.0.key.name",
   138  			Value: 1,
   139  		},
   140  		{
   141  			Config: map[string]interface{}{
   142  				"mapname": []map[string]interface{}{
   143  					map[string]interface{}{
   144  						"listkey": []map[string]interface{}{
   145  							{"key": 3},
   146  						},
   147  					},
   148  				},
   149  			},
   150  			Key:   "mapname.0.listkey.0.key",
   151  			Value: 3,
   152  		},
   153  		// FIXME: this is ambiguous, and matches the nested map
   154  		//        leaving here to catch this behaviour if it changes.
   155  		{
   156  			Config: map[string]interface{}{
   157  				"mapname": []map[string]interface{}{
   158  					map[string]interface{}{
   159  						"key.name":   1,
   160  						"key.name.0": 2,
   161  						"key":        map[string]interface{}{"name": 3},
   162  					},
   163  				},
   164  			},
   165  			Key:   "mapname.0.key.name",
   166  			Value: 3,
   167  		},
   168  		/*
   169  			// TODO: can't access this nested list at all.
   170  			// FIXME: key with name matching substring of nested list can panic
   171  			{
   172  				Config: map[string]interface{}{
   173  					"mapname": []map[string]interface{}{
   174  						map[string]interface{}{
   175  							"key.name": []map[string]interface{}{
   176  								{"subkey": 1},
   177  							},
   178  							"key": 3,
   179  						},
   180  					},
   181  				},
   182  				Key:   "mapname.0.key.name.0.subkey",
   183  				Value: 3,
   184  			},
   185  		*/
   186  	}
   187  
   188  	for i, tc := range cases {
   189  		var rawC *config.RawConfig
   190  		if tc.Config != nil {
   191  			var err error
   192  			rawC, err = config.NewRawConfig(tc.Config)
   193  			if err != nil {
   194  				t.Fatalf("err: %s", err)
   195  			}
   196  		}
   197  
   198  		if tc.Vars != nil {
   199  			vs := make(map[string]ast.Variable)
   200  			for k, v := range tc.Vars {
   201  				vs["var."+k] = ast.Variable{Value: v, Type: ast.TypeString}
   202  			}
   203  
   204  			if err := rawC.Interpolate(vs); err != nil {
   205  				t.Fatalf("err: %s", err)
   206  			}
   207  		}
   208  
   209  		rc := NewResourceConfig(rawC)
   210  		rc.interpolateForce()
   211  
   212  		// Test getting a key
   213  		t.Run(fmt.Sprintf("get-%d", i), func(t *testing.T) {
   214  			v, _ := rc.Get(tc.Key)
   215  			if !reflect.DeepEqual(v, tc.Value) {
   216  				t.Fatalf("%d bad: %#v", i, v)
   217  			}
   218  		})
   219  
   220  		// If we have vars, we don't test copying
   221  		if len(tc.Vars) > 0 {
   222  			continue
   223  		}
   224  
   225  		// Test copying and equality
   226  		t.Run(fmt.Sprintf("copy-and-equal-%d", i), func(t *testing.T) {
   227  			copy := rc.DeepCopy()
   228  			if !reflect.DeepEqual(copy, rc) {
   229  				t.Fatalf("bad:\n\n%#v\n\n%#v", copy, rc)
   230  			}
   231  
   232  			if !copy.Equal(rc) {
   233  				t.Fatalf("copy != rc:\n\n%#v\n\n%#v", copy, rc)
   234  			}
   235  			if !rc.Equal(copy) {
   236  				t.Fatalf("rc != copy:\n\n%#v\n\n%#v", copy, rc)
   237  			}
   238  		})
   239  	}
   240  }
   241  
   242  func TestResourceConfigDeepCopy_nil(t *testing.T) {
   243  	var nilRc *ResourceConfig
   244  	actual := nilRc.DeepCopy()
   245  	if actual != nil {
   246  		t.Fatalf("bad: %#v", actual)
   247  	}
   248  }
   249  
   250  func TestResourceConfigDeepCopy_nilComputed(t *testing.T) {
   251  	rc := &ResourceConfig{}
   252  	actual := rc.DeepCopy()
   253  	if actual.ComputedKeys != nil {
   254  		t.Fatalf("bad: %#v", actual)
   255  	}
   256  }
   257  
   258  func TestResourceConfigEqual_nil(t *testing.T) {
   259  	var nilRc *ResourceConfig
   260  	notNil := NewResourceConfig(nil)
   261  
   262  	if nilRc.Equal(notNil) {
   263  		t.Fatal("should not be equal")
   264  	}
   265  
   266  	if notNil.Equal(nilRc) {
   267  		t.Fatal("should not be equal")
   268  	}
   269  }
   270  
   271  func TestResourceConfigEqual_computedKeyOrder(t *testing.T) {
   272  	c := map[string]interface{}{"foo": "${a.b.c}"}
   273  	rc := NewResourceConfig(config.TestRawConfig(t, c))
   274  	rc2 := NewResourceConfig(config.TestRawConfig(t, c))
   275  
   276  	// Set the computed keys manual
   277  	rc.ComputedKeys = []string{"foo", "bar"}
   278  	rc2.ComputedKeys = []string{"bar", "foo"}
   279  
   280  	if !rc.Equal(rc2) {
   281  		t.Fatal("should be equal")
   282  	}
   283  }
   284  
   285  func testResourceConfig(
   286  	t *testing.T, c map[string]interface{}) *ResourceConfig {
   287  	raw, err := config.NewRawConfig(c)
   288  	if err != nil {
   289  		t.Fatalf("err: %s", err)
   290  	}
   291  
   292  	return NewResourceConfig(raw)
   293  }