Skip to content

Commit

Permalink
Add single quote escaping while parsing input command
Browse files Browse the repository at this point in the history
  • Loading branch information
mszostok committed Apr 18, 2024
1 parent 19e9467 commit 0c26435
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
4 changes: 2 additions & 2 deletions pkg/execute/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ func (e *DefaultExecutor) Execute(ctx context.Context) interactive.CoreMessage {

flags, err := ParseFlags(expandedRawCmd)
if err != nil {
e.log.Errorf("while parsing command flags %q: %s", expandedRawCmd, err.Error())
e.log.WithError(err).WithField("msg", expandedRawCmd).Error("Failed to parse user message")
return interactive.CoreMessage{
Description: header(cmdCtx),
Message: api.Message{
BaseBody: api.Body{
Plaintext: err.Error(),
Plaintext: cantParseCmd,
},
},
}
Expand Down
20 changes: 18 additions & 2 deletions pkg/execute/params.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package execute

import (
"errors"
"fmt"
"regexp"
"strings"
Expand Down Expand Up @@ -31,6 +30,8 @@ type Flags struct {

// ParseFlags parses raw cmd and removes optional params with flags.
func ParseFlags(cmd string) (Flags, error) {
cmd = ensureEvenSingleQuotes(cmd)

cmd, clusterName, err := extractParam(cmd, "cluster-name")
if err != nil {
return Flags{}, err
Expand All @@ -54,7 +55,7 @@ func ParseFlags(cmd string) (Flags, error) {

tokenized, err := shellwords.Parse(cmd)
if err != nil {
return Flags{}, errors.New(cantParseCmd)
return Flags{}, err
}
return Flags{
CleanCmd: cmd,
Expand Down Expand Up @@ -110,6 +111,21 @@ func extractParam(cmd, flagName string) (string, string, error) {
return cmd, withParam, nil
}

// ensureEvenSingleQuotes ensures that single quotes are even. It is required, e.g., for AI plugins to work.
// Otherwise, the command won't be parsed correctly (removing cluster name flags, etc.) and will result in an error.
// This is only a workaround for now. Ultimately, we should find a better and more generic way for extracting
// parameters. Additionally, we should delegate command tokenizing to the plugin.
func ensureEvenSingleQuotes(cmd string) string {
for _, k := range []string{`‘`, `'`, `’`} {
no := strings.Count(cmd, k)
if no%2 == 0 {
continue
}
cmd = strings.Replace(cmd, k, k+k, 1)
}
return cmd
}

func extractBoolParam(cmd, flagName string) (string, bool, error) {
flag := fmt.Sprintf("--%s", flagName)
var isSet bool
Expand Down
14 changes: 14 additions & 0 deletions pkg/execute/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,20 @@ func TestRemoveBotkubeRelatedFlags(t *testing.T) {
ClusterName: "api",
Filter: "=./Users/botkube/somefile.txt [info]",
},
{
Name: "Handle even number of single quotes with text filter and cluster name extraction",
Input: `@botkube ai I'm not sure if it's what's best for us, but let's give it a try. --cluster-name='api' --filter="=./Users/botkube/somefile.txt"`,
Cmd: `@botkube ai I'm not sure if it's what's best for us, but let's give it a try. `,
ClusterName: "api",
Filter: "=./Users/botkube/somefile.txt",
},
{
Name: "Handle odd number of single quotes with text filter and cluster name extraction",
Input: `@botkube ai are there any failing pods? It's what's been keeping me energized lately --cluster-name='api' --filter="=./Users/botkube/somefile.txt"`,
Cmd: `@botkube ai are there any failing pods? It's what's been keeping me energized lately `,
ClusterName: "api",
Filter: "=./Users/botkube/somefile.txt",
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
Expand Down

0 comments on commit 0c26435

Please sign in to comment.