github.com/vmware/govmomi@v0.43.0/govc/host/esxcli/esxcli.go (about)

     1  /*
     2  Copyright (c) 2014-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 esxcli
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"flag"
    23  	"fmt"
    24  	"io"
    25  	"sort"
    26  	"strings"
    27  	"text/tabwriter"
    28  
    29  	"github.com/vmware/govmomi/govc/cli"
    30  	"github.com/vmware/govmomi/govc/flags"
    31  )
    32  
    33  type esxcli struct {
    34  	*flags.HostSystemFlag
    35  
    36  	hints bool
    37  }
    38  
    39  func init() {
    40  	cli.Register("host.esxcli", &esxcli{})
    41  }
    42  
    43  func (cmd *esxcli) Usage() string {
    44  	return "COMMAND [ARG]..."
    45  }
    46  
    47  func (cmd *esxcli) Register(ctx context.Context, f *flag.FlagSet) {
    48  	cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
    49  	cmd.HostSystemFlag.Register(ctx, f)
    50  
    51  	f.BoolVar(&cmd.hints, "hints", true, "Use command info hints when formatting output")
    52  }
    53  
    54  func (cmd *esxcli) Description() string {
    55  	return `Invoke esxcli command on HOST.
    56  
    57  Output is rendered in table form when possible, unless disabled with '-hints=false'.
    58  
    59  Examples:
    60    govc host.esxcli network ip connection list
    61    govc host.esxcli system settings advanced set -o /Net/GuestIPHack -i 1
    62    govc host.esxcli network firewall ruleset set -r remoteSerialPort -e true
    63    govc host.esxcli network firewall set -e false
    64    govc host.esxcli hardware platform get`
    65  }
    66  
    67  func (cmd *esxcli) Process(ctx context.Context) error {
    68  	if err := cmd.HostSystemFlag.Process(ctx); err != nil {
    69  		return err
    70  	}
    71  	return nil
    72  }
    73  
    74  func (cmd *esxcli) Run(ctx context.Context, f *flag.FlagSet) error {
    75  	if f.NArg() == 0 {
    76  		return flag.ErrHelp
    77  	}
    78  
    79  	c, err := cmd.Client()
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	host, err := cmd.HostSystem()
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	e, err := NewExecutor(c, host)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	res, err := e.Run(f.Args())
    95  	if err != nil {
    96  		if f, ok := err.(*Fault); ok {
    97  			return errors.New(f.messageDetail())
    98  		}
    99  		return err
   100  	}
   101  
   102  	if len(res.Values) == 0 {
   103  		if res.String != "" {
   104  			fmt.Print(res.String)
   105  			if !strings.HasSuffix(res.String, "\n") {
   106  				fmt.Println()
   107  			}
   108  		}
   109  		return nil
   110  	}
   111  
   112  	return cmd.WriteResult(&result{res, cmd})
   113  }
   114  
   115  type result struct {
   116  	*Response
   117  	cmd *esxcli
   118  }
   119  
   120  func (r *result) Write(w io.Writer) error {
   121  	var formatType string
   122  	if r.cmd.hints {
   123  		formatType = r.Info.Hints.Formatter()
   124  	}
   125  
   126  	switch formatType {
   127  	case "table":
   128  		r.cmd.formatTable(w, r.Response)
   129  	default:
   130  		r.cmd.formatSimple(w, r.Response)
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  func (cmd *esxcli) formatSimple(w io.Writer, res *Response) {
   137  	var keys []string
   138  	for key := range res.Values[0] {
   139  		keys = append(keys, key)
   140  	}
   141  	sort.Strings(keys)
   142  
   143  	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
   144  
   145  	for i, rv := range res.Values {
   146  		if i > 0 {
   147  			fmt.Fprintln(tw)
   148  			_ = tw.Flush()
   149  		}
   150  		for _, key := range keys {
   151  			fmt.Fprintf(tw, "%s:\t%s\n", key, strings.Join(rv[key], ", "))
   152  		}
   153  	}
   154  
   155  	_ = tw.Flush()
   156  }
   157  
   158  func (cmd *esxcli) formatTable(w io.Writer, res *Response) {
   159  	fields := res.Info.Hints.Fields()
   160  	if len(fields) == 0 {
   161  		cmd.formatSimple(w, res)
   162  		return
   163  	}
   164  	tw := tabwriter.NewWriter(w, len(fields), 0, 2, ' ', 0)
   165  
   166  	var hr []string
   167  	for _, name := range fields {
   168  		hr = append(hr, strings.Repeat("-", len(name)))
   169  	}
   170  
   171  	fmt.Fprintln(tw, strings.Join(fields, "\t"))
   172  	fmt.Fprintln(tw, strings.Join(hr, "\t"))
   173  
   174  	for _, vals := range res.Values {
   175  		var row []string
   176  
   177  		for _, name := range fields {
   178  			key := strings.Replace(name, " ", "", -1)
   179  			if val, ok := vals[key]; ok {
   180  				row = append(row, strings.Join(val, ", "))
   181  			} else {
   182  				row = append(row, "")
   183  			}
   184  		}
   185  
   186  		fmt.Fprintln(tw, strings.Join(row, "\t"))
   187  	}
   188  
   189  	_ = tw.Flush()
   190  }