mirror of
https://github.com/kemko/nomad.git
synced 2026-01-04 09:25:46 +03:00
This adds a `nomad alloc stop` command that can be used to stop and force migrate an allocation to a different node. This is built on top of the AllocUpdateDesiredTransitionRequest and explicitly limits the scope of access to that transition to expose it under the alloc-lifecycle ACL. The API returns the follow up eval that can be used as part of monitoring in the CLI or parsed and used in an external tool.
685 lines
14 KiB
Go
685 lines
14 KiB
Go
package command
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/hashicorp/nomad/command/agent"
|
|
"github.com/hashicorp/nomad/drivers/docker/docklog"
|
|
"github.com/hashicorp/nomad/version"
|
|
colorable "github.com/mattn/go-colorable"
|
|
"github.com/mitchellh/cli"
|
|
)
|
|
|
|
const (
|
|
// EnvNomadCLINoColor is an env var that toggles colored UI output.
|
|
EnvNomadCLINoColor = `NOMAD_CLI_NO_COLOR`
|
|
)
|
|
|
|
// DeprecatedCommand is a command that wraps an existing command and prints a
|
|
// deprecation notice and points the user to the new command. Deprecated
|
|
// commands are always hidden from help output.
|
|
type DeprecatedCommand struct {
|
|
cli.Command
|
|
Meta
|
|
|
|
// Old is the old command name, New is the new command name.
|
|
Old, New string
|
|
}
|
|
|
|
// Help wraps the embedded Help command and prints a warning about deprecations.
|
|
func (c *DeprecatedCommand) Help() string {
|
|
c.warn()
|
|
return c.Command.Help()
|
|
}
|
|
|
|
// Run wraps the embedded Run command and prints a warning about deprecation.
|
|
func (c *DeprecatedCommand) Run(args []string) int {
|
|
c.warn()
|
|
return c.Command.Run(args)
|
|
}
|
|
|
|
func (c *DeprecatedCommand) warn() {
|
|
c.Ui.Warn(wrapAtLength(fmt.Sprintf(
|
|
"WARNING! The \"nomad %s\" command is deprecated. Please use \"nomad %s\" "+
|
|
"instead. This command will be removed in Nomad 0.10 (or later).",
|
|
c.Old,
|
|
c.New)))
|
|
c.Ui.Warn("")
|
|
}
|
|
|
|
// NamedCommand is a interface to denote a commmand's name.
|
|
type NamedCommand interface {
|
|
Name() string
|
|
}
|
|
|
|
// Commands returns the mapping of CLI commands for Nomad. The meta
|
|
// parameter lets you set meta options for all commands.
|
|
func Commands(metaPtr *Meta, agentUi cli.Ui) map[string]cli.CommandFactory {
|
|
if metaPtr == nil {
|
|
metaPtr = new(Meta)
|
|
}
|
|
|
|
meta := *metaPtr
|
|
if meta.Ui == nil {
|
|
meta.Ui = &cli.BasicUi{
|
|
Reader: os.Stdin,
|
|
Writer: colorable.NewColorableStdout(),
|
|
ErrorWriter: colorable.NewColorableStderr(),
|
|
}
|
|
}
|
|
|
|
all := map[string]cli.CommandFactory{
|
|
"acl": func() (cli.Command, error) {
|
|
return &ACLCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl bootstrap": func() (cli.Command, error) {
|
|
return &ACLBootstrapCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl policy": func() (cli.Command, error) {
|
|
return &ACLPolicyCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl policy apply": func() (cli.Command, error) {
|
|
return &ACLPolicyApplyCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl policy delete": func() (cli.Command, error) {
|
|
return &ACLPolicyDeleteCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl policy info": func() (cli.Command, error) {
|
|
return &ACLPolicyInfoCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl policy list": func() (cli.Command, error) {
|
|
return &ACLPolicyListCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl token": func() (cli.Command, error) {
|
|
return &ACLTokenCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl token create": func() (cli.Command, error) {
|
|
return &ACLTokenCreateCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl token update": func() (cli.Command, error) {
|
|
return &ACLTokenUpdateCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl token delete": func() (cli.Command, error) {
|
|
return &ACLTokenDeleteCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl token info": func() (cli.Command, error) {
|
|
return &ACLTokenInfoCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"acl token self": func() (cli.Command, error) {
|
|
return &ACLTokenSelfCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"alloc": func() (cli.Command, error) {
|
|
return &AllocCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"alloc stop": func() (cli.Command, error) {
|
|
return &AllocStopCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"alloc fs": func() (cli.Command, error) {
|
|
return &AllocFSCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"alloc logs": func() (cli.Command, error) {
|
|
return &AllocLogsCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"alloc restart": func() (cli.Command, error) {
|
|
return &AllocRestartCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"alloc status": func() (cli.Command, error) {
|
|
return &AllocStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"alloc-status": func() (cli.Command, error) {
|
|
return &AllocStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"agent": func() (cli.Command, error) {
|
|
return &agent.Command{
|
|
Version: version.GetVersion(),
|
|
Ui: agentUi,
|
|
ShutdownCh: make(chan struct{}),
|
|
}, nil
|
|
},
|
|
"agent-info": func() (cli.Command, error) {
|
|
return &AgentInfoCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"check": func() (cli.Command, error) {
|
|
return &AgentCheckCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"deployment": func() (cli.Command, error) {
|
|
return &DeploymentCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"deployment fail": func() (cli.Command, error) {
|
|
return &DeploymentFailCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"deployment list": func() (cli.Command, error) {
|
|
return &DeploymentListCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"deployment pause": func() (cli.Command, error) {
|
|
return &DeploymentPauseCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"deployment promote": func() (cli.Command, error) {
|
|
return &DeploymentPromoteCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"deployment resume": func() (cli.Command, error) {
|
|
return &DeploymentResumeCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"deployment status": func() (cli.Command, error) {
|
|
return &DeploymentStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
docklog.PluginName: func() (cli.Command, error) {
|
|
return &DockerLoggerPluginCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"eval": func() (cli.Command, error) {
|
|
return &EvalCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"eval status": func() (cli.Command, error) {
|
|
return &EvalStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"eval-status": func() (cli.Command, error) {
|
|
return &EvalStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"executor": func() (cli.Command, error) {
|
|
return &ExecutorPluginCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"fs": func() (cli.Command, error) {
|
|
return &AllocFSCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"init": func() (cli.Command, error) {
|
|
return &JobInitCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"inspect": func() (cli.Command, error) {
|
|
return &JobInspectCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"keygen": func() (cli.Command, error) {
|
|
return &OperatorKeygenCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"keyring": func() (cli.Command, error) {
|
|
return &OperatorKeyringCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job": func() (cli.Command, error) {
|
|
return &JobCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job deployments": func() (cli.Command, error) {
|
|
return &JobDeploymentsCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job dispatch": func() (cli.Command, error) {
|
|
return &JobDispatchCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job eval": func() (cli.Command, error) {
|
|
return &JobEvalCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job history": func() (cli.Command, error) {
|
|
return &JobHistoryCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job init": func() (cli.Command, error) {
|
|
return &JobInitCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job inspect": func() (cli.Command, error) {
|
|
return &JobInspectCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job plan": func() (cli.Command, error) {
|
|
return &JobPlanCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job promote": func() (cli.Command, error) {
|
|
return &JobPromoteCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job revert": func() (cli.Command, error) {
|
|
return &JobRevertCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job run": func() (cli.Command, error) {
|
|
return &JobRunCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job status": func() (cli.Command, error) {
|
|
return &JobStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job stop": func() (cli.Command, error) {
|
|
return &JobStopCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"job validate": func() (cli.Command, error) {
|
|
return &JobValidateCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"logmon": func() (cli.Command, error) {
|
|
return &LogMonPluginCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"logs": func() (cli.Command, error) {
|
|
return &AllocLogsCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"namespace": func() (cli.Command, error) {
|
|
return &NamespaceCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"namespace apply": func() (cli.Command, error) {
|
|
return &NamespaceApplyCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"namespace delete": func() (cli.Command, error) {
|
|
return &NamespaceDeleteCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"namespace inspect": func() (cli.Command, error) {
|
|
return &NamespaceInspectCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"namespace list": func() (cli.Command, error) {
|
|
return &NamespaceListCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"namespace status": func() (cli.Command, error) {
|
|
return &NamespaceStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"node": func() (cli.Command, error) {
|
|
return &NodeCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"node config": func() (cli.Command, error) {
|
|
return &NodeConfigCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"node-drain": func() (cli.Command, error) {
|
|
return &NodeDrainCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"node drain": func() (cli.Command, error) {
|
|
return &NodeDrainCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"node eligibility": func() (cli.Command, error) {
|
|
return &NodeEligibilityCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"node-status": func() (cli.Command, error) {
|
|
return &NodeStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"node status": func() (cli.Command, error) {
|
|
return &NodeStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"operator": func() (cli.Command, error) {
|
|
return &OperatorCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"operator autopilot": func() (cli.Command, error) {
|
|
return &OperatorAutopilotCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"operator autopilot get-config": func() (cli.Command, error) {
|
|
return &OperatorAutopilotGetCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"operator autopilot set-config": func() (cli.Command, error) {
|
|
return &OperatorAutopilotSetCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"operator keygen": func() (cli.Command, error) {
|
|
return &OperatorKeygenCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"operator keyring": func() (cli.Command, error) {
|
|
return &OperatorKeyringCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"operator raft": func() (cli.Command, error) {
|
|
return &OperatorRaftCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"operator raft list-peers": func() (cli.Command, error) {
|
|
return &OperatorRaftListCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"operator raft remove-peer": func() (cli.Command, error) {
|
|
return &OperatorRaftRemoveCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"plan": func() (cli.Command, error) {
|
|
return &JobPlanCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"quota": func() (cli.Command, error) {
|
|
return &QuotaCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"quota apply": func() (cli.Command, error) {
|
|
return &QuotaApplyCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"quota delete": func() (cli.Command, error) {
|
|
return &QuotaDeleteCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"quota init": func() (cli.Command, error) {
|
|
return &QuotaInitCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"quota inspect": func() (cli.Command, error) {
|
|
return &QuotaInspectCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"quota list": func() (cli.Command, error) {
|
|
return &QuotaListCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"quota status": func() (cli.Command, error) {
|
|
return &QuotaStatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
|
|
"run": func() (cli.Command, error) {
|
|
return &JobRunCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"sentinel": func() (cli.Command, error) {
|
|
return &SentinelCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"sentinel list": func() (cli.Command, error) {
|
|
return &SentinelListCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"sentinel apply": func() (cli.Command, error) {
|
|
return &SentinelApplyCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"sentinel delete": func() (cli.Command, error) {
|
|
return &SentinelDeleteCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"sentinel read": func() (cli.Command, error) {
|
|
return &SentinelReadCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"server": func() (cli.Command, error) {
|
|
return &ServerCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"server force-leave": func() (cli.Command, error) {
|
|
return &ServerForceLeaveCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"server join": func() (cli.Command, error) {
|
|
return &ServerJoinCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"server members": func() (cli.Command, error) {
|
|
return &ServerMembersCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"server-force-leave": func() (cli.Command, error) {
|
|
return &ServerForceLeaveCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"server-join": func() (cli.Command, error) {
|
|
return &ServerJoinCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"server-members": func() (cli.Command, error) {
|
|
return &ServerMembersCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"status": func() (cli.Command, error) {
|
|
return &StatusCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"stop": func() (cli.Command, error) {
|
|
return &JobStopCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"ui": func() (cli.Command, error) {
|
|
return &UiCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"validate": func() (cli.Command, error) {
|
|
return &JobValidateCommand{
|
|
Meta: meta,
|
|
}, nil
|
|
},
|
|
"version": func() (cli.Command, error) {
|
|
return &VersionCommand{
|
|
Version: version.GetVersion(),
|
|
Ui: meta.Ui,
|
|
}, nil
|
|
},
|
|
}
|
|
|
|
deprecated := map[string]cli.CommandFactory{
|
|
"client-config": func() (cli.Command, error) {
|
|
return &DeprecatedCommand{
|
|
Old: "client-config",
|
|
New: "node config",
|
|
Meta: meta,
|
|
Command: &NodeConfigCommand{
|
|
Meta: meta,
|
|
},
|
|
}, nil
|
|
},
|
|
|
|
"keygen": func() (cli.Command, error) {
|
|
return &DeprecatedCommand{
|
|
Old: "keygen",
|
|
New: "operator keygen",
|
|
Meta: meta,
|
|
Command: &OperatorKeygenCommand{
|
|
Meta: meta,
|
|
},
|
|
}, nil
|
|
},
|
|
|
|
"keyring": func() (cli.Command, error) {
|
|
return &DeprecatedCommand{
|
|
Old: "keyring",
|
|
New: "operator keyring",
|
|
Meta: meta,
|
|
Command: &OperatorKeyringCommand{
|
|
Meta: meta,
|
|
},
|
|
}, nil
|
|
},
|
|
|
|
"server-force-leave": func() (cli.Command, error) {
|
|
return &DeprecatedCommand{
|
|
Old: "server-force-leave",
|
|
New: "server force-leave",
|
|
Meta: meta,
|
|
Command: &ServerForceLeaveCommand{
|
|
Meta: meta,
|
|
},
|
|
}, nil
|
|
},
|
|
|
|
"server-join": func() (cli.Command, error) {
|
|
return &DeprecatedCommand{
|
|
Old: "server-join",
|
|
New: "server join",
|
|
Meta: meta,
|
|
Command: &ServerJoinCommand{
|
|
Meta: meta,
|
|
},
|
|
}, nil
|
|
},
|
|
|
|
"server-members": func() (cli.Command, error) {
|
|
return &DeprecatedCommand{
|
|
Old: "server-members",
|
|
New: "server members",
|
|
Meta: meta,
|
|
Command: &ServerMembersCommand{
|
|
Meta: meta,
|
|
},
|
|
}, nil
|
|
},
|
|
}
|
|
|
|
for k, v := range deprecated {
|
|
all[k] = v
|
|
}
|
|
return all
|
|
}
|