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