github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/helper/schema/resource_test.go (about) 1 package schema 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 8 "github.com/hashicorp/terraform/terraform" 9 ) 10 11 func TestResourceApply_create(t *testing.T) { 12 r := &Resource{ 13 Schema: map[string]*Schema{ 14 "foo": &Schema{ 15 Type: TypeInt, 16 Optional: true, 17 }, 18 }, 19 } 20 21 called := false 22 r.Create = func(d *ResourceData, m interface{}) error { 23 called = true 24 d.SetId("foo") 25 return nil 26 } 27 28 var s *terraform.InstanceState = nil 29 30 d := &terraform.InstanceDiff{ 31 Attributes: map[string]*terraform.ResourceAttrDiff{ 32 "foo": &terraform.ResourceAttrDiff{ 33 New: "42", 34 }, 35 }, 36 } 37 38 actual, err := r.Apply(s, d, nil) 39 if err != nil { 40 t.Fatalf("err: %s", err) 41 } 42 43 if !called { 44 t.Fatal("not called") 45 } 46 47 expected := &terraform.InstanceState{ 48 ID: "foo", 49 Attributes: map[string]string{ 50 "id": "foo", 51 "foo": "42", 52 }, 53 } 54 55 if !reflect.DeepEqual(actual, expected) { 56 t.Fatalf("bad: %#v", actual) 57 } 58 } 59 60 func TestResourceApply_destroy(t *testing.T) { 61 r := &Resource{ 62 Schema: map[string]*Schema{ 63 "foo": &Schema{ 64 Type: TypeInt, 65 Optional: true, 66 }, 67 }, 68 } 69 70 called := false 71 r.Delete = func(d *ResourceData, m interface{}) error { 72 called = true 73 return nil 74 } 75 76 s := &terraform.InstanceState{ 77 ID: "bar", 78 } 79 80 d := &terraform.InstanceDiff{ 81 Destroy: true, 82 } 83 84 actual, err := r.Apply(s, d, nil) 85 if err != nil { 86 t.Fatalf("err: %s", err) 87 } 88 89 if !called { 90 t.Fatal("delete not called") 91 } 92 93 if actual != nil { 94 t.Fatalf("bad: %#v", actual) 95 } 96 } 97 98 func TestResourceApply_destroyCreate(t *testing.T) { 99 r := &Resource{ 100 Schema: map[string]*Schema{ 101 "foo": &Schema{ 102 Type: TypeInt, 103 Optional: true, 104 }, 105 106 "tags": &Schema{ 107 Type: TypeMap, 108 Optional: true, 109 Computed: true, 110 }, 111 }, 112 } 113 114 change := false 115 r.Create = func(d *ResourceData, m interface{}) error { 116 change = d.HasChange("tags") 117 d.SetId("foo") 118 return nil 119 } 120 r.Delete = func(d *ResourceData, m interface{}) error { 121 return nil 122 } 123 124 var s *terraform.InstanceState = &terraform.InstanceState{ 125 ID: "bar", 126 Attributes: map[string]string{ 127 "foo": "bar", 128 "tags.Name": "foo", 129 }, 130 } 131 132 d := &terraform.InstanceDiff{ 133 Attributes: map[string]*terraform.ResourceAttrDiff{ 134 "foo": &terraform.ResourceAttrDiff{ 135 New: "42", 136 RequiresNew: true, 137 }, 138 "tags.Name": &terraform.ResourceAttrDiff{ 139 Old: "foo", 140 New: "foo", 141 RequiresNew: true, 142 }, 143 }, 144 } 145 146 actual, err := r.Apply(s, d, nil) 147 if err != nil { 148 t.Fatalf("err: %s", err) 149 } 150 151 if !change { 152 t.Fatal("should have change") 153 } 154 155 expected := &terraform.InstanceState{ 156 ID: "foo", 157 Attributes: map[string]string{ 158 "id": "foo", 159 "foo": "42", 160 "tags.#": "1", 161 "tags.Name": "foo", 162 }, 163 } 164 165 if !reflect.DeepEqual(actual, expected) { 166 t.Fatalf("bad: %#v", actual) 167 } 168 } 169 170 func TestResourceApply_destroyPartial(t *testing.T) { 171 r := &Resource{ 172 Schema: map[string]*Schema{ 173 "foo": &Schema{ 174 Type: TypeInt, 175 Optional: true, 176 }, 177 }, 178 } 179 180 r.Delete = func(d *ResourceData, m interface{}) error { 181 d.Set("foo", 42) 182 return fmt.Errorf("some error") 183 } 184 185 s := &terraform.InstanceState{ 186 ID: "bar", 187 Attributes: map[string]string{ 188 "foo": "12", 189 }, 190 } 191 192 d := &terraform.InstanceDiff{ 193 Destroy: true, 194 } 195 196 actual, err := r.Apply(s, d, nil) 197 if err == nil { 198 t.Fatal("should error") 199 } 200 201 expected := &terraform.InstanceState{ 202 ID: "bar", 203 Attributes: map[string]string{ 204 "id": "bar", 205 "foo": "42", 206 }, 207 } 208 209 if !reflect.DeepEqual(actual, expected) { 210 t.Fatalf("bad: %#v", actual) 211 } 212 } 213 214 func TestResourceApply_update(t *testing.T) { 215 r := &Resource{ 216 Schema: map[string]*Schema{ 217 "foo": &Schema{ 218 Type: TypeInt, 219 Optional: true, 220 }, 221 }, 222 } 223 224 r.Update = func(d *ResourceData, m interface{}) error { 225 d.Set("foo", 42) 226 return nil 227 } 228 229 s := &terraform.InstanceState{ 230 ID: "foo", 231 Attributes: map[string]string{ 232 "foo": "12", 233 }, 234 } 235 236 d := &terraform.InstanceDiff{ 237 Attributes: map[string]*terraform.ResourceAttrDiff{ 238 "foo": &terraform.ResourceAttrDiff{ 239 New: "13", 240 }, 241 }, 242 } 243 244 actual, err := r.Apply(s, d, nil) 245 if err != nil { 246 t.Fatalf("err: %s", err) 247 } 248 249 expected := &terraform.InstanceState{ 250 ID: "foo", 251 Attributes: map[string]string{ 252 "id": "foo", 253 "foo": "42", 254 }, 255 } 256 257 if !reflect.DeepEqual(actual, expected) { 258 t.Fatalf("bad: %#v", actual) 259 } 260 } 261 262 func TestResourceApply_updateNoCallback(t *testing.T) { 263 r := &Resource{ 264 Schema: map[string]*Schema{ 265 "foo": &Schema{ 266 Type: TypeInt, 267 Optional: true, 268 }, 269 }, 270 } 271 272 r.Update = nil 273 274 s := &terraform.InstanceState{ 275 ID: "foo", 276 Attributes: map[string]string{ 277 "foo": "12", 278 }, 279 } 280 281 d := &terraform.InstanceDiff{ 282 Attributes: map[string]*terraform.ResourceAttrDiff{ 283 "foo": &terraform.ResourceAttrDiff{ 284 New: "13", 285 }, 286 }, 287 } 288 289 actual, err := r.Apply(s, d, nil) 290 if err == nil { 291 t.Fatal("should error") 292 } 293 294 expected := &terraform.InstanceState{ 295 ID: "foo", 296 Attributes: map[string]string{ 297 "foo": "12", 298 }, 299 } 300 301 if !reflect.DeepEqual(actual, expected) { 302 t.Fatalf("bad: %#v", actual) 303 } 304 } 305 306 func TestResourceInternalValidate(t *testing.T) { 307 cases := []struct { 308 In *Resource 309 Err bool 310 }{ 311 { 312 nil, 313 true, 314 }, 315 316 // No optional and no required 317 { 318 &Resource{ 319 Schema: map[string]*Schema{ 320 "foo": &Schema{ 321 Type: TypeInt, 322 Optional: true, 323 Required: true, 324 }, 325 }, 326 }, 327 true, 328 }, 329 } 330 331 for i, tc := range cases { 332 err := tc.In.InternalValidate() 333 if (err != nil) != tc.Err { 334 t.Fatalf("%d: bad: %s", i, err) 335 } 336 } 337 } 338 339 func TestResourceRefresh(t *testing.T) { 340 r := &Resource{ 341 Schema: map[string]*Schema{ 342 "foo": &Schema{ 343 Type: TypeInt, 344 Optional: true, 345 }, 346 }, 347 } 348 349 r.Read = func(d *ResourceData, m interface{}) error { 350 if m != 42 { 351 return fmt.Errorf("meta not passed") 352 } 353 354 return d.Set("foo", d.Get("foo").(int)+1) 355 } 356 357 s := &terraform.InstanceState{ 358 ID: "bar", 359 Attributes: map[string]string{ 360 "foo": "12", 361 }, 362 } 363 364 expected := &terraform.InstanceState{ 365 ID: "bar", 366 Attributes: map[string]string{ 367 "id": "bar", 368 "foo": "13", 369 }, 370 } 371 372 actual, err := r.Refresh(s, 42) 373 if err != nil { 374 t.Fatalf("err: %s", err) 375 } 376 377 if !reflect.DeepEqual(actual, expected) { 378 t.Fatalf("bad: %#v", actual) 379 } 380 } 381 382 func TestResourceRefresh_delete(t *testing.T) { 383 r := &Resource{ 384 Schema: map[string]*Schema{ 385 "foo": &Schema{ 386 Type: TypeInt, 387 Optional: true, 388 }, 389 }, 390 } 391 392 r.Read = func(d *ResourceData, m interface{}) error { 393 d.SetId("") 394 return nil 395 } 396 397 s := &terraform.InstanceState{ 398 ID: "bar", 399 Attributes: map[string]string{ 400 "foo": "12", 401 }, 402 } 403 404 actual, err := r.Refresh(s, 42) 405 if err != nil { 406 t.Fatalf("err: %s", err) 407 } 408 409 if actual != nil { 410 t.Fatalf("bad: %#v", actual) 411 } 412 } 413 414 func TestResourceRefresh_existsError(t *testing.T) { 415 r := &Resource{ 416 Schema: map[string]*Schema{ 417 "foo": &Schema{ 418 Type: TypeInt, 419 Optional: true, 420 }, 421 }, 422 } 423 424 r.Exists = func(*ResourceData, interface{}) (bool, error) { 425 return false, fmt.Errorf("error") 426 } 427 428 r.Read = func(d *ResourceData, m interface{}) error { 429 panic("shouldn't be called") 430 } 431 432 s := &terraform.InstanceState{ 433 ID: "bar", 434 Attributes: map[string]string{ 435 "foo": "12", 436 }, 437 } 438 439 actual, err := r.Refresh(s, 42) 440 if err == nil { 441 t.Fatalf("should error") 442 } 443 if !reflect.DeepEqual(actual, s) { 444 t.Fatalf("bad: %#v", actual) 445 } 446 } 447 448 func TestResourceRefresh_noExists(t *testing.T) { 449 r := &Resource{ 450 Schema: map[string]*Schema{ 451 "foo": &Schema{ 452 Type: TypeInt, 453 Optional: true, 454 }, 455 }, 456 } 457 458 r.Exists = func(*ResourceData, interface{}) (bool, error) { 459 return false, nil 460 } 461 462 r.Read = func(d *ResourceData, m interface{}) error { 463 panic("shouldn't be called") 464 } 465 466 s := &terraform.InstanceState{ 467 ID: "bar", 468 Attributes: map[string]string{ 469 "foo": "12", 470 }, 471 } 472 473 actual, err := r.Refresh(s, 42) 474 if err != nil { 475 t.Fatalf("err: %s", err) 476 } 477 if actual != nil { 478 t.Fatalf("should have no state") 479 } 480 }