Skip to content

Commit

Permalink
feat(core): set can handle all positional args together (scaleway#3722)
Browse files Browse the repository at this point in the history
Co-authored-by: Jules Castéran <jules.casteran@gmail.com>
  • Loading branch information
2 people authored and jremy42 committed Apr 12, 2024
1 parent db2ae8d commit 0465a7a
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 2 deletions.
20 changes: 18 additions & 2 deletions internal/core/cobra_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,31 @@ func cobraRun(ctx context.Context, cmd *Command) func(*cobra.Command, []string)

results := MultiResults(nil)
rawArgs = rawArgs.RemoveAllPositional()
for _, positionalArg := range positionalArgs {
rawArgsWithPositional := rawArgs.Add(positionalArgSpec.Name, positionalArg)

if cmd.AcceptMultiplePositionalArgs {
argNameWithIndex := fmt.Sprintf("%s.%d", positionalArgSpec.Name, 0)
rawArgsWithPositional := rawArgs.Add(argNameWithIndex, positionalArgs[0])
for i := 1; i < len(positionalArgs); i++ {
argNameWithIndex = fmt.Sprintf("%s.%d", positionalArgSpec.Name, i)
rawArgsWithPositional = rawArgsWithPositional.Add(argNameWithIndex, positionalArgs[i])
}
result, err := run(ctx, cobraCmd, cmd, rawArgsWithPositional)
if err != nil {
return err
}

results = append(results, result)
} else {
for _, positionalArg := range positionalArgs {
rawArgsWithPositional := rawArgs.Add(positionalArgSpec.Name, positionalArg)

result, err := run(ctx, cobraCmd, cmd, rawArgsWithPositional)
if err != nil {
return err
}

results = append(results, result)
}
}
// If only one positional parameter was provided we return the result directly instead of
// an array of results
Expand Down
71 changes: 71 additions & 0 deletions internal/core/cobra_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/scaleway/scaleway-cli/v2/internal/core"
"github.com/stretchr/testify/assert"

"github.com/scaleway/scaleway-cli/v2/internal/args"
)
Expand All @@ -21,6 +22,11 @@ type testDate struct {
Date *time.Time
}

type testAcceptMultiPositionalArgsType struct {
NameIDs []string
Tag string
}

func testGetCommands() *core.Commands {
return core.NewCommands(
&core.Command{
Expand Down Expand Up @@ -54,6 +60,25 @@ func testGetCommands() *core.Commands {
return argsI, nil
},
},
&core.Command{
Namespace: "test",
Resource: "multi-positional",
ArgSpecs: core.ArgSpecs{
{
Name: "name-ids",
Positional: true,
},
{
Name: "tag",
},
},
AcceptMultiplePositionalArgs: true,
AllowAnonymousClient: true,
ArgsType: reflect.TypeOf(testAcceptMultiPositionalArgsType{}),
Run: func(_ context.Context, argsI interface{}) (i interface{}, e error) {
return argsI, nil
},
},
&core.Command{
Namespace: "test",
Resource: "raw-args",
Expand Down Expand Up @@ -247,3 +272,49 @@ func Test_PositionalArg(t *testing.T) {
),
}))
}

func Test_MultiPositionalArg(t *testing.T) {
t.Run("multi-positional with one positional", core.Test(&core.TestConfig{
Commands: testGetCommands(),
Cmd: "scw test multi-positional pos1 tag=tag1",
Check: core.TestCheckCombine(
core.TestCheckExitCode(0),
core.TestCheckGolden(),
func(t *testing.T, ctx *core.CheckFuncCtx) {
res := ctx.Result.(*testAcceptMultiPositionalArgsType)
assert.Equal(t, 1, len(res.NameIDs))
assert.Equal(t, "pos1", res.NameIDs[0])
assert.Equal(t, "tag1", res.Tag)
},
),
}))

t.Run("multi-positional with multi positional", core.Test(&core.TestConfig{
Commands: testGetCommands(),
Cmd: "scw test multi-positional pos1 pos2 pos3 tag=tag1",
Check: core.TestCheckCombine(
core.TestCheckExitCode(0),
core.TestCheckGolden(),
func(t *testing.T, ctx *core.CheckFuncCtx) {
res := ctx.Result.(*testAcceptMultiPositionalArgsType)
assert.Equal(t, 3, len(res.NameIDs))
assert.Equal(t, "pos1", res.NameIDs[0])
assert.Equal(t, "pos2", res.NameIDs[1])
assert.Equal(t, "pos3", res.NameIDs[2])
assert.Equal(t, "tag1", res.Tag)
},
),
}))

t.Run("multi-positional with no positional", core.Test(&core.TestConfig{
Commands: testGetCommands(),
Cmd: "scw test multi-positional tag=tag1",
Check: core.TestCheckCombine(
core.TestCheckExitCode(1),
core.TestCheckError(&core.CliError{
Err: fmt.Errorf("a positional argument is required for this command"),
Hint: "Try running: scw test multi-positional <name-ids> tag=tag1",
}),
),
}))
}
4 changes: 4 additions & 0 deletions internal/core/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ type Command struct {
// ArgSpecs defines specifications for arguments.
ArgSpecs ArgSpecs

// AcceptMultiplePositionalArgs defines whether the command can accept multiple positional arguments.
// If enabled, positional argument is expected to be a list.
AcceptMultiplePositionalArgs bool

// View defines the View for this command.
// It is used to create the different options for the different Marshalers.
View *View
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲
🟩🟩🟩 STDOUT️ 🟩🟩🟩️
NameIDs.0 pos1
NameIDs.1 pos2
NameIDs.2 pos3
Tag tag1
🟩🟩🟩 JSON STDOUT 🟩🟩🟩
{
"NameIDs": [
"pos1",
"pos2",
"pos3"
],
"Tag": "tag1"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲
🟩🟩🟩 STDOUT️ 🟩🟩🟩️
NameIDs.0 pos1
Tag tag1
🟩🟩🟩 JSON STDOUT 🟩🟩🟩
{
"NameIDs": [
"pos1"
],
"Tag": "tag1"
}

0 comments on commit 0465a7a

Please sign in to comment.