github.com/serbaut/terraform@v0.6.12-0.20160607213102-ac2d195cc560/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go (about) 1 package vsphere 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "testing" 8 9 "github.com/hashicorp/terraform/helper/resource" 10 "github.com/hashicorp/terraform/terraform" 11 "github.com/vmware/govmomi" 12 "github.com/vmware/govmomi/find" 13 "github.com/vmware/govmomi/object" 14 "github.com/vmware/govmomi/property" 15 "github.com/vmware/govmomi/vim25/mo" 16 "github.com/vmware/govmomi/vim25/types" 17 "golang.org/x/net/context" 18 "path/filepath" 19 ) 20 21 /////// 22 // Various ENV vars are used to setup these tests. Look for `os.Getenv` 23 /////// 24 25 // Base setup function to check that a template, and nic information is set 26 // TODO needs some TLC - determine exactly how we want to do this 27 func testBasicPreCheck(t *testing.T) { 28 29 testAccPreCheck(t) 30 31 if v := os.Getenv("VSPHERE_TEMPLATE"); v == "" { 32 t.Fatal("env variable VSPHERE_TEMPLATE must be set for acceptance tests") 33 } 34 35 if v := os.Getenv("VSPHERE_IPV4_GATEWAY"); v == "" { 36 t.Fatal("env variable VSPHERE_IPV4_GATEWAY must be set for acceptance tests") 37 } 38 39 if v := os.Getenv("VSPHERE_IPV4_ADDRESS"); v == "" { 40 t.Fatal("env variable VSPHERE_IPV4_ADDRESS must be set for acceptance tests") 41 } 42 43 if v := os.Getenv("VSPHERE_NETWORK_LABEL"); v == "" { 44 t.Fatal("env variable VSPHERE_NETWORK_LABEL must be set for acceptance tests") 45 } 46 } 47 48 //// 49 // Collects optional env vars used in the tests 50 //// 51 func setupBaseVars() (string, string) { 52 var locationOpt string 53 var datastoreOpt string 54 55 if v := os.Getenv("VSPHERE_DATACENTER"); v != "" { 56 locationOpt += fmt.Sprintf(" datacenter = \"%s\"\n", v) 57 } 58 if v := os.Getenv("VSPHERE_CLUSTER"); v != "" { 59 locationOpt += fmt.Sprintf(" cluster = \"%s\"\n", v) 60 } 61 if v := os.Getenv("VSPHERE_RESOURCE_POOL"); v != "" { 62 locationOpt += fmt.Sprintf(" resource_pool = \"%s\"\n", v) 63 } 64 if v := os.Getenv("VSPHERE_DATASTORE"); v != "" { 65 datastoreOpt = fmt.Sprintf(" datastore = \"%s\"\n", v) 66 } 67 68 return locationOpt, datastoreOpt 69 } 70 71 //// 72 // Structs and funcs used with DHCP data template 73 //// 74 type TestDHCPBodyData struct { 75 template string 76 locationOpt string 77 datastoreOpt string 78 label string 79 } 80 81 func (body TestDHCPBodyData) parseDHCPTemplateConfigWithTemplate(template string) string { 82 return fmt.Sprintf( 83 template, 84 body.locationOpt, 85 body.label, 86 body.datastoreOpt, 87 body.template, 88 ) 89 90 } 91 92 const testAccCheckVSphereTemplate_dhcp = ` 93 %s 94 vcpu = 2 95 memory = 1024 96 network_interface { 97 label = "%s" 98 } 99 disk { 100 %s 101 template = "%s" 102 } 103 } 104 ` 105 106 // replaces data in the above template 107 func (body TestDHCPBodyData) parseDHCPTemplateConfig() string { 108 return fmt.Sprintf( 109 testAccCheckVSphereTemplate_dhcp, 110 body.locationOpt, 111 body.label, 112 body.datastoreOpt, 113 body.template, 114 ) 115 } 116 117 func (body TestDHCPBodyData) testSprintfDHCPTemplateBodySecondArgDynamic(template string, arg string) string { 118 return fmt.Sprintf( 119 template, 120 body.locationOpt, 121 arg, 122 body.label, 123 body.datastoreOpt, 124 body.template, 125 ) 126 } 127 128 // returns variables that are used in DHCP tests 129 func setupTemplateFuncDHCPData() TestDHCPBodyData { 130 131 locationOpt, datastoreOpt := setupBaseVars() 132 data := TestDHCPBodyData{ 133 template: os.Getenv("VSPHERE_TEMPLATE"), 134 label: os.Getenv("VSPHERE_NETWORK_LABEL_DHCP"), 135 locationOpt: locationOpt, 136 datastoreOpt: datastoreOpt, 137 } 138 // log.Printf("[DEBUG] basic vars= %v", data) 139 return data 140 141 } 142 143 //// 144 // Structs and funcs used with static ip data templates 145 //// 146 type TemplateBasicBodyVars struct { 147 locationOpt string 148 label string 149 ipv4IpAddress string 150 ipv4Prefix string 151 ipv4Gateway string 152 datastoreOpt string 153 template string 154 } 155 156 // Takes a base template that has seven "%s" values in it, used by most fixed ip 157 // tests 158 func (body TemplateBasicBodyVars) testSprintfTemplateBody(template string) string { 159 160 return fmt.Sprintf( 161 template, 162 body.locationOpt, 163 body.label, 164 body.ipv4IpAddress, 165 body.ipv4Prefix, 166 body.ipv4Gateway, 167 body.datastoreOpt, 168 body.template, 169 ) 170 } 171 172 // setups variables used by fixed ip tests 173 func setupTemplateBasicBodyVars() TemplateBasicBodyVars { 174 175 locationOpt, datastoreOpt := setupBaseVars() 176 prefix := os.Getenv("VSPHERE_IPV4_PREFIX") 177 if prefix == "" { 178 prefix = "24" 179 } 180 data := TemplateBasicBodyVars{ 181 template: os.Getenv("VSPHERE_TEMPLATE"), 182 ipv4Gateway: os.Getenv("VSPHERE_IPV4_GATEWAY"), 183 label: os.Getenv("VSPHERE_NETWORK_LABEL"), 184 ipv4IpAddress: os.Getenv("VSPHERE_IPV4_ADDRESS"), 185 ipv4Prefix: prefix, 186 locationOpt: locationOpt, 187 datastoreOpt: datastoreOpt, 188 } 189 // log.Printf("[DEBUG] basic vars= %v", data) 190 return data 191 } 192 193 //// 194 // Basic data to create series of testing functions 195 //// 196 type TestFuncData struct { 197 vm virtualMachine 198 label string 199 vmName string 200 vmResource string 201 numDisks string 202 numCPU string 203 mem string 204 } 205 206 // returns TestCheckFunc's that are used in many of our tests 207 // mem defaults to 1024 208 // cpu defaults to 2 209 // disks defatuls to 1 210 // vmResource defaults to "terraform-test" 211 // vmName defaults to "vsphere_virtual_machine.foo 212 func (test TestFuncData) testCheckFuncBasic() ( 213 resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc, 214 resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc) { 215 // log.Printf("[DEBUG] data= %v", test) 216 mem := test.mem 217 if mem == "" { 218 mem = "1024" 219 } 220 cpu := test.numCPU 221 if cpu == "" { 222 cpu = "2" 223 } 224 disks := test.numDisks 225 if disks == "" { 226 disks = "1" 227 } 228 res := test.vmResource 229 if res == "" { 230 res = "terraform-test" 231 } 232 vmName := test.vmName 233 if vmName == "" { 234 vmName = "vsphere_virtual_machine.foo" 235 } 236 return testAccCheckVSphereVirtualMachineExists(vmName, &test.vm), 237 resource.TestCheckResourceAttr(vmName, "name", res), 238 resource.TestCheckResourceAttr(vmName, "vcpu", cpu), 239 resource.TestCheckResourceAttr(vmName, "memory", mem), 240 resource.TestCheckResourceAttr(vmName, "disk.#", disks), 241 resource.TestCheckResourceAttr(vmName, "network_interface.#", "1"), 242 resource.TestCheckResourceAttr(vmName, "network_interface.0.label", test.label) 243 } 244 245 const testAccCheckVSphereVirtualMachineConfig_really_basic = ` 246 resource "vsphere_virtual_machine" "foo" { 247 name = "terraform-test" 248 ` + testAccTemplateBasicBodyWithEnd 249 250 // WARNING this is one of the base templates. You change this and you will 251 // be impacting multiple tests 252 const testAccTemplateBasicBody = ` 253 %s 254 vcpu = 2 255 memory = 1024 256 network_interface { 257 label = "%s" 258 ipv4_address = "%s" 259 ipv4_prefix_length = %s 260 ipv4_gateway = "%s" 261 } 262 disk { 263 %s 264 template = "%s" 265 iops = 500 266 } 267 ` 268 const testAccTemplateBasicBodyWithEnd = testAccTemplateBasicBody + ` 269 }` 270 271 func TestAccVSphereVirtualMachine_basic(t *testing.T) { 272 var vm virtualMachine 273 basic_vars := setupTemplateBasicBodyVars() 274 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic) 275 276 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic) 277 log.Printf("[DEBUG] template config= %s", config) 278 279 resource.Test(t, resource.TestCase{ 280 PreCheck: func() { testBasicPreCheck(t) }, 281 Providers: testAccProviders, 282 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 283 Steps: []resource.TestStep{ 284 resource.TestStep{ 285 Config: config, 286 Check: resource.ComposeTestCheckFunc( 287 TestFuncData{vm: vm, label: basic_vars.label}.testCheckFuncBasic(), 288 ), 289 }, 290 }, 291 }) 292 } 293 294 const testAccCheckVSphereVirtualMachineConfig_debug = ` 295 provider "vsphere" { 296 client_debug = true 297 } 298 299 ` + testAccCheckVSphereVirtualMachineConfig_really_basic 300 301 func TestAccVSphereVirtualMachine_client_debug(t *testing.T) { 302 var vm virtualMachine 303 basic_vars := setupTemplateBasicBodyVars() 304 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_debug) 305 306 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_debug) 307 log.Printf("[DEBUG] template config= %s", config) 308 309 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 310 TestFuncData{vm: vm, label: basic_vars.label}.testCheckFuncBasic() 311 312 resource.Test(t, resource.TestCase{ 313 PreCheck: func() { testBasicPreCheck(t) }, 314 Providers: testAccProviders, 315 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 316 Steps: []resource.TestStep{ 317 resource.TestStep{ 318 Config: config, 319 Check: resource.ComposeTestCheckFunc( 320 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 321 testAccCheckDebugExists(), 322 ), 323 }, 324 }, 325 }) 326 } 327 328 const testAccCheckVSphereVirtualMachineConfig_initType = ` 329 resource "vsphere_virtual_machine" "thin" { 330 name = "terraform-test" 331 ` + testAccTemplateBasicBody + ` 332 disk { 333 size = 1 334 iops = 500 335 controller_type = "scsi" 336 name = "one" 337 } 338 disk { 339 size = 1 340 controller_type = "ide" 341 type = "eager_zeroed" 342 name = "two" 343 } 344 } 345 ` 346 347 func TestAccVSphereVirtualMachine_diskInitType(t *testing.T) { 348 var vm virtualMachine 349 basic_vars := setupTemplateBasicBodyVars() 350 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_initType) 351 352 vmName := "vsphere_virtual_machine.thin" 353 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 354 TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "3"}.testCheckFuncBasic() 355 356 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_initType) 357 log.Printf("[DEBUG] template config= %s", config) 358 359 resource.Test(t, resource.TestCase{ 360 PreCheck: func() { testAccPreCheck(t) }, 361 Providers: testAccProviders, 362 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 363 Steps: []resource.TestStep{ 364 resource.TestStep{ 365 Config: config, 366 Check: resource.ComposeTestCheckFunc( 367 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 368 // FIXME dynmically calculate the hashes 369 resource.TestCheckResourceAttr(vmName, "disk.294918912.type", "eager_zeroed"), 370 resource.TestCheckResourceAttr(vmName, "disk.294918912.controller_type", "ide"), 371 resource.TestCheckResourceAttr(vmName, "disk.1380467090.controller_type", "scsi"), 372 ), 373 }, 374 }, 375 }) 376 } 377 378 const testAccCheckVSphereVirtualMachineConfig_dhcp = ` 379 resource "vsphere_virtual_machine" "bar" { 380 name = "terraform-test" 381 ` 382 383 func TestAccVSphereVirtualMachine_dhcp(t *testing.T) { 384 var vm virtualMachine 385 data := setupTemplateFuncDHCPData() 386 config := testAccCheckVSphereVirtualMachineConfig_dhcp + data.parseDHCPTemplateConfigWithTemplate(testAccCheckVSphereTemplate_dhcp) 387 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_dhcp+testAccCheckVSphereTemplate_dhcp) 388 log.Printf("[DEBUG] config= %s", config) 389 390 resource.Test(t, resource.TestCase{ 391 PreCheck: func() { testAccPreCheck(t) }, 392 Providers: testAccProviders, 393 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 394 Steps: []resource.TestStep{ 395 resource.TestStep{ 396 Config: config, 397 Check: resource.ComposeTestCheckFunc( 398 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 399 ), 400 }, 401 }, 402 }) 403 } 404 405 const testAccCheckVSphereVirtualMachineConfig_custom_configs = ` 406 resource "vsphere_virtual_machine" "car" { 407 name = "terraform-test-custom" 408 custom_configuration_parameters { 409 "foo" = "bar" 410 "car" = "ferrari" 411 "num" = 42 412 } 413 414 ` 415 416 func TestAccVSphereVirtualMachine_custom_configs(t *testing.T) { 417 418 var vm virtualMachine 419 data := setupTemplateFuncDHCPData() 420 config := testAccCheckVSphereVirtualMachineConfig_custom_configs + data.parseDHCPTemplateConfigWithTemplate(testAccCheckVSphereTemplate_dhcp) 421 vmName := "vsphere_virtual_machine.car" 422 res := "terraform-test-custom" 423 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 424 TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: res}.testCheckFuncBasic() 425 426 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_custom_configs+testAccCheckVSphereTemplate_dhcp) 427 log.Printf("[DEBUG] config= %s", config) 428 429 resource.Test(t, resource.TestCase{ 430 PreCheck: func() { testAccPreCheck(t) }, 431 Providers: testAccProviders, 432 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 433 Steps: []resource.TestStep{ 434 resource.TestStep{ 435 Config: config, 436 Check: resource.ComposeTestCheckFunc( 437 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 438 testAccCheckVSphereVirtualMachineExistsHasCustomConfig(vmName, &vm), 439 resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.foo", "bar"), 440 resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.car", "ferrari"), 441 resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.num", "42"), 442 ), 443 }, 444 }, 445 }) 446 } 447 448 const testAccCheckVSphereVirtualMachineConfig_createInFolder = ` 449 resource "vsphere_virtual_machine" "folder" { 450 name = "terraform-test-folder" 451 folder = "%s" 452 ` 453 454 func TestAccVSphereVirtualMachine_createInExistingFolder(t *testing.T) { 455 var vm virtualMachine 456 datacenter := os.Getenv("VSPHERE_DATACENTER") 457 458 folder := "tf_test_cpureateInExistingFolder" 459 460 data := setupTemplateFuncDHCPData() 461 config := fmt.Sprintf(testAccCheckVSphereVirtualMachineConfig_createInFolder, 462 folder, 463 ) + data.parseDHCPTemplateConfig() 464 465 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_createInFolder) 466 log.Printf("[DEBUG] template config= %s", config) 467 468 resource.Test(t, resource.TestCase{ 469 PreCheck: func() { testAccPreCheck(t) }, 470 Providers: testAccProviders, 471 CheckDestroy: resource.ComposeTestCheckFunc( 472 testAccCheckVSphereVirtualMachineDestroy, 473 removeVSphereFolder(datacenter, folder, ""), 474 ), 475 Steps: []resource.TestStep{ 476 resource.TestStep{ 477 PreConfig: func() { createVSphereFolder(datacenter, folder) }, 478 Config: config, 479 Check: resource.ComposeTestCheckFunc( 480 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.folder", vmResource: "terraform-test-folder"}.testCheckFuncBasic(), 481 ), 482 }, 483 }, 484 }) 485 } 486 487 const testAccCheckVSphereVirtualMachineConfig_createWithFolder = ` 488 resource "vsphere_folder" "with_folder" { 489 path = "%s" 490 %s 491 } 492 resource "vsphere_virtual_machine" "with_folder" { 493 name = "terraform-test-with-folder" 494 folder = "${vsphere_folder.with_folder.path}" 495 ` 496 497 func TestAccVSphereVirtualMachine_createWithFolder(t *testing.T) { 498 var vm virtualMachine 499 var folderLocationOpt string 500 var f folder 501 502 if v := os.Getenv("VSPHERE_DATACENTER"); v != "" { 503 folderLocationOpt = fmt.Sprintf(" datacenter = \"%s\"\n", v) 504 } 505 506 folder := "tf_test_cpureateWithFolder" 507 508 data := setupTemplateFuncDHCPData() 509 vmName := "vsphere_virtual_machine.with_folder" 510 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 511 TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: "terraform-test-with-folder"}.testCheckFuncBasic() 512 513 config := fmt.Sprintf(testAccCheckVSphereVirtualMachineConfig_createWithFolder, 514 folder, 515 folderLocationOpt, 516 ) + data.parseDHCPTemplateConfig() 517 518 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_createWithFolder+testAccCheckVSphereTemplate_dhcp) 519 log.Printf("[DEBUG] template config= %s", config) 520 521 resource.Test(t, resource.TestCase{ 522 PreCheck: func() { testAccPreCheck(t) }, 523 Providers: testAccProviders, 524 CheckDestroy: resource.ComposeTestCheckFunc( 525 testAccCheckVSphereVirtualMachineDestroy, 526 testAccCheckVSphereFolderDestroy, 527 ), 528 Steps: []resource.TestStep{ 529 resource.TestStep{ 530 Config: config, 531 Check: resource.ComposeTestCheckFunc( 532 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 533 testAccCheckVSphereFolderExists(vmName, &f), 534 resource.TestCheckResourceAttr(vmName, "folder", folder), 535 ), 536 }, 537 }, 538 }) 539 } 540 541 const testAccCheckVsphereVirtualMachineConfig_cdrom = ` 542 resource "vsphere_virtual_machine" "with_cdrom" { 543 name = "terraform-test-with-cdrom" 544 cdrom { 545 datastore = "%s" 546 path = "%s" 547 } 548 ` 549 550 func TestAccVSphereVirtualMachine_createWithCdrom(t *testing.T) { 551 var vm virtualMachine 552 553 // FIXME check that these exist 554 cdromDatastore := os.Getenv("VSPHERE_CDROM_DATASTORE") 555 cdromPath := os.Getenv("VSPHERE_CDROM_PATH") 556 vmName := "vsphere_virtual_machine.with_cdrom" 557 558 data := setupTemplateFuncDHCPData() 559 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 560 TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: "terraform-test-with-cdrom"}.testCheckFuncBasic() 561 562 config := fmt.Sprintf( 563 testAccCheckVsphereVirtualMachineConfig_cdrom, 564 cdromDatastore, 565 cdromPath, 566 ) + data.parseDHCPTemplateConfig() 567 568 log.Printf("[DEBUG] template= %s", testAccCheckVsphereVirtualMachineConfig_cdrom) 569 log.Printf("[DEBUG] template config= %s", config) 570 571 resource.Test(t, resource.TestCase{ 572 PreCheck: func() { testAccPreCheck(t) }, 573 Providers: testAccProviders, 574 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 575 Steps: []resource.TestStep{ 576 resource.TestStep{ 577 Config: config, 578 Check: resource.ComposeTestCheckFunc( 579 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 580 //resource.TestCheckResourceAttr( 581 // "vsphere_virtual_machine.with_cdrom", "disk.4088143748.template", template), 582 resource.TestCheckResourceAttr(vmName, "cdrom.#", "1"), 583 resource.TestCheckResourceAttr(vmName, "cdrom.0.datastore", cdromDatastore), 584 resource.TestCheckResourceAttr(vmName, "cdrom.0.path", cdromPath), 585 ), 586 }, 587 }, 588 }) 589 } 590 591 const testAccCheckVSphereVirtualMachineConfig_withExistingVmdk = ` 592 resource "vsphere_virtual_machine" "with_existing_vmdk" { 593 name = "terraform-test-with-existing-vmdk" 594 %s 595 vcpu = 2 596 memory = 1024 597 network_interface { 598 label = "%s" 599 } 600 disk { 601 %s 602 vmdk = "%s" 603 bootable = true 604 } 605 } 606 ` 607 608 func TestAccVSphereVirtualMachine_createWithExistingVmdk(t *testing.T) { 609 var vm virtualMachine 610 vmdk_path := os.Getenv("VSPHERE_VMDK_PATH") 611 612 data := setupTemplateFuncDHCPData() 613 config := fmt.Sprintf( 614 testAccCheckVSphereVirtualMachineConfig_withExistingVmdk, 615 data.locationOpt, 616 data.label, 617 data.datastoreOpt, 618 vmdk_path, 619 ) 620 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_withExistingVmdk) 621 log.Printf("[DEBUG] template config= %s", config) 622 623 resource.Test(t, resource.TestCase{ 624 PreCheck: func() { testAccPreCheck(t) }, 625 Providers: testAccProviders, 626 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 627 Steps: []resource.TestStep{ 628 resource.TestStep{ 629 Config: config, 630 Check: resource.ComposeTestCheckFunc( 631 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.with_existing_vmdk", 632 vmResource: "terraform-test-with-existing-vmdk"}.testCheckFuncBasic(), 633 //resource.TestCheckResourceAttr( 634 // "vsphere_virtual_machine.with_existing_vmdk", "disk.2393891804.vmdk", vmdk_path), 635 //resource.TestCheckResourceAttr( 636 // "vsphere_virtual_machine.with_existing_vmdk", "disk.2393891804.bootable", "true"), 637 ), 638 }, 639 }, 640 }) 641 } 642 643 const testAccCheckVSphereVirtualMachineConfig_updateMemory = ` 644 resource "vsphere_virtual_machine" "bar" { 645 name = "terraform-test" 646 %s 647 vcpu = 2 648 memory = %s 649 network_interface { 650 label = "%s" 651 } 652 disk { 653 %s 654 template = "%s" 655 } 656 } 657 ` 658 659 func TestAccVSphereVirtualMachine_updateMemory(t *testing.T) { 660 var vm virtualMachine 661 data := setupTemplateFuncDHCPData() 662 663 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_updateMemory) 664 665 config := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateMemory, "1024") 666 log.Printf("[DEBUG] template config= %s", config) 667 668 configUpdate := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateMemory, "2048") 669 log.Printf("[DEBUG] template configUpdate= %s", configUpdate) 670 671 resource.Test(t, resource.TestCase{ 672 PreCheck: func() { testAccPreCheck(t) }, 673 Providers: testAccProviders, 674 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 675 Steps: []resource.TestStep{ 676 resource.TestStep{ 677 Config: config, 678 Check: resource.ComposeTestCheckFunc( 679 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 680 ), 681 }, 682 resource.TestStep{ 683 Config: configUpdate, 684 Check: resource.ComposeTestCheckFunc( 685 TestFuncData{vm: vm, label: data.label, mem: "2048", vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 686 ), 687 }, 688 }, 689 }) 690 } 691 692 const testAccCheckVSphereVirtualMachineConfig_updateVcpu = ` 693 resource "vsphere_virtual_machine" "bar" { 694 name = "terraform-test" 695 %s 696 vcpu = %s 697 memory = 1024 698 network_interface { 699 label = "%s" 700 } 701 disk { 702 %s 703 template = "%s" 704 } 705 } 706 ` 707 708 func TestAccVSphereVirtualMachine_updateVcpu(t *testing.T) { 709 var vm virtualMachine 710 data := setupTemplateFuncDHCPData() 711 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_updateVcpu) 712 713 config := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateVcpu, "2") 714 log.Printf("[DEBUG] template config= %s", config) 715 716 configUpdate := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateVcpu, "4") 717 log.Printf("[DEBUG] template configUpdate= %s", configUpdate) 718 719 resource.Test(t, resource.TestCase{ 720 PreCheck: func() { testAccPreCheck(t) }, 721 Providers: testAccProviders, 722 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 723 Steps: []resource.TestStep{ 724 resource.TestStep{ 725 Config: config, 726 Check: resource.ComposeTestCheckFunc( 727 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 728 ), 729 }, 730 resource.TestStep{ 731 Config: configUpdate, 732 Check: resource.ComposeTestCheckFunc( 733 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar", numCPU: "4"}.testCheckFuncBasic(), 734 ), 735 }, 736 }, 737 }) 738 } 739 740 const testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6 = ` 741 resource "vsphere_virtual_machine" "ipv4ipv6" { 742 name = "terraform-test-ipv4-ipv6" 743 %s 744 vcpu = 2 745 memory = 1024 746 network_interface { 747 label = "%s" 748 ipv4_address = "%s" 749 ipv4_prefix_length = %s 750 ipv4_gateway = "%s" 751 ipv6_address = "%s" 752 ipv6_prefix_length = 64 753 ipv6_gateway = "%s" 754 } 755 disk { 756 %s 757 template = "%s" 758 iops = 500 759 } 760 disk { 761 size = 1 762 iops = 500 763 name = "one" 764 } 765 } 766 ` 767 768 func TestAccVSphereVirtualMachine_ipv4Andipv6(t *testing.T) { 769 var vm virtualMachine 770 data := setupTemplateBasicBodyVars() 771 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6) 772 773 vmName := "vsphere_virtual_machine.ipv4ipv6" 774 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 775 TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "2", vmResource: "terraform-test-ipv4-ipv6"}.testCheckFuncBasic() 776 777 // FIXME test for this or warn?? 778 ipv6Address := os.Getenv("VSPHERE_IPV6_ADDRESS") 779 ipv6Gateway := os.Getenv("VSPHERE_IPV6_GATEWAY") 780 781 config := fmt.Sprintf( 782 testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6, 783 data.locationOpt, 784 data.label, 785 data.ipv4IpAddress, 786 data.ipv4Prefix, 787 data.ipv4Gateway, 788 ipv6Address, 789 ipv6Gateway, 790 data.datastoreOpt, 791 data.template, 792 ) 793 794 log.Printf("[DEBUG] template config= %s", config) 795 796 resource.Test(t, resource.TestCase{ 797 PreCheck: func() { testAccPreCheck(t) }, 798 Providers: testAccProviders, 799 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 800 Steps: []resource.TestStep{ 801 resource.TestStep{ 802 Config: config, 803 Check: resource.ComposeTestCheckFunc( 804 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 805 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_address", data.ipv4IpAddress), 806 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_gateway", data.ipv4Gateway), 807 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_address", ipv6Address), 808 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_gateway", ipv6Gateway), 809 ), 810 }, 811 }, 812 }) 813 } 814 815 const testAccCheckVSphereVirtualMachineConfig_updateAddDisks = ` 816 resource "vsphere_virtual_machine" "foo" { 817 name = "terraform-test" 818 ` + testAccTemplateBasicBody + ` 819 disk { 820 size = 1 821 iops = 500 822 name = "one" 823 } 824 disk { 825 size = 1 826 iops = 500 827 name = "two" 828 } 829 disk { 830 size = 1 831 iops = 500 832 name = "three" 833 } 834 } 835 ` 836 const testAccCheckVSphereVirtualMachineConfig_basic = ` 837 resource "vsphere_virtual_machine" "foo" { 838 name = "terraform-test" 839 ` + testAccTemplateBasicBody + ` 840 disk { 841 size = 1 842 iops = 500 843 name = "one" 844 } 845 } 846 ` 847 848 func TestAccVSphereVirtualMachine_updateDisks(t *testing.T) { 849 var vm virtualMachine 850 basic_vars := setupTemplateBasicBodyVars() 851 config_basic := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_basic) 852 853 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic) 854 log.Printf("[DEBUG] template config= %s", config_basic) 855 856 config_add := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_updateAddDisks) 857 858 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic) 859 log.Printf("[DEBUG] template config= %s", config_add) 860 861 config_del := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic) 862 863 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic) 864 log.Printf("[DEBUG] template config= %s", config_del) 865 866 resource.Test(t, resource.TestCase{ 867 PreCheck: func() { testAccPreCheck(t) }, 868 Providers: testAccProviders, 869 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 870 Steps: []resource.TestStep{ 871 resource.TestStep{ 872 Config: config_basic, 873 Check: resource.ComposeTestCheckFunc( 874 TestFuncData{vm: vm, label: basic_vars.label, numDisks: "2"}.testCheckFuncBasic(), 875 ), 876 }, 877 resource.TestStep{ 878 Config: config_add, 879 Check: resource.ComposeTestCheckFunc( 880 TestFuncData{vm: vm, label: basic_vars.label, numDisks: "4"}.testCheckFuncBasic(), 881 ), 882 }, 883 resource.TestStep{ 884 Config: config_del, 885 Check: resource.ComposeTestCheckFunc( 886 TestFuncData{vm: vm, label: basic_vars.label, numDisks: "1"}.testCheckFuncBasic(), 887 ), 888 }, 889 }, 890 }) 891 } 892 893 const testAccCheckVSphereVirtualMachineConfig_mac_address = ` 894 resource "vsphere_virtual_machine" "mac_address" { 895 name = "terraform-mac-address" 896 %s 897 vcpu = 2 898 memory = 1024 899 network_interface { 900 label = "%s" 901 mac_address = "%s" 902 } 903 disk { 904 %s 905 template = "%s" 906 } 907 } 908 ` 909 910 // VSPHERE_NETWORK_MAC_ADDRESS needs to be set to run TestAccVSphereVirtualMachine_mac_address 911 // use a basic NIC MAC address like 6:5c:89:2b:a0:64 912 func testMacPreCheck(t *testing.T) { 913 914 testBasicPreCheck(t) 915 916 // TODO should start do parse values to ensure they are correct 917 // for instance 918 // func ParseMAC(s string) (hw HardwareAddr, err error) 919 if v := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS"); v == "" { 920 t.Fatal("env variable VSPHERE_NETWORK_MAC_ADDRESS must be set for this acceptance test") 921 } 922 } 923 924 // test new mac address feature 925 func TestAccVSphereVirtualMachine_mac_address(t *testing.T) { 926 var vm virtualMachine 927 data := setupTemplateFuncDHCPData() 928 vmName := "vsphere_virtual_machine.mac_address" 929 930 macAddress := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS") 931 932 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_mac_address) 933 config := fmt.Sprintf( 934 testAccCheckVSphereVirtualMachineConfig_mac_address, 935 data.locationOpt, 936 data.label, 937 macAddress, 938 data.datastoreOpt, 939 data.template, 940 ) 941 log.Printf("[DEBUG] template config= %s", config) 942 943 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 944 TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "1", vmResource: "terraform-mac-address"}.testCheckFuncBasic() 945 946 resource.Test(t, resource.TestCase{ 947 PreCheck: func() { testMacPreCheck(t) }, 948 Providers: testAccProviders, 949 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 950 Steps: []resource.TestStep{ 951 resource.TestStep{ 952 Config: config, 953 Check: resource.ComposeTestCheckFunc( 954 test_exists, test_name, test_cpu, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 955 resource.TestCheckResourceAttr(vmName, "network_interface.0.mac_address", macAddress), 956 ), 957 }, 958 }, 959 }) 960 } 961 962 func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error { 963 client := testAccProvider.Meta().(*govmomi.Client) 964 finder := find.NewFinder(client.Client, true) 965 966 for _, rs := range s.RootModule().Resources { 967 if rs.Type != "vsphere_virtual_machine" { 968 continue 969 } 970 971 dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) 972 if err != nil { 973 return fmt.Errorf("error %s", err) 974 } 975 976 dcFolders, err := dc.Folders(context.TODO()) 977 if err != nil { 978 return fmt.Errorf("error %s", err) 979 } 980 981 folder := dcFolders.VmFolder 982 if len(rs.Primary.Attributes["folder"]) > 0 { 983 si := object.NewSearchIndex(client.Client) 984 folderRef, err := si.FindByInventoryPath( 985 context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"])) 986 if err != nil { 987 return err 988 } else if folderRef != nil { 989 folder = folderRef.(*object.Folder) 990 } 991 } 992 993 v, err := object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) 994 995 if v != nil { 996 return fmt.Errorf("Record still exists") 997 } 998 } 999 1000 return nil 1001 } 1002 1003 func testAccCheckVSphereVirtualMachineExistsHasCustomConfig(n string, vm *virtualMachine) resource.TestCheckFunc { 1004 return func(s *terraform.State) error { 1005 1006 rs, ok := s.RootModule().Resources[n] 1007 if !ok { 1008 return fmt.Errorf("Not found: %s", n) 1009 } 1010 1011 if rs.Primary.ID == "" { 1012 return fmt.Errorf("No ID is set") 1013 } 1014 1015 client := testAccProvider.Meta().(*govmomi.Client) 1016 finder := find.NewFinder(client.Client, true) 1017 1018 dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) 1019 if err != nil { 1020 return fmt.Errorf("error %s", err) 1021 } 1022 1023 dcFolders, err := dc.Folders(context.TODO()) 1024 if err != nil { 1025 return fmt.Errorf("error %s", err) 1026 } 1027 1028 _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["name"]) 1029 if err != nil { 1030 return fmt.Errorf("error %s", err) 1031 } 1032 1033 finder = finder.SetDatacenter(dc) 1034 instance, err := finder.VirtualMachine(context.TODO(), rs.Primary.Attributes["name"]) 1035 if err != nil { 1036 return fmt.Errorf("error %s", err) 1037 } 1038 1039 var mvm mo.VirtualMachine 1040 1041 collector := property.DefaultCollector(client.Client) 1042 1043 if err := collector.RetrieveOne(context.TODO(), instance.Reference(), []string{"config.extraConfig"}, &mvm); err != nil { 1044 return fmt.Errorf("error %s", err) 1045 } 1046 1047 var configMap = make(map[string]types.AnyType) 1048 if mvm.Config != nil && mvm.Config.ExtraConfig != nil && len(mvm.Config.ExtraConfig) > 0 { 1049 for _, v := range mvm.Config.ExtraConfig { 1050 value := v.GetOptionValue() 1051 configMap[value.Key] = value.Value 1052 } 1053 } else { 1054 return fmt.Errorf("error no ExtraConfig") 1055 } 1056 1057 if configMap["foo"] == nil { 1058 return fmt.Errorf("error no ExtraConfig for 'foo'") 1059 } 1060 1061 if configMap["foo"] != "bar" { 1062 return fmt.Errorf("error ExtraConfig 'foo' != bar") 1063 } 1064 1065 if configMap["car"] == nil { 1066 return fmt.Errorf("error no ExtraConfig for 'car'") 1067 } 1068 1069 if configMap["car"] != "ferrari" { 1070 return fmt.Errorf("error ExtraConfig 'car' != ferrari") 1071 } 1072 1073 if configMap["num"] == nil { 1074 return fmt.Errorf("error no ExtraConfig for 'num'") 1075 } 1076 1077 // todo this should be an int, getting back a string 1078 if configMap["num"] != "42" { 1079 return fmt.Errorf("error ExtraConfig 'num' != 42") 1080 } 1081 *vm = virtualMachine{ 1082 name: rs.Primary.ID, 1083 } 1084 1085 return nil 1086 } 1087 } 1088 1089 func testAccCheckDebugExists() resource.TestCheckFunc { 1090 return func(s *terraform.State) error { 1091 if _, err := os.Stat(filepath.Join(os.Getenv("HOME"), ".govmomi")); os.IsNotExist(err) { 1092 return fmt.Errorf("Debug logs not found") 1093 } 1094 1095 return nil 1096 } 1097 1098 } 1099 func testAccCheckVSphereVirtualMachineExists(n string, vm *virtualMachine) resource.TestCheckFunc { 1100 return func(s *terraform.State) error { 1101 if n == "" { 1102 return fmt.Errorf("No vm name passed in") 1103 } 1104 if vm == nil { 1105 return fmt.Errorf("No vm obj passed in") 1106 } 1107 rs, ok := s.RootModule().Resources[n] 1108 if !ok { 1109 return fmt.Errorf("Not found: %s", n) 1110 } 1111 1112 if rs.Primary.ID == "" { 1113 return fmt.Errorf("No ID is set") 1114 } 1115 1116 client := testAccProvider.Meta().(*govmomi.Client) 1117 finder := find.NewFinder(client.Client, true) 1118 1119 dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) 1120 if err != nil { 1121 return fmt.Errorf("error %s", err) 1122 } 1123 1124 dcFolders, err := dc.Folders(context.TODO()) 1125 if err != nil { 1126 return fmt.Errorf("error %s", err) 1127 } 1128 1129 folder := dcFolders.VmFolder 1130 if len(rs.Primary.Attributes["folder"]) > 0 { 1131 si := object.NewSearchIndex(client.Client) 1132 folderRef, err := si.FindByInventoryPath( 1133 context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"])) 1134 if err != nil { 1135 return err 1136 } else if folderRef != nil { 1137 folder = folderRef.(*object.Folder) 1138 } 1139 } 1140 1141 _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) 1142 1143 *vm = virtualMachine{ 1144 name: rs.Primary.ID, 1145 } 1146 1147 return nil 1148 } 1149 }