github.com/djenriquez/nomad-1@v0.8.1/command/meta.go (about)

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