Skip to content

Commit

Permalink
Split mixin command args by whitespace
Browse files Browse the repository at this point in the history
Some mixin commands have whitespace and right now we are passing them in
as packed into a single array element when executing the command

exec.Cmd("aws", []string{"ec2", "run-instances", "--security-group-ids
group1 group2"})

When the debug command is printed, we can't tell that this has happened,
and why the command failed. What needs to happen is that when there is a
space, and it's not enclosed in double quotes, it should be split into
its own array element

exec.Cmd("aws", []string{"ec2", "run-instances", "--security-group-ids",
"group1", "group2"})
  • Loading branch information
carolynvs-msft committed Feb 27, 2020
1 parent 283c437 commit 3e66098
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
30 changes: 30 additions & 0 deletions pkg/exec/builder/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package builder

import (
"bytes"
"encoding/csv"
"fmt"
"io"
"strings"
Expand Down Expand Up @@ -77,6 +78,11 @@ func ExecuteStep(cxt *context.Context, step ExecutableStep) (string, error) {
}
args = append(args, flags.ToSlice(dashes)...)

// Split up any arguments or flags that have spaces so that we pass them as separate array elements
// It doesn't show up any differently in the printed command, but it matters to how the command
// it executed against the system.
args = expandOnWhitespace(args)

cmd := cxt.NewCommand(step.GetCommand(), args...)
output := &bytes.Buffer{}
cmd.Stdout = io.MultiWriter(cxt.Out, output)
Expand All @@ -99,3 +105,27 @@ func ExecuteStep(cxt *context.Context, step ExecutableStep) (string, error) {

return output.String(), nil
}

// expandOnWhitespace finds elements with multiple words that are not "glued" together with quotes
// and splits them into separate elements in the slice
func expandOnWhitespace(slice []string) []string {
expandedSlice := make([]string, 0, len(slice))
for _, chunk := range slice {
r := csv.NewReader(strings.NewReader(chunk))
r.Comma = ' '
r.LazyQuotes = true
group, err := r.Read()
if err != nil {
if err == io.EOF {
break
}
expandedSlice = append(expandedSlice, chunk)
} else {
for _, chunkette := range group {
expandedSlice = append(expandedSlice, chunkette)
}
}
}

return expandedSlice
}
22 changes: 22 additions & 0 deletions pkg/exec/builder/execute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,25 @@ func TestExecuteSingleStepAction(t *testing.T) {
exists, _ = c.FileSystem.Exists("/cnab/app/porter/outputs/jsonpath")
assert.True(t, exists, "jsonpath output was not evaluated")
}

func Test_expandOnWhitespace(t *testing.T) {
t.Run("split whitespace", func(t *testing.T) {
result := expandOnWhitespace([]string{"cmd", "--myarg", "val1 val2"})
assert.Equal(t, []string{"cmd", "--myarg", "val1", "val2"}, result)
})

t.Run("keep double quoted whitespace", func(t *testing.T) {
result := expandOnWhitespace([]string{"cmd", "--myarg", "\"val1 val2\" val3"})
assert.Equal(t, []string{"cmd", "--myarg", "val1 val2", "val3"}, result)
})

t.Run("embedded single quote", func(t *testing.T) {
result := expandOnWhitespace([]string{"cmd", "--myarg", `"Patty O'Brien" true`})
assert.Equal(t, []string{"cmd", "--myarg", "Patty O'Brien", "true"}, result)
})

t.Run("embedded double quote", func(t *testing.T) {
result := expandOnWhitespace([]string{"cmd", "--myarg", `"Patty O"Brien" true`})
assert.Equal(t, []string{"cmd", "--myarg", "Patty O\"Brien", "true"}, result)
})
}

0 comments on commit 3e66098

Please sign in to comment.