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 }