github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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_UpdateUserData(t *testing.T) { 148 var afterCreate, afterUpdate 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", &afterCreate), 160 testAccCheckDigitalOceanDropletAttributes(&afterCreate), 161 resource.TestCheckResourceAttr( 162 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 163 ), 164 }, 165 166 { 167 Config: testAccCheckDigitalOceanDropletConfig_userdata_update(rInt), 168 Check: resource.ComposeTestCheckFunc( 169 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &afterUpdate), 170 resource.TestCheckResourceAttr( 171 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 172 resource.TestCheckResourceAttr( 173 "digitalocean_droplet.foobar", 174 "user_data", 175 "foobar foobar"), 176 testAccCheckDigitalOceanDropletRecreated( 177 t, &afterCreate, &afterUpdate), 178 ), 179 }, 180 }, 181 }) 182 } 183 184 func TestAccDigitalOceanDroplet_UpdateTags(t *testing.T) { 185 var afterCreate, afterUpdate godo.Droplet 186 rInt := acctest.RandInt() 187 188 resource.Test(t, resource.TestCase{ 189 PreCheck: func() { testAccPreCheck(t) }, 190 Providers: testAccProviders, 191 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 192 Steps: []resource.TestStep{ 193 { 194 Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), 195 Check: resource.ComposeTestCheckFunc( 196 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &afterCreate), 197 testAccCheckDigitalOceanDropletAttributes(&afterCreate), 198 resource.TestCheckResourceAttr( 199 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 200 ), 201 }, 202 203 { 204 Config: testAccCheckDigitalOceanDropletConfig_tag_update(rInt), 205 Check: resource.ComposeTestCheckFunc( 206 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &afterUpdate), 207 resource.TestCheckResourceAttr( 208 "digitalocean_droplet.foobar", "name", fmt.Sprintf("foo-%d", rInt)), 209 resource.TestCheckResourceAttr( 210 "digitalocean_droplet.foobar", 211 "tags.#", 212 "1"), 213 resource.TestCheckResourceAttr( 214 "digitalocean_droplet.foobar", 215 "tags.0", 216 "barbaz"), 217 ), 218 }, 219 }, 220 }) 221 } 222 223 func TestAccDigitalOceanDroplet_PrivateNetworkingIpv6(t *testing.T) { 224 var droplet godo.Droplet 225 rInt := acctest.RandInt() 226 227 resource.Test(t, resource.TestCase{ 228 PreCheck: func() { testAccPreCheck(t) }, 229 Providers: testAccProviders, 230 CheckDestroy: testAccCheckDigitalOceanDropletDestroy, 231 Steps: []resource.TestStep{ 232 { 233 Config: testAccCheckDigitalOceanDropletConfig_PrivateNetworkingIpv6(rInt), 234 Check: resource.ComposeTestCheckFunc( 235 testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), 236 testAccCheckDigitalOceanDropletAttributes_PrivateNetworkingIpv6(&droplet), 237 resource.TestCheckResourceAttr( 238 "digitalocean_droplet.foobar", "private_networking", "true"), 239 resource.TestCheckResourceAttr( 240 "digitalocean_droplet.foobar", "ipv6", "true"), 241 ), 242 }, 243 }, 244 }) 245 } 246 247 func testAccCheckDigitalOceanDropletDestroy(s *terraform.State) error { 248 client := testAccProvider.Meta().(*godo.Client) 249 250 for _, rs := range s.RootModule().Resources { 251 if rs.Type != "digitalocean_droplet" { 252 continue 253 } 254 255 id, err := strconv.Atoi(rs.Primary.ID) 256 if err != nil { 257 return err 258 } 259 260 // Try to find the Droplet 261 _, _, err = client.Droplets.Get(id) 262 263 // Wait 264 265 if err != nil && !strings.Contains(err.Error(), "404") { 266 return fmt.Errorf( 267 "Error waiting for droplet (%s) to be destroyed: %s", 268 rs.Primary.ID, err) 269 } 270 } 271 272 return nil 273 } 274 275 func testAccCheckDigitalOceanDropletAttributes(droplet *godo.Droplet) resource.TestCheckFunc { 276 return func(s *terraform.State) error { 277 278 if droplet.Image.Slug != "centos-7-x64" { 279 return fmt.Errorf("Bad image_slug: %s", droplet.Image.Slug) 280 } 281 282 if droplet.Size.Slug != "512mb" { 283 return fmt.Errorf("Bad size_slug: %s", droplet.Size.Slug) 284 } 285 286 if droplet.Region.Slug != "nyc3" { 287 return fmt.Errorf("Bad region_slug: %s", droplet.Region.Slug) 288 } 289 290 return nil 291 } 292 } 293 294 func testAccCheckDigitalOceanDropletRenamedAndResized(droplet *godo.Droplet) resource.TestCheckFunc { 295 return func(s *terraform.State) error { 296 297 if droplet.Size.Slug != "1gb" { 298 return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug) 299 } 300 301 if droplet.Disk != 30 { 302 return fmt.Errorf("Bad disk: %d", droplet.Disk) 303 } 304 305 return nil 306 } 307 } 308 309 func testAccCheckDigitalOceanDropletResizeWithOutDisk(droplet *godo.Droplet) resource.TestCheckFunc { 310 return func(s *terraform.State) error { 311 312 if droplet.Size.Slug != "1gb" { 313 return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug) 314 } 315 316 if droplet.Disk != 20 { 317 return fmt.Errorf("Bad disk: %d", droplet.Disk) 318 } 319 320 return nil 321 } 322 } 323 324 func testAccCheckDigitalOceanDropletAttributes_PrivateNetworkingIpv6(droplet *godo.Droplet) resource.TestCheckFunc { 325 return func(s *terraform.State) error { 326 327 if droplet.Image.Slug != "centos-7-x64" { 328 return fmt.Errorf("Bad image_slug: %s", droplet.Image.Slug) 329 } 330 331 if droplet.Size.Slug != "1gb" { 332 return fmt.Errorf("Bad size_slug: %s", droplet.Size.Slug) 333 } 334 335 if droplet.Region.Slug != "sgp1" { 336 return fmt.Errorf("Bad region_slug: %s", droplet.Region.Slug) 337 } 338 339 if findIPv4AddrByType(droplet, "private") == "" { 340 return fmt.Errorf("No ipv4 private: %s", findIPv4AddrByType(droplet, "private")) 341 } 342 343 // if droplet.IPV6Address("private") == "" { 344 // return fmt.Errorf("No ipv6 private: %s", droplet.IPV6Address("private")) 345 // } 346 347 if findIPv4AddrByType(droplet, "public") == "" { 348 return fmt.Errorf("No ipv4 public: %s", findIPv4AddrByType(droplet, "public")) 349 } 350 351 if findIPv6AddrByType(droplet, "public") == "" { 352 return fmt.Errorf("No ipv6 public: %s", findIPv6AddrByType(droplet, "public")) 353 } 354 355 for _, rs := range s.RootModule().Resources { 356 if rs.Type != "digitalocean_droplet" { 357 continue 358 } 359 if rs.Primary.Attributes["ipv6_address"] != strings.ToLower(findIPv6AddrByType(droplet, "public")) { 360 return fmt.Errorf("IPV6 Address should be lowercase") 361 } 362 363 } 364 365 return nil 366 } 367 } 368 369 func testAccCheckDigitalOceanDropletExists(n string, droplet *godo.Droplet) resource.TestCheckFunc { 370 return func(s *terraform.State) error { 371 rs, ok := s.RootModule().Resources[n] 372 if !ok { 373 return fmt.Errorf("Not found: %s", n) 374 } 375 376 if rs.Primary.ID == "" { 377 return fmt.Errorf("No Droplet ID is set") 378 } 379 380 client := testAccProvider.Meta().(*godo.Client) 381 382 id, err := strconv.Atoi(rs.Primary.ID) 383 if err != nil { 384 return err 385 } 386 387 // Try to find the Droplet 388 retrieveDroplet, _, err := client.Droplets.Get(id) 389 390 if err != nil { 391 return err 392 } 393 394 if strconv.Itoa(retrieveDroplet.ID) != rs.Primary.ID { 395 return fmt.Errorf("Droplet not found") 396 } 397 398 *droplet = *retrieveDroplet 399 400 return nil 401 } 402 } 403 404 func testAccCheckDigitalOceanDropletRecreated(t *testing.T, 405 before, after *godo.Droplet) resource.TestCheckFunc { 406 return func(s *terraform.State) error { 407 if before.ID == after.ID { 408 t.Fatalf("Expected change of droplet IDs, but both were %v", before.ID) 409 } 410 return nil 411 } 412 } 413 414 func testAccCheckDigitalOceanDropletConfig_basic(rInt int) string { 415 return fmt.Sprintf(` 416 resource "digitalocean_droplet" "foobar" { 417 name = "foo-%d" 418 size = "512mb" 419 image = "centos-7-x64" 420 region = "nyc3" 421 user_data = "foobar" 422 }`, rInt) 423 } 424 425 func testAccCheckDigitalOceanDropletConfig_withSSH(rInt int) string { 426 return fmt.Sprintf(` 427 resource "digitalocean_ssh_key" "foobar" { 428 name = "foobar-%d" 429 public_key = "%s" 430 } 431 432 resource "digitalocean_droplet" "foobar" { 433 name = "foo-%d" 434 size = "512mb" 435 image = "centos-7-x64" 436 region = "nyc3" 437 user_data = "foobar" 438 ssh_keys = ["${digitalocean_ssh_key.foobar.id}"] 439 }`, rInt, testAccValidPublicKey, rInt) 440 } 441 442 func testAccCheckDigitalOceanDropletConfig_tag_update(rInt int) string { 443 return fmt.Sprintf(` 444 resource "digitalocean_tag" "barbaz" { 445 name = "barbaz" 446 } 447 448 resource "digitalocean_droplet" "foobar" { 449 name = "foo-%d" 450 size = "512mb" 451 image = "centos-7-x64" 452 region = "nyc3" 453 user_data = "foobar" 454 tags = ["${digitalocean_tag.barbaz.id}"] 455 } 456 `, rInt) 457 } 458 459 func testAccCheckDigitalOceanDropletConfig_userdata_update(rInt int) string { 460 return fmt.Sprintf(` 461 resource "digitalocean_droplet" "foobar" { 462 name = "foo-%d" 463 size = "512mb" 464 image = "centos-7-x64" 465 region = "nyc3" 466 user_data = "foobar foobar" 467 } 468 `, rInt) 469 } 470 471 func testAccCheckDigitalOceanDropletConfig_RenameAndResize(rInt int) string { 472 return fmt.Sprintf(` 473 resource "digitalocean_droplet" "foobar" { 474 name = "baz-%d" 475 size = "1gb" 476 image = "centos-7-x64" 477 region = "nyc3" 478 } 479 `, rInt) 480 } 481 482 func testAccCheckDigitalOceanDropletConfig_resize_without_disk(rInt int) string { 483 return fmt.Sprintf(` 484 resource "digitalocean_droplet" "foobar" { 485 name = "foo-%d" 486 size = "1gb" 487 image = "centos-7-x64" 488 region = "nyc3" 489 user_data = "foobar" 490 resize_disk = false 491 } 492 `, rInt) 493 } 494 495 // IPV6 only in singapore 496 func testAccCheckDigitalOceanDropletConfig_PrivateNetworkingIpv6(rInt int) string { 497 return fmt.Sprintf(` 498 resource "digitalocean_droplet" "foobar" { 499 name = "baz-%d" 500 size = "1gb" 501 image = "centos-7-x64" 502 region = "sgp1" 503 ipv6 = true 504 private_networking = true 505 } 506 `, rInt) 507 }