Skip to content

Commit

Permalink
Merge pull request #57 from vladimirvivien/parsing-cmd-with-colons
Browse files Browse the repository at this point in the history
Handle commands with embedded colons
  • Loading branch information
vladimirvivien authored Mar 27, 2020
2 parents c558caa + 218f3db commit 2d878bf
Show file tree
Hide file tree
Showing 13 changed files with 554 additions and 30 deletions.
54 changes: 54 additions & 0 deletions exec/run_exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,60 @@ func TestExecRUN(t *testing.T) {
return nil
},
},
{
name: "RUN single command with embeddec colon",
source: func() string {
return fmt.Sprintf(`FROM 127.0.0.1:%s
AUTHCONFIG username:${USER} private-key:${HOME}/.ssh/id_rsa
RUN /bin/echo "HELLO:WORLD"
`, testSSHPort)
},
exec: func(s *script.Script) error {

e := New(s)
if err := e.Execute(); err != nil {
return err
}

exitcode := os.Getenv("CMD_EXITCODE")
if exitcode != "0" {
return fmt.Errorf("RUN has unexpected exit code %s", exitcode)
}

result := os.Getenv("CMD_RESULT")
if result != "HELLO:WORLD" {
return fmt.Errorf("RUN has unexpected CMD_RESULT: %s", result)
}
return nil
},
},
{
name: "RUN with shell wrapped quoted subcommand with embedded colon",
source: func() string {
return fmt.Sprintf(`
FROM 127.0.0.1:%s
AUTHCONFIG username:${USER} private-key:${HOME}/.ssh/id_rsa
RUN shell:"/bin/bash -c" cmd:'echo "Hello:World"'`, testSSHPort)
},
exec: func(s *script.Script) error {

e := New(s)
if err := e.Execute(); err != nil {
return err
}

exitcode := os.Getenv("CMD_EXITCODE")
if exitcode != "0" {
return fmt.Errorf("RUN has unexpected exit code %s", exitcode)
}

result := os.Getenv("CMD_RESULT")
if strings.TrimSpace(result) != "Hello:World" {
return fmt.Errorf("RUN has unexpected CMD_RESULT: %s", result)
}
return nil
},
},
}

for _, test := range tests {
Expand Down
24 changes: 24 additions & 0 deletions script/authconfig_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,30 @@ func TestCommandAUTHCONFIG(t *testing.T) {
},
shouldFail: true,
},

{
name: "AUTHCONFIG - with embedded colon",
source: func() string {
return "AUTHCONFIG username:test-user private-key:'/a/:b/c'"
},
script: func(s *Script) error {
cmds := s.Preambles[CmdAuthConfig]
if len(cmds) != 1 {
return fmt.Errorf("Script missing preamble %s", CmdAuthConfig)
}
authCmd, ok := cmds[0].(*AuthConfigCommand)
if !ok {
return fmt.Errorf("Unexpected type %T in script", cmds[0])
}
if authCmd.GetUsername() != "test-user" {
return fmt.Errorf("Unexpected username %s", authCmd.GetUsername())
}
if authCmd.GetPrivateKey() != "/a/:b/c" {
return fmt.Errorf("Unexpected private-key %s", authCmd.GetPrivateKey())
}
return nil
},
},
}

for _, test := range tests {
Expand Down
186 changes: 186 additions & 0 deletions script/capture_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,192 @@ func TestCommandCAPTURE(t *testing.T) {
return nil
},
},
{
name: "CAPTURE with unqoted default with embeded colons",
source: func() string {
return `CAPTURE /bin/echo "HELLO:WORLD"`
},
script: func(s *Script) error {
if len(s.Actions) != 1 {
return fmt.Errorf("Script has unexpected action count, needs %d", len(s.Actions))
}
cmd, ok := s.Actions[0].(*CaptureCommand)
if !ok {
return fmt.Errorf("Unexpected action type %T in script", s.Actions[0])
}

if cmd.Args()["cmd"] != cmd.GetCmdString() {
return fmt.Errorf("CAPTURE action with unexpected command string %s", cmd.GetCmdString())
}
cliCmd, cliArgs, err := cmd.GetParsedCmd()
if err != nil {
return fmt.Errorf("CAPTURE command parse failed: %s", err)
}
if cliCmd != "/bin/echo" {
return fmt.Errorf("CAPTURE unexpected command parsed: %s", cliCmd)
}
if len(cliArgs) != 1 {
return fmt.Errorf("CAPTURE unexpected command args parsed: %d", len(cliArgs))
}
if cliArgs[0] != "HELLO:WORLD" {
return fmt.Errorf("CAPTURE has unexpected cli args: %#v", cliArgs)
}
return nil
},
},
{
name: "CAPTURE single-quoted-default with embedded colon",
source: func() string {
return `CAPTURE '/bin/echo -n "HELLO:WORLD"'`
},
script: func(s *Script) error {
if len(s.Actions) != 1 {
return fmt.Errorf("Script has unexpected actions, needs %d", len(s.Actions))
}
cmd := s.Actions[0].(*CaptureCommand)
if cmd.Args()["cmd"] != cmd.GetCmdString() {
return fmt.Errorf("CAPTURE action with unexpected CLI string %s", cmd.GetCmdString())
}
cliCmd, cliArgs, err := cmd.GetParsedCmd()
if err != nil {
return fmt.Errorf("CAPTURE command parse failed: %s", err)
}
if cliCmd != "/bin/echo" {
return fmt.Errorf("CAPTURE unexpected command parsed: %s", cliCmd)
}
if len(cliArgs) != 2 {
return fmt.Errorf("CAPTURE unexpected command args parsed: %d", len(cliArgs))
}
if cliArgs[0] != "-n" {
return fmt.Errorf("CAPTURE has unexpected cli args: %#v", cliArgs)
}
if cliArgs[1] != "HELLO:WORLD" {
return fmt.Errorf("CAPTURE has unexpected cli args: %#v", cliArgs)
}
return nil
},
},
{
name: "CAPTURE single-quoted named param with embedded colon",
source: func() string {
return `CAPTURE cmd:'/bin/echo -n "HELLO:WORLD"'`
},
script: func(s *Script) error {
if len(s.Actions) != 1 {
return fmt.Errorf("Script has unexpected actions, needs %d", len(s.Actions))
}
cmd := s.Actions[0].(*CaptureCommand)
if cmd.Args()["cmd"] != cmd.GetCmdString() {
return fmt.Errorf("CAPTURE action with unexpected CLI string %s", cmd.GetCmdString())
}
cliCmd, cliArgs, err := cmd.GetParsedCmd()
if err != nil {
return fmt.Errorf("CAPTURE command parse failed: %s", err)
}
if cliCmd != "/bin/echo" {
return fmt.Errorf("CAPTURE unexpected command parsed: %s", cliCmd)
}
if len(cliArgs) != 2 {
return fmt.Errorf("CAPTURE unexpected command args parsed: %d", len(cliArgs))
}
if cliArgs[0] != "-n" {
return fmt.Errorf("CAPTURE has unexpected cli args: %#v", cliArgs)
}
if cliArgs[1] != "HELLO:WORLD" {
return fmt.Errorf("CAPTURE has unexpected cli args: %#v", cliArgs)
}
return nil
},
},
{
name: "CAPTURE double-quoted named param with embedded colon",
source: func() string {
return `CAPTURE cmd:"/bin/echo -n 'HELLO:WORLD'"`
},
script: func(s *Script) error {
if len(s.Actions) != 1 {
return fmt.Errorf("Script has unexpected actions, needs %d", len(s.Actions))
}
cmd := s.Actions[0].(*CaptureCommand)
if cmd.Args()["cmd"] != cmd.GetCmdString() {
return fmt.Errorf("CAPTURE action with unexpected CLI string %s", cmd.GetCmdString())
}
cliCmd, cliArgs, err := cmd.GetParsedCmd()
if err != nil {
return fmt.Errorf("CAPTURE command parse failed: %s", err)
}
if cliCmd != "/bin/echo" {
return fmt.Errorf("CAPTURE unexpected command parsed: %s", cliCmd)
}
if len(cliArgs) != 2 {
return fmt.Errorf("CAPTURE unexpected command args parsed: %d", len(cliArgs))
}
if cliArgs[0] != "-n" {
return fmt.Errorf("CAPTURE has unexpected cli args: %#v", cliArgs)
}
if cliArgs[1] != "HELLO:WORLD" {
return fmt.Errorf("CAPTURE has unexpected cli args: %#v", cliArgs)
}
return nil
},
},
{
name: "CAPTURE unquoted named param with multiple embedded colons",
source: func() string {
return "CAPTURE cmd:/bin/date:time:"
},
script: func(s *Script) error {
cmd := s.Actions[0].(*CaptureCommand)
cliCmd, cliArgs, err := cmd.GetParsedCmd()
if err != nil {
return fmt.Errorf("CAPTURE command parse failed: %s", err)
}
if cliCmd != "/bin/date:time:" {
return fmt.Errorf("CAPTURE parsed unexpected command name: %s", cliCmd)
}
if len(cliArgs) != 0 {
return fmt.Errorf("CAPTURE parsed unexpected command args: %d", len(cliArgs))
}

return nil
},
},
{
name: "CAPTURE with shell and quoted subproc with embedded colon",
source: func() string {
return `CAPTURE shell:"/bin/bash -c" cmd:"echo 'HELLO:WORLD'"`
},
script: func(s *Script) error {
if len(s.Actions) != 1 {
return fmt.Errorf("Script has unexpected actions, needs %d", len(s.Actions))
}
cmd := s.Actions[0].(*CaptureCommand)
if cmd.Args()["cmd"] != cmd.GetCmdString() {
return fmt.Errorf("CAPTURE action with unexpected command string %s", cmd.GetCmdString())
}
if cmd.Args()["shell"] != cmd.GetCmdShell() {
return fmt.Errorf("CAPTURE action with unexpected shell %s", cmd.GetCmdShell())
}

cliCmd, cliArgs, err := cmd.GetParsedCmd()
if err != nil {
return fmt.Errorf("CAPTURE command parse failed: %s", err)
}
if len(cliArgs) != 2 {
return fmt.Errorf("CAPTURE unexpected command args parsed: %#v", cliArgs)
}
if cliCmd != "/bin/bash" {
return fmt.Errorf("CAPTURE unexpected command parsed: %#v", cliCmd)
}
if cliArgs[0] != "-c" {
return fmt.Errorf("CAPTURE has unexpected shell argument: expecting -c, got %s", cliArgs[0])
}
if cliArgs[1] != "echo 'HELLO:WORLD'" {
return fmt.Errorf("CAPTURE has unexpected shell argument: expecting -c, got %s", cliArgs[0])
}
return nil
},
},
}

for _, test := range tests {
Expand Down
46 changes: 46 additions & 0 deletions script/copy_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,52 @@ func TestCommandCOPY(t *testing.T) {
},
shouldFail: true,
},
{
name: "COPY with quoted default with ebedded colon",
source: func() string {
return `COPY '/a/:b/c'`
},
script: func(s *Script) error {
if len(s.Actions) != 1 {
return fmt.Errorf("Script has unexpected COPY actions, has %d COPY", len(s.Actions))
}

cmd := s.Actions[0].(*CopyCommand)
if len(cmd.Paths()) != 1 {
return fmt.Errorf("COPY has unexpected number of paths %d", len(cmd.Paths()))
}

arg := cmd.Paths()[0]
if arg != "/a/:b/c" {
return fmt.Errorf("COPY has unexpected argument %s", arg)
}
return nil
},
},
{
name: "COPY multiple with named param",
source: func() string {
return `COPY paths:"/a/b/c /e/:f/g"`
},
script: func(s *Script) error {
if len(s.Actions) != 1 {
return fmt.Errorf("Script has unexpected COPY actions, has %d COPY", len(s.Actions))
}

cmd := s.Actions[0].(*CopyCommand)
if len(cmd.Paths()) != 2 {
return fmt.Errorf("COPY has unexpected number of args %d", len(cmd.Paths()))
}
if cmd.Paths()[0] != "/a/b/c" {
return fmt.Errorf("COPY has unexpected argument[0] %s", cmd.Paths()[0])
}
if cmd.Paths()[1] != "/e/:f/g" {
return fmt.Errorf("COPY has unexpected argument[1] %s", cmd.Paths()[1])
}

return nil
},
},
}

for _, test := range tests {
Expand Down
4 changes: 2 additions & 2 deletions script/env_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewEnvCommand(index int, rawArgs string) (*EnvCommand, error) {
// supported format keyN=valN keyN="valN" keyN='valN'
// foreach key0=val0 key1=val1 ... keyN=valN
// split into keyN, valN
envs, err := wordSplit(argMap["vars"])
envs, err := commandSplit(argMap["vars"])
if err != nil {
return nil, fmt.Errorf("ENV: %s", err)
}
Expand All @@ -65,7 +65,7 @@ func NewEnvCommand(index int, rawArgs string) (*EnvCommand, error) {
}

key := parts[0]
val, err := wordSplit(parts[1]) // safely remove outer quotes
val, err := commandSplit(parts[1]) // safely remove outer quotes
if err != nil {
return nil, fmt.Errorf("ENV: %s", err)
}
Expand Down
Loading

0 comments on commit 2d878bf

Please sign in to comment.