github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/command/meta.go (about)

     1  package command
     2  
     3  import (
     4  	"flag"
     5  	"os"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/nomad/api"
     9  	"github.com/mitchellh/cli"
    10  	"github.com/mitchellh/colorstring"
    11  	"github.com/posener/complete"
    12  	"golang.org/x/crypto/ssh/terminal"
    13  )
    14  
    15  const (
    16  	// Constants for CLI identifier length
    17  	shortId = 8
    18  	fullId  = 36
    19  )
    20  
    21  // FlagSetFlags is an enum to define what flags are present in the
    22  // default FlagSet returned by Meta.FlagSet.
    23  type FlagSetFlags uint
    24  
    25  const (
    26  	FlagSetNone    FlagSetFlags = 0
    27  	FlagSetClient  FlagSetFlags = 1 << iota
    28  	FlagSetDefault              = FlagSetClient
    29  )
    30  
    31  // Meta contains the meta-options and functionality that nearly every
    32  // Nomad command inherits.
    33  type Meta struct {
    34  	Ui cli.Ui
    35  
    36  	// These are set by the command line flags.
    37  	flagAddress string
    38  
    39  	// Whether to not-colorize output
    40  	noColor bool
    41  
    42  	// The region to send API requests
    43  	region string
    44  
    45  	// namespace to send API requests
    46  	namespace string
    47  
    48  	// token is used for ACLs to access privileged information
    49  	token string
    50  
    51  	caCert        string
    52  	caPath        string
    53  	clientCert    string
    54  	clientKey     string
    55  	tlsServerName string
    56  	insecure      bool
    57  }
    58  
    59  // FlagSet returns a FlagSet with the common flags that every
    60  // command implements. The exact behavior of FlagSet can be configured
    61  // using the flags as the second parameter, for example to disable
    62  // server settings on the commands that don't talk to a server.
    63  func (m *Meta) FlagSet(n string, fs FlagSetFlags) *flag.FlagSet {
    64  	f := flag.NewFlagSet(n, flag.ContinueOnError)
    65  
    66  	// FlagSetClient is used to enable the settings for specifying
    67  	// client connectivity options.
    68  	if fs&FlagSetClient != 0 {
    69  		f.StringVar(&m.flagAddress, "address", "", "")
    70  		f.StringVar(&m.region, "region", "", "")
    71  		f.StringVar(&m.namespace, "namespace", "", "")
    72  		f.BoolVar(&m.noColor, "no-color", false, "")
    73  		f.StringVar(&m.caCert, "ca-cert", "", "")
    74  		f.StringVar(&m.caPath, "ca-path", "", "")
    75  		f.StringVar(&m.clientCert, "client-cert", "", "")
    76  		f.StringVar(&m.clientKey, "client-key", "", "")
    77  		f.BoolVar(&m.insecure, "insecure", false, "")
    78  		f.StringVar(&m.tlsServerName, "tls-server-name", "", "")
    79  		f.BoolVar(&m.insecure, "tls-skip-verify", false, "")
    80  		f.StringVar(&m.token, "token", "", "")
    81  
    82  	}
    83  
    84  	f.SetOutput(&uiErrorWriter{ui: m.Ui})
    85  
    86  	return f
    87  }
    88  
    89  // AutocompleteFlags returns a set of flag completions for the given flag set.
    90  func (m *Meta) AutocompleteFlags(fs FlagSetFlags) complete.Flags {
    91  	if fs&FlagSetClient == 0 {
    92  		return nil
    93  	}
    94  
    95  	return complete.Flags{
    96  		"-address":         complete.PredictAnything,
    97  		"-region":          complete.PredictAnything,
    98  		"-namespace":       NamespacePredictor(m.Client, nil),
    99  		"-no-color":        complete.PredictNothing,
   100  		"-ca-cert":         complete.PredictFiles("*"),
   101  		"-ca-path":         complete.PredictDirs("*"),
   102  		"-client-cert":     complete.PredictFiles("*"),
   103  		"-client-key":      complete.PredictFiles("*"),
   104  		"-insecure":        complete.PredictNothing,
   105  		"-tls-server-name": complete.PredictNothing,
   106  		"-tls-skip-verify": complete.PredictNothing,
   107  		"-token":           complete.PredictAnything,
   108  	}
   109  }
   110  
   111  // ApiClientFactory is the signature of a API client factory
   112  type ApiClientFactory func() (*api.Client, error)
   113  
   114  // Client is used to initialize and return a new API client using
   115  // the default command line arguments and env vars.
   116  func (m *Meta) clientConfig() *api.Config {
   117  	config := api.DefaultConfig()
   118  	if m.flagAddress != "" {
   119  		config.Address = m.flagAddress
   120  	}
   121  	if m.region != "" {
   122  		config.Region = m.region
   123  	}
   124  	if m.namespace != "" {
   125  		config.Namespace = m.namespace
   126  	}
   127  
   128  	// If we need custom TLS configuration, then set it
   129  	if m.caCert != "" || m.caPath != "" || m.clientCert != "" || m.clientKey != "" || m.tlsServerName != "" || m.insecure {
   130  		t := &api.TLSConfig{
   131  			CACert:        m.caCert,
   132  			CAPath:        m.caPath,
   133  			ClientCert:    m.clientCert,
   134  			ClientKey:     m.clientKey,
   135  			TLSServerName: m.tlsServerName,
   136  			Insecure:      m.insecure,
   137  		}
   138  		config.TLSConfig = t
   139  	}
   140  
   141  	if m.token != "" {
   142  		config.SecretID = m.token
   143  	}
   144  
   145  	return config
   146  }
   147  
   148  func (m *Meta) Client() (*api.Client, error) {
   149  	return api.NewClient(m.clientConfig())
   150  }
   151  
   152  func (m *Meta) allNamespaces() bool {
   153  	return m.clientConfig().Namespace == api.AllNamespacesNamespace
   154  }
   155  
   156  func (m *Meta) Colorize() *colorstring.Colorize {
   157  	return &colorstring.Colorize{
   158  		Colors:  colorstring.DefaultColors,
   159  		Disable: m.noColor || !terminal.IsTerminal(int(os.Stdout.Fd())),
   160  		Reset:   true,
   161  	}
   162  }
   163  
   164  type usageOptsFlags uint8
   165  
   166  const (
   167  	usageOptsDefault     usageOptsFlags = 0
   168  	usageOptsNoNamespace                = 1 << iota
   169  )
   170  
   171  // generalOptionsUsage returns the help string for the global options.
   172  func generalOptionsUsage(usageOpts usageOptsFlags) string {
   173  
   174  	helpText := `
   175    -address=<addr>
   176      The address of the Nomad server.
   177      Overrides the NOMAD_ADDR environment variable if set.
   178      Default = http://127.0.0.1:4646
   179  
   180    -region=<region>
   181      The region of the Nomad servers to forward commands to.
   182      Overrides the NOMAD_REGION environment variable if set.
   183      Defaults to the Agent's local region.
   184  `
   185  
   186  	namespaceText := `
   187    -namespace=<namespace>
   188      The target namespace for queries and actions bound to a namespace.
   189      Overrides the NOMAD_NAMESPACE environment variable if set.
   190      If set to '*', job and alloc subcommands query all namespaces authorized
   191      to user.
   192      Defaults to the "default" namespace.
   193  `
   194  
   195  	// note: that although very few commands use color explicitly, all of them
   196  	// return red-colored text on error so we don't want to make this
   197  	// configurable
   198  	remainingText := `
   199    -no-color
   200      Disables colored command output. Alternatively, NOMAD_CLI_NO_COLOR may be
   201      set.
   202  
   203    -ca-cert=<path>
   204      Path to a PEM encoded CA cert file to use to verify the
   205      Nomad server SSL certificate.  Overrides the NOMAD_CACERT
   206      environment variable if set.
   207  
   208    -ca-path=<path>
   209      Path to a directory of PEM encoded CA cert files to verify
   210      the Nomad server SSL certificate. If both -ca-cert and
   211      -ca-path are specified, -ca-cert is used. Overrides the
   212      NOMAD_CAPATH environment variable if set.
   213  
   214    -client-cert=<path>
   215      Path to a PEM encoded client certificate for TLS authentication
   216      to the Nomad server. Must also specify -client-key. Overrides
   217      the NOMAD_CLIENT_CERT environment variable if set.
   218  
   219    -client-key=<path>
   220      Path to an unencrypted PEM encoded private key matching the
   221      client certificate from -client-cert. Overrides the
   222      NOMAD_CLIENT_KEY environment variable if set.
   223  
   224    -tls-server-name=<value>
   225      The server name to use as the SNI host when connecting via
   226      TLS. Overrides the NOMAD_TLS_SERVER_NAME environment variable if set.
   227  
   228    -tls-skip-verify
   229      Do not verify TLS certificate. This is highly not recommended. Verification
   230      will also be skipped if NOMAD_SKIP_VERIFY is set.
   231  
   232    -token
   233      The SecretID of an ACL token to use to authenticate API requests with.
   234      Overrides the NOMAD_TOKEN environment variable if set.
   235  `
   236  
   237  	if usageOpts&usageOptsNoNamespace == 0 {
   238  		helpText = helpText + namespaceText
   239  	}
   240  
   241  	helpText = helpText + remainingText
   242  	return strings.TrimSpace(helpText)
   243  }
   244  
   245  // funcVar is a type of flag that accepts a function that is the string given
   246  // by the user.
   247  type funcVar func(s string) error
   248  
   249  func (f funcVar) Set(s string) error { return f(s) }
   250  func (f funcVar) String() string     { return "" }
   251  func (f funcVar) IsBoolFlag() bool   { return false }