github.com/vmware/govmomi@v0.51.0/cli/fields/info.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package fields
     6  
     7  import (
     8  	"context"
     9  	"flag"
    10  	"fmt"
    11  	"io"
    12  	"os"
    13  	"text/tabwriter"
    14  
    15  	"github.com/vmware/govmomi/cli"
    16  	"github.com/vmware/govmomi/cli/flags"
    17  	"github.com/vmware/govmomi/object"
    18  	"github.com/vmware/govmomi/property"
    19  	"github.com/vmware/govmomi/vim25/mo"
    20  	"github.com/vmware/govmomi/vim25/types"
    21  )
    22  
    23  type info struct {
    24  	*flags.DatacenterFlag
    25  
    26  	name string
    27  }
    28  
    29  func init() {
    30  	cli.Register("fields.info", &info{})
    31  }
    32  
    33  func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
    34  	cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
    35  	cmd.DatacenterFlag.Register(ctx, f)
    36  
    37  	f.StringVar(&cmd.name, "n", "", "Filter by custom field name")
    38  }
    39  
    40  func (cmd *info) Usage() string {
    41  	return "PATH..."
    42  }
    43  
    44  func (cmd *info) Description() string {
    45  	return `Display custom field values for PATH.
    46  
    47  Also known as "Custom Attributes".
    48  
    49  Examples:
    50    govc fields.info vm/*
    51    govc fields.info -n my-field-name vm/*`
    52  }
    53  
    54  type Info struct {
    55  	Object types.ManagedObjectReference `json:"object"`
    56  	Path   string                       `json:"path"`
    57  	Name   string                       `json:"name"`
    58  	Key    string                       `json:"key"`
    59  	Value  string                       `json:"value"`
    60  }
    61  
    62  type infoResult struct {
    63  	Info []Info `json:"info"`
    64  }
    65  
    66  func (r *infoResult) Write(w io.Writer) error {
    67  	tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
    68  
    69  	for _, info := range r.Info {
    70  		_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\n", info.Path, info.Key, info.Value)
    71  	}
    72  
    73  	return tw.Flush()
    74  }
    75  
    76  func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
    77  	c, err := cmd.Client()
    78  	if err != nil {
    79  		return err
    80  	}
    81  
    82  	m, err := object.GetCustomFieldsManager(c)
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	paths := make(map[types.ManagedObjectReference]string)
    88  	var refs []types.ManagedObjectReference
    89  
    90  	finder, err := cmd.Finder()
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	for _, arg := range f.Args() {
    96  		elements, ferr := finder.ManagedObjectList(ctx, arg)
    97  		if ferr != nil {
    98  			return ferr
    99  		}
   100  
   101  		if len(elements) == 0 {
   102  			return fmt.Errorf("object '%s' not found", arg)
   103  		}
   104  
   105  		for _, e := range elements {
   106  			ref := e.Object.Reference()
   107  			refs = append(refs, ref)
   108  			paths[ref] = e.Path
   109  		}
   110  	}
   111  
   112  	var objs []mo.ManagedEntity
   113  	err = property.DefaultCollector(c).Retrieve(ctx, refs, []string{"name", "customValue"}, &objs)
   114  	if err != nil {
   115  		return err
   116  	}
   117  
   118  	matches := func(key int32) bool {
   119  		return true
   120  	}
   121  
   122  	if cmd.name != "" {
   123  		fkey, cerr := m.FindKey(ctx, cmd.name)
   124  		if cerr != nil {
   125  			return cerr
   126  		}
   127  		matches = func(key int32) bool {
   128  			return key == fkey
   129  		}
   130  	}
   131  
   132  	field, err := m.Field(ctx)
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	var res infoResult
   138  
   139  	for _, obj := range objs {
   140  		for i := range obj.CustomValue {
   141  			val := obj.CustomValue[i].(*types.CustomFieldStringValue)
   142  
   143  			if !matches(val.Key) {
   144  				continue
   145  			}
   146  
   147  			res.Info = append(res.Info, Info{
   148  				Object: obj.Self,
   149  				Path:   paths[obj.Self],
   150  				Name:   obj.Name,
   151  				Key:    field.ByKey(val.Key).Name,
   152  				Value:  val.Value,
   153  			})
   154  		}
   155  	}
   156  
   157  	return cmd.WriteResult(&res)
   158  }