debian-forge-composer/vendor/github.com/vmware/govmomi/find/finder.go
Achilleas Koutsou 3fd7092db5 go.mod: update osbuild/images to v0.156.0
tag v0.155.0
Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com>

Changes with 0.155.0

----------------
  * Fedora 43: add shadow-utils when LockRoot is enabled, update cloud-init service name (osbuild/images#1618)
    * Author: Achilleas Koutsou, Reviewers: Gianluca Zuccarelli, Michael Vogt
  * Update osbuild dependency commit ID to latest (osbuild/images#1609)
    * Author: SchutzBot, Reviewers: Achilleas Koutsou, Simon de Vlieger, Tomáš Hozza
  * Update snapshots to 20250626 (osbuild/images#1623)
    * Author: SchutzBot, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * distro/rhel9: xz compress azure-cvm image type [HMS-8587] (osbuild/images#1620)
    * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza
  * distro/rhel: introduce new image type: Azure SAP Apps [HMS-8738] (osbuild/images#1612)
    * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza
  * distro/rhel: move ansible-core to sap_extras_pkgset (osbuild/images#1624)
    * Author: Achilleas Koutsou, Reviewers: Brian C. Lane, Tomáš Hozza
  * github/create-tag: allow passing the version when run manually (osbuild/images#1621)
    * Author: Achilleas Koutsou, Reviewers: Lukáš Zapletal, Tomáš Hozza
  * rhel9: move image-config into pure YAML (HMS-8593) (osbuild/images#1616)
    * Author: Michael Vogt, Reviewers: Achilleas Koutsou, Simon de Vlieger
  * test: split manifest checksums into separate files (osbuild/images#1625)
    * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza

— Somewhere on the Internet, 2025-06-30

---

tag v0.156.0
Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com>

Changes with 0.156.0

----------------
  * Many: delete repositories for EOL distributions (HMS-7044) (osbuild/images#1607)
    * Author: Tomáš Hozza, Reviewers: Michael Vogt, Simon de Vlieger
  * RHSM/facts: add 'image-builder CLI' API type (osbuild/images#1640)
    * Author: Tomáš Hozza, Reviewers: Brian C. Lane, Simon de Vlieger
  * Update dependencies 2025-06-29 (osbuild/images#1628)
    * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza
  * Update osbuild dependency commit ID to latest (osbuild/images#1627)
    * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza
  * [RFC] image: drop `InstallWeakDeps` from image.DiskImage (osbuild/images#1642)
    * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger, Tomáš Hozza
  * build(deps): bump the go-deps group across 1 directory with 3 updates (osbuild/images#1632)
    * Author: dependabot[bot], Reviewers: SchutzBot, Tomáš Hozza
  * distro/rhel10: xz compress azure-cvm image type (osbuild/images#1638)
    * Author: Achilleas Koutsou, Reviewers: Brian C. Lane, Simon de Vlieger
  * distro: cleanup/refactor distro/{defs,generic} (HMS-8744) (osbuild/images#1570)
    * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza
  * distro: remove some hardcoded values from generic/images.go (osbuild/images#1636)
    * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza
  * distro: small tweaks for the YAML based imagetypes (osbuild/images#1622)
    * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger
  * fedora/wsl: packages and locale (osbuild/images#1635)
    * Author: Simon de Vlieger, Reviewers: Michael Vogt, Tomáš Hozza
  * image/many: make compression more generic (osbuild/images#1634)
    * Author: Simon de Vlieger, Reviewers: Brian C. Lane, Michael Vogt
  * manifest: handle content template name with spaces (osbuild/images#1641)
    * Author: Bryttanie, Reviewers: Brian C. Lane, Michael Vogt, Tomáš Hozza
  * many: implement gzip (osbuild/images#1633)
    * Author: Simon de Vlieger, Reviewers: Michael Vogt, Tomáš Hozza
  * rhel/azure: set GRUB_TERMINAL based on architecture [RHEL-91383] (osbuild/images#1626)
    * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza

— Somewhere on the Internet, 2025-07-07

---
2025-07-14 13:13:20 +02:00

1111 lines
25 KiB
Go

// © Broadcom. All Rights Reserved.
// The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
// SPDX-License-Identifier: Apache-2.0
package find
import (
"context"
"errors"
"path"
"strings"
"github.com/vmware/govmomi/fault"
"github.com/vmware/govmomi/internal"
"github.com/vmware/govmomi/list"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type Finder struct {
client *vim25.Client
r recurser
dc *object.Datacenter
si *object.SearchIndex
folders *object.DatacenterFolders
}
func NewFinder(client *vim25.Client, all ...bool) *Finder {
props := false
if len(all) == 1 {
props = all[0]
}
f := &Finder{
client: client,
si: object.NewSearchIndex(client),
r: recurser{
Collector: property.DefaultCollector(client),
All: props,
},
}
if len(all) == 0 {
// attempt to avoid SetDatacenter() requirement
f.dc, _ = f.DefaultDatacenter(context.Background())
}
return f
}
func (f *Finder) SetDatacenter(dc *object.Datacenter) *Finder {
f.dc = dc
f.folders = nil
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
}
return internal.InventoryPath(entities), nil
}
// 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 {
if len(parts) == 0 {
return false
}
ix := len(parts) - 1
if parts[ix] != "..." {
return false
}
if ix == 0 {
return true // We already have the Object for root.Path
}
// Lookup the Object for the new root.Path
rootPath := path.Join(root.Path, path.Join(parts[:ix]...))
ref, err := f.si.FindByInventoryPath(ctx, rootPath)
if err != nil || ref == nil {
// If we get an error or fail to match, fall through to find() with the original root and path
return false
}
root.Path = rootPath
root.Object = ref
return true
}
func (f *Finder) find(ctx context.Context, arg string, s *spec) ([]list.Element, error) {
isPath := strings.Contains(arg, "/")
if !isPath {
if ref := object.ReferenceFromString(arg); ref != nil {
p, err := InventoryPath(ctx, f.client, *ref)
if err == nil {
if t, ok := mo.Value(*ref); ok {
return []list.Element{{Object: t, Path: p}}, nil
}
} else if !fault.Is(err, &types.ManagedObjectNotFound{}) {
return nil, err
} // else fall through to name based lookup
}
}
root := list.Element{
Object: object.NewRootFolder(f.client),
Path: "/",
}
parts := list.ToParts(arg)
if len(parts) > 0 {
switch parts[0] {
case "..": // Not supported; many edge case, little value
return nil, errors.New("cannot traverse up a tree")
case ".": // Relative to whatever
pivot, err := s.Relative(ctx)
if err != nil {
return nil, err
}
root.Path, err = InventoryPath(ctx, f.client, pivot.Reference())
if err != nil {
return nil, err
}
root.Object = pivot
parts = parts[1:]
}
}
if s.listMode(isPath) {
if f.findRoot(ctx, &root, parts) {
parts = []string{"*"}
} else {
return f.r.List(ctx, s, root, parts)
}
}
s.Parents = append(s.Parents, s.Nested...)
return f.r.Find(ctx, s, root, parts)
}
func (f *Finder) datacenter() (*object.Datacenter, error) {
if f.dc == nil {
return nil, errors.New("please specify a datacenter")
}
return f.dc, nil
}
// datacenterPath returns the absolute path to the Datacenter containing the given ref
func (f *Finder) datacenterPath(ctx context.Context, ref types.ManagedObjectReference) (string, error) {
mes, err := mo.Ancestors(ctx, f.client, f.client.ServiceContent.PropertyCollector, ref)
if err != nil {
return "", err
}
// Chop leaves under the Datacenter
for i := len(mes) - 1; i > 0; i-- {
if mes[i].Self.Type == "Datacenter" {
break
}
mes = mes[:i]
}
var p string
for _, me := range mes {
// Skip root entity in building inventory path.
if me.Parent == nil {
continue
}
p = p + "/" + me.Name
}
return p, nil
}
func (f *Finder) dcFolders(ctx context.Context) (*object.DatacenterFolders, error) {
if f.folders != nil {
return f.folders, nil
}
dc, err := f.datacenter()
if err != nil {
return nil, err
}
folders, err := dc.Folders(ctx)
if err != nil {
return nil, err
}
f.folders = folders
return f.folders, nil
}
func (f *Finder) dcReference(_ context.Context) (object.Reference, error) {
dc, err := f.datacenter()
if err != nil {
return nil, err
}
return dc, nil
}
func (f *Finder) vmFolder(ctx context.Context) (object.Reference, error) {
folders, err := f.dcFolders(ctx)
if err != nil {
return nil, err
}
return folders.VmFolder, nil
}
func (f *Finder) hostFolder(ctx context.Context) (object.Reference, error) {
folders, err := f.dcFolders(ctx)
if err != nil {
return nil, err
}
return folders.HostFolder, nil
}
func (f *Finder) datastoreFolder(ctx context.Context) (object.Reference, error) {
folders, err := f.dcFolders(ctx)
if err != nil {
return nil, err
}
return folders.DatastoreFolder, nil
}
func (f *Finder) networkFolder(ctx context.Context) (object.Reference, error) {
folders, err := f.dcFolders(ctx)
if err != nil {
return nil, err
}
return folders.NetworkFolder, nil
}
func (f *Finder) rootFolder(_ context.Context) (object.Reference, error) {
return object.NewRootFolder(f.client), nil
}
func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool, include []string) ([]list.Element, error) {
fn := f.rootFolder
if f.dc != nil {
fn = f.dcReference
}
if path == "" {
path = "."
}
s := &spec{
Relative: fn,
Parents: []string{"ComputeResource", "ClusterComputeResource", "HostSystem", "VirtualApp", "StoragePod"},
Include: include,
}
if tl {
s.Contents = true
s.ListMode = types.NewBool(true)
}
return f.find(ctx, path, s)
}
// 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
}
s := &spec{
Relative: rl,
}
e, err := f.find(ctx, "./", s)
if err != nil {
return nil, err
}
if len(e) == 0 {
return nil, &NotFoundError{ref.Type, ref.Value}
}
if len(e) > 1 {
panic("ManagedObjectReference must be unique")
}
return &e[0], nil
}
// 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) {
path, err := InventoryPath(ctx, f.client, ref)
if err != nil {
return nil, err
}
r := object.NewReference(f.client, ref)
type common interface {
SetInventoryPath(string)
}
r.(common).SetInventoryPath(path)
if f.dc != nil {
if ds, ok := r.(*object.Datastore); ok {
ds.DatacenterPath = f.dc.InventoryPath
}
}
return r, nil
}
func (f *Finder) ManagedObjectList(ctx context.Context, path string, include ...string) ([]list.Element, error) {
return f.managedObjectList(ctx, path, false, include)
}
func (f *Finder) ManagedObjectListChildren(ctx context.Context, path string, include ...string) ([]list.Element, error) {
return f.managedObjectList(ctx, path, true, include)
}
func (f *Finder) DatacenterList(ctx context.Context, path string) ([]*object.Datacenter, error) {
s := &spec{
Relative: f.rootFolder,
Include: []string{"Datacenter"},
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var dcs []*object.Datacenter
for _, e := range es {
ref := e.Object.Reference()
if ref.Type == "Datacenter" {
dc := object.NewDatacenter(f.client, ref)
dc.InventoryPath = e.Path
dcs = append(dcs, dc)
}
}
if len(dcs) == 0 {
return nil, &NotFoundError{"datacenter", path}
}
return dcs, nil
}
func (f *Finder) Datacenter(ctx context.Context, path string) (*object.Datacenter, error) {
dcs, err := f.DatacenterList(ctx, path)
if err != nil {
return nil, err
}
if len(dcs) > 1 {
return nil, &MultipleFoundError{"datacenter", path}
}
return dcs[0], nil
}
func (f *Finder) DefaultDatacenter(ctx context.Context) (*object.Datacenter, error) {
dc, err := f.Datacenter(ctx, "*")
if err != nil {
return nil, toDefaultError(err)
}
return dc, nil
}
func (f *Finder) DatacenterOrDefault(ctx context.Context, path string) (*object.Datacenter, error) {
if path != "" {
dc, err := f.Datacenter(ctx, path)
if err != nil {
return nil, err
}
return dc, nil
}
return f.DefaultDatacenter(ctx)
}
func (f *Finder) DatastoreList(ctx context.Context, path string) ([]*object.Datastore, error) {
s := &spec{
Relative: f.datastoreFolder,
Parents: []string{"StoragePod"},
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var dss []*object.Datastore
for _, e := range es {
ref := e.Object.Reference()
if ref.Type == "Datastore" {
ds := object.NewDatastore(f.client, ref)
ds.InventoryPath = e.Path
if f.dc == nil {
// In this case SetDatacenter was not called and path is absolute
ds.DatacenterPath, err = f.datacenterPath(ctx, ref)
if err != nil {
return nil, err
}
} else {
ds.DatacenterPath = f.dc.InventoryPath
}
dss = append(dss, ds)
}
}
if len(dss) == 0 {
return nil, &NotFoundError{"datastore", path}
}
return dss, nil
}
func (f *Finder) Datastore(ctx context.Context, path string) (*object.Datastore, error) {
dss, err := f.DatastoreList(ctx, path)
if err != nil {
return nil, err
}
if len(dss) > 1 {
return nil, &MultipleFoundError{"datastore", path}
}
return dss[0], nil
}
func (f *Finder) DefaultDatastore(ctx context.Context) (*object.Datastore, error) {
ds, err := f.Datastore(ctx, "*")
if err != nil {
return nil, toDefaultError(err)
}
return ds, nil
}
func (f *Finder) DatastoreOrDefault(ctx context.Context, path string) (*object.Datastore, error) {
if path != "" {
ds, err := f.Datastore(ctx, path)
if err != nil {
return nil, err
}
return ds, nil
}
return f.DefaultDatastore(ctx)
}
func (f *Finder) DatastoreClusterList(ctx context.Context, path string) ([]*object.StoragePod, error) {
s := &spec{
Relative: f.datastoreFolder,
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var sps []*object.StoragePod
for _, e := range es {
ref := e.Object.Reference()
if ref.Type == "StoragePod" {
sp := object.NewStoragePod(f.client, ref)
sp.InventoryPath = e.Path
sps = append(sps, sp)
}
}
if len(sps) == 0 {
return nil, &NotFoundError{"datastore cluster", path}
}
return sps, nil
}
func (f *Finder) DatastoreCluster(ctx context.Context, path string) (*object.StoragePod, error) {
sps, err := f.DatastoreClusterList(ctx, path)
if err != nil {
return nil, err
}
if len(sps) > 1 {
return nil, &MultipleFoundError{"datastore cluster", path}
}
return sps[0], nil
}
func (f *Finder) DefaultDatastoreCluster(ctx context.Context) (*object.StoragePod, error) {
sp, err := f.DatastoreCluster(ctx, "*")
if err != nil {
return nil, toDefaultError(err)
}
return sp, nil
}
func (f *Finder) DatastoreClusterOrDefault(ctx context.Context, path string) (*object.StoragePod, error) {
if path != "" {
sp, err := f.DatastoreCluster(ctx, path)
if err != nil {
return nil, err
}
return sp, nil
}
return f.DefaultDatastoreCluster(ctx)
}
func (f *Finder) ComputeResourceList(ctx context.Context, path string) ([]*object.ComputeResource, error) {
s := &spec{
Relative: f.hostFolder,
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var crs []*object.ComputeResource
for _, e := range es {
var cr *object.ComputeResource
switch o := e.Object.(type) {
case mo.ComputeResource, mo.ClusterComputeResource:
cr = object.NewComputeResource(f.client, o.Reference())
default:
continue
}
cr.InventoryPath = e.Path
crs = append(crs, cr)
}
if len(crs) == 0 {
return nil, &NotFoundError{"compute resource", path}
}
return crs, nil
}
func (f *Finder) ComputeResource(ctx context.Context, path string) (*object.ComputeResource, error) {
crs, err := f.ComputeResourceList(ctx, path)
if err != nil {
return nil, err
}
if len(crs) > 1 {
return nil, &MultipleFoundError{"compute resource", path}
}
return crs[0], nil
}
func (f *Finder) DefaultComputeResource(ctx context.Context) (*object.ComputeResource, error) {
cr, err := f.ComputeResource(ctx, "*")
if err != nil {
return nil, toDefaultError(err)
}
return cr, nil
}
func (f *Finder) ComputeResourceOrDefault(ctx context.Context, path string) (*object.ComputeResource, error) {
if path != "" {
cr, err := f.ComputeResource(ctx, path)
if err != nil {
return nil, err
}
return cr, nil
}
return f.DefaultComputeResource(ctx)
}
func (f *Finder) ClusterComputeResourceList(ctx context.Context, path string) ([]*object.ClusterComputeResource, error) {
s := &spec{
Relative: f.hostFolder,
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var ccrs []*object.ClusterComputeResource
for _, e := range es {
var ccr *object.ClusterComputeResource
switch o := e.Object.(type) {
case mo.ClusterComputeResource:
ccr = object.NewClusterComputeResource(f.client, o.Reference())
default:
continue
}
ccr.InventoryPath = e.Path
ccrs = append(ccrs, ccr)
}
if len(ccrs) == 0 {
return nil, &NotFoundError{"cluster", path}
}
return ccrs, nil
}
func (f *Finder) DefaultClusterComputeResource(ctx context.Context) (*object.ClusterComputeResource, error) {
cr, err := f.ClusterComputeResource(ctx, "*")
if err != nil {
return nil, toDefaultError(err)
}
return cr, nil
}
func (f *Finder) ClusterComputeResource(ctx context.Context, path string) (*object.ClusterComputeResource, error) {
ccrs, err := f.ClusterComputeResourceList(ctx, path)
if err != nil {
return nil, err
}
if len(ccrs) > 1 {
return nil, &MultipleFoundError{"cluster", path}
}
return ccrs[0], nil
}
func (f *Finder) ClusterComputeResourceOrDefault(ctx context.Context, path string) (*object.ClusterComputeResource, error) {
if path != "" {
cr, err := f.ClusterComputeResource(ctx, path)
if err != nil {
return nil, err
}
return cr, nil
}
return f.DefaultClusterComputeResource(ctx)
}
func (f *Finder) HostSystemList(ctx context.Context, path string) ([]*object.HostSystem, error) {
s := &spec{
Relative: f.hostFolder,
Parents: []string{"ComputeResource", "ClusterComputeResource"},
Include: []string{"HostSystem"},
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var hss []*object.HostSystem
for _, e := range es {
var hs *object.HostSystem
switch o := e.Object.(type) {
case mo.HostSystem:
hs = object.NewHostSystem(f.client, o.Reference())
hs.InventoryPath = e.Path
hss = append(hss, hs)
case mo.ComputeResource, mo.ClusterComputeResource:
cr := object.NewComputeResource(f.client, o.Reference())
cr.InventoryPath = e.Path
hosts, err := cr.Hosts(ctx)
if err != nil {
return nil, err
}
hss = append(hss, hosts...)
}
}
if len(hss) == 0 {
return nil, &NotFoundError{"host", path}
}
return hss, nil
}
func (f *Finder) HostSystem(ctx context.Context, path string) (*object.HostSystem, error) {
hss, err := f.HostSystemList(ctx, path)
if err != nil {
return nil, err
}
if len(hss) > 1 {
return nil, &MultipleFoundError{"host", path}
}
return hss[0], nil
}
func (f *Finder) DefaultHostSystem(ctx context.Context) (*object.HostSystem, error) {
hs, err := f.HostSystem(ctx, "*")
if err != nil {
return nil, toDefaultError(err)
}
return hs, nil
}
func (f *Finder) HostSystemOrDefault(ctx context.Context, path string) (*object.HostSystem, error) {
if path != "" {
hs, err := f.HostSystem(ctx, path)
if err != nil {
return nil, err
}
return hs, nil
}
return f.DefaultHostSystem(ctx)
}
func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.NetworkReference, error) {
s := &spec{
Relative: f.networkFolder,
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var ns []object.NetworkReference
for _, e := range es {
ref := e.Object.Reference()
switch ref.Type {
case "Network":
r := object.NewNetwork(f.client, ref)
r.InventoryPath = e.Path
ns = append(ns, r)
case "OpaqueNetwork":
r := object.NewOpaqueNetwork(f.client, ref)
r.InventoryPath = e.Path
ns = append(ns, r)
case "DistributedVirtualPortgroup":
r := object.NewDistributedVirtualPortgroup(f.client, ref)
r.InventoryPath = e.Path
ns = append(ns, r)
case "DistributedVirtualSwitch", "VmwareDistributedVirtualSwitch":
r := object.NewDistributedVirtualSwitch(f.client, ref)
r.InventoryPath = e.Path
ns = append(ns, r)
}
}
if len(ns) == 0 {
net, nerr := f.networkByID(ctx, path)
if nerr == nil {
return []object.NetworkReference{net}, nil
}
return nil, &NotFoundError{"network", path}
}
return ns, nil
}
// Network finds a NetworkReference using a Name, Inventory Path, ManagedObject ID, Logical Switch UUID or Segment ID.
// With standard vSphere networking, Portgroups cannot have the same name within the same network folder.
// With NSX, Portgroups can have the same name, even within the same Switch. In this case, using an inventory path
// results in a MultipleFoundError. A MOID, switch UUID or segment ID can be used instead, as both are unique.
// See also: https://knowledge.broadcom.com/external/article?articleNumber=320145#Duplicate_names
// Examples:
// - Name: "dvpg-1"
// - Inventory Path: "vds-1/dvpg-1"
// - Cluster Path: "/dc-1/host/cluster-1/dvpg-1"
// - ManagedObject ID: "DistributedVirtualPortgroup:dvportgroup-53"
// - Logical Switch UUID: "da2a59b8-2450-4cb2-b5cc-79c4c1d2144c"
// - Segment ID: "/infra/segments/vnet_ce50e69b-1784-4a14-9206-ffd7f1f146f7"
func (f *Finder) Network(ctx context.Context, path string) (object.NetworkReference, error) {
networks, err := f.NetworkList(ctx, path)
if err != nil {
return nil, err
}
if len(networks) > 1 {
return nil, &MultipleFoundError{"network", path}
}
return networks[0], nil
}
func (f *Finder) networkByID(ctx context.Context, path string) (object.NetworkReference, error) {
kind := []string{"DistributedVirtualPortgroup"}
m := view.NewManager(f.client)
v, err := m.CreateContainerView(ctx, f.client.ServiceContent.RootFolder, kind, true)
if err != nil {
return nil, err
}
defer v.Destroy(ctx)
filter := property.Match{
"config.logicalSwitchUuid": path,
"config.segmentId": path,
}
refs, err := v.FindAny(ctx, kind, filter)
if err != nil {
return nil, err
}
if len(refs) == 0 {
return nil, &NotFoundError{"network", path}
}
if len(refs) > 1 {
return nil, &MultipleFoundError{"network", path}
}
return object.NewReference(f.client, refs[0]).(object.NetworkReference), nil
}
func (f *Finder) DefaultNetwork(ctx context.Context) (object.NetworkReference, error) {
network, err := f.Network(ctx, "*")
if err != nil {
return nil, toDefaultError(err)
}
return network, nil
}
func (f *Finder) NetworkOrDefault(ctx context.Context, path string) (object.NetworkReference, error) {
if path != "" {
network, err := f.Network(ctx, path)
if err != nil {
return nil, err
}
return network, nil
}
return f.DefaultNetwork(ctx)
}
func (f *Finder) ResourcePoolList(ctx context.Context, path string) ([]*object.ResourcePool, error) {
s := &spec{
Relative: f.hostFolder,
Parents: []string{"ComputeResource", "ClusterComputeResource", "VirtualApp"},
Nested: []string{"ResourcePool"},
Contents: true,
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var rps []*object.ResourcePool
for _, e := range es {
var rp *object.ResourcePool
switch o := e.Object.(type) {
case mo.ResourcePool:
rp = object.NewResourcePool(f.client, o.Reference())
rp.InventoryPath = e.Path
rps = append(rps, rp)
}
}
if len(rps) == 0 {
return nil, &NotFoundError{"resource pool", path}
}
return rps, nil
}
func (f *Finder) ResourcePool(ctx context.Context, path string) (*object.ResourcePool, error) {
rps, err := f.ResourcePoolList(ctx, path)
if err != nil {
return nil, err
}
if len(rps) > 1 {
return nil, &MultipleFoundError{"resource pool", path}
}
return rps[0], nil
}
func (f *Finder) DefaultResourcePool(ctx context.Context) (*object.ResourcePool, error) {
rp, err := f.ResourcePool(ctx, "*/Resources")
if err != nil {
return nil, toDefaultError(err)
}
return rp, nil
}
func (f *Finder) ResourcePoolOrDefault(ctx context.Context, path string) (*object.ResourcePool, error) {
if path != "" {
rp, err := f.ResourcePool(ctx, path)
if err != nil {
return nil, err
}
return rp, nil
}
return f.DefaultResourcePool(ctx)
}
// ResourcePoolListAll combines ResourcePoolList and VirtualAppList
// VirtualAppList is only called if ResourcePoolList does not find any pools with the given path.
func (f *Finder) ResourcePoolListAll(ctx context.Context, path string) ([]*object.ResourcePool, error) {
pools, err := f.ResourcePoolList(ctx, path)
if err != nil {
if _, ok := err.(*NotFoundError); !ok {
return nil, err
}
vapps, _ := f.VirtualAppList(ctx, path)
if len(vapps) == 0 {
return nil, err
}
for _, vapp := range vapps {
pools = append(pools, vapp.ResourcePool)
}
}
return pools, nil
}
func (f *Finder) DefaultFolder(ctx context.Context) (*object.Folder, error) {
ref, err := f.vmFolder(ctx)
if err != nil {
return nil, toDefaultError(err)
}
folder := object.NewFolder(f.client, ref.Reference())
// Set the InventoryPath of the newly created folder object
// The default foler becomes the datacenter's "vm" folder.
// The "vm" folder always exists for a datacenter. It cannot be
// removed or replaced
folder.SetInventoryPath(path.Join(f.dc.InventoryPath, "vm"))
return folder, nil
}
func (f *Finder) FolderOrDefault(ctx context.Context, path string) (*object.Folder, error) {
if path != "" {
folder, err := f.Folder(ctx, path)
if err != nil {
return nil, err
}
return folder, nil
}
return f.DefaultFolder(ctx)
}
func (f *Finder) VirtualMachineList(ctx context.Context, path string) ([]*object.VirtualMachine, error) {
s := &spec{
Relative: f.vmFolder,
Parents: []string{"VirtualApp"},
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var vms []*object.VirtualMachine
for _, e := range es {
switch o := e.Object.(type) {
case mo.VirtualMachine:
vm := object.NewVirtualMachine(f.client, o.Reference())
vm.InventoryPath = e.Path
vms = append(vms, vm)
}
}
if len(vms) == 0 {
return nil, &NotFoundError{"vm", path}
}
return vms, nil
}
func (f *Finder) VirtualMachine(ctx context.Context, path string) (*object.VirtualMachine, error) {
vms, err := f.VirtualMachineList(ctx, path)
if err != nil {
return nil, err
}
if len(vms) > 1 {
return nil, &MultipleFoundError{"vm", path}
}
return vms[0], nil
}
func (f *Finder) VirtualAppList(ctx context.Context, path string) ([]*object.VirtualApp, error) {
s := &spec{
Relative: f.vmFolder,
}
es, err := f.find(ctx, path, s)
if err != nil {
return nil, err
}
var apps []*object.VirtualApp
for _, e := range es {
switch o := e.Object.(type) {
case mo.VirtualApp:
app := object.NewVirtualApp(f.client, o.Reference())
app.InventoryPath = e.Path
apps = append(apps, app)
}
}
if len(apps) == 0 {
return nil, &NotFoundError{"app", path}
}
return apps, nil
}
func (f *Finder) VirtualApp(ctx context.Context, path string) (*object.VirtualApp, error) {
apps, err := f.VirtualAppList(ctx, path)
if err != nil {
return nil, err
}
if len(apps) > 1 {
return nil, &MultipleFoundError{"app", path}
}
return apps[0], nil
}
func (f *Finder) FolderList(ctx context.Context, path string) ([]*object.Folder, error) {
es, err := f.ManagedObjectList(ctx, path)
if err != nil {
return nil, err
}
var folders []*object.Folder
for _, e := range es {
switch o := e.Object.(type) {
case mo.Folder, mo.StoragePod:
folder := object.NewFolder(f.client, o.Reference())
folder.InventoryPath = e.Path
folders = append(folders, folder)
case *object.Folder:
// RootFolder
folders = append(folders, o)
}
}
if len(folders) == 0 {
return nil, &NotFoundError{"folder", path}
}
return folders, nil
}
func (f *Finder) Folder(ctx context.Context, path string) (*object.Folder, error) {
folders, err := f.FolderList(ctx, path)
if err != nil {
return nil, err
}
if len(folders) > 1 {
return nil, &MultipleFoundError{"folder", path}
}
return folders[0], nil
}