github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/vsphere/resource_vsphere_virtual_machine_test.go (about) 1 package vsphere 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "regexp" 8 "testing" 9 10 "path/filepath" 11 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/terraform" 14 "github.com/vmware/govmomi" 15 "github.com/vmware/govmomi/find" 16 "github.com/vmware/govmomi/object" 17 "github.com/vmware/govmomi/property" 18 "github.com/vmware/govmomi/vim25/mo" 19 "github.com/vmware/govmomi/vim25/types" 20 "golang.org/x/net/context" 21 ) 22 23 /////// 24 // Various ENV vars are used to setup these tests. Look for `os.Getenv` 25 /////// 26 27 // Base setup function to check that a template, and nic information is set 28 // TODO needs some TLC - determine exactly how we want to do this 29 func testBasicPreCheck(t *testing.T) { 30 31 testAccPreCheck(t) 32 33 if v := os.Getenv("VSPHERE_TEMPLATE"); v == "" { 34 t.Fatal("env variable VSPHERE_TEMPLATE must be set for acceptance tests") 35 } 36 37 if v := os.Getenv("VSPHERE_IPV4_GATEWAY"); v == "" { 38 t.Fatal("env variable VSPHERE_IPV4_GATEWAY must be set for acceptance tests") 39 } 40 41 if v := os.Getenv("VSPHERE_IPV4_ADDRESS"); v == "" { 42 t.Fatal("env variable VSPHERE_IPV4_ADDRESS must be set for acceptance tests") 43 } 44 45 if v := os.Getenv("VSPHERE_NETWORK_LABEL"); v == "" { 46 t.Fatal("env variable VSPHERE_NETWORK_LABEL must be set for acceptance tests") 47 } 48 } 49 50 //// 51 // Collects optional env vars used in the tests 52 //// 53 func setupBaseVars() (string, string) { 54 var locationOpt string 55 var datastoreOpt string 56 57 if v := os.Getenv("VSPHERE_DATACENTER"); v != "" { 58 locationOpt += fmt.Sprintf(" datacenter = \"%s\"\n", v) 59 } 60 if v := os.Getenv("VSPHERE_CLUSTER"); v != "" { 61 locationOpt += fmt.Sprintf(" cluster = \"%s\"\n", v) 62 } 63 if v := os.Getenv("VSPHERE_RESOURCE_POOL"); v != "" { 64 locationOpt += fmt.Sprintf(" resource_pool = \"%s\"\n", v) 65 } 66 if v := os.Getenv("VSPHERE_DATASTORE"); v != "" { 67 datastoreOpt = fmt.Sprintf(" datastore = \"%s\"\n", v) 68 } 69 70 return locationOpt, datastoreOpt 71 } 72 73 //// 74 // Structs and funcs used with DHCP data template 75 //// 76 type TestDHCPBodyData struct { 77 template string 78 locationOpt string 79 datastoreOpt string 80 label string 81 } 82 83 func (body TestDHCPBodyData) parseDHCPTemplateConfigWithTemplate(template string) string { 84 return fmt.Sprintf( 85 template, 86 body.locationOpt, 87 body.label, 88 body.datastoreOpt, 89 body.template, 90 ) 91 92 } 93 94 const testAccCheckVSphereTemplate_dhcp = ` 95 %s 96 vcpu = 2 97 memory = 1024 98 network_interface { 99 label = "%s" 100 } 101 disk { 102 %s 103 template = "%s" 104 } 105 } 106 ` 107 108 // replaces data in the above template 109 func (body TestDHCPBodyData) parseDHCPTemplateConfig() string { 110 return fmt.Sprintf( 111 testAccCheckVSphereTemplate_dhcp, 112 body.locationOpt, 113 body.label, 114 body.datastoreOpt, 115 body.template, 116 ) 117 } 118 119 func (body TestDHCPBodyData) testSprintfDHCPTemplateBodySecondArgDynamic(template string, arg string) string { 120 return fmt.Sprintf( 121 template, 122 body.locationOpt, 123 arg, 124 body.label, 125 body.datastoreOpt, 126 body.template, 127 ) 128 } 129 130 // returns variables that are used in DHCP tests 131 func setupTemplateFuncDHCPData() TestDHCPBodyData { 132 133 locationOpt, datastoreOpt := setupBaseVars() 134 data := TestDHCPBodyData{ 135 template: os.Getenv("VSPHERE_TEMPLATE"), 136 label: os.Getenv("VSPHERE_NETWORK_LABEL_DHCP"), 137 locationOpt: locationOpt, 138 datastoreOpt: datastoreOpt, 139 } 140 // log.Printf("[DEBUG] basic vars= %v", data) 141 return data 142 143 } 144 145 //// 146 // Structs and funcs used with static ip data templates 147 //// 148 type TemplateBasicBodyVars struct { 149 locationOpt string 150 label string 151 ipv4IpAddress string 152 ipv4Prefix string 153 ipv4Gateway string 154 datastoreOpt string 155 template string 156 } 157 158 // Takes a base template that has seven "%s" values in it, used by most fixed ip 159 // tests 160 func (body TemplateBasicBodyVars) testSprintfTemplateBody(template string) string { 161 162 return fmt.Sprintf( 163 template, 164 body.locationOpt, 165 body.label, 166 body.ipv4IpAddress, 167 body.ipv4Prefix, 168 body.ipv4Gateway, 169 body.datastoreOpt, 170 body.template, 171 ) 172 } 173 174 // setups variables used by fixed ip tests 175 func setupTemplateBasicBodyVars() TemplateBasicBodyVars { 176 177 locationOpt, datastoreOpt := setupBaseVars() 178 prefix := os.Getenv("VSPHERE_IPV4_PREFIX") 179 if prefix == "" { 180 prefix = "24" 181 } 182 data := TemplateBasicBodyVars{ 183 template: os.Getenv("VSPHERE_TEMPLATE"), 184 ipv4Gateway: os.Getenv("VSPHERE_IPV4_GATEWAY"), 185 label: os.Getenv("VSPHERE_NETWORK_LABEL"), 186 ipv4IpAddress: os.Getenv("VSPHERE_IPV4_ADDRESS"), 187 ipv4Prefix: prefix, 188 locationOpt: locationOpt, 189 datastoreOpt: datastoreOpt, 190 } 191 // log.Printf("[DEBUG] basic vars= %v", data) 192 return data 193 } 194 195 //// 196 // Basic data to create series of testing functions 197 //// 198 type TestFuncData struct { 199 vm virtualMachine 200 label string 201 vmName string 202 vmResource string 203 numDisks string 204 numCPU string 205 mem string 206 } 207 208 // returns TestCheckFunc's that are used in many of our tests 209 // mem defaults to 1024 210 // cpu defaults to 2 211 // disks defatuls to 1 212 // vmResource defaults to "terraform-test" 213 // vmName defaults to "vsphere_virtual_machine.foo 214 func (test TestFuncData) testCheckFuncBasic() ( 215 resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc, 216 resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc, resource.TestCheckFunc) { 217 //log.Printf("[DEBUG] data= %v", test) 218 mem := test.mem 219 if mem == "" { 220 mem = "1024" 221 } 222 cpu := test.numCPU 223 if cpu == "" { 224 cpu = "2" 225 } 226 disks := test.numDisks 227 if disks == "" { 228 disks = "1" 229 } 230 res := test.vmResource 231 if res == "" { 232 res = "terraform-test" 233 } 234 vmName := test.vmName 235 if vmName == "" { 236 vmName = "vsphere_virtual_machine.foo" 237 } 238 return testAccCheckVSphereVirtualMachineExists(vmName, &test.vm), 239 resource.TestCheckResourceAttr(vmName, "name", res), 240 resource.TestCheckResourceAttr(vmName, "vcpu", cpu), 241 resource.TestMatchResourceAttr(vmName, "uuid", regexp.MustCompile("[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}")), 242 resource.TestCheckResourceAttr(vmName, "memory", mem), 243 resource.TestCheckResourceAttr(vmName, "disk.#", disks), 244 resource.TestCheckResourceAttr(vmName, "network_interface.#", "1"), 245 resource.TestCheckResourceAttr(vmName, "network_interface.0.label", test.label) 246 } 247 248 const testAccCheckVSphereVirtualMachineConfig_really_basic = ` 249 resource "vsphere_virtual_machine" "foo" { 250 name = "terraform-test" 251 ` + testAccTemplateBasicBodyWithEnd 252 253 // WARNING this is one of the base templates. You change this and you will 254 // be impacting multiple tests 255 const testAccTemplateBasicBody = ` 256 %s 257 vcpu = 2 258 memory = 1024 259 network_interface { 260 label = "%s" 261 ipv4_address = "%s" 262 ipv4_prefix_length = %s 263 ipv4_gateway = "%s" 264 } 265 disk { 266 %s 267 template = "%s" 268 iops = 500 269 } 270 ` 271 const testAccTemplateBasicBodyWithEnd = testAccTemplateBasicBody + ` 272 }` 273 274 func TestAccVSphereVirtualMachine_basic(t *testing.T) { 275 var vm virtualMachine 276 basic_vars := setupTemplateBasicBodyVars() 277 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic) 278 279 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic) 280 log.Printf("[DEBUG] template config= %s", config) 281 282 resource.Test(t, resource.TestCase{ 283 PreCheck: func() { testBasicPreCheck(t) }, 284 Providers: testAccProviders, 285 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 286 Steps: []resource.TestStep{ 287 resource.TestStep{ 288 Config: config, 289 Check: resource.ComposeTestCheckFunc( 290 TestFuncData{vm: vm, label: basic_vars.label}.testCheckFuncBasic(), 291 ), 292 }, 293 }, 294 }) 295 } 296 297 const testAccCheckVSphereVirtualMachineConfig_debug = ` 298 provider "vsphere" { 299 client_debug = true 300 } 301 302 ` + testAccCheckVSphereVirtualMachineConfig_really_basic 303 304 func TestAccVSphereVirtualMachine_client_debug(t *testing.T) { 305 var vm virtualMachine 306 basic_vars := setupTemplateBasicBodyVars() 307 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_debug) 308 309 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_debug) 310 log.Printf("[DEBUG] template config= %s", config) 311 312 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 313 TestFuncData{vm: vm, label: basic_vars.label}.testCheckFuncBasic() 314 315 resource.Test(t, resource.TestCase{ 316 PreCheck: func() { testBasicPreCheck(t) }, 317 Providers: testAccProviders, 318 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 319 Steps: []resource.TestStep{ 320 resource.TestStep{ 321 Config: config, 322 Check: resource.ComposeTestCheckFunc( 323 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 324 testAccCheckDebugExists(), 325 ), 326 }, 327 }, 328 }) 329 } 330 331 const testAccCheckVSphereVirtualMachineConfig_diskSCSICapacity = ` 332 resource "vsphere_virtual_machine" "scsiCapacity" { 333 name = "terraform-test" 334 ` + testAccTemplateBasicBody + ` 335 disk { 336 size = 1 337 controller_type = "scsi-paravirtual" 338 name = "one" 339 } 340 disk { 341 size = 1 342 controller_type = "scsi-paravirtual" 343 name = "two" 344 } 345 disk { 346 size = 1 347 controller_type = "scsi-paravirtual" 348 name = "three" 349 } 350 disk { 351 size = 1 352 controller_type = "scsi-paravirtual" 353 name = "four" 354 } 355 disk { 356 size = 1 357 controller_type = "scsi-paravirtual" 358 name = "five" 359 } 360 disk { 361 size = 1 362 controller_type = "scsi-paravirtual" 363 name = "six" 364 } 365 disk { 366 size = 1 367 controller_type = "scsi-paravirtual" 368 name = "seven" 369 } 370 } 371 ` 372 373 func TestAccVSphereVirtualMachine_diskSCSICapacity(t *testing.T) { 374 var vm virtualMachine 375 basic_vars := setupTemplateBasicBodyVars() 376 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_diskSCSICapacity) 377 378 vmName := "vsphere_virtual_machine.scsiCapacity" 379 380 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 381 TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "8"}.testCheckFuncBasic() 382 383 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_diskSCSICapacity) 384 log.Printf("[DEBUG] template config= %s", config) 385 386 resource.Test(t, resource.TestCase{ 387 PreCheck: func() { testAccPreCheck(t) }, 388 Providers: testAccProviders, 389 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 390 Steps: []resource.TestStep{ 391 resource.TestStep{ 392 Config: config, 393 Check: resource.ComposeTestCheckFunc( 394 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 395 ), 396 }, 397 }, 398 }) 399 } 400 401 const testAccCheckVSphereVirtualMachineConfig_initTypeEager = ` 402 resource "vsphere_virtual_machine" "thickEagerZero" { 403 name = "terraform-test" 404 ` + testAccTemplateBasicBody + ` 405 disk { 406 size = 1 407 iops = 500 408 controller_type = "scsi" 409 name = "one" 410 } 411 disk { 412 size = 1 413 controller_type = "ide" 414 type = "eager_zeroed" 415 name = "two" 416 } 417 } 418 ` 419 420 func TestAccVSphereVirtualMachine_diskInitTypeEager(t *testing.T) { 421 var vm virtualMachine 422 basic_vars := setupTemplateBasicBodyVars() 423 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_initTypeEager) 424 425 vmName := "vsphere_virtual_machine.thickEagerZero" 426 427 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 428 TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "3"}.testCheckFuncBasic() 429 430 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_initTypeEager) 431 log.Printf("[DEBUG] template config= %s", config) 432 433 resource.Test(t, resource.TestCase{ 434 PreCheck: func() { testAccPreCheck(t) }, 435 Providers: testAccProviders, 436 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 437 Steps: []resource.TestStep{ 438 resource.TestStep{ 439 Config: config, 440 Check: resource.ComposeTestCheckFunc( 441 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 442 // FIXME dynmically calculate the hashes 443 resource.TestCheckResourceAttr(vmName, "disk.294918912.type", "eager_zeroed"), 444 resource.TestCheckResourceAttr(vmName, "disk.294918912.controller_type", "ide"), 445 resource.TestCheckResourceAttr(vmName, "disk.1380467090.controller_type", "scsi"), 446 ), 447 }, 448 }, 449 }) 450 } 451 452 const testAccCheckVSphereVirtualMachineConfig_initTypeLazy = ` 453 resource "vsphere_virtual_machine" "lazy" { 454 name = "terraform-test" 455 ` + testAccTemplateBasicBody + ` 456 disk { 457 size = 1 458 iops = 500 459 controller_type = "scsi" 460 name = "one" 461 } 462 disk { 463 size = 1 464 controller_type = "ide" 465 type = "lazy" 466 name = "two" 467 } 468 } 469 ` 470 471 func TestAccVSphereVirtualMachine_diskInitTypeLazy(t *testing.T) { 472 var vm virtualMachine 473 basic_vars := setupTemplateBasicBodyVars() 474 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_initTypeLazy) 475 476 vmName := "vsphere_virtual_machine.lazy" 477 478 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 479 TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "3"}.testCheckFuncBasic() 480 481 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_initTypeLazy) 482 log.Printf("[DEBUG] template config= %s", config) 483 484 resource.Test(t, resource.TestCase{ 485 PreCheck: func() { testAccPreCheck(t) }, 486 Providers: testAccProviders, 487 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 488 Steps: []resource.TestStep{ 489 resource.TestStep{ 490 Config: config, 491 Check: resource.ComposeTestCheckFunc( 492 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 493 // FIXME dynmically calculate the hashes 494 resource.TestCheckResourceAttr(vmName, "disk.692719290.type", "lazy"), 495 resource.TestCheckResourceAttr(vmName, "disk.692719290.controller_type", "ide"), 496 resource.TestCheckResourceAttr(vmName, "disk.531766495.controller_type", "scsi"), 497 ), 498 }, 499 }, 500 }) 501 } 502 503 const testAccCheckVSphereVirtualMachineConfig_dhcp = ` 504 resource "vsphere_virtual_machine" "bar" { 505 name = "terraform-test" 506 ` 507 508 func TestAccVSphereVirtualMachine_dhcp(t *testing.T) { 509 var vm virtualMachine 510 data := setupTemplateFuncDHCPData() 511 config := testAccCheckVSphereVirtualMachineConfig_dhcp + data.parseDHCPTemplateConfigWithTemplate(testAccCheckVSphereTemplate_dhcp) 512 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_dhcp+testAccCheckVSphereTemplate_dhcp) 513 log.Printf("[DEBUG] config= %s", config) 514 515 resource.Test(t, resource.TestCase{ 516 PreCheck: func() { testAccPreCheck(t) }, 517 Providers: testAccProviders, 518 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 519 Steps: []resource.TestStep{ 520 resource.TestStep{ 521 Config: config, 522 Check: resource.ComposeTestCheckFunc( 523 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 524 ), 525 }, 526 }, 527 }) 528 } 529 530 const testAccCheckVSphereVirtualMachineConfig_custom_configs = ` 531 resource "vsphere_virtual_machine" "car" { 532 name = "terraform-test-custom" 533 custom_configuration_parameters { 534 "foo" = "bar" 535 "car" = "ferrari" 536 "num" = 42 537 } 538 enable_disk_uuid = true 539 ` 540 541 func TestAccVSphereVirtualMachine_custom_configs(t *testing.T) { 542 543 var vm virtualMachine 544 data := setupTemplateFuncDHCPData() 545 config := testAccCheckVSphereVirtualMachineConfig_custom_configs + data.parseDHCPTemplateConfigWithTemplate(testAccCheckVSphereTemplate_dhcp) 546 vmName := "vsphere_virtual_machine.car" 547 res := "terraform-test-custom" 548 549 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 550 TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: res}.testCheckFuncBasic() 551 552 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_custom_configs+testAccCheckVSphereTemplate_dhcp) 553 log.Printf("[DEBUG] config= %s", config) 554 555 resource.Test(t, resource.TestCase{ 556 PreCheck: func() { testAccPreCheck(t) }, 557 Providers: testAccProviders, 558 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 559 Steps: []resource.TestStep{ 560 resource.TestStep{ 561 Config: config, 562 Check: resource.ComposeTestCheckFunc( 563 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 564 testAccCheckVSphereVirtualMachineExistsHasCustomConfig(vmName, &vm), 565 resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.foo", "bar"), 566 resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.car", "ferrari"), 567 resource.TestCheckResourceAttr(vmName, "custom_configuration_parameters.num", "42"), 568 resource.TestCheckResourceAttr(vmName, "enable_disk_uuid", "true"), 569 ), 570 }, 571 }, 572 }) 573 } 574 575 const testAccCheckVSphereVirtualMachineConfig_createInFolder = ` 576 resource "vsphere_virtual_machine" "folder" { 577 name = "terraform-test-folder" 578 folder = "%s" 579 ` 580 581 func TestAccVSphereVirtualMachine_createInExistingFolder(t *testing.T) { 582 var vm virtualMachine 583 datacenter := os.Getenv("VSPHERE_DATACENTER") 584 585 folder := "tf_test_cpureateInExistingFolder" 586 587 data := setupTemplateFuncDHCPData() 588 config := fmt.Sprintf(testAccCheckVSphereVirtualMachineConfig_createInFolder, 589 folder, 590 ) + data.parseDHCPTemplateConfig() 591 592 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_createInFolder) 593 log.Printf("[DEBUG] template config= %s", config) 594 595 resource.Test(t, resource.TestCase{ 596 PreCheck: func() { testAccPreCheck(t) }, 597 Providers: testAccProviders, 598 CheckDestroy: resource.ComposeTestCheckFunc( 599 testAccCheckVSphereVirtualMachineDestroy, 600 removeVSphereFolder(datacenter, folder, ""), 601 ), 602 Steps: []resource.TestStep{ 603 resource.TestStep{ 604 PreConfig: func() { createVSphereFolder(datacenter, folder) }, 605 Config: config, 606 Check: resource.ComposeTestCheckFunc( 607 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.folder", vmResource: "terraform-test-folder"}.testCheckFuncBasic(), 608 ), 609 }, 610 }, 611 }) 612 } 613 614 const testAccCheckVSphereVirtualMachineConfig_createWithFolder = ` 615 resource "vsphere_folder" "with_folder" { 616 path = "%s" 617 %s 618 } 619 resource "vsphere_virtual_machine" "with_folder" { 620 name = "terraform-test-with-folder" 621 folder = "${vsphere_folder.with_folder.path}" 622 ` 623 624 func TestAccVSphereVirtualMachine_createWithFolder(t *testing.T) { 625 var vm virtualMachine 626 var folderLocationOpt string 627 var f folder 628 629 if v := os.Getenv("VSPHERE_DATACENTER"); v != "" { 630 folderLocationOpt = fmt.Sprintf(" datacenter = \"%s\"\n", v) 631 } 632 633 folder := "tf_test_cpureateWithFolder" 634 635 data := setupTemplateFuncDHCPData() 636 vmName := "vsphere_virtual_machine.with_folder" 637 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 638 TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: "terraform-test-with-folder"}.testCheckFuncBasic() 639 640 config := fmt.Sprintf(testAccCheckVSphereVirtualMachineConfig_createWithFolder, 641 folder, 642 folderLocationOpt, 643 ) + data.parseDHCPTemplateConfig() 644 645 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_createWithFolder+testAccCheckVSphereTemplate_dhcp) 646 log.Printf("[DEBUG] template config= %s", config) 647 648 resource.Test(t, resource.TestCase{ 649 PreCheck: func() { testAccPreCheck(t) }, 650 Providers: testAccProviders, 651 CheckDestroy: resource.ComposeTestCheckFunc( 652 testAccCheckVSphereVirtualMachineDestroy, 653 testAccCheckVSphereFolderDestroy, 654 ), 655 Steps: []resource.TestStep{ 656 resource.TestStep{ 657 Config: config, 658 Check: resource.ComposeTestCheckFunc( 659 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 660 testAccCheckVSphereFolderExists(vmName, &f), 661 resource.TestCheckResourceAttr(vmName, "folder", folder), 662 ), 663 }, 664 }, 665 }) 666 } 667 668 const testAccCheckVsphereVirtualMachineConfig_cdrom = ` 669 resource "vsphere_virtual_machine" "with_cdrom" { 670 name = "terraform-test-with-cdrom" 671 cdrom { 672 datastore = "%s" 673 path = "%s" 674 } 675 ` 676 677 func TestAccVSphereVirtualMachine_createWithCdrom(t *testing.T) { 678 var vm virtualMachine 679 680 // FIXME check that these exist 681 cdromDatastore := os.Getenv("VSPHERE_CDROM_DATASTORE") 682 cdromPath := os.Getenv("VSPHERE_CDROM_PATH") 683 vmName := "vsphere_virtual_machine.with_cdrom" 684 685 data := setupTemplateFuncDHCPData() 686 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 687 TestFuncData{vm: vm, label: data.label, vmName: vmName, vmResource: "terraform-test-with-cdrom"}.testCheckFuncBasic() 688 689 config := fmt.Sprintf( 690 testAccCheckVsphereVirtualMachineConfig_cdrom, 691 cdromDatastore, 692 cdromPath, 693 ) + data.parseDHCPTemplateConfig() 694 695 log.Printf("[DEBUG] template= %s", testAccCheckVsphereVirtualMachineConfig_cdrom) 696 log.Printf("[DEBUG] template config= %s", config) 697 698 resource.Test(t, resource.TestCase{ 699 PreCheck: func() { testAccPreCheck(t) }, 700 Providers: testAccProviders, 701 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 702 Steps: []resource.TestStep{ 703 resource.TestStep{ 704 Config: config, 705 Check: resource.ComposeTestCheckFunc( 706 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 707 //resource.TestCheckResourceAttr( 708 // "vsphere_virtual_machine.with_cdrom", "disk.4088143748.template", template), 709 resource.TestCheckResourceAttr(vmName, "cdrom.#", "1"), 710 resource.TestCheckResourceAttr(vmName, "cdrom.0.datastore", cdromDatastore), 711 resource.TestCheckResourceAttr(vmName, "cdrom.0.path", cdromPath), 712 ), 713 }, 714 }, 715 }) 716 } 717 718 const testAccCheckVSphereVirtualMachineConfig_withExistingVmdk = ` 719 resource "vsphere_virtual_machine" "with_existing_vmdk" { 720 name = "terraform-test-with-existing-vmdk" 721 %s 722 vcpu = 2 723 memory = 1024 724 network_interface { 725 label = "%s" 726 } 727 disk { 728 %s 729 vmdk = "%s" 730 bootable = true 731 } 732 disk { 733 size = 1 734 iops = 500 735 name = "one" 736 } 737 } 738 ` 739 740 func TestAccVSphereVirtualMachine_createWithExistingVmdk(t *testing.T) { 741 var vm virtualMachine 742 vmdk_path := os.Getenv("VSPHERE_VMDK_PATH") 743 744 data := setupTemplateFuncDHCPData() 745 config := fmt.Sprintf( 746 testAccCheckVSphereVirtualMachineConfig_withExistingVmdk, 747 data.locationOpt, 748 data.label, 749 data.datastoreOpt, 750 vmdk_path, 751 ) 752 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_withExistingVmdk) 753 log.Printf("[DEBUG] template config= %s", config) 754 755 resource.Test(t, resource.TestCase{ 756 PreCheck: func() { testAccPreCheck(t) }, 757 Providers: testAccProviders, 758 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 759 Steps: []resource.TestStep{ 760 resource.TestStep{ 761 Config: config, 762 Check: resource.ComposeTestCheckFunc( 763 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.with_existing_vmdk", 764 vmResource: "terraform-test-with-existing-vmdk", numDisks: "2"}.testCheckFuncBasic(), 765 //resource.TestCheckResourceAttr( 766 // "vsphere_virtual_machine.with_existing_vmdk", "disk.2393891804.vmdk", vmdk_path), 767 //resource.TestCheckResourceAttr( 768 // "vsphere_virtual_machine.with_existing_vmdk", "disk.2393891804.bootable", "true"), 769 ), 770 }, 771 }, 772 }) 773 } 774 775 const testAccCheckVSphereVirtualMachineConfig_updateMemory = ` 776 resource "vsphere_virtual_machine" "bar" { 777 name = "terraform-test" 778 %s 779 vcpu = 2 780 memory = %s 781 network_interface { 782 label = "%s" 783 } 784 disk { 785 %s 786 template = "%s" 787 } 788 } 789 ` 790 791 func TestAccVSphereVirtualMachine_updateMemory(t *testing.T) { 792 var vm virtualMachine 793 data := setupTemplateFuncDHCPData() 794 795 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_updateMemory) 796 797 config := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateMemory, "1024") 798 log.Printf("[DEBUG] template config= %s", config) 799 800 configUpdate := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateMemory, "2048") 801 log.Printf("[DEBUG] template configUpdate= %s", configUpdate) 802 803 resource.Test(t, resource.TestCase{ 804 PreCheck: func() { testAccPreCheck(t) }, 805 Providers: testAccProviders, 806 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 807 Steps: []resource.TestStep{ 808 resource.TestStep{ 809 Config: config, 810 Check: resource.ComposeTestCheckFunc( 811 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 812 ), 813 }, 814 resource.TestStep{ 815 Config: configUpdate, 816 Check: resource.ComposeTestCheckFunc( 817 TestFuncData{vm: vm, label: data.label, mem: "2048", vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 818 ), 819 }, 820 }, 821 }) 822 } 823 824 const testAccCheckVSphereVirtualMachineConfig_updateVcpu = ` 825 resource "vsphere_virtual_machine" "bar" { 826 name = "terraform-test" 827 %s 828 vcpu = %s 829 memory = 1024 830 network_interface { 831 label = "%s" 832 } 833 disk { 834 %s 835 template = "%s" 836 } 837 } 838 ` 839 840 func TestAccVSphereVirtualMachine_updateVcpu(t *testing.T) { 841 var vm virtualMachine 842 data := setupTemplateFuncDHCPData() 843 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_updateVcpu) 844 845 config := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateVcpu, "2") 846 log.Printf("[DEBUG] template config= %s", config) 847 848 configUpdate := data.testSprintfDHCPTemplateBodySecondArgDynamic(testAccCheckVSphereVirtualMachineConfig_updateVcpu, "4") 849 log.Printf("[DEBUG] template configUpdate= %s", configUpdate) 850 851 resource.Test(t, resource.TestCase{ 852 PreCheck: func() { testAccPreCheck(t) }, 853 Providers: testAccProviders, 854 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 855 Steps: []resource.TestStep{ 856 resource.TestStep{ 857 Config: config, 858 Check: resource.ComposeTestCheckFunc( 859 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar"}.testCheckFuncBasic(), 860 ), 861 }, 862 resource.TestStep{ 863 Config: configUpdate, 864 Check: resource.ComposeTestCheckFunc( 865 TestFuncData{vm: vm, label: data.label, vmName: "vsphere_virtual_machine.bar", numCPU: "4"}.testCheckFuncBasic(), 866 ), 867 }, 868 }, 869 }) 870 } 871 872 const testAccCheckVSphereVirtualMachineConfig_ipv6 = ` 873 resource "vsphere_virtual_machine" "ipv6" { 874 name = "terraform-test-ipv6" 875 %s 876 vcpu = 2 877 memory = 1024 878 network_interface { 879 label = "%s" 880 %s 881 ipv6_address = "%s" 882 ipv6_prefix_length = 64 883 ipv6_gateway = "%s" 884 } 885 disk { 886 %s 887 template = "%s" 888 iops = 500 889 } 890 disk { 891 size = 1 892 iops = 500 893 name = "one" 894 } 895 } 896 ` 897 898 func TestAccVSphereVirtualMachine_ipv4Andipv6(t *testing.T) { 899 var vm virtualMachine 900 data := setupTemplateBasicBodyVars() 901 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_ipv6) 902 903 vmName := "vsphere_virtual_machine.ipv6" 904 905 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 906 TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "2", vmResource: "terraform-test-ipv6"}.testCheckFuncBasic() 907 908 // FIXME test for this or warn?? 909 ipv6Address := os.Getenv("VSPHERE_IPV6_ADDRESS") 910 ipv6Gateway := os.Getenv("VSPHERE_IPV6_GATEWAY") 911 912 ipv4Settings := fmt.Sprintf(` 913 ipv4_address = "%s" 914 ipv4_prefix_length = %s 915 ipv4_gateway = "%s" 916 `, data.ipv4IpAddress, data.ipv4Prefix, data.ipv4Gateway) 917 918 config := fmt.Sprintf( 919 testAccCheckVSphereVirtualMachineConfig_ipv6, 920 data.locationOpt, 921 data.label, 922 ipv4Settings, 923 ipv6Address, 924 ipv6Gateway, 925 data.datastoreOpt, 926 data.template, 927 ) 928 929 log.Printf("[DEBUG] template config= %s", config) 930 931 resource.Test(t, resource.TestCase{ 932 PreCheck: func() { testAccPreCheck(t) }, 933 Providers: testAccProviders, 934 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 935 Steps: []resource.TestStep{ 936 resource.TestStep{ 937 Config: config, 938 Check: resource.ComposeTestCheckFunc( 939 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 940 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_address", data.ipv4IpAddress), 941 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_gateway", data.ipv4Gateway), 942 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_address", ipv6Address), 943 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_gateway", ipv6Gateway), 944 ), 945 }, 946 }, 947 }) 948 } 949 950 func TestAccVSphereVirtualMachine_ipv6Only(t *testing.T) { 951 var vm virtualMachine 952 data := setupTemplateBasicBodyVars() 953 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_ipv6) 954 955 vmName := "vsphere_virtual_machine.ipv6" 956 957 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 958 TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "2", vmResource: "terraform-test-ipv6"}.testCheckFuncBasic() 959 960 // Checks for this will be handled when this code is merged with https://github.com/hashicorp/terraform/pull/7575. 961 ipv6Address := os.Getenv("VSPHERE_IPV6_ADDRESS") 962 ipv6Gateway := os.Getenv("VSPHERE_IPV6_GATEWAY") 963 964 config := fmt.Sprintf( 965 testAccCheckVSphereVirtualMachineConfig_ipv6, 966 data.locationOpt, 967 data.label, 968 "", 969 ipv6Address, 970 ipv6Gateway, 971 data.datastoreOpt, 972 data.template, 973 ) 974 975 log.Printf("[DEBUG] template config= %s", config) 976 977 resource.Test(t, resource.TestCase{ 978 PreCheck: func() { testAccPreCheck(t) }, 979 Providers: testAccProviders, 980 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 981 Steps: []resource.TestStep{ 982 resource.TestStep{ 983 Config: config, 984 Check: resource.ComposeTestCheckFunc( 985 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 986 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_address", ipv6Address), 987 resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_gateway", ipv6Gateway), 988 ), 989 }, 990 }, 991 }) 992 } 993 994 const testAccCheckVSphereVirtualMachineConfig_updateAddDisks = ` 995 resource "vsphere_virtual_machine" "foo" { 996 name = "terraform-test" 997 ` + testAccTemplateBasicBody + ` 998 disk { 999 size = 1 1000 iops = 500 1001 name = "one" 1002 %s 1003 } 1004 disk { 1005 size = 1 1006 iops = 500 1007 name = "two" 1008 %s 1009 } 1010 disk { 1011 size = 1 1012 iops = 500 1013 name = "three" 1014 %s 1015 } 1016 } 1017 ` 1018 const testAccCheckVSphereVirtualMachineConfig_basic = ` 1019 resource "vsphere_virtual_machine" "foo" { 1020 name = "terraform-test" 1021 ` + testAccTemplateBasicBody + ` 1022 disk { 1023 size = 1 1024 iops = 500 1025 name = "one" 1026 } 1027 } 1028 ` 1029 1030 func TestAccVSphereVirtualMachine_updateDisks(t *testing.T) { 1031 var vm virtualMachine 1032 basic_vars := setupTemplateBasicBodyVars() 1033 config_basic := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_basic) 1034 1035 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic) 1036 log.Printf("[DEBUG] template config= %s", config_basic) 1037 1038 config_add := fmt.Sprintf( 1039 testAccCheckVSphereVirtualMachineConfig_updateAddDisks, 1040 basic_vars.locationOpt, 1041 basic_vars.label, 1042 basic_vars.ipv4IpAddress, 1043 basic_vars.ipv4Prefix, 1044 basic_vars.ipv4Gateway, 1045 basic_vars.datastoreOpt, 1046 basic_vars.template, 1047 basic_vars.datastoreOpt, 1048 basic_vars.datastoreOpt, 1049 basic_vars.datastoreOpt, 1050 ) 1051 1052 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic) 1053 log.Printf("[DEBUG] template config= %s", config_add) 1054 1055 config_del := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic) 1056 1057 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic) 1058 log.Printf("[DEBUG] template config= %s", config_del) 1059 1060 resource.Test(t, resource.TestCase{ 1061 PreCheck: func() { testAccPreCheck(t) }, 1062 Providers: testAccProviders, 1063 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 1064 Steps: []resource.TestStep{ 1065 resource.TestStep{ 1066 Config: config_basic, 1067 Check: resource.ComposeTestCheckFunc( 1068 TestFuncData{vm: vm, label: basic_vars.label, numDisks: "2"}.testCheckFuncBasic(), 1069 ), 1070 }, 1071 resource.TestStep{ 1072 Config: config_add, 1073 Check: resource.ComposeTestCheckFunc( 1074 TestFuncData{vm: vm, label: basic_vars.label, numDisks: "4"}.testCheckFuncBasic(), 1075 ), 1076 }, 1077 resource.TestStep{ 1078 Config: config_del, 1079 Check: resource.ComposeTestCheckFunc( 1080 TestFuncData{vm: vm, label: basic_vars.label, numDisks: "1"}.testCheckFuncBasic(), 1081 ), 1082 }, 1083 }, 1084 }) 1085 } 1086 1087 const testAccCheckVSphereVirtualMachineConfig_mac_address = ` 1088 resource "vsphere_virtual_machine" "mac_address" { 1089 name = "terraform-mac-address" 1090 %s 1091 vcpu = 2 1092 memory = 1024 1093 network_interface { 1094 label = "%s" 1095 mac_address = "%s" 1096 } 1097 disk { 1098 %s 1099 template = "%s" 1100 } 1101 } 1102 ` 1103 1104 // VSPHERE_NETWORK_MAC_ADDRESS needs to be set to run TestAccVSphereVirtualMachine_mac_address 1105 // use a basic NIC MAC address like 6:5c:89:2b:a0:64 1106 func testMacPreCheck(t *testing.T) { 1107 1108 testBasicPreCheck(t) 1109 1110 // TODO should start do parse values to ensure they are correct 1111 // for instance 1112 // func ParseMAC(s string) (hw HardwareAddr, err error) 1113 if v := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS"); v == "" { 1114 t.Fatal("env variable VSPHERE_NETWORK_MAC_ADDRESS must be set for this acceptance test") 1115 } 1116 } 1117 1118 // test new mac address feature 1119 func TestAccVSphereVirtualMachine_mac_address(t *testing.T) { 1120 var vm virtualMachine 1121 data := setupTemplateFuncDHCPData() 1122 vmName := "vsphere_virtual_machine.mac_address" 1123 1124 macAddress := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS") 1125 1126 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_mac_address) 1127 config := fmt.Sprintf( 1128 testAccCheckVSphereVirtualMachineConfig_mac_address, 1129 data.locationOpt, 1130 data.label, 1131 macAddress, 1132 data.datastoreOpt, 1133 data.template, 1134 ) 1135 log.Printf("[DEBUG] template config= %s", config) 1136 1137 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 1138 TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "1", vmResource: "terraform-mac-address"}.testCheckFuncBasic() 1139 1140 resource.Test(t, resource.TestCase{ 1141 PreCheck: func() { testMacPreCheck(t) }, 1142 Providers: testAccProviders, 1143 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 1144 Steps: []resource.TestStep{ 1145 resource.TestStep{ 1146 Config: config, 1147 Check: resource.ComposeTestCheckFunc( 1148 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 1149 resource.TestCheckResourceAttr(vmName, "network_interface.0.mac_address", macAddress), 1150 ), 1151 }, 1152 }, 1153 }) 1154 } 1155 1156 func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error { 1157 client := testAccProvider.Meta().(*govmomi.Client) 1158 finder := find.NewFinder(client.Client, true) 1159 1160 for _, rs := range s.RootModule().Resources { 1161 if rs.Type != "vsphere_virtual_machine" { 1162 continue 1163 } 1164 1165 dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) 1166 if err != nil { 1167 return fmt.Errorf("error %s", err) 1168 } 1169 1170 dcFolders, err := dc.Folders(context.TODO()) 1171 if err != nil { 1172 return fmt.Errorf("error %s", err) 1173 } 1174 1175 folder := dcFolders.VmFolder 1176 if len(rs.Primary.Attributes["folder"]) > 0 { 1177 si := object.NewSearchIndex(client.Client) 1178 folderRef, err := si.FindByInventoryPath( 1179 context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"])) 1180 if err != nil { 1181 return err 1182 } else if folderRef != nil { 1183 folder = folderRef.(*object.Folder) 1184 } 1185 } 1186 1187 v, err := object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) 1188 1189 if v != nil { 1190 return fmt.Errorf("Record still exists") 1191 } 1192 } 1193 1194 return nil 1195 } 1196 1197 func testAccCheckVSphereVirtualMachineExistsHasCustomConfig(n string, vm *virtualMachine) resource.TestCheckFunc { 1198 return func(s *terraform.State) error { 1199 1200 rs, ok := s.RootModule().Resources[n] 1201 if !ok { 1202 return fmt.Errorf("Not found: %s", n) 1203 } 1204 1205 if rs.Primary.ID == "" { 1206 return fmt.Errorf("No ID is set") 1207 } 1208 1209 client := testAccProvider.Meta().(*govmomi.Client) 1210 finder := find.NewFinder(client.Client, true) 1211 1212 dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) 1213 if err != nil { 1214 return fmt.Errorf("error %s", err) 1215 } 1216 1217 dcFolders, err := dc.Folders(context.TODO()) 1218 if err != nil { 1219 return fmt.Errorf("error %s", err) 1220 } 1221 1222 _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["name"]) 1223 if err != nil { 1224 return fmt.Errorf("error %s", err) 1225 } 1226 1227 finder = finder.SetDatacenter(dc) 1228 instance, err := finder.VirtualMachine(context.TODO(), rs.Primary.Attributes["name"]) 1229 if err != nil { 1230 return fmt.Errorf("error %s", err) 1231 } 1232 1233 var mvm mo.VirtualMachine 1234 1235 collector := property.DefaultCollector(client.Client) 1236 1237 if err := collector.RetrieveOne(context.TODO(), instance.Reference(), []string{"config.extraConfig"}, &mvm); err != nil { 1238 return fmt.Errorf("error %s", err) 1239 } 1240 1241 var configMap = make(map[string]types.AnyType) 1242 if mvm.Config != nil && mvm.Config.ExtraConfig != nil && len(mvm.Config.ExtraConfig) > 0 { 1243 for _, v := range mvm.Config.ExtraConfig { 1244 value := v.GetOptionValue() 1245 configMap[value.Key] = value.Value 1246 } 1247 } else { 1248 return fmt.Errorf("error no ExtraConfig") 1249 } 1250 1251 if configMap["foo"] == nil { 1252 return fmt.Errorf("error no ExtraConfig for 'foo'") 1253 } 1254 1255 if configMap["foo"] != "bar" { 1256 return fmt.Errorf("error ExtraConfig 'foo' != bar") 1257 } 1258 1259 if configMap["car"] == nil { 1260 return fmt.Errorf("error no ExtraConfig for 'car'") 1261 } 1262 1263 if configMap["car"] != "ferrari" { 1264 return fmt.Errorf("error ExtraConfig 'car' != ferrari") 1265 } 1266 1267 if configMap["num"] == nil { 1268 return fmt.Errorf("error no ExtraConfig for 'num'") 1269 } 1270 1271 // todo this should be an int, getting back a string 1272 if configMap["num"] != "42" { 1273 return fmt.Errorf("error ExtraConfig 'num' != 42") 1274 } 1275 *vm = virtualMachine{ 1276 name: rs.Primary.ID, 1277 } 1278 1279 return nil 1280 } 1281 } 1282 1283 func testAccCheckDebugExists() resource.TestCheckFunc { 1284 return func(s *terraform.State) error { 1285 if _, err := os.Stat(filepath.Join(os.Getenv("HOME"), ".govmomi")); os.IsNotExist(err) { 1286 return fmt.Errorf("Debug logs not found") 1287 } 1288 1289 return nil 1290 } 1291 1292 } 1293 func testAccCheckVSphereVirtualMachineExists(n string, vm *virtualMachine) resource.TestCheckFunc { 1294 return func(s *terraform.State) error { 1295 if n == "" { 1296 return fmt.Errorf("No vm name passed in") 1297 } 1298 if vm == nil { 1299 return fmt.Errorf("No vm obj passed in") 1300 } 1301 rs, ok := s.RootModule().Resources[n] 1302 if !ok { 1303 return fmt.Errorf("Not found: %s", n) 1304 } 1305 1306 if rs.Primary.ID == "" { 1307 return fmt.Errorf("No ID is set") 1308 } 1309 1310 client := testAccProvider.Meta().(*govmomi.Client) 1311 finder := find.NewFinder(client.Client, true) 1312 1313 dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"]) 1314 if err != nil { 1315 return fmt.Errorf("error %s", err) 1316 } 1317 1318 dcFolders, err := dc.Folders(context.TODO()) 1319 if err != nil { 1320 return fmt.Errorf("error %s", err) 1321 } 1322 1323 folder := dcFolders.VmFolder 1324 if len(rs.Primary.Attributes["folder"]) > 0 { 1325 si := object.NewSearchIndex(client.Client) 1326 folderRef, err := si.FindByInventoryPath( 1327 context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"])) 1328 if err != nil { 1329 return err 1330 } else if folderRef != nil { 1331 folder = folderRef.(*object.Folder) 1332 } 1333 } 1334 1335 _, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"]) 1336 1337 *vm = virtualMachine{ 1338 name: rs.Primary.ID, 1339 } 1340 1341 return nil 1342 } 1343 } 1344 1345 const testAccCheckVSphereVirtualMachineConfig_keepOnRemove = ` 1346 resource "vsphere_virtual_machine" "keep_disk" { 1347 name = "terraform-test" 1348 ` + testAccTemplateBasicBody + ` 1349 disk { 1350 size = 1 1351 iops = 500 1352 controller_type = "scsi" 1353 name = "one" 1354 keep_on_remove = true 1355 } 1356 } 1357 ` 1358 1359 func TestAccVSphereVirtualMachine_keepOnRemove(t *testing.T) { 1360 var vm virtualMachine 1361 basic_vars := setupTemplateBasicBodyVars() 1362 config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_keepOnRemove) 1363 var datastore string 1364 if v := os.Getenv("VSPHERE_DATASTORE"); v != "" { 1365 datastore = v 1366 } 1367 var datacenter string 1368 if v := os.Getenv("VSPHERE_DATACENTER"); v != "" { 1369 datacenter = v 1370 } 1371 1372 vmName := "vsphere_virtual_machine.keep_disk" 1373 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 1374 TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "2"}.testCheckFuncBasic() 1375 1376 log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_keepOnRemove) 1377 log.Printf("[DEBUG] template config= %s", config) 1378 1379 resource.Test(t, resource.TestCase{ 1380 PreCheck: func() { testAccPreCheck(t) }, 1381 Providers: testAccProviders, 1382 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 1383 Steps: []resource.TestStep{ 1384 resource.TestStep{ 1385 Config: config, 1386 Check: resource.ComposeTestCheckFunc( 1387 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 1388 ), 1389 }, 1390 resource.TestStep{ 1391 Config: " ", 1392 Check: checkForDisk(datacenter, datastore, "terraform-test", "one.vmdk", true, true), 1393 }, 1394 }, 1395 }) 1396 } 1397 1398 const testAccVSphereVirtualMachine_DetachUnknownDisks = ` 1399 resource "vsphere_virtual_machine" "detach_unkown_disks" { 1400 name = "terraform-test" 1401 ` + testAccTemplateBasicBody + ` 1402 detach_unknown_disks_on_delete = true 1403 disk { 1404 size = 1 1405 iops = 500 1406 controller_type = "scsi" 1407 name = "one" 1408 keep_on_remove = true 1409 } 1410 disk { 1411 size = 2 1412 iops = 500 1413 controller_type = "scsi" 1414 name = "two" 1415 keep_on_remove = false 1416 } 1417 disk { 1418 size = 3 1419 iops = 500 1420 controller_type = "scsi" 1421 name = "three" 1422 keep_on_remove = true 1423 } 1424 } 1425 ` 1426 1427 func TestAccVSphereVirtualMachine_DetachUnknownDisks(t *testing.T) { 1428 var vm virtualMachine 1429 basic_vars := setupTemplateBasicBodyVars() 1430 config := basic_vars.testSprintfTemplateBody(testAccVSphereVirtualMachine_DetachUnknownDisks) 1431 var datastore string 1432 if v := os.Getenv("VSPHERE_DATASTORE"); v != "" { 1433 datastore = v 1434 } 1435 var datacenter string 1436 if v := os.Getenv("VSPHERE_DATACENTER"); v != "" { 1437 datacenter = v 1438 } 1439 1440 vmName := "vsphere_virtual_machine.detach_unkown_disks" 1441 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label := 1442 TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "4"}.testCheckFuncBasic() 1443 1444 log.Printf("[DEBUG] template= %s", testAccVSphereVirtualMachine_DetachUnknownDisks) 1445 log.Printf("[DEBUG] template config= %s", config) 1446 1447 resource.Test(t, resource.TestCase{ 1448 PreCheck: func() { testAccPreCheck(t) }, 1449 Providers: testAccProviders, 1450 CheckDestroy: testAccCheckVSphereVirtualMachineDestroy, 1451 Steps: []resource.TestStep{ 1452 resource.TestStep{ 1453 Config: config, 1454 Check: resource.ComposeTestCheckFunc( 1455 test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label, 1456 ), 1457 }, 1458 resource.TestStep{ 1459 PreConfig: func() { 1460 createAndAttachDisk(t, "terraform-test", 1, datastore, "terraform-test/tf_custom_disk.vmdk", "lazy", "scsi", datacenter) 1461 }, 1462 Config: " ", 1463 Check: resource.ComposeTestCheckFunc( 1464 checkForDisk(datacenter, datastore, "terraform-test", "one.vmdk", true, false), 1465 checkForDisk(datacenter, datastore, "terraform-test", "two.vmdk", false, false), 1466 checkForDisk(datacenter, datastore, "terraform-test", "three.vmdk", true, false), 1467 checkForDisk(datacenter, datastore, "terraform-test", "tf_custom_disk.vmdk", true, true), 1468 ), 1469 }, 1470 }, 1471 }) 1472 } 1473 1474 func createAndAttachDisk(t *testing.T, vmName string, size int, datastore string, diskPath string, diskType string, adapterType string, datacenter string) { 1475 client := testAccProvider.Meta().(*govmomi.Client) 1476 finder := find.NewFinder(client.Client, true) 1477 1478 dc, err := finder.Datacenter(context.TODO(), datacenter) 1479 if err != nil { 1480 log.Printf("[ERROR] finding Datacenter %s: %v", datacenter, err) 1481 t.Fail() 1482 return 1483 } 1484 finder = finder.SetDatacenter(dc) 1485 ds, err := getDatastore(finder, datastore) 1486 if err != nil { 1487 log.Printf("[ERROR] getDatastore %s: %v", datastore, err) 1488 t.Fail() 1489 return 1490 } 1491 vm, err := finder.VirtualMachine(context.TODO(), vmName) 1492 if err != nil { 1493 log.Printf("[ERROR] finding VM %s: %v", vmName, err) 1494 t.Fail() 1495 return 1496 } 1497 err = addHardDisk(vm, int64(size), int64(0), diskType, ds, diskPath, adapterType) 1498 if err != nil { 1499 log.Printf("[ERROR] addHardDisk: %v", err) 1500 t.Fail() 1501 return 1502 } 1503 } 1504 1505 func vmCleanup(dc *object.Datacenter, ds *object.Datastore, vmName string) error { 1506 client := testAccProvider.Meta().(*govmomi.Client) 1507 fileManager := object.NewFileManager(client.Client) 1508 task, err := fileManager.DeleteDatastoreFile(context.TODO(), ds.Path(vmName), dc) 1509 if err != nil { 1510 log.Printf("[ERROR] checkForDisk - Couldn't delete vm folder '%v': %v", vmName, err) 1511 return err 1512 } 1513 1514 _, err = task.WaitForResult(context.TODO(), nil) 1515 if err != nil { 1516 log.Printf("[ERROR] checForDisk - Failed while deleting vm folder '%v': %v", vmName, err) 1517 return err 1518 } 1519 return nil 1520 } 1521 1522 func checkForDisk(datacenter string, datastore string, vmName string, path string, exists bool, cleanup bool) resource.TestCheckFunc { 1523 return func(s *terraform.State) error { 1524 client := testAccProvider.Meta().(*govmomi.Client) 1525 finder := find.NewFinder(client.Client, true) 1526 1527 dc, err := getDatacenter(client, datacenter) 1528 if err != nil { 1529 return err 1530 } 1531 finder.SetDatacenter(dc) 1532 1533 ds, err := finder.Datastore(context.TODO(), datastore) 1534 if err != nil { 1535 log.Printf("[ERROR] checkForDisk - Couldn't find Datastore '%v': %v", datastore, err) 1536 return err 1537 } 1538 1539 diskPath := vmName + "/" + path 1540 1541 _, err = ds.Stat(context.TODO(), diskPath) 1542 if err != nil && exists { 1543 log.Printf("[ERROR] checkForDisk - Couldn't stat file '%v': %v", diskPath, err) 1544 return err 1545 } else if err == nil && !exists { 1546 errorMessage := fmt.Sprintf("checkForDisk - disk %s still exists", diskPath) 1547 err = vmCleanup(dc, ds, vmName) 1548 if err != nil { 1549 return fmt.Errorf("[ERROR] %s, cleanup also failed: %v", errorMessage, err) 1550 } 1551 return fmt.Errorf("[ERROR] %s", errorMessage) 1552 } 1553 1554 if !cleanup || !exists { 1555 return nil 1556 } 1557 1558 err = vmCleanup(dc, ds, vmName) 1559 if err != nil { 1560 return fmt.Errorf("[ERROR] cleanup failed: %v", err) 1561 } 1562 1563 return nil 1564 } 1565 }