github.com/bfallik/terraform@v0.7.1-0.20160814101525-d3a4714efbf5/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_ipv4Andipv6 = `
   873  resource "vsphere_virtual_machine" "ipv4ipv6" {
   874      name = "terraform-test-ipv4-ipv6"
   875  %s
   876      vcpu = 2
   877      memory = 1024
   878      network_interface {
   879          label = "%s"
   880          ipv4_address = "%s"
   881          ipv4_prefix_length = %s
   882          ipv4_gateway = "%s"
   883          ipv6_address = "%s"
   884          ipv6_prefix_length = 64
   885          ipv6_gateway = "%s"
   886      }
   887      disk {
   888  %s
   889          template = "%s"
   890          iops = 500
   891      }
   892      disk {
   893          size = 1
   894          iops = 500
   895  		name = "one"
   896      }
   897  }
   898  `
   899  
   900  func TestAccVSphereVirtualMachine_ipv4Andipv6(t *testing.T) {
   901  	var vm virtualMachine
   902  	data := setupTemplateBasicBodyVars()
   903  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6)
   904  
   905  	vmName := "vsphere_virtual_machine.ipv4ipv6"
   906  
   907  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
   908  		TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "2", vmResource: "terraform-test-ipv4-ipv6"}.testCheckFuncBasic()
   909  
   910  	// FIXME test for this or warn??
   911  	ipv6Address := os.Getenv("VSPHERE_IPV6_ADDRESS")
   912  	ipv6Gateway := os.Getenv("VSPHERE_IPV6_GATEWAY")
   913  
   914  	config := fmt.Sprintf(
   915  		testAccCheckVSphereVirtualMachineConfig_ipv4Andipv6,
   916  		data.locationOpt,
   917  		data.label,
   918  		data.ipv4IpAddress,
   919  		data.ipv4Prefix,
   920  		data.ipv4Gateway,
   921  		ipv6Address,
   922  		ipv6Gateway,
   923  		data.datastoreOpt,
   924  		data.template,
   925  	)
   926  
   927  	log.Printf("[DEBUG] template config= %s", config)
   928  
   929  	resource.Test(t, resource.TestCase{
   930  		PreCheck:     func() { testAccPreCheck(t) },
   931  		Providers:    testAccProviders,
   932  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
   933  		Steps: []resource.TestStep{
   934  			resource.TestStep{
   935  				Config: config,
   936  				Check: resource.ComposeTestCheckFunc(
   937  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
   938  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_address", data.ipv4IpAddress),
   939  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv4_gateway", data.ipv4Gateway),
   940  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_address", ipv6Address),
   941  					resource.TestCheckResourceAttr(vmName, "network_interface.0.ipv6_gateway", ipv6Gateway),
   942  				),
   943  			},
   944  		},
   945  	})
   946  }
   947  
   948  const testAccCheckVSphereVirtualMachineConfig_updateAddDisks = `
   949  resource "vsphere_virtual_machine" "foo" {
   950      name = "terraform-test"
   951  ` + testAccTemplateBasicBody + `
   952      disk {
   953          size = 1
   954          iops = 500
   955  	name = "one"
   956      }
   957  	disk {
   958          size = 1
   959          iops = 500
   960  	name = "two"
   961      }
   962  	disk {
   963          size = 1
   964          iops = 500
   965  	name = "three"
   966      }
   967  }
   968  `
   969  const testAccCheckVSphereVirtualMachineConfig_basic = `
   970  resource "vsphere_virtual_machine" "foo" {
   971      name = "terraform-test"
   972  ` + testAccTemplateBasicBody + `
   973      disk {
   974          size = 1
   975          iops = 500
   976  	name = "one"
   977      }
   978  }
   979  `
   980  
   981  func TestAccVSphereVirtualMachine_updateDisks(t *testing.T) {
   982  	var vm virtualMachine
   983  	basic_vars := setupTemplateBasicBodyVars()
   984  	config_basic := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_basic)
   985  
   986  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic)
   987  	log.Printf("[DEBUG] template config= %s", config_basic)
   988  
   989  	config_add := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_updateAddDisks)
   990  
   991  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_basic)
   992  	log.Printf("[DEBUG] template config= %s", config_add)
   993  
   994  	config_del := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_really_basic)
   995  
   996  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_really_basic)
   997  	log.Printf("[DEBUG] template config= %s", config_del)
   998  
   999  	resource.Test(t, resource.TestCase{
  1000  		PreCheck:     func() { testAccPreCheck(t) },
  1001  		Providers:    testAccProviders,
  1002  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
  1003  		Steps: []resource.TestStep{
  1004  			resource.TestStep{
  1005  				Config: config_basic,
  1006  				Check: resource.ComposeTestCheckFunc(
  1007  					TestFuncData{vm: vm, label: basic_vars.label, numDisks: "2"}.testCheckFuncBasic(),
  1008  				),
  1009  			},
  1010  			resource.TestStep{
  1011  				Config: config_add,
  1012  				Check: resource.ComposeTestCheckFunc(
  1013  					TestFuncData{vm: vm, label: basic_vars.label, numDisks: "4"}.testCheckFuncBasic(),
  1014  				),
  1015  			},
  1016  			resource.TestStep{
  1017  				Config: config_del,
  1018  				Check: resource.ComposeTestCheckFunc(
  1019  					TestFuncData{vm: vm, label: basic_vars.label, numDisks: "1"}.testCheckFuncBasic(),
  1020  				),
  1021  			},
  1022  		},
  1023  	})
  1024  }
  1025  
  1026  const testAccCheckVSphereVirtualMachineConfig_mac_address = `
  1027  resource "vsphere_virtual_machine" "mac_address" {
  1028      name = "terraform-mac-address"
  1029  %s
  1030      vcpu = 2
  1031      memory = 1024
  1032      network_interface {
  1033          label = "%s"
  1034          mac_address = "%s"
  1035      }
  1036      disk {
  1037  %s
  1038          template = "%s"
  1039      }
  1040  }
  1041  `
  1042  
  1043  // VSPHERE_NETWORK_MAC_ADDRESS needs to be set to run TestAccVSphereVirtualMachine_mac_address
  1044  // use a basic NIC MAC address like 6:5c:89:2b:a0:64
  1045  func testMacPreCheck(t *testing.T) {
  1046  
  1047  	testBasicPreCheck(t)
  1048  
  1049  	// TODO should start do parse values to ensure they are correct
  1050  	// for instance
  1051  	//  func ParseMAC(s string) (hw HardwareAddr, err error)
  1052  	if v := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS"); v == "" {
  1053  		t.Fatal("env variable VSPHERE_NETWORK_MAC_ADDRESS must be set for this acceptance test")
  1054  	}
  1055  }
  1056  
  1057  // test new mac address feature
  1058  func TestAccVSphereVirtualMachine_mac_address(t *testing.T) {
  1059  	var vm virtualMachine
  1060  	data := setupTemplateFuncDHCPData()
  1061  	vmName := "vsphere_virtual_machine.mac_address"
  1062  
  1063  	macAddress := os.Getenv("VSPHERE_NETWORK_MAC_ADDRESS")
  1064  
  1065  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_mac_address)
  1066  	config := fmt.Sprintf(
  1067  		testAccCheckVSphereVirtualMachineConfig_mac_address,
  1068  		data.locationOpt,
  1069  		data.label,
  1070  		macAddress,
  1071  		data.datastoreOpt,
  1072  		data.template,
  1073  	)
  1074  	log.Printf("[DEBUG] template config= %s", config)
  1075  
  1076  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
  1077  		TestFuncData{vm: vm, label: data.label, vmName: vmName, numDisks: "1", vmResource: "terraform-mac-address"}.testCheckFuncBasic()
  1078  
  1079  	resource.Test(t, resource.TestCase{
  1080  		PreCheck:     func() { testMacPreCheck(t) },
  1081  		Providers:    testAccProviders,
  1082  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
  1083  		Steps: []resource.TestStep{
  1084  			resource.TestStep{
  1085  				Config: config,
  1086  				Check: resource.ComposeTestCheckFunc(
  1087  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
  1088  					resource.TestCheckResourceAttr(vmName, "network_interface.0.mac_address", macAddress),
  1089  				),
  1090  			},
  1091  		},
  1092  	})
  1093  }
  1094  
  1095  func testAccCheckVSphereVirtualMachineDestroy(s *terraform.State) error {
  1096  	client := testAccProvider.Meta().(*govmomi.Client)
  1097  	finder := find.NewFinder(client.Client, true)
  1098  
  1099  	for _, rs := range s.RootModule().Resources {
  1100  		if rs.Type != "vsphere_virtual_machine" {
  1101  			continue
  1102  		}
  1103  
  1104  		dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"])
  1105  		if err != nil {
  1106  			return fmt.Errorf("error %s", err)
  1107  		}
  1108  
  1109  		dcFolders, err := dc.Folders(context.TODO())
  1110  		if err != nil {
  1111  			return fmt.Errorf("error %s", err)
  1112  		}
  1113  
  1114  		folder := dcFolders.VmFolder
  1115  		if len(rs.Primary.Attributes["folder"]) > 0 {
  1116  			si := object.NewSearchIndex(client.Client)
  1117  			folderRef, err := si.FindByInventoryPath(
  1118  				context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"]))
  1119  			if err != nil {
  1120  				return err
  1121  			} else if folderRef != nil {
  1122  				folder = folderRef.(*object.Folder)
  1123  			}
  1124  		}
  1125  
  1126  		v, err := object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"])
  1127  
  1128  		if v != nil {
  1129  			return fmt.Errorf("Record still exists")
  1130  		}
  1131  	}
  1132  
  1133  	return nil
  1134  }
  1135  
  1136  func testAccCheckVSphereVirtualMachineExistsHasCustomConfig(n string, vm *virtualMachine) resource.TestCheckFunc {
  1137  	return func(s *terraform.State) error {
  1138  
  1139  		rs, ok := s.RootModule().Resources[n]
  1140  		if !ok {
  1141  			return fmt.Errorf("Not found: %s", n)
  1142  		}
  1143  
  1144  		if rs.Primary.ID == "" {
  1145  			return fmt.Errorf("No ID is set")
  1146  		}
  1147  
  1148  		client := testAccProvider.Meta().(*govmomi.Client)
  1149  		finder := find.NewFinder(client.Client, true)
  1150  
  1151  		dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"])
  1152  		if err != nil {
  1153  			return fmt.Errorf("error %s", err)
  1154  		}
  1155  
  1156  		dcFolders, err := dc.Folders(context.TODO())
  1157  		if err != nil {
  1158  			return fmt.Errorf("error %s", err)
  1159  		}
  1160  
  1161  		_, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), dcFolders.VmFolder, rs.Primary.Attributes["name"])
  1162  		if err != nil {
  1163  			return fmt.Errorf("error %s", err)
  1164  		}
  1165  
  1166  		finder = finder.SetDatacenter(dc)
  1167  		instance, err := finder.VirtualMachine(context.TODO(), rs.Primary.Attributes["name"])
  1168  		if err != nil {
  1169  			return fmt.Errorf("error %s", err)
  1170  		}
  1171  
  1172  		var mvm mo.VirtualMachine
  1173  
  1174  		collector := property.DefaultCollector(client.Client)
  1175  
  1176  		if err := collector.RetrieveOne(context.TODO(), instance.Reference(), []string{"config.extraConfig"}, &mvm); err != nil {
  1177  			return fmt.Errorf("error %s", err)
  1178  		}
  1179  
  1180  		var configMap = make(map[string]types.AnyType)
  1181  		if mvm.Config != nil && mvm.Config.ExtraConfig != nil && len(mvm.Config.ExtraConfig) > 0 {
  1182  			for _, v := range mvm.Config.ExtraConfig {
  1183  				value := v.GetOptionValue()
  1184  				configMap[value.Key] = value.Value
  1185  			}
  1186  		} else {
  1187  			return fmt.Errorf("error no ExtraConfig")
  1188  		}
  1189  
  1190  		if configMap["foo"] == nil {
  1191  			return fmt.Errorf("error no ExtraConfig for 'foo'")
  1192  		}
  1193  
  1194  		if configMap["foo"] != "bar" {
  1195  			return fmt.Errorf("error ExtraConfig 'foo' != bar")
  1196  		}
  1197  
  1198  		if configMap["car"] == nil {
  1199  			return fmt.Errorf("error no ExtraConfig for 'car'")
  1200  		}
  1201  
  1202  		if configMap["car"] != "ferrari" {
  1203  			return fmt.Errorf("error ExtraConfig 'car' != ferrari")
  1204  		}
  1205  
  1206  		if configMap["num"] == nil {
  1207  			return fmt.Errorf("error no ExtraConfig for 'num'")
  1208  		}
  1209  
  1210  		// todo this should be an int, getting back a string
  1211  		if configMap["num"] != "42" {
  1212  			return fmt.Errorf("error ExtraConfig 'num' != 42")
  1213  		}
  1214  		*vm = virtualMachine{
  1215  			name: rs.Primary.ID,
  1216  		}
  1217  
  1218  		return nil
  1219  	}
  1220  }
  1221  
  1222  func testAccCheckDebugExists() resource.TestCheckFunc {
  1223  	return func(s *terraform.State) error {
  1224  		if _, err := os.Stat(filepath.Join(os.Getenv("HOME"), ".govmomi")); os.IsNotExist(err) {
  1225  			return fmt.Errorf("Debug logs not found")
  1226  		}
  1227  
  1228  		return nil
  1229  	}
  1230  
  1231  }
  1232  func testAccCheckVSphereVirtualMachineExists(n string, vm *virtualMachine) resource.TestCheckFunc {
  1233  	return func(s *terraform.State) error {
  1234  		if n == "" {
  1235  			return fmt.Errorf("No vm name passed in")
  1236  		}
  1237  		if vm == nil {
  1238  			return fmt.Errorf("No vm obj passed in")
  1239  		}
  1240  		rs, ok := s.RootModule().Resources[n]
  1241  		if !ok {
  1242  			return fmt.Errorf("Not found: %s", n)
  1243  		}
  1244  
  1245  		if rs.Primary.ID == "" {
  1246  			return fmt.Errorf("No ID is set")
  1247  		}
  1248  
  1249  		client := testAccProvider.Meta().(*govmomi.Client)
  1250  		finder := find.NewFinder(client.Client, true)
  1251  
  1252  		dc, err := finder.Datacenter(context.TODO(), rs.Primary.Attributes["datacenter"])
  1253  		if err != nil {
  1254  			return fmt.Errorf("error %s", err)
  1255  		}
  1256  
  1257  		dcFolders, err := dc.Folders(context.TODO())
  1258  		if err != nil {
  1259  			return fmt.Errorf("error %s", err)
  1260  		}
  1261  
  1262  		folder := dcFolders.VmFolder
  1263  		if len(rs.Primary.Attributes["folder"]) > 0 {
  1264  			si := object.NewSearchIndex(client.Client)
  1265  			folderRef, err := si.FindByInventoryPath(
  1266  				context.TODO(), fmt.Sprintf("%v/vm/%v", rs.Primary.Attributes["datacenter"], rs.Primary.Attributes["folder"]))
  1267  			if err != nil {
  1268  				return err
  1269  			} else if folderRef != nil {
  1270  				folder = folderRef.(*object.Folder)
  1271  			}
  1272  		}
  1273  
  1274  		_, err = object.NewSearchIndex(client.Client).FindChild(context.TODO(), folder, rs.Primary.Attributes["name"])
  1275  
  1276  		*vm = virtualMachine{
  1277  			name: rs.Primary.ID,
  1278  		}
  1279  
  1280  		return nil
  1281  	}
  1282  }
  1283  
  1284  const testAccCheckVSphereVirtualMachineConfig_keepOnRemove = `
  1285  resource "vsphere_virtual_machine" "keep_disk" {
  1286      name = "terraform-test"
  1287  ` + testAccTemplateBasicBody + `
  1288      disk {
  1289          size = 1
  1290          iops = 500
  1291  		controller_type = "scsi"
  1292  		name = "one"
  1293  		keep_on_remove = true
  1294      }
  1295  }
  1296  `
  1297  
  1298  func TestAccVSphereVirtualMachine_keepOnRemove(t *testing.T) {
  1299  	var vm virtualMachine
  1300  	basic_vars := setupTemplateBasicBodyVars()
  1301  	config := basic_vars.testSprintfTemplateBody(testAccCheckVSphereVirtualMachineConfig_keepOnRemove)
  1302  	var datastore string
  1303  	if v := os.Getenv("VSPHERE_DATASTORE"); v != "" {
  1304  		datastore = v
  1305  	}
  1306  	var datacenter string
  1307  	if v := os.Getenv("VSPHERE_DATACENTER"); v != "" {
  1308  		datacenter = v
  1309  	}
  1310  
  1311  	vmName := "vsphere_virtual_machine.keep_disk"
  1312  	test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label :=
  1313  		TestFuncData{vm: vm, label: basic_vars.label, vmName: vmName, numDisks: "2"}.testCheckFuncBasic()
  1314  
  1315  	log.Printf("[DEBUG] template= %s", testAccCheckVSphereVirtualMachineConfig_keepOnRemove)
  1316  	log.Printf("[DEBUG] template config= %s", config)
  1317  
  1318  	resource.Test(t, resource.TestCase{
  1319  		PreCheck:     func() { testAccPreCheck(t) },
  1320  		Providers:    testAccProviders,
  1321  		CheckDestroy: testAccCheckVSphereVirtualMachineDestroy,
  1322  		Steps: []resource.TestStep{
  1323  			resource.TestStep{
  1324  				Config: config,
  1325  				Check: resource.ComposeTestCheckFunc(
  1326  					test_exists, test_name, test_cpu, test_uuid, test_mem, test_num_disk, test_num_of_nic, test_nic_label,
  1327  				),
  1328  			},
  1329  			resource.TestStep{
  1330  				Config: " ",
  1331  				Check:  checkForDisk(datacenter, datastore, "terraform-test", "one.vmdk"),
  1332  			},
  1333  		},
  1334  	})
  1335  }
  1336  
  1337  func checkForDisk(datacenter string, datastore string, vmName string, path string) resource.TestCheckFunc {
  1338  	return func(s *terraform.State) error {
  1339  		client := testAccProvider.Meta().(*govmomi.Client)
  1340  		finder := find.NewFinder(client.Client, true)
  1341  
  1342  		dc, err := getDatacenter(client, datacenter)
  1343  		if err != nil {
  1344  			return err
  1345  		}
  1346  		finder.SetDatacenter(dc)
  1347  
  1348  		ds, err := finder.Datastore(context.TODO(), datastore)
  1349  		if err != nil {
  1350  			log.Printf("[ERROR] checkForDisk - Couldn't find Datastore '%v': %v", datastore, err)
  1351  			return err
  1352  		}
  1353  
  1354  		diskPath := vmName + "/" + path
  1355  
  1356  		_, err = ds.Stat(context.TODO(), diskPath)
  1357  		if err != nil {
  1358  			log.Printf("[ERROR] checkForDisk - Couldn't stat file '%v': %v", diskPath, err)
  1359  			return err
  1360  		}
  1361  
  1362  		// Cleanup
  1363  		fileManager := object.NewFileManager(client.Client)
  1364  		task, err := fileManager.DeleteDatastoreFile(context.TODO(), ds.Path(vmName), dc)
  1365  		if err != nil {
  1366  			log.Printf("[ERROR] checkForDisk - Couldn't delete vm folder '%v': %v", vmName, err)
  1367  			return err
  1368  		}
  1369  
  1370  		_, err = task.WaitForResult(context.TODO(), nil)
  1371  		if err != nil {
  1372  			log.Printf("[ERROR] checForDisk - Failed while deleting vm folder '%v': %v", vmName, err)
  1373  			return err
  1374  		}
  1375  
  1376  		return nil
  1377  	}
  1378  }