Skip to content

Commit 1cfd0cd

Browse files
authored
Cloud Slack E2e Tests (#1205)
1 parent 6c85373 commit 1cfd0cd

11 files changed

+1257
-192
lines changed

.golangci.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ linters-settings:
4747
local-prefixes: github.com/kubeshop/botkube
4848
gocyclo:
4949
# https://github.com/kubeshop/botkube/issues/745
50-
min-complexity: 51
50+
# Merging slack and discord test cases increased cyclo due to if conditions
51+
min-complexity: 55
5152
revive:
5253
rules:
5354
# Disable warns about capitalized and ended with punctuation error messages

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ test: system-check
1818
@go test -v -race ./...
1919

2020
test-integration-slack: system-check
21-
@go test -v -tags=integration -race -count=1 ./test/e2e/... -run "TestSlack"
21+
@go test -timeout=20m -v -tags=integration -race -count=1 ./test/e2e/... -run "TestSlack"
2222

2323
test-integration-discord: system-check
24-
@go test -v -tags=integration -race -count=1 ./test/e2e/... -run "TestDiscord"
24+
@go test -timeout=20m -v -tags=integration -race -count=1 ./test/e2e/... -run "TestDiscord"
2525

2626
test-cli-migration-e2e: system-check
2727
@go test -v -tags=migration -race -count=1 ./test/e2e/...
+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
analytics:
2+
disable: true
3+
4+
rbac:
5+
create: true
6+
rules:
7+
- apiGroups: [ "*" ]
8+
resources: [ "*" ]
9+
verbs: [ "get", "watch", "list" ] # defaults
10+
staticGroupName: "botkube-plugins-default"
11+
12+
extraObjects:
13+
14+
# Group 'kubectl-first-channel': permissions for kubectl for first channel
15+
## namespace scoped permissions
16+
- apiVersion: rbac.authorization.k8s.io/v1
17+
kind: ClusterRole
18+
metadata: &kubectl-wait
19+
name: kubectl-first-channel-namespaced-perms
20+
labels:
21+
app.kubernetes.io/instance: botkube-e2e-test
22+
rules:
23+
- apiGroups: [ "apps" ]
24+
resources: [ "deployments" ]
25+
verbs: [ "get","watch","list" ]
26+
- apiGroups: [ "" ]
27+
resources: [ "configmaps", "pods" ]
28+
verbs: [ "get", "watch", "list" ]
29+
- apiVersion: rbac.authorization.k8s.io/v1
30+
kind: RoleBinding
31+
metadata:
32+
<<: *kubectl-wait
33+
namespace: botkube
34+
roleRef: &kubectl-wait-role
35+
apiGroup: rbac.authorization.k8s.io
36+
kind: ClusterRole
37+
name: kubectl-first-channel-namespaced-perms
38+
subjects: &kubectl-first-channel-subject
39+
- kind: User
40+
name: kubectl-first-channel
41+
apiGroup: rbac.authorization.k8s.io
42+
- apiVersion: rbac.authorization.k8s.io/v1
43+
kind: RoleBinding
44+
metadata:
45+
<<: *kubectl-wait
46+
namespace: default
47+
roleRef: *kubectl-wait-role
48+
subjects: *kubectl-first-channel-subject
49+
50+
### cluster permissions
51+
- apiVersion: rbac.authorization.k8s.io/v1
52+
kind: ClusterRole
53+
metadata: &kubectl-deploy-all-meta
54+
name: kc-first-channel-cluster-perms
55+
labels:
56+
app.kubernetes.io/instance: botkube-e2e-test
57+
rules:
58+
- apiGroups: [ "apps" ]
59+
resources: [ "deployments" ]
60+
verbs: [ "get", "list" ]
61+
- apiVersion: rbac.authorization.k8s.io/v1
62+
kind: ClusterRoleBinding
63+
metadata: *kubectl-deploy-all-meta
64+
roleRef:
65+
apiGroup: rbac.authorization.k8s.io
66+
kind: ClusterRole
67+
name: kc-first-channel-cluster-perms
68+
subjects: *kubectl-first-channel-subject
69+
70+
# Group 'kc-exec-only'
71+
## exec only for default and botkube namespaces:
72+
- apiVersion: rbac.authorization.k8s.io/v1
73+
kind: ClusterRole
74+
metadata: &kc-exec-only-meta
75+
name: kc-exec-only
76+
labels:
77+
app.kubernetes.io/instance: botkube-e2e-test
78+
rules:
79+
- apiGroups: [ "" ]
80+
resources: [ "pods/exec" ]
81+
verbs: [ "create" ]
82+
- apiVersion: rbac.authorization.k8s.io/v1
83+
kind: RoleBinding
84+
metadata:
85+
<<: *kc-exec-only-meta
86+
namespace: botkube
87+
roleRef: &kc-exec-only-role
88+
apiGroup: rbac.authorization.k8s.io
89+
kind: ClusterRole
90+
name: kc-exec-only
91+
subjects: &kc-exec-only-subject
92+
- kind: User
93+
name: kc-exec-only
94+
apiGroup: rbac.authorization.k8s.io
95+
- apiVersion: rbac.authorization.k8s.io/v1
96+
kind: RoleBinding
97+
metadata:
98+
<<: *kc-exec-only-meta
99+
namespace: default
100+
roleRef: *kc-exec-only-role
101+
subjects: *kc-exec-only-subject
102+
103+
# Group 'kc-label-svc-all':
104+
## namespace scoped permissions
105+
- apiVersion: rbac.authorization.k8s.io/v1
106+
kind: ClusterRole
107+
metadata: &kc-label-svc-all-meta
108+
name: kc-label-svc-all
109+
labels:
110+
app.kubernetes.io/instance: botkube-e2e-test
111+
rules:
112+
- apiGroups: [ "" ]
113+
resources: [ "services" ]
114+
verbs: [ "get", "patch" ]
115+
- apiVersion: rbac.authorization.k8s.io/v1
116+
kind: ClusterRoleBinding
117+
metadata: *kc-label-svc-all-meta
118+
roleRef:
119+
apiGroup: rbac.authorization.k8s.io
120+
kind: ClusterRole
121+
name: kc-label-svc-all
122+
subjects:
123+
- kind: User
124+
name: kc-label-svc-all
125+
apiGroup: rbac.authorization.k8s.io
126+
127+
# Group 'rbac-with-static-mapping':
128+
- apiVersion: rbac.authorization.k8s.io/v1
129+
kind: ClusterRole
130+
metadata: &k8s-cm-watch-meta
131+
name: kc-watch-cm
132+
labels:
133+
app.kubernetes.io/instance: botkube-e2e-test
134+
rules:
135+
- apiGroups: [ "" ]
136+
resources: [ "configmaps" ]
137+
verbs: [ "watch", "list" ]
138+
- apiVersion: rbac.authorization.k8s.io/v1
139+
kind: ClusterRoleBinding
140+
metadata: *k8s-cm-watch-meta
141+
roleRef:
142+
apiGroup: rbac.authorization.k8s.io
143+
kind: ClusterRole
144+
name: kc-watch-cm
145+
subjects:
146+
- kind: Group
147+
name: kc-watch-cm
148+
apiGroup: rbac.authorization.k8s.io

helm/botkube/e2e-test-values.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ executors:
293293
value: "kc-label-svc-all"
294294

295295
'other-plugins':
296-
botkube/echo@v1.0.1-devel:
296+
botkube/echo@v0.0.0-latest:
297297
enabled: true
298298
config:
299299
changeResponseToUpperCase: true

test/botkubex/botkube_cli_helpers.go

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package botkubex
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
type InstallParams struct {
13+
BinaryPath string
14+
HelmRepoDirectory string
15+
ConfigProviderEndpoint string
16+
ConfigProviderIdentifier string
17+
ConfigProviderAPIKey string
18+
ImageRegistry string
19+
ImageRepository string
20+
ImageTag string
21+
PluginRestartPolicyThreshold int
22+
PluginRestartHealthCheckIntervalSeconds int
23+
}
24+
25+
func Install(t *testing.T, params InstallParams) error {
26+
//nolint:gosec // this is not production code
27+
cmd := exec.Command(params.BinaryPath, "install",
28+
"--auto-approve",
29+
"--verbose",
30+
fmt.Sprintf("--repo=%s", params.HelmRepoDirectory),
31+
fmt.Sprintf("--values=%s/botkube/e2e-cloud-test-values.yaml", params.HelmRepoDirectory),
32+
`--version=""`, // installer doesn't call Helm repo`index.yaml` when version is empty, so local Helm chart works as expected.
33+
"--set",
34+
fmt.Sprintf("image.registry=%s", params.ImageRegistry),
35+
"--set",
36+
fmt.Sprintf("image.repository=%s", params.ImageRepository),
37+
"--set",
38+
fmt.Sprintf("image.tag=%s", params.ImageTag),
39+
"--set",
40+
fmt.Sprintf("config.provider.endpoint=%s", params.ConfigProviderEndpoint),
41+
"--set",
42+
fmt.Sprintf("config.provider.identifier=%s", params.ConfigProviderIdentifier),
43+
"--set",
44+
fmt.Sprintf("extraEnv[0].name=%s", "BOTKUBE_PLUGINS_RESTART__POLICY_THRESHOLD"),
45+
"--set-string",
46+
fmt.Sprintf("extraEnv[0].value=%d", params.PluginRestartPolicyThreshold),
47+
"--set",
48+
fmt.Sprintf("extraEnv[1].name=%s", "BOTKUBE_PLUGINS_HEALTH__CHECK__INTERVAL"),
49+
"--set-string",
50+
fmt.Sprintf("extraEnv[1].value=%ds", params.PluginRestartHealthCheckIntervalSeconds),
51+
"--set",
52+
fmt.Sprintf("config.provider.apiKey=%s", params.ConfigProviderAPIKey))
53+
t.Logf("Executing command: %s", cmd.String())
54+
cmd.Env = os.Environ()
55+
56+
o, err := cmd.CombinedOutput()
57+
t.Logf("CLI output:\n%s", string(o))
58+
return err
59+
}
60+
61+
func Uninstall(t *testing.T, binaryPath string) {
62+
//nolint:gosec // this is not production code
63+
cmd := exec.Command(binaryPath, "uninstall", "--release-name", "botkube", "--namespace", "botkube", "--auto-approve")
64+
cmd.Env = os.Environ()
65+
66+
o, err := cmd.CombinedOutput()
67+
t.Logf("CLI output:\n%s", string(o))
68+
require.NoError(t, err)
69+
}

test/commplatform/discord_tester.go

+12
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,14 @@ func (d *DiscordTester) WaitForLastInteractiveMessagePostedEqualWithCustomRender
442442
})
443443
}
444444

445+
func (d *DiscordTester) SetTimeout(timeout time.Duration) {
446+
d.cfg.MessageWaitTimeout = timeout
447+
}
448+
449+
func (d *DiscordTester) Timeout() time.Duration {
450+
return d.cfg.MessageWaitTimeout
451+
}
452+
445453
func (d *DiscordTester) findUserID(t *testing.T, name string) string {
446454
t.Logf("Getting user %q...", name)
447455
res, err := d.cli.GuildMembersSearch(d.cfg.GuildID, name, 50)
@@ -457,3 +465,7 @@ func (d *DiscordTester) findUserID(t *testing.T, name string) string {
457465

458466
return ""
459467
}
468+
469+
func (d *DiscordTester) ReplaceBotNamePlaceholder(msg *interactive.CoreMessage, clusterName string) {
470+
msg.ReplaceBotNamePlaceholder(d.BotName())
471+
}

test/commplatform/generic.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package commplatform
22

33
import (
4+
"strings"
45
"testing"
56
"time"
67

@@ -47,6 +48,9 @@ type BotDriver interface {
4748
WaitForInteractiveMessagePostedRecentlyEqual(userID string, channelID string, message interactive.CoreMessage) error
4849
WaitForLastInteractiveMessagePostedEqual(userID string, channelID string, message interactive.CoreMessage) error
4950
WaitForLastInteractiveMessagePostedEqualWithCustomRender(userID, channelID string, renderedMsg string) error
51+
SetTimeout(timeout time.Duration)
52+
Timeout() time.Duration
53+
ReplaceBotNamePlaceholder(msg *interactive.CoreMessage, clusterName string)
5054
}
5155

5256
type MessageAssertion func(content string) (bool, int, string)
@@ -62,6 +66,20 @@ type ExpAttachmentInput struct {
6266
type DriverType string
6367

6468
const (
65-
SlackBot DriverType = "slack"
69+
SlackBot DriverType = "cloudSlack"
6670
DiscordBot DriverType = "discord"
6771
)
72+
73+
// AssertContains checks if message contains expected message
74+
func AssertContains(expectedMessage string) MessageAssertion {
75+
return func(msg string) (bool, int, string) {
76+
return strings.Contains(msg, expectedMessage), 0, ""
77+
}
78+
}
79+
80+
// AssertEquals checks if message is equal to expected message
81+
func AssertEquals(expectedMessage string) MessageAssertion {
82+
return func(msg string) (bool, int, string) {
83+
return msg == expectedMessage, 0, ""
84+
}
85+
}

0 commit comments

Comments
 (0)