github.com/smithx10/nomad@v0.9.1-rc1/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 }