Skip to content

Commit

Permalink
Added '@botkube commands list' to show all the supported kubectl cmds (
Browse files Browse the repository at this point in the history
…#328)

##### ISSUE TYPE
 - Feature Pull Request

##### SUMMARY
Added new botkube command to list all the supported commands, @botkube commands list

Below are the changes
made changes in executor.go to handle newly added command  
added common method in utils.go to format the allowed commands  

Fixes #312
  • Loading branch information
girishg4t authored Sep 2, 2020
1 parent e94e914 commit ae980c7
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 2 deletions.
34 changes: 34 additions & 0 deletions pkg/execute/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ var (
validFilterCommand = map[string]bool{
"filters": true,
}
validInfoCommand = map[string]bool{
"commands": true,
}
validDebugCommands = map[string]bool{
"exec": true,
"logs": true,
Expand Down Expand Up @@ -146,6 +149,14 @@ const (
FilterDisable FiltersAction = "disable"
)

// infoAction for options in Info commands
type infoAction string

// Info command options
const (
infoList infoAction = "list"
)

func (action FiltersAction) String() string {
return string(action)
}
Expand Down Expand Up @@ -210,6 +221,12 @@ func (e *DefaultExecutor) Execute() string {
if validFilterCommand[args[0]] {
return e.runFilterCommand(args, e.ClusterName, e.IsAuthChannel)
}

//Check if info command
if validInfoCommand[args[0]] {
return e.runInfoCommand(args, e.IsAuthChannel)
}

if e.IsAuthChannel {
return printDefaultMsg(e.Platform)
}
Expand Down Expand Up @@ -360,6 +377,23 @@ func (e *DefaultExecutor) runFilterCommand(args []string, clusterName string, is
return printDefaultMsg(e.Platform)
}

//runInfoCommand to list allowed commands
func (e *DefaultExecutor) runInfoCommand(args []string, isAuthChannel bool) string {
if isAuthChannel == false {
return ""
}
if len(args) < 2 && args[1] != string(infoList) {
return IncompleteCmdMsg
}
return makeCommandInfoList()
}

func makeCommandInfoList() string {
allowedVerbs := utils.GetStringInYamlFormat("allowed verbs:", utils.AllowedKubectlVerbMap)
allowedResources := utils.GetStringInYamlFormat("allowed resources:", utils.AllowedKubectlResourceMap)
return allowedVerbs + allowedResources
}

// Use tabwriter to display string in tabular form
// https://golang.org/pkg/text/tabwriter
func makeFiltersList() string {
Expand Down
14 changes: 14 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package utils

import (
"bytes"
"fmt"
"os"
"regexp"
"strconv"
Expand Down Expand Up @@ -477,3 +479,15 @@ func GetClusterNameFromKubectlCmd(cmd string) string {
}
return s
}

//GetStringInYamlFormat get the formated commands list
func GetStringInYamlFormat(header string, commands map[string]bool) string {
var b bytes.Buffer
fmt.Fprintln(&b, header)
for k, v := range commands {
if v {
fmt.Fprintf(&b, " - %s\n", k)
}
}
return b.String()
}
13 changes: 13 additions & 0 deletions pkg/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package utils

import (
"fmt"
"testing"
)

Expand Down Expand Up @@ -49,3 +50,15 @@ func TestGetClusterNameFromKubectlCmd(t *testing.T) {
}
}
}

func TestGetStringInYamlFormat(t *testing.T) {
var header = "allowed verbs"
var commands = map[string]bool{
"api-versions": true,
}
expected := fmt.Sprintf(header + "\n - api-versions\n")
got := GetStringInYamlFormat(header, commands)
if got != expected {
t.Errorf("expected: %v, got: %v", expected, got)
}
}
26 changes: 25 additions & 1 deletion test/e2e/command/botkube.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,29 @@ func (c *context) testBotkubeCommand(t *testing.T) {
"ImageTagChecker true Checks and adds recommendation if 'latest' image tag is used for container image.\n" +
"IngressValidator true Checks if services and tls secrets used in ingress specs are available.\n",
},
"BotKube commands list": {
command: "commands list",
expected: "allowed verbs:\n" +
" - api-resources\n" +
" - describe\n" +
" - diff\n" +
" - explain\n" +
" - get\n" +
" - logs\n" +
" - api-versions\n" +
" - cluster-info\n" +
" - top\n" +
" - auth\n" +
"allowed resources:\n" +
" - nodes\n" +
" - deployments\n" +
" - pods\n" +
" - namespaces\n" +
" - daemonsets\n" +
" - statefulsets\n" +
" - storageclasses\n",
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
if c.TestEnv.Config.Communications.Slack.Enabled {
Expand All @@ -80,6 +101,9 @@ func (c *context) testBotkubeCommand(t *testing.T) {
case "filters list":
fl := compareFilters(strings.Split(test.expected, "\n"), strings.Split(strings.Trim(m.Text, "```"), "\n"))
assert.Equal(t, fl, true)
case "commands list":
cl := compareFilters(strings.Split(test.expected, "\n"), strings.Split(strings.Trim(m.Text, "```"), "\n"))
assert.Equal(t, cl, true)
default:
assert.Equal(t, test.expected, m.Text)
}
Expand Down
3 changes: 2 additions & 1 deletion test/resource_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ settings:
# method which are allowed
verbs: ["api-resources", "api-versions", "cluster-info", "describe", "diff", "explain", "get", "logs", "top", "auth"]
# resource configuration which is allowed
resources: ["deployments", "pods" , "namespaces", "daemonsets", "statefulsets", "storageclasses", "serviceaccounts"]
resources: ["deployments", "pods" , "namespaces", "daemonsets", "statefulsets", "storageclasses", "nodes"]

# set Namespace to execute botkube kubectl commands by default
defaultNamespace: default
# Set true to enable commands execution from configured channel only
Expand Down

0 comments on commit ae980c7

Please sign in to comment.