Repository: vmware/govmomi (go)

Issue:
get resource pool name under VM
I'm currently trying to switch from using the govc binary to govmomi library and can't quite get my head around how to get the resource pool name (not the id) for every one of my vms.
As a heads up, I've no much prior experience with vmware or vms in general, so please be patient.
The way it works right now with govc is that I get a list of all resource pool paths over `govc find -type resourcePool .`, later on I use the result in a new find request for VirtualMachines specifying the resource pool path.
I extract the pool name from the path.

Can you do the same with govmomi library? Whenever I try to get the name, I only get the ID _resgroup-xx_.

I've found a way to get all the resource pool paths with govmomi using the find package and calling the `ResourcePoolListAll` function and returning the `InventoryPath`
I know I can set the default datacenter when I use the find package, however I've not found a way to do the same for resource pool paths like I can with govc. 
Is it possible and is there an even better approach?


Pull request description:
finder: simplify direct use of InventoryPath func
Rather than suggest Finder.Element to get an object's inventory path,
refactor to an InventoryPath function that does not require a Finder
instance.

examples: add VirtualMachine.ResourcePool

Fixes #2078


Patch:
diff --git a/find/finder.go b/find/finder.go
index a46c70bf..bd1a9191 100644
--- a/find/finder.go
+++ b/find/finder.go
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
+Copyright (c) 2014-2020 VMware, Inc. All Rights Reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -67,6 +67,29 @@ func (f *Finder) SetDatacenter(dc *object.Datacenter) *Finder {
 	return f
 }
 
+// InventoryPath composes the given object's inventory path.
+// There is no vSphere property or method that provides an inventory path directly.
+// This method uses the ManagedEntity.Parent field to determine the ancestry tree of the object and
+// the ManagedEntity.Name field for each ancestor to compose the path.
+func InventoryPath(ctx context.Context, client *vim25.Client, obj types.ManagedObjectReference) (string, error) {
+	entities, err := mo.Ancestors(ctx, client, client.ServiceContent.PropertyCollector, obj)
+	if err != nil {
+		return "", err
+	}
+
+	val := "/"
+
+	for _, entity := range entities {
+		// Skip root folder in building inventory path.
+		if entity.Parent == nil {
+			continue
+		}
+		val = path.Join(val, entity.Name)
+	}
+
+	return val, err
+}
+
 // findRoot makes it possible to use "find" mode with a different root path.
 // Example: ResourcePoolList("/dc1/host/cluster1/...")
 func (f *Finder) findRoot(ctx context.Context, root *list.Element, parts []string) bool {
@@ -103,8 +126,8 @@ func (f *Finder) find(ctx context.Context, arg string, s *spec) ([]list.Element,
 	isPath := strings.Contains(arg, "/")
 
 	root := list.Element{
-		Path:   "/",
 		Object: object.NewRootFolder(f.client),
+		Path:   "/",
 	}
 
 	parts := list.ToParts(arg)
@@ -119,19 +142,10 @@ func (f *Finder) find(ctx context.Context, arg string, s *spec) ([]list.Element,
 				return nil, err
 			}
 
-			mes, err := mo.Ancestors(ctx, f.client, f.client.ServiceContent.PropertyCollector, pivot.Reference())
+			root.Path, err = InventoryPath(ctx, f.client, pivot.Reference())
 			if err != nil {
 				return nil, err
 			}
-
-			for _, me := range mes {
-				// Skip root entity in building inventory path.
-				if me.Parent == nil {
-					continue
-				}
-				root.Path = path.Join(root.Path, me.Name)
-			}
-
 			root.Object = pivot
 			parts = parts[1:]
 		}
@@ -281,8 +295,7 @@ func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool, in
 	return f.find(ctx, path, s)
 }
 
-// Element returns an Element for the given ManagedObjectReference
-// This method is only useful for looking up the InventoryPath of a ManagedObjectReference.
+// Element is deprecated, use InventoryPath() instead.
 func (f *Finder) Element(ctx context.Context, ref types.ManagedObjectReference) (*list.Element, error) {
 	rl := func(_ context.Context) (object.Reference, error) {
 		return ref, nil
@@ -311,7 +324,7 @@ func (f *Finder) Element(ctx context.Context, ref types.ManagedObjectReference)
 // ObjectReference converts the given ManagedObjectReference to a type from the object package via object.NewReference
 // with the object.Common.InventoryPath field set.
 func (f *Finder) ObjectReference(ctx context.Context, ref types.ManagedObjectReference) (object.Reference, error) {
-	e, err := f.Element(ctx, ref)
+	path, err := InventoryPath(ctx, f.client, ref)
 	if err != nil {
 		return nil, err
 	}
@@ -322,7 +335,7 @@ func (f *Finder) ObjectReference(ctx context.Context, ref types.ManagedObjectRef
 		SetInventoryPath(string)
 	}
 
-	r.(common).SetInventoryPath(e.Path)
+	r.(common).SetInventoryPath(path)
 
 	if f.dc != nil {
 		if ds, ok := r.(*object.Datastore); ok {


Test patch:
diff --git a/object/example_test.go b/object/example_test.go
index eb14c3f3..ef5800ed 100644
--- a/object/example_test.go
+++ b/object/example_test.go
@@ -188,6 +188,42 @@ func ExampleVirtualMachine_HostSystem() {
 	// Output: DC0_H0
 }
 
+func ExampleVirtualMachine_ResourcePool() {
+	simulator.Run(func(ctx context.Context, c *vim25.Client) error {
+		finder := find.NewFinder(c)
+		vm, err := finder.VirtualMachine(ctx, "DC0_C0_RP0_VM0")
+		if err != nil {
+			return err
+		}
+
+		pool, err := vm.ResourcePool(ctx)
+		if err != nil {
+			return err
+		}
+
+		name, err := pool.ObjectName(ctx)
+		if err != nil {
+			return err
+		}
+
+		fmt.Println(name)
+
+		// The InventoryPath field not populated unless Finder.ResourcePool() or
+		// Finder.ResourcePoolList() was used. But we can populate it explicity.
+		pool.InventoryPath, err = find.InventoryPath(ctx, c, pool.Reference())
+		if err != nil {
+			return err
+		}
+
+		fmt.Println(pool.InventoryPath)
+
+		return nil
+	})
+	// Output:
+	// Resources
+	// /DC0/host/DC0_C0/Resources
+}
+
 func ExampleVirtualMachine_Clone() {
 	simulator.Run(func(ctx context.Context, c *vim25.Client) error {
 		finder := find.NewFinder(c)