github.com/cbroglie/terraform@v0.7.0-rc3.0.20170410193827-735dfc416d46/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go (about) 1 package digitalocean 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 "testing" 8 9 "github.com/digitalocean/godo" 10 "github.com/hashicorp/terraform/helper/acctest" 11 "github.com/hashicorp/terraform/helper/resource" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 func TestAccDigitalOceanDroplet_Basic(t *testing.T) { 16 var droplet godo.Droplet 17 rInt := acctest.RandInt() 18 19 resource.Test(t, resource.TestCase{ 20 PreCheck: func() { testAccPreCheck(t) }, 21 Providers: testAccProviders, 22 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 23 Steps: []resource.TestStep{ 24 { 25 Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), 26 Check: resource.ComposeTestCheckFunc( 27 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 28 testAccCheckDigitalOceanDropletAttributes(&droplet), 29 resource.TestCheckResourceAttr( 30 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 31 resource.TestCheckResourceAttr( 32 "digitalocean_droplet.foobar", "size", "512mb"), 33 resource.TestCheckResourceAttr( 34 "digitalocean_droplet.foobar", "image", "centos-7-x64"), 35 resource.TestCheckResourceAttr( 36 "digitalocean_droplet.foobar", "region", "nyc3"), 37 resource.TestCheckResourceAttr( 38 "digitalocean_droplet.foobar", "user_data", "foobar"), 39 ), 40 }, 41 }, 42 }) 43 } 44 45 func TestAccDigitalOceanDroplet_withSSH(t *testing.T) { 46 var droplet godo.Droplet 47 rInt := acctest.RandInt() 48 49 resource.Test(t, resource.TestCase{ 50 PreCheck: func() { testAccPreCheck(t) }, 51 Providers: testAccProviders, 52 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 53 Steps: []resource.TestStep{ 54 { 55 Config: testAccCheckDigitalOceanDropletConfig_withSSH(rInt), 56 Check: resource.ComposeTestCheckFunc( 57 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 58 testAccCheckDigitalOceanDropletAttributes(&droplet), 59 resource.TestCheckResourceAttr( 60 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 61 resource.TestCheckResourceAttr( 62 "digitalocean_droplet.foobar", "size", "512mb"), 63 resource.TestCheckResourceAttr( 64 "digitalocean_droplet.foobar", "image", "centos-7-x64"), 65 resource.TestCheckResourceAttr( 66 "digitalocean_droplet.foobar", "region", "nyc3"), 67 resource.TestCheckResourceAttr( 68 "digitalocean_droplet.foobar", "user_data", "foobar"), 69 ), 70 }, 71 }, 72 }) 73 } 74 75 func TestAccDigitalOceanDroplet_Update(t *testing.T) { 76 var droplet godo.Droplet 77 rInt := acctest.RandInt() 78 79 resource.Test(t, resource.TestCase{ 80 PreCheck: func() { testAccPreCheck(t) }, 81 Providers: testAccProviders, 82 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 83 Steps: []resource.TestStep{ 84 { 85 Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), 86 Check: resource.ComposeTestCheckFunc( 87 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 88 testAccCheckDigitalOceanDropletAttributes(&droplet), 89 resource.TestCheckResourceAttr( 90 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 91 ), 92 }, 93 94 { 95 Config: testAccCheckDigitalOceanDropletConfig_RenameAndResize(rInt), 96 Check: resource.ComposeTestCheckFunc( 97 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 98 testAccCheckDigitalOceanDropletRenamedAndResized(&droplet), 99 resource.TestCheckResourceAttr( 100 "digitalocean_droplet.foobar", "name", fmt.Sprintf("baz-%d", rInt)), 101 resource.TestCheckResourceAttr( 102 "digitalocean_droplet.foobar", "size", "1gb"), 103 resource.TestCheckResourceAttr( 104 "digitalocean_droplet.foobar", "disk", "30"), 105 ), 106 }, 107 }, 108 }) 109 } 110 111 func TestAccDigitalOceanDroplet_ResizeWithOutDisk(t *testing.T) { 112 var droplet godo.Droplet 113 rInt := acctest.RandInt() 114 115 resource.Test(t, resource.TestCase{ 116 PreCheck: func() { testAccPreCheck(t) }, 117 Providers: testAccProviders, 118 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 119 Steps: []resource.TestStep{ 120 { 121 Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), 122 Check: resource.ComposeTestCheckFunc( 123 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 124 testAccCheckDigitalOceanDropletAttributes(&droplet), 125 resource.TestCheckResourceAttr( 126 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 127 ), 128 }, 129 130 { 131 Config: testAccCheckDigitalOceanDropletConfig_resize_without_disk(rInt), 132 Check: resource.ComposeTestCheckFunc( 133 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 134 testAccCheckDigitalOceanDropletResizeWithOutDisk(&droplet), 135 resource.TestCheckResourceAttr( 136 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 137 resource.TestCheckResourceAttr( 138 "digitalocean_droplet.foobar", "size", "1gb"), 139 resource.TestCheckResourceAttr( 140 "digitalocean_droplet.foobar", "disk", "20"), 141 ), 142 }, 143 }, 144 }) 145 } 146 147 func TestAccDigitalOceanDroplet_ResizeOnlyDisk(t *testing.T) { 148 var droplet godo.Droplet 149 rInt := acctest.RandInt() 150 151 resource.Test(t, resource.TestCase{ 152 PreCheck: func() { testAccPreCheck(t) }, 153 Providers: testAccProviders, 154 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 155 Steps: []resource.TestStep{ 156 { 157 Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), 158 Check: resource.ComposeTestCheckFunc( 159 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 160 testAccCheckDigitalOceanDropletAttributes(&droplet), 161 resource.TestCheckResourceAttr( 162 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 163 ), 164 }, 165 166 { 167 Config: testAccCheckDigitalOceanDropletConfig_resize_without_disk(rInt), 168 Check: resource.ComposeTestCheckFunc( 169 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 170 testAccCheckDigitalOceanDropletResizeWithOutDisk(&droplet), 171 resource.TestCheckResourceAttr( 172 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 173 resource.TestCheckResourceAttr( 174 "digitalocean_droplet.foobar", "size", "1gb"), 175 resource.TestCheckResourceAttr( 176 "digitalocean_droplet.foobar", "disk", "20"), 177 ), 178 }, 179 180 { 181 Config: testAccCheckDigitalOceanDropletConfig_resize_only_disk(rInt), 182 Check: resource.ComposeTestCheckFunc( 183 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 184 testAccCheckDigitalOceanDropletResizeOnlyDisk(&droplet), 185 resource.TestCheckResourceAttr( 186 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 187 resource.TestCheckResourceAttr( 188 "digitalocean_droplet.foobar", "size", "1gb"), 189 resource.TestCheckResourceAttr( 190 "digitalocean_droplet.foobar", "disk", "30"), 191 ), 192 }, 193 }, 194 }) 195 } 196 197 func TestAccDigitalOceanDroplet_UpdateUserData(t *testing.T) { 198 var afterCreate, afterUpdate godo.Droplet 199 rInt := acctest.RandInt() 200 201 resource.Test(t, resource.TestCase{ 202 PreCheck: func() { testAccPreCheck(t) }, 203 Providers: testAccProviders, 204 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 205 Steps: []resource.TestStep{ 206 { 207 Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), 208 Check: resource.ComposeTestCheckFunc( 209 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &afterCreate), 210 testAccCheckDigitalOceanDropletAttributes(&afterCreate), 211 resource.TestCheckResourceAttr( 212 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 213 ), 214 }, 215 216 { 217 Config: testAccCheckDigitalOceanDropletConfig_userdata_update(rInt), 218 Check: resource.ComposeTestCheckFunc( 219 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &afterUpdate), 220 resource.TestCheckResourceAttr( 221 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 222 resource.TestCheckResourceAttr( 223 "digitalocean_droplet.foobar", 224 "user_data", 225 "foobar foobar"), 226 testAccCheckDigitalOceanDropletRecreated( 227 t, &afterCreate, &afterUpdate), 228 ), 229 }, 230 }, 231 }) 232 } 233 234 func TestAccDigitalOceanDroplet_UpdateTags(t *testing.T) { 235 var afterCreate, afterUpdate godo.Droplet 236 rInt := acctest.RandInt() 237 238 resource.Test(t, resource.TestCase{ 239 PreCheck: func() { testAccPreCheck(t) }, 240 Providers: testAccProviders, 241 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 242 Steps: []resource.TestStep{ 243 { 244 Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), 245 Check: resource.ComposeTestCheckFunc( 246 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &afterCreate), 247 testAccCheckDigitalOceanDropletAttributes(&afterCreate), 248 resource.TestCheckResourceAttr( 249 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 250 ), 251 }, 252 253 { 254 Config: testAccCheckDigitalOceanDropletConfig_tag_update(rInt), 255 Check: resource.ComposeTestCheckFunc( 256 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &afterUpdate), 257 resource.TestCheckResourceAttr( 258 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 259 resource.TestCheckResourceAttr( 260 "digitalocean_droplet.foobar", 261 "tags.#", 262 "1"), 263 resource.TestCheckResourceAttr( 264 "digitalocean_droplet.foobar", 265 "tags.0", 266 "barbaz"), 267 ), 268 }, 269 }, 270 }) 271 } 272 273 func TestAccDigitalOceanDroplet_PrivateNetworkingIpv6(t *testing.T) { 274 var droplet godo.Droplet 275 rInt := acctest.RandInt() 276 277 resource.Test(t, resource.TestCase{ 278 PreCheck: func() { testAccPreCheck(t) }, 279 Providers: testAccProviders, 280 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 281 Steps: []resource.TestStep{ 282 { 283 Config: testAccCheckDigitalOceanDropletConfig_PrivateNetworkingIpv6(rInt), 284 Check: resource.ComposeTestCheckFunc( 285 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 286 testAccCheckDigitalOceanDropletAttributes_PrivateNetworkingIpv6(&droplet), 287 resource.TestCheckResourceAttr( 288 "digitalocean_droplet.foobar", "private_networking", "true"), 289 resource.TestCheckResourceAttr( 290 "digitalocean_droplet.foobar", "ipv6", "true"), 291 ), 292 }, 293 }, 294 }) 295 } 296 297 func testAccCheckDigitalOceanDropletDestroy(s *terraform.State) error { 298 client := testAccProvider.Meta().(*godo.Client) 299 300 for _, rs := range s.RootModule().Resources { 301 if rs.Type != "digitalocean_droplet" { 302 continue 303 } 304 305 id, err := strconv.Atoi(rs.Primary.ID) 306 if err != nil { 307 return err 308 } 309 310 // Try to find the Droplet 311 _, _, err = client.Droplets.Get(id) 312 313 // Wait 314 315 if err != nil && !strings.Contains(err.Error(), "404") { 316 return fmt.Errorf( 317 "Error waiting for droplet (%s) to be destroyed: %s", 318 rs.Primary.ID, err) 319 } 320 } 321 322 return nil 323 } 324 325 func testAccCheckDigitalOceanDropletAttributes(droplet *godo.Droplet) resource.TestCheckFunc { 326 return func(s *terraform.State) error { 327 328 if droplet.Image.Slug != "centos-7-x64" { 329 return fmt.Errorf("Bad image_slug: %s", droplet.Image.Slug) 330 } 331 332 if droplet.Size.Slug != "512mb" { 333 return fmt.Errorf("Bad size_slug: %s", droplet.Size.Slug) 334 } 335 336 if droplet.Region.Slug != "nyc3" { 337 return fmt.Errorf("Bad region_slug: %s", droplet.Region.Slug) 338 } 339 340 return nil 341 } 342 } 343 344 func testAccCheckDigitalOceanDropletRenamedAndResized(droplet *godo.Droplet) resource.TestCheckFunc { 345 return func(s *terraform.State) error { 346 347 if droplet.Size.Slug != "1gb" { 348 return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug) 349 } 350 351 if droplet.Disk != 30 { 352 return fmt.Errorf("Bad disk: %d", droplet.Disk) 353 } 354 355 return nil 356 } 357 } 358 359 func testAccCheckDigitalOceanDropletResizeWithOutDisk(droplet *godo.Droplet) resource.TestCheckFunc { 360 return func(s *terraform.State) error { 361 362 if droplet.Size.Slug != "1gb" { 363 return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug) 364 } 365 366 if droplet.Disk != 20 { 367 return fmt.Errorf("Bad disk: %d", droplet.Disk) 368 } 369 370 return nil 371 } 372 } 373 374 func testAccCheckDigitalOceanDropletResizeOnlyDisk(droplet *godo.Droplet) resource.TestCheckFunc { 375 return func(s *terraform.State) error { 376 377 if droplet.Size.Slug != "1gb" { 378 return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug) 379 } 380 381 if droplet.Disk != 30 { 382 return fmt.Errorf("Bad disk: %d", droplet.Disk) 383 } 384 385 return nil 386 } 387 } 388 389 func testAccCheckDigitalOceanDropletAttributes_PrivateNetworkingIpv6(droplet *godo.Droplet) resource.TestCheckFunc { 390 return func(s *terraform.State) error { 391 392 if droplet.Image.Slug != "centos-7-x64" { 393 return fmt.Errorf("Bad image_slug: %s", droplet.Image.Slug) 394 } 395 396 if droplet.Size.Slug != "1gb" { 397 return fmt.Errorf("Bad size_slug: %s", droplet.Size.Slug) 398 } 399 400 if droplet.Region.Slug != "sgp1" { 401 return fmt.Errorf("Bad region_slug: %s", droplet.Region.Slug) 402 } 403 404 if findIPv4AddrByType(droplet, "private") == "" { 405 return fmt.Errorf("No ipv4 private: %s", findIPv4AddrByType(droplet, "private")) 406 } 407 408 // if droplet.IPV6Address("private") == "" { 409 // return fmt.Errorf("No ipv6 private: %s", droplet.IPV6Address("private")) 410 // } 411 412 if findIPv4AddrByType(droplet, "public") == "" { 413 return fmt.Errorf("No ipv4 public: %s", findIPv4AddrByType(droplet, "public")) 414 } 415 416 if findIPv6AddrByType(droplet, "public") == "" { 417 return fmt.Errorf("No ipv6 public: %s", findIPv6AddrByType(droplet, "public")) 418 } 419 420 for _, rs := range s.RootModule().Resources { 421 if rs.Type != "digitalocean_droplet" { 422 continue 423 } 424 if rs.Primary.Attributes["ipv6_address"] != strings.ToLower(findIPv6AddrByType(droplet, "public")) { 425 return fmt.Errorf("IPV6 Address should be lowercase") 426 } 427 428 } 429 430 return nil 431 } 432 } 433 434 func testAccCheckDigitalOceanDropletExists(n string, droplet *godo.Droplet) resource.TestCheckFunc { 435 return func(s *terraform.State) error { 436 rs, ok := s.RootModule().Resources[n] 437 if !ok { 438 return fmt.Errorf("Not found: %s", n) 439 } 440 441 if rs.Primary.ID == "" { 442 return fmt.Errorf("No Droplet ID is set") 443 } 444 445 client := testAccProvider.Meta().(*godo.Client) 446 447 id, err := strconv.Atoi(rs.Primary.ID) 448 if err != nil { 449 return err 450 } 451 452 // Try to find the Droplet 453 retrieveDroplet, _, err := client.Droplets.Get(id) 454 455 if err != nil { 456 return err 457 } 458 459 if strconv.Itoa(retrieveDroplet.ID) != rs.Primary.ID { 460 return fmt.Errorf("Droplet not found") 461 } 462 463 *droplet = *retrieveDroplet 464 465 return nil 466 } 467 } 468 469 func testAccCheckDigitalOceanDropletRecreated(t *testing.T, 470 before, after *godo.Droplet) resource.TestCheckFunc { 471 return func(s *terraform.State) error { 472 if before.ID == after.ID { 473 t.Fatalf("Expected change of droplet IDs, but both were %v", before.ID) 474 } 475 return nil 476 } 477 } 478 479 func testAccCheckDigitalOceanDropletConfig_basic(rInt int) string { 480 return fmt.Sprintf(` 481 resource "digitalocean_droplet" "foobar" { 482 name = "foo-%d" 483 size = "512mb" 484 image = "centos-7-x64" 485 region = "nyc3" 486 user_data = "foobar" 487 }`, rInt) 488 } 489 490 func testAccCheckDigitalOceanDropletConfig_withSSH(rInt int) string { 491 return fmt.Sprintf(` 492 resource "digitalocean_ssh_key" "foobar" { 493 name = "foobar-%d" 494 public_key = "%s" 495 } 496 497 resource "digitalocean_droplet" "foobar" { 498 name = "foo-%d" 499 size = "512mb" 500 image = "centos-7-x64" 501 region = "nyc3" 502 user_data = "foobar" 503 ssh_keys = ["${digitalocean_ssh_key.foobar.id}"] 504 }`, rInt, testAccValidPublicKey, rInt) 505 } 506 507 func testAccCheckDigitalOceanDropletConfig_tag_update(rInt int) string { 508 return fmt.Sprintf(` 509 resource "digitalocean_tag" "barbaz" { 510 name = "barbaz" 511 } 512 513 resource "digitalocean_droplet" "foobar" { 514 name = "foo-%d" 515 size = "512mb" 516 image = "centos-7-x64" 517 region = "nyc3" 518 user_data = "foobar" 519 tags = ["${digitalocean_tag.barbaz.id}"] 520 } 521 `, rInt) 522 } 523 524 func testAccCheckDigitalOceanDropletConfig_userdata_update(rInt int) string { 525 return fmt.Sprintf(` 526 resource "digitalocean_droplet" "foobar" { 527 name = "foo-%d" 528 size = "512mb" 529 image = "centos-7-x64" 530 region = "nyc3" 531 user_data = "foobar foobar" 532 } 533 `, rInt) 534 } 535 536 func testAccCheckDigitalOceanDropletConfig_RenameAndResize(rInt int) string { 537 return fmt.Sprintf(` 538 resource "digitalocean_droplet" "foobar" { 539 name = "baz-%d" 540 size = "1gb" 541 image = "centos-7-x64" 542 region = "nyc3" 543 } 544 `, rInt) 545 } 546 547 func testAccCheckDigitalOceanDropletConfig_resize_without_disk(rInt int) string { 548 return fmt.Sprintf(` 549 resource "digitalocean_droplet" "foobar" { 550 name = "foo-%d" 551 size = "1gb" 552 image = "centos-7-x64" 553 region = "nyc3" 554 user_data = "foobar" 555 resize_disk = false 556 } 557 `, rInt) 558 } 559 560 func testAccCheckDigitalOceanDropletConfig_resize_only_disk(rInt int) string { 561 return fmt.Sprintf(` 562 resource "digitalocean_droplet" "foobar" { 563 name = "foo-%d" 564 size = "1gb" 565 image = "centos-7-x64" 566 region = "nyc3" 567 user_data = "foobar" 568 resize_disk = true 569 } 570 `, rInt) 571 } 572 573 // IPV6 only in singapore 574 func testAccCheckDigitalOceanDropletConfig_PrivateNetworkingIpv6(rInt int) string { 575 return fmt.Sprintf(` 576 resource "digitalocean_droplet" "foobar" { 577 name = "baz-%d" 578 size = "1gb" 579 image = "centos-7-x64" 580 region = "sgp1" 581 ipv6 = true 582 private_networking = true 583 } 584 `, rInt) 585 } 586 587 var testAccValidPublicKey = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR`