Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support looking up VM by UUID #1650

Merged
merged 2 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions vsphere/data_source_vsphere_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ func dataSourceVSphereVirtualMachine() *schema.Resource {
// include the number of cpus, memory, firmware, disks, etc.
structure.MergeSchema(s, schemaVirtualMachineConfigSpec())

// make name/uuid Optional/AtLeastOneOf since UUID lookup is now supported
s["name"].Required = false
s["name"].Optional = true
s["name"].AtLeastOneOf = []string{"name", "uuid"}
s["uuid"].Required = false
s["uuid"].Optional = true
s["uuid"].AtLeastOneOf = []string{"name", "uuid"}

// Now that the schema has been composed and merged, we can attach our reader and
// return the resource back to our host process.
return &schema.Resource{
Expand All @@ -159,22 +167,31 @@ func dataSourceVSphereVirtualMachine() *schema.Resource {

func dataSourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Client).vimClient

uuid := d.Get("uuid").(string)
name := d.Get("name").(string)
log.Printf("[DEBUG] Looking for VM or template by name/path %q", name)
var dc *object.Datacenter
if dcID, ok := d.GetOk("datacenter_id"); ok {
var err error
dc, err = datacenterFromID(client, dcID.(string))
if err != nil {
return fmt.Errorf("cannot locate datacenter: %s", err)
var vm *object.VirtualMachine
var err error

if uuid != "" {
log.Printf("[DEBUG] Looking for VM or template by UUID %q", uuid)
vm, err = virtualmachine.FromUUID(client, uuid)
} else {
log.Printf("[DEBUG] Looking for VM or template by name/path %q", name)
var dc *object.Datacenter
if dcID, ok := d.GetOk("datacenter_id"); ok {
dc, err = datacenterFromID(client, dcID.(string))
if err != nil {
return fmt.Errorf("cannot locate datacenter: %s", err)
}
log.Printf("[DEBUG] Datacenter for VM/template search: %s", dc.InventoryPath)
}
log.Printf("[DEBUG] Datacenter for VM/template search: %s", dc.InventoryPath)
vm, err = virtualmachine.FromPath(client, name, dc)
}
vm, err := virtualmachine.FromPath(client, name, dc)

if err != nil {
return fmt.Errorf("error fetching virtual machine: %s", err)
}

props, err := virtualmachine.Properties(vm)
if err != nil {
return fmt.Errorf("error fetching virtual machine properties: %s", err)
Expand Down
68 changes: 68 additions & 0 deletions vsphere/data_source_vsphere_virtual_machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,52 @@ func TestAccDataSourceVSphereVirtualMachine_noDatacenterAndAbsolutePath(t *testi
})
}

func TestAccDataSourceVSphereVirtualMachine_uuid(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
RunSweepers()
testAccPreCheck(t)
testAccDataSourceVSphereVirtualMachinePreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceVSphereVirtualMachineConfigUUID(),
Check: resource.ComposeTestCheckFunc(
resource.TestMatchResourceAttr(
"data.vsphere_virtual_machine.uuid",
"id",
regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "guest_id"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "scsi_type"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "memory"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "num_cpus"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "num_cores_per_socket"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "firmware"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "hardware_version"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "disks.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "disks.0.size"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "disks.0.eagerly_scrub"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "disks.0.thin_provisioned"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "disks.0.unit_number"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "disks.0.label"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interface_types.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.#"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.0.adapter_type"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.0.bandwidth_limit"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.0.bandwidth_reservation"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.0.bandwidth_share_level"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.0.bandwidth_share_count"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.0.mac_address"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "network_interfaces.0.network_id"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "firmware"),
resource.TestCheckResourceAttrSet("data.vsphere_virtual_machine.uuid", "uuid"),
),
},
},
})
}

func testAccDataSourceVSphereVirtualMachinePreCheck(t *testing.T) {
if os.Getenv("TF_VAR_VSPHERE_DATACENTER") == "" {
t.Skip("set TF_VAR_VSPHERE_DATACENTER to run vsphere_virtual_machine data source acceptance tests")
Expand All @@ -110,6 +156,28 @@ func testAccDataSourceVSphereVirtualMachinePreCheck(t *testing.T) {
}
}

func testAccDataSourceVSphereVirtualMachineConfigUUID() string {
return fmt.Sprintf(`
%s

variable "template" {
default = "%s"
}

data "vsphere_virtual_machine" "template" {
name = var.template
datacenter_id = data.vsphere_datacenter.rootdc1.id
}

data "vsphere_virtual_machine" "uuid" {
uuid = data.vsphere_virtual_machine.template.uuid
}
`,
testhelper.CombineConfigs(testhelper.ConfigDataRootDC1(), testhelper.ConfigDataRootPortGroup1()),
os.Getenv("TF_VAR_VSPHERE_TEMPLATE"),
)
}

func testAccDataSourceVSphereVirtualMachineConfig() string {
return fmt.Sprintf(`
%s
Expand Down
7 changes: 5 additions & 2 deletions website/docs/d/virtual_machine.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ data "vsphere_virtual_machine" "development_template" {

The following arguments are supported:

* `name` - (Required) The name of the virtual machine. This can be a name or
the full path relative to the datacenter.
* `name` - (Optional) The name of the virtual machine. This can be a name or
the full path relative to the datacenter. This is required if a UUID lookup
is not performed.
* `uuid` - (Optional) Specify this field for a UUID lookup, `name` and `datacenter_id`
are not required if this is specified.
* `datacenter_id` - (Optional) The [managed object reference
ID][docs-about-morefs] of the datacenter the virtual machine is located in.
This can be omitted if the search path used in `name` is an absolute path.
Expand Down