1package command
2
3import (
4	"os"
5	"os/signal"
6	"syscall"
7
8	"github.com/hashicorp/vault/audit"
9	"github.com/hashicorp/vault/builtin/plugin"
10	"github.com/hashicorp/vault/sdk/logical"
11	"github.com/hashicorp/vault/sdk/physical"
12	"github.com/hashicorp/vault/sdk/version"
13	"github.com/mitchellh/cli"
14
15	/*
16		The builtinplugins package is initialized here because it, in turn,
17		initializes the database plugins.
18		They register multiple database drivers for the "database/sql" package.
19	*/
20	_ "github.com/hashicorp/vault/helper/builtinplugins"
21
22	auditFile "github.com/hashicorp/vault/builtin/audit/file"
23	auditSocket "github.com/hashicorp/vault/builtin/audit/socket"
24	auditSyslog "github.com/hashicorp/vault/builtin/audit/syslog"
25
26	credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
27	credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
28	credCF "github.com/hashicorp/vault-plugin-auth-cf"
29	credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
30	credOIDC "github.com/hashicorp/vault-plugin-auth-jwt"
31	credKerb "github.com/hashicorp/vault-plugin-auth-kerberos"
32	credOCI "github.com/hashicorp/vault-plugin-auth-oci"
33	credAws "github.com/hashicorp/vault/builtin/credential/aws"
34	credCert "github.com/hashicorp/vault/builtin/credential/cert"
35	credGitHub "github.com/hashicorp/vault/builtin/credential/github"
36	credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
37	credOkta "github.com/hashicorp/vault/builtin/credential/okta"
38	credToken "github.com/hashicorp/vault/builtin/credential/token"
39	credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
40
41	logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
42	logicalDb "github.com/hashicorp/vault/builtin/logical/database"
43
44	physAerospike "github.com/hashicorp/vault/physical/aerospike"
45	physAliCloudOSS "github.com/hashicorp/vault/physical/alicloudoss"
46	physAzure "github.com/hashicorp/vault/physical/azure"
47	physCassandra "github.com/hashicorp/vault/physical/cassandra"
48	physCockroachDB "github.com/hashicorp/vault/physical/cockroachdb"
49	physConsul "github.com/hashicorp/vault/physical/consul"
50	physCouchDB "github.com/hashicorp/vault/physical/couchdb"
51	physDynamoDB "github.com/hashicorp/vault/physical/dynamodb"
52	physEtcd "github.com/hashicorp/vault/physical/etcd"
53	physFoundationDB "github.com/hashicorp/vault/physical/foundationdb"
54	physGCS "github.com/hashicorp/vault/physical/gcs"
55	physManta "github.com/hashicorp/vault/physical/manta"
56	physMSSQL "github.com/hashicorp/vault/physical/mssql"
57	physMySQL "github.com/hashicorp/vault/physical/mysql"
58	physOCI "github.com/hashicorp/vault/physical/oci"
59	physPostgreSQL "github.com/hashicorp/vault/physical/postgresql"
60	physRaft "github.com/hashicorp/vault/physical/raft"
61	physS3 "github.com/hashicorp/vault/physical/s3"
62	physSpanner "github.com/hashicorp/vault/physical/spanner"
63	physSwift "github.com/hashicorp/vault/physical/swift"
64	physZooKeeper "github.com/hashicorp/vault/physical/zookeeper"
65	physFile "github.com/hashicorp/vault/sdk/physical/file"
66	physInmem "github.com/hashicorp/vault/sdk/physical/inmem"
67
68	sr "github.com/hashicorp/vault/serviceregistration"
69	csr "github.com/hashicorp/vault/serviceregistration/consul"
70	ksr "github.com/hashicorp/vault/serviceregistration/kubernetes"
71)
72
73const (
74	// EnvVaultCLINoColor is an env var that toggles colored UI output.
75	EnvVaultCLINoColor = `VAULT_CLI_NO_COLOR`
76	// EnvVaultFormat is the output format
77	EnvVaultFormat = `VAULT_FORMAT`
78	// EnvVaultLicense is an env var used in Vault Enterprise to provide a license blob
79	EnvVaultLicense = "VAULT_LICENSE"
80	// EnvVaultLicensePath is an env var used in Vault Enterprise to provide a
81	// path to a license file on disk
82	EnvVaultLicensePath = "VAULT_LICENSE_PATH"
83
84	// flagNameAddress is the flag used in the base command to read in the
85	// address of the Vault server.
86	flagNameAddress = "address"
87	// flagnameCACert is the flag used in the base command to read in the CA
88	// cert.
89	flagNameCACert = "ca-cert"
90	// flagnameCAPath is the flag used in the base command to read in the CA
91	// cert path.
92	flagNameCAPath = "ca-path"
93	// flagNameClientCert is the flag used in the base command to read in the
94	// client key
95	flagNameClientKey = "client-key"
96	// flagNameClientCert is the flag used in the base command to read in the
97	// client cert
98	flagNameClientCert = "client-cert"
99	// flagNameTLSSkipVerify is the flag used in the base command to read in
100	// the option to ignore TLS certificate verification.
101	flagNameTLSSkipVerify = "tls-skip-verify"
102	// flagTLSServerName is the flag used in the base command to read in
103	// the TLS server name.
104	flagTLSServerName = "tls-server-name"
105	// flagNameAuditNonHMACRequestKeys is the flag name used for auth/secrets enable
106	flagNameAuditNonHMACRequestKeys = "audit-non-hmac-request-keys"
107	// flagNameAuditNonHMACResponseKeys is the flag name used for auth/secrets enable
108	flagNameAuditNonHMACResponseKeys = "audit-non-hmac-response-keys"
109	// flagNameDescription is the flag name used for tuning the secret and auth mount description parameter
110	flagNameDescription = "description"
111	// flagListingVisibility is the flag to toggle whether to show the mount in the UI-specific listing endpoint
112	flagNameListingVisibility = "listing-visibility"
113	// flagNamePassthroughRequestHeaders is the flag name used to set passthrough request headers to the backend
114	flagNamePassthroughRequestHeaders = "passthrough-request-headers"
115	// flagNameAllowedResponseHeaders is used to set allowed response headers from a plugin
116	flagNameAllowedResponseHeaders = "allowed-response-headers"
117	// flagNameTokenType is the flag name used to force a specific token type
118	flagNameTokenType = "token-type"
119)
120
121var (
122	auditBackends = map[string]audit.Factory{
123		"file":   auditFile.Factory,
124		"socket": auditSocket.Factory,
125		"syslog": auditSyslog.Factory,
126	}
127
128	credentialBackends = map[string]logical.Factory{
129		"plugin": plugin.Factory,
130	}
131
132	logicalBackends = map[string]logical.Factory{
133		"plugin":   plugin.Factory,
134		"database": logicalDb.Factory,
135		// This is also available in the plugin catalog, but is here due to the need to
136		// automatically mount it.
137		"kv": logicalKv.Factory,
138	}
139
140	physicalBackends = map[string]physical.Factory{
141		"aerospike":              physAerospike.NewAerospikeBackend,
142		"alicloudoss":            physAliCloudOSS.NewAliCloudOSSBackend,
143		"azure":                  physAzure.NewAzureBackend,
144		"cassandra":              physCassandra.NewCassandraBackend,
145		"cockroachdb":            physCockroachDB.NewCockroachDBBackend,
146		"consul":                 physConsul.NewConsulBackend,
147		"couchdb_transactional":  physCouchDB.NewTransactionalCouchDBBackend,
148		"couchdb":                physCouchDB.NewCouchDBBackend,
149		"dynamodb":               physDynamoDB.NewDynamoDBBackend,
150		"etcd":                   physEtcd.NewEtcdBackend,
151		"file_transactional":     physFile.NewTransactionalFileBackend,
152		"file":                   physFile.NewFileBackend,
153		"foundationdb":           physFoundationDB.NewFDBBackend,
154		"gcs":                    physGCS.NewBackend,
155		"inmem_ha":               physInmem.NewInmemHA,
156		"inmem_transactional_ha": physInmem.NewTransactionalInmemHA,
157		"inmem_transactional":    physInmem.NewTransactionalInmem,
158		"inmem":                  physInmem.NewInmem,
159		"manta":                  physManta.NewMantaBackend,
160		"mssql":                  physMSSQL.NewMSSQLBackend,
161		"mysql":                  physMySQL.NewMySQLBackend,
162		"oci":                    physOCI.NewBackend,
163		"postgresql":             physPostgreSQL.NewPostgreSQLBackend,
164		"s3":                     physS3.NewS3Backend,
165		"spanner":                physSpanner.NewBackend,
166		"swift":                  physSwift.NewSwiftBackend,
167		"raft":                   physRaft.NewRaftBackend,
168		"zookeeper":              physZooKeeper.NewZooKeeperBackend,
169	}
170
171	serviceRegistrations = map[string]sr.Factory{
172		"consul":     csr.NewServiceRegistration,
173		"kubernetes": ksr.NewServiceRegistration,
174	}
175
176	initCommandsEnt = func(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {}
177)
178
179// Commands is the mapping of all the available commands.
180var Commands map[string]cli.CommandFactory
181
182func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
183	loginHandlers := map[string]LoginHandler{
184		"alicloud": &credAliCloud.CLIHandler{},
185		"aws":      &credAws.CLIHandler{},
186		"centrify": &credCentrify.CLIHandler{},
187		"cert":     &credCert.CLIHandler{},
188		"cf":       &credCF.CLIHandler{},
189		"gcp":      &credGcp.CLIHandler{},
190		"github":   &credGitHub.CLIHandler{},
191		"kerberos": &credKerb.CLIHandler{},
192		"ldap":     &credLdap.CLIHandler{},
193		"oci":      &credOCI.CLIHandler{},
194		"oidc":     &credOIDC.CLIHandler{},
195		"okta":     &credOkta.CLIHandler{},
196		"pcf":      &credCF.CLIHandler{}, // Deprecated.
197		"radius": &credUserpass.CLIHandler{
198			DefaultMount: "radius",
199		},
200		"token": &credToken.CLIHandler{},
201		"userpass": &credUserpass.CLIHandler{
202			DefaultMount: "userpass",
203		},
204	}
205
206	getBaseCommand := func() *BaseCommand {
207		return &BaseCommand{
208			UI:          ui,
209			tokenHelper: runOpts.TokenHelper,
210			flagAddress: runOpts.Address,
211			client:      runOpts.Client,
212		}
213	}
214
215	Commands = map[string]cli.CommandFactory{
216		"agent": func() (cli.Command, error) {
217			return &AgentCommand{
218				BaseCommand: &BaseCommand{
219					UI: serverCmdUi,
220				},
221				ShutdownCh: MakeShutdownCh(),
222			}, nil
223		},
224		"audit": func() (cli.Command, error) {
225			return &AuditCommand{
226				BaseCommand: getBaseCommand(),
227			}, nil
228		},
229		"audit disable": func() (cli.Command, error) {
230			return &AuditDisableCommand{
231				BaseCommand: getBaseCommand(),
232			}, nil
233		},
234		"audit enable": func() (cli.Command, error) {
235			return &AuditEnableCommand{
236				BaseCommand: getBaseCommand(),
237			}, nil
238		},
239		"audit list": func() (cli.Command, error) {
240			return &AuditListCommand{
241				BaseCommand: getBaseCommand(),
242			}, nil
243		},
244		"auth tune": func() (cli.Command, error) {
245			return &AuthTuneCommand{
246				BaseCommand: getBaseCommand(),
247			}, nil
248		},
249		"auth": func() (cli.Command, error) {
250			return &AuthCommand{
251				BaseCommand: getBaseCommand(),
252			}, nil
253		},
254		"auth disable": func() (cli.Command, error) {
255			return &AuthDisableCommand{
256				BaseCommand: getBaseCommand(),
257			}, nil
258		},
259		"auth enable": func() (cli.Command, error) {
260			return &AuthEnableCommand{
261				BaseCommand: getBaseCommand(),
262			}, nil
263		},
264		"auth help": func() (cli.Command, error) {
265			return &AuthHelpCommand{
266				BaseCommand: getBaseCommand(),
267				Handlers:    loginHandlers,
268			}, nil
269		},
270		"auth list": func() (cli.Command, error) {
271			return &AuthListCommand{
272				BaseCommand: getBaseCommand(),
273			}, nil
274		},
275		"debug": func() (cli.Command, error) {
276			return &DebugCommand{
277				BaseCommand: getBaseCommand(),
278				ShutdownCh:  MakeShutdownCh(),
279			}, nil
280		},
281		"delete": func() (cli.Command, error) {
282			return &DeleteCommand{
283				BaseCommand: getBaseCommand(),
284			}, nil
285		},
286		"lease": func() (cli.Command, error) {
287			return &LeaseCommand{
288				BaseCommand: getBaseCommand(),
289			}, nil
290		},
291		"lease renew": func() (cli.Command, error) {
292			return &LeaseRenewCommand{
293				BaseCommand: getBaseCommand(),
294			}, nil
295		},
296		"lease lookup": func() (cli.Command, error) {
297			return &LeaseLookupCommand{
298				BaseCommand: getBaseCommand(),
299			}, nil
300		},
301		"lease revoke": func() (cli.Command, error) {
302			return &LeaseRevokeCommand{
303				BaseCommand: getBaseCommand(),
304			}, nil
305		},
306		"list": func() (cli.Command, error) {
307			return &ListCommand{
308				BaseCommand: getBaseCommand(),
309			}, nil
310		},
311		"login": func() (cli.Command, error) {
312			return &LoginCommand{
313				BaseCommand: getBaseCommand(),
314				Handlers:    loginHandlers,
315			}, nil
316		},
317		"namespace": func() (cli.Command, error) {
318			return &NamespaceCommand{
319				BaseCommand: getBaseCommand(),
320			}, nil
321		},
322		"namespace list": func() (cli.Command, error) {
323			return &NamespaceListCommand{
324				BaseCommand: getBaseCommand(),
325			}, nil
326		},
327		"namespace lookup": func() (cli.Command, error) {
328			return &NamespaceLookupCommand{
329				BaseCommand: getBaseCommand(),
330			}, nil
331		},
332		"namespace create": func() (cli.Command, error) {
333			return &NamespaceCreateCommand{
334				BaseCommand: getBaseCommand(),
335			}, nil
336		},
337		"namespace delete": func() (cli.Command, error) {
338			return &NamespaceDeleteCommand{
339				BaseCommand: getBaseCommand(),
340			}, nil
341		},
342		"operator": func() (cli.Command, error) {
343			return &OperatorCommand{
344				BaseCommand: getBaseCommand(),
345			}, nil
346		},
347		"operator diagnose": func() (cli.Command, error) {
348			return &OperatorDiagnoseCommand{
349				BaseCommand: getBaseCommand(),
350			}, nil
351		},
352		"operator generate-root": func() (cli.Command, error) {
353			return &OperatorGenerateRootCommand{
354				BaseCommand: getBaseCommand(),
355			}, nil
356		},
357		"operator init": func() (cli.Command, error) {
358			return &OperatorInitCommand{
359				BaseCommand: getBaseCommand(),
360			}, nil
361		},
362		"operator key-status": func() (cli.Command, error) {
363			return &OperatorKeyStatusCommand{
364				BaseCommand: getBaseCommand(),
365			}, nil
366		},
367		"operator migrate": func() (cli.Command, error) {
368			return &OperatorMigrateCommand{
369				BaseCommand:      getBaseCommand(),
370				PhysicalBackends: physicalBackends,
371				ShutdownCh:       MakeShutdownCh(),
372			}, nil
373		},
374		"operator raft": func() (cli.Command, error) {
375			return &OperatorRaftCommand{
376				BaseCommand: getBaseCommand(),
377			}, nil
378		},
379		"operator raft autopilot get-config": func() (cli.Command, error) {
380			return &OperatorRaftAutopilotGetConfigCommand{
381				BaseCommand: getBaseCommand(),
382			}, nil
383		},
384		"operator raft autopilot set-config": func() (cli.Command, error) {
385			return &OperatorRaftAutopilotSetConfigCommand{
386				BaseCommand: getBaseCommand(),
387			}, nil
388		},
389		"operator raft autopilot state": func() (cli.Command, error) {
390			return &OperatorRaftAutopilotStateCommand{
391				BaseCommand: getBaseCommand(),
392			}, nil
393		},
394		"operator raft list-peers": func() (cli.Command, error) {
395			return &OperatorRaftListPeersCommand{
396				BaseCommand: getBaseCommand(),
397			}, nil
398		},
399		"operator raft join": func() (cli.Command, error) {
400			return &OperatorRaftJoinCommand{
401				BaseCommand: getBaseCommand(),
402			}, nil
403		},
404		"operator raft remove-peer": func() (cli.Command, error) {
405			return &OperatorRaftRemovePeerCommand{
406				BaseCommand: getBaseCommand(),
407			}, nil
408		},
409		"operator raft snapshot": func() (cli.Command, error) {
410			return &OperatorRaftSnapshotCommand{
411				BaseCommand: getBaseCommand(),
412			}, nil
413		},
414		"operator raft snapshot restore": func() (cli.Command, error) {
415			return &OperatorRaftSnapshotRestoreCommand{
416				BaseCommand: getBaseCommand(),
417			}, nil
418		},
419		"operator raft snapshot save": func() (cli.Command, error) {
420			return &OperatorRaftSnapshotSaveCommand{
421				BaseCommand: getBaseCommand(),
422			}, nil
423		},
424		"operator rekey": func() (cli.Command, error) {
425			return &OperatorRekeyCommand{
426				BaseCommand: getBaseCommand(),
427			}, nil
428		},
429		"operator rotate": func() (cli.Command, error) {
430			return &OperatorRotateCommand{
431				BaseCommand: getBaseCommand(),
432			}, nil
433		},
434		"operator seal": func() (cli.Command, error) {
435			return &OperatorSealCommand{
436				BaseCommand: getBaseCommand(),
437			}, nil
438		},
439		"operator step-down": func() (cli.Command, error) {
440			return &OperatorStepDownCommand{
441				BaseCommand: getBaseCommand(),
442			}, nil
443		},
444		"operator usage": func() (cli.Command, error) {
445			return &OperatorUsageCommand{
446				BaseCommand: getBaseCommand(),
447			}, nil
448		},
449		"operator unseal": func() (cli.Command, error) {
450			return &OperatorUnsealCommand{
451				BaseCommand: getBaseCommand(),
452			}, nil
453		},
454		"path-help": func() (cli.Command, error) {
455			return &PathHelpCommand{
456				BaseCommand: getBaseCommand(),
457			}, nil
458		},
459		"plugin": func() (cli.Command, error) {
460			return &PluginCommand{
461				BaseCommand: getBaseCommand(),
462			}, nil
463		},
464		"plugin deregister": func() (cli.Command, error) {
465			return &PluginDeregisterCommand{
466				BaseCommand: getBaseCommand(),
467			}, nil
468		},
469		"plugin info": func() (cli.Command, error) {
470			return &PluginInfoCommand{
471				BaseCommand: getBaseCommand(),
472			}, nil
473		},
474		"plugin list": func() (cli.Command, error) {
475			return &PluginListCommand{
476				BaseCommand: getBaseCommand(),
477			}, nil
478		},
479		"plugin register": func() (cli.Command, error) {
480			return &PluginRegisterCommand{
481				BaseCommand: getBaseCommand(),
482			}, nil
483		},
484		"plugin reload": func() (cli.Command, error) {
485			return &PluginReloadCommand{
486				BaseCommand: getBaseCommand(),
487			}, nil
488		},
489		"plugin reload-status": func() (cli.Command, error) {
490			return &PluginReloadStatusCommand{
491				BaseCommand: getBaseCommand(),
492			}, nil
493		},
494		"policy": func() (cli.Command, error) {
495			return &PolicyCommand{
496				BaseCommand: getBaseCommand(),
497			}, nil
498		},
499		"policy delete": func() (cli.Command, error) {
500			return &PolicyDeleteCommand{
501				BaseCommand: getBaseCommand(),
502			}, nil
503		},
504		"policy fmt": func() (cli.Command, error) {
505			return &PolicyFmtCommand{
506				BaseCommand: getBaseCommand(),
507			}, nil
508		},
509		"policy list": func() (cli.Command, error) {
510			return &PolicyListCommand{
511				BaseCommand: getBaseCommand(),
512			}, nil
513		},
514		"policy read": func() (cli.Command, error) {
515			return &PolicyReadCommand{
516				BaseCommand: getBaseCommand(),
517			}, nil
518		},
519		"policy write": func() (cli.Command, error) {
520			return &PolicyWriteCommand{
521				BaseCommand: getBaseCommand(),
522			}, nil
523		},
524		"print": func() (cli.Command, error) {
525			return &PrintCommand{
526				BaseCommand: getBaseCommand(),
527			}, nil
528		},
529		"print token": func() (cli.Command, error) {
530			return &PrintTokenCommand{
531				BaseCommand: getBaseCommand(),
532			}, nil
533		},
534		"read": func() (cli.Command, error) {
535			return &ReadCommand{
536				BaseCommand: getBaseCommand(),
537			}, nil
538		},
539		"secrets": func() (cli.Command, error) {
540			return &SecretsCommand{
541				BaseCommand: getBaseCommand(),
542			}, nil
543		},
544		"secrets disable": func() (cli.Command, error) {
545			return &SecretsDisableCommand{
546				BaseCommand: getBaseCommand(),
547			}, nil
548		},
549		"secrets enable": func() (cli.Command, error) {
550			return &SecretsEnableCommand{
551				BaseCommand: getBaseCommand(),
552			}, nil
553		},
554		"secrets list": func() (cli.Command, error) {
555			return &SecretsListCommand{
556				BaseCommand: getBaseCommand(),
557			}, nil
558		},
559		"secrets move": func() (cli.Command, error) {
560			return &SecretsMoveCommand{
561				BaseCommand: getBaseCommand(),
562			}, nil
563		},
564		"secrets tune": func() (cli.Command, error) {
565			return &SecretsTuneCommand{
566				BaseCommand: getBaseCommand(),
567			}, nil
568		},
569		"server": func() (cli.Command, error) {
570			return &ServerCommand{
571				BaseCommand: &BaseCommand{
572					UI:          serverCmdUi,
573					tokenHelper: runOpts.TokenHelper,
574					flagAddress: runOpts.Address,
575				},
576				AuditBackends:      auditBackends,
577				CredentialBackends: credentialBackends,
578				LogicalBackends:    logicalBackends,
579				PhysicalBackends:   physicalBackends,
580
581				ServiceRegistrations: serviceRegistrations,
582
583				ShutdownCh: MakeShutdownCh(),
584				SighupCh:   MakeSighupCh(),
585				SigUSR2Ch:  MakeSigUSR2Ch(),
586			}, nil
587		},
588		"ssh": func() (cli.Command, error) {
589			return &SSHCommand{
590				BaseCommand: getBaseCommand(),
591			}, nil
592		},
593		"status": func() (cli.Command, error) {
594			return &StatusCommand{
595				BaseCommand: getBaseCommand(),
596			}, nil
597		},
598		"token": func() (cli.Command, error) {
599			return &TokenCommand{
600				BaseCommand: getBaseCommand(),
601			}, nil
602		},
603		"token create": func() (cli.Command, error) {
604			return &TokenCreateCommand{
605				BaseCommand: getBaseCommand(),
606			}, nil
607		},
608		"token capabilities": func() (cli.Command, error) {
609			return &TokenCapabilitiesCommand{
610				BaseCommand: getBaseCommand(),
611			}, nil
612		},
613		"token lookup": func() (cli.Command, error) {
614			return &TokenLookupCommand{
615				BaseCommand: getBaseCommand(),
616			}, nil
617		},
618		"token renew": func() (cli.Command, error) {
619			return &TokenRenewCommand{
620				BaseCommand: getBaseCommand(),
621			}, nil
622		},
623		"token revoke": func() (cli.Command, error) {
624			return &TokenRevokeCommand{
625				BaseCommand: getBaseCommand(),
626			}, nil
627		},
628		"unwrap": func() (cli.Command, error) {
629			return &UnwrapCommand{
630				BaseCommand: getBaseCommand(),
631			}, nil
632		},
633		"version": func() (cli.Command, error) {
634			return &VersionCommand{
635				VersionInfo: version.GetVersion(),
636				BaseCommand: getBaseCommand(),
637			}, nil
638		},
639		"write": func() (cli.Command, error) {
640			return &WriteCommand{
641				BaseCommand: getBaseCommand(),
642			}, nil
643		},
644		"kv": func() (cli.Command, error) {
645			return &KVCommand{
646				BaseCommand: getBaseCommand(),
647			}, nil
648		},
649		"kv put": func() (cli.Command, error) {
650			return &KVPutCommand{
651				BaseCommand: getBaseCommand(),
652			}, nil
653		},
654		"kv patch": func() (cli.Command, error) {
655			return &KVPatchCommand{
656				BaseCommand: getBaseCommand(),
657			}, nil
658		},
659		"kv rollback": func() (cli.Command, error) {
660			return &KVRollbackCommand{
661				BaseCommand: getBaseCommand(),
662			}, nil
663		},
664		"kv get": func() (cli.Command, error) {
665			return &KVGetCommand{
666				BaseCommand: getBaseCommand(),
667			}, nil
668		},
669		"kv delete": func() (cli.Command, error) {
670			return &KVDeleteCommand{
671				BaseCommand: getBaseCommand(),
672			}, nil
673		},
674		"kv list": func() (cli.Command, error) {
675			return &KVListCommand{
676				BaseCommand: getBaseCommand(),
677			}, nil
678		},
679		"kv destroy": func() (cli.Command, error) {
680			return &KVDestroyCommand{
681				BaseCommand: getBaseCommand(),
682			}, nil
683		},
684		"kv undelete": func() (cli.Command, error) {
685			return &KVUndeleteCommand{
686				BaseCommand: getBaseCommand(),
687			}, nil
688		},
689		"kv enable-versioning": func() (cli.Command, error) {
690			return &KVEnableVersioningCommand{
691				BaseCommand: getBaseCommand(),
692			}, nil
693		},
694		"kv metadata": func() (cli.Command, error) {
695			return &KVMetadataCommand{
696				BaseCommand: getBaseCommand(),
697			}, nil
698		},
699		"kv metadata put": func() (cli.Command, error) {
700			return &KVMetadataPutCommand{
701				BaseCommand: getBaseCommand(),
702			}, nil
703		},
704		"kv metadata get": func() (cli.Command, error) {
705			return &KVMetadataGetCommand{
706				BaseCommand: getBaseCommand(),
707			}, nil
708		},
709		"kv metadata delete": func() (cli.Command, error) {
710			return &KVMetadataDeleteCommand{
711				BaseCommand: getBaseCommand(),
712			}, nil
713		},
714		"monitor": func() (cli.Command, error) {
715			return &MonitorCommand{
716				BaseCommand: getBaseCommand(),
717				ShutdownCh:  MakeShutdownCh(),
718			}, nil
719		},
720	}
721
722	// Disabled by default until functional
723	if os.Getenv(OperatorDiagnoseEnableEnv) != "" {
724		Commands["operator diagnose"] = func() (cli.Command, error) {
725			return &OperatorDiagnoseCommand{
726				BaseCommand: getBaseCommand(),
727			}, nil
728		}
729	}
730
731	initCommandsEnt(ui, serverCmdUi, runOpts)
732}
733
734// MakeShutdownCh returns a channel that can be used for shutdown
735// notifications for commands. This channel will send a message for every
736// SIGINT or SIGTERM received.
737func MakeShutdownCh() chan struct{} {
738	resultCh := make(chan struct{})
739
740	shutdownCh := make(chan os.Signal, 4)
741	signal.Notify(shutdownCh, os.Interrupt, syscall.SIGTERM)
742	go func() {
743		<-shutdownCh
744		close(resultCh)
745	}()
746	return resultCh
747}
748
749// MakeSighupCh returns a channel that can be used for SIGHUP
750// reloading. This channel will send a message for every
751// SIGHUP received.
752func MakeSighupCh() chan struct{} {
753	resultCh := make(chan struct{})
754
755	signalCh := make(chan os.Signal, 4)
756	signal.Notify(signalCh, syscall.SIGHUP)
757	go func() {
758		for {
759			<-signalCh
760			resultCh <- struct{}{}
761		}
762	}()
763	return resultCh
764}
765