Skip to content

Commit

Permalink
Introduce v3 command names for run-action and run
Browse files Browse the repository at this point in the history
  • Loading branch information
wallyworld committed Aug 27, 2019
1 parent b109dc2 commit d770e56
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 96 deletions.
9 changes: 8 additions & 1 deletion cmd/juju/action/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/juju/cmd"
"github.com/juju/errors"
"github.com/juju/gnuflag"
"github.com/juju/utils/featureflag"
"gopkg.in/juju/charm.v6"
"gopkg.in/juju/names.v3"
"gopkg.in/yaml.v2"
Expand All @@ -20,6 +21,7 @@ import (
"github.com/juju/juju/cmd/juju/common"
"github.com/juju/juju/cmd/modelcmd"
"github.com/juju/juju/cmd/output"
"github.com/juju/juju/feature"
)

// leaderSnippet is a regular expression for unit ID-like syntax that is used
Expand Down Expand Up @@ -97,12 +99,17 @@ func (c *runCommand) SetFlags(f *gnuflag.FlagSet) {
}

func (c *runCommand) Info() *cmd.Info {
return jujucmd.Info(&cmd.Info{
info := jujucmd.Info(&cmd.Info{
Name: "run-action",
Args: "<unit> [<unit> ...] <action name> [key.key.key...=value]",
Purpose: "Queue an action for execution.",
Doc: runDoc,
})
if featureflag.Enabled(feature.JujuV3) {
info.Name = "run"
info.Doc = strings.Replace(info.Doc, "run-action", "run", -1)
}
return info
}

// Init gets the unit tag(s), action name and action arguments.
Expand Down
2 changes: 1 addition & 1 deletion cmd/juju/action/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func (s *RunSuite) TestInit(c *gc.C) {
for i, t := range tests {
for _, modelFlag := range s.modelFlags {
wrappedCommand, command := action.NewRunCommandForTest(s.store)
c.Logf("test %d: should %s:\n$ juju run-action %s\n", i,
c.Logf("test %d: should %s:\n$ juju run (action) %s\n", i,
t.should, strings.Join(t.args, " "))
args := append([]string{modelFlag, "admin"}, t.args...)
err := cmdtesting.InitCommand(wrappedCommand, args)
Expand Down
50 changes: 28 additions & 22 deletions cmd/juju/commands/run.go → cmd/juju/commands/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ const leaderSnippet = "(" + names.ApplicationSnippet + ")/leader"
var validLeader = regexp.MustCompile("^" + leaderSnippet + "$")

func newDefaultRunCommand(store jujuclient.ClientStore) cmd.Command {
return newRunCommand(store, time.After)
return newExecCommand(store, time.After)
}

func newRunCommand(store jujuclient.ClientStore, timeAfter func(time.Duration) <-chan time.Time) cmd.Command {
cmd := modelcmd.Wrap(&runCommand{
func newExecCommand(store jujuclient.ClientStore, timeAfter func(time.Duration) <-chan time.Time) cmd.Command {
cmd := modelcmd.Wrap(&execCommand{
timeAfter: timeAfter,
})
cmd.SetClientStore(store)
return cmd
}

// runCommand is responsible for running arbitrary commands on remote machines.
type runCommand struct {
// execCommand is responsible for running arbitrary commands on remote machines.
type execCommand struct {
modelcmd.ModelCommandBase
out cmd.Output
all bool
Expand All @@ -61,7 +61,7 @@ type runCommand struct {
timeAfter func(time.Duration) <-chan time.Time
}

const runDoc = `
const execDoc = `
Run a shell command on the specified targets. Only admin users of a model
are able to use this command.
Expand Down Expand Up @@ -99,26 +99,32 @@ the unit.
in the model. If you specify --all you cannot provide additional
targets.
Since juju run creates actions, you can query for the status of commands
Since juju exec creates actions, you can query for the status of commands
started with juju run by calling "juju show-action-status --name juju-run".
If you need to pass options to the command being run, you must precede the
command and its arguments with "--", to tell "juju run" to stop processing
command and its arguments with "--", to tell "juju exec" to stop processing
those arguments. For example:
juju run --all -- hostname -f
juju exec --all -- hostname -f
NOTE: Juju 2 uses "juju run" which is deprecated in favour of "juju exec".
`

func (c *runCommand) Info() *cmd.Info {
return jujucmd.Info(&cmd.Info{
Name: "run",
func (c *execCommand) Info() *cmd.Info {
info := jujucmd.Info(&cmd.Info{
Name: "exec",
Args: "<commands>",
Purpose: "Run the commands on the remote targets specified.",
Doc: runDoc,
Doc: execDoc,
})
if !featureflag.Enabled(feature.JujuV3) {
info.Aliases = []string{"run"}
}
return info
}

func (c *runCommand) SetFlags(f *gnuflag.FlagSet) {
func (c *execCommand) SetFlags(f *gnuflag.FlagSet) {
c.ModelCommandBase.SetFlags(f)
c.out.AddFlags(f, "default", map[string]cmd.Formatter{
"yaml": cmd.FormatYaml,
Expand All @@ -139,7 +145,7 @@ func (c *runCommand) SetFlags(f *gnuflag.FlagSet) {
f.Var(cmd.NewStringsValue(nil, &c.units), "unit", "")
}

func (c *runCommand) Init(args []string) error {
func (c *execCommand) Init(args []string) error {
if len(args) == 0 {
return errors.Errorf("no commands specified")
}
Expand Down Expand Up @@ -191,7 +197,7 @@ func (c *runCommand) Init(args []string) error {
}
}
if len(nameErrors) > 0 {
return errors.Errorf("The following run targets are not valid:\n%s",
return errors.Errorf("The following exec targets are not valid:\n%s",
strings.Join(nameErrors, "\n"))
}

Expand Down Expand Up @@ -246,8 +252,8 @@ func ConvertActionResults(result params.ActionResult, query actionQuery) map[str
return values
}

func (c *runCommand) Run(ctx *cmd.Context) error {
client, err := getRunAPIClient(c)
func (c *execCommand) Run(ctx *cmd.Context) error {
client, err := getExecAPIClient(c)
if err != nil {
return err
}
Expand All @@ -264,7 +270,7 @@ func (c *runCommand) Run(ctx *cmd.Context) error {
}

if client.BestAPIVersion() < 4 {
return errors.Errorf("k8s controller does not support juju run" +
return errors.Errorf("k8s controller does not support juju exec" +
"\nconsider upgrading your controller")
}
if len(c.machines) > 0 {
Expand Down Expand Up @@ -442,15 +448,15 @@ type actionQuery struct {
}

// RunClient exposes the capabilities required by the CLI
type RunClient interface {
type ExecClient interface {
action.APIClient
RunOnAllMachines(commands string, timeout time.Duration) ([]params.ActionResult, error)
Run(params.RunParams) ([]params.ActionResult, error)
}

// In order to be able to easily mock out the API side for testing,
// the API client is retrieved using a function.
var getRunAPIClient = func(c *runCommand) (RunClient, error) {
var getExecAPIClient = func(c *execCommand) (ExecClient, error) {
root, err := c.NewAPIRoot()
if err != nil {
return nil, errors.Trace(err)
Expand All @@ -459,7 +465,7 @@ var getRunAPIClient = func(c *runCommand) (RunClient, error) {
}

// getActionResult abstracts over the action CLI function that we use here to fetch results
var getActionResult = func(c RunClient, actionId string, wait *time.Timer) (params.ActionResult, error) {
var getActionResult = func(c ExecClient, actionId string, wait *time.Timer) (params.ActionResult, error) {
return action.GetActionResult(c, actionId, wait)
}

Expand Down

0 comments on commit d770e56

Please sign in to comment.