github.com/vmware/govmomi@v0.37.1/govc/fields/info.go (about)

     1  /*
     2  Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package fields
    18  
    19  import (
    20  	"context"
    21  	"flag"
    22  	"fmt"
    23  	"io"
    24  	"os"
    25  	"text/tabwriter"
    26  
    27  	"github.com/vmware/govmomi/govc/cli"
    28  	"github.com/vmware/govmomi/govc/flags"
    29  	"github.com/vmware/govmomi/object"
    30  	"github.com/vmware/govmomi/property"
    31  	"github.com/vmware/govmomi/vim25/mo"
    32  	"github.com/vmware/govmomi/vim25/types"
    33  )
    34  
    35  type info struct {
    36  	*flags.DatacenterFlag
    37  
    38  	name string
    39  }
    40  
    41  func init() {
    42  	cli.Register("fields.info", &info{})
    43  }
    44  
    45  func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
    46  	cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
    47  	cmd.DatacenterFlag.Register(ctx, f)
    48  
    49  	f.StringVar(&cmd.name, "n", "", "Filter by custom field name")
    50  }
    51  
    52  func (cmd *info) Usage() string {
    53  	return "PATH..."
    54  }
    55  
    56  func (cmd *info) Description() string {
    57  	return `Display custom field values for PATH.
    58  
    59  Also known as "Custom Attributes".
    60  
    61  Examples:
    62    govc fields.info vm/*
    63    govc fields.info -n my-field-name vm/*`
    64  }
    65  
    66  type Info struct {
    67  	Object types.ManagedObjectReference `json:"object"`
    68  	Path   string                       `json:"path"`
    69  	Name   string                       `json:"name"`
    70  	Key    string                       `json:"key"`
    71  	Value  string                       `json:"value"`
    72  }
    73  
    74  type infoResult struct {
    75  	Info []Info `json:"info"`
    76  }
    77  
    78  func (r *infoResult) Write(w io.Writer) error {
    79  	tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
    80  
    81  	for _, info := range r.Info {
    82  		_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\n", info.Path, info.Key, info.Value)
    83  	}
    84  
    85  	return tw.Flush()
    86  }
    87  
    88  func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
    89  	c, err := cmd.Client()
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	m, err := object.GetCustomFieldsManager(c)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	paths := make(map[types.ManagedObjectReference]string)
   100  	var refs []types.ManagedObjectReference
   101  
   102  	finder, err := cmd.Finder()
   103  	if err != nil {
   104  		return err
   105  	}
   106  
   107  	for _, arg := range f.Args() {
   108  		elements, ferr := finder.ManagedObjectList(ctx, arg)
   109  		if ferr != nil {
   110  			return ferr
   111  		}
   112  
   113  		if len(elements) == 0 {
   114  			return fmt.Errorf("object '%s' not found", arg)
   115  		}
   116  
   117  		for _, e := range elements {
   118  			ref := e.Object.Reference()
   119  			refs = append(refs, ref)
   120  			paths[ref] = e.Path
   121  		}
   122  	}
   123  
   124  	var objs []mo.ManagedEntity
   125  	err = property.DefaultCollector(c).Retrieve(ctx, refs, []string{"name", "customValue"}, &objs)
   126  	if err != nil {
   127  		return err
   128  	}
   129  
   130  	matches := func(key int32) bool {
   131  		return true
   132  	}
   133  
   134  	if cmd.name != "" {
   135  		fkey, cerr := m.FindKey(ctx, cmd.name)
   136  		if cerr != nil {
   137  			return err
   138  		}
   139  		matches = func(key int32) bool {
   140  			return key == fkey
   141  		}
   142  	}
   143  
   144  	field, err := m.Field(ctx)
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	var res infoResult
   150  
   151  	for _, obj := range objs {
   152  		for i := range obj.CustomValue {
   153  			val := obj.CustomValue[i].(*types.CustomFieldStringValue)
   154  
   155  			if !matches(val.Key) {
   156  				continue
   157  			}
   158  
   159  			res.Info = append(res.Info, Info{
   160  				Object: obj.Self,
   161  				Path:   paths[obj.Self],
   162  				Name:   obj.Name,
   163  				Key:    field.ByKey(val.Key).Name,
   164  				Value:  val.Value,
   165  			})
   166  		}
   167  	}
   168  
   169  	return cmd.WriteResult(&res)
   170  }