@@ -3,47 +3,37 @@ package e2e
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "math/rand"
6
7
"os"
8
+ "path/filepath"
7
9
"time"
8
10
9
11
"github.com/actions-runner-controller/actions-runner-controller/testing"
12
+ "github.com/onsi/gomega"
13
+ "sigs.k8s.io/yaml"
10
14
)
11
15
12
- // If you're willing to run this test via VS Code "run test" or "debug test",
13
- // almost certainly you'd want to make the default go test timeout from 30s to longer and enough value.
14
- // Press Cmd + Shift + P, type "Workspace Settings" and open it, and type "go test timeout" and set e.g. 600s there.
15
- // See https://github.com/golang/vscode-go/blob/master/docs/settings.md#gotesttimeout for more information.
16
- //
17
- // This tests ues testing.Logf extensively for debugging purpose.
18
- // But messages logged via Logf shows up only when the test failed by default.
19
- // To always enable logging, do not forget to pass `-test.v` to `go test`.
20
- // If you're using VS Code, open `Workspace Settings` and search for `go test flags`, edit the `settings.json` and put the below:
21
- // "go.testFlags": ["-v"]
22
- func TestE2E (t * testing.T ) {
23
- if testing .Short () {
24
- t .Skip ("Skipped as -short is set" )
25
- }
26
-
27
- Img := func (repo , tag string ) testing.ContainerImage {
16
+ var (
17
+ Img = func (repo , tag string ) testing.ContainerImage {
28
18
return testing.ContainerImage {
29
19
Repo : repo ,
30
20
Tag : tag ,
31
21
}
32
22
}
33
23
34
- controllerImageRepo : = "actionsrunnercontrollere2e/actions-runner-controller"
35
- controllerImageTag : = "e2e"
36
- controllerImage : = Img (controllerImageRepo , controllerImageTag )
37
- runnerImageRepo : = "actionsrunnercontrollere2e/actions-runner"
38
- runnerImageTag : = "e2e"
39
- runnerImage : = Img (runnerImageRepo , runnerImageTag )
24
+ controllerImageRepo = "actionsrunnercontrollere2e/actions-runner-controller"
25
+ controllerImageTag = "e2e"
26
+ controllerImage = Img (controllerImageRepo , controllerImageTag )
27
+ runnerImageRepo = "actionsrunnercontrollere2e/actions-runner"
28
+ runnerImageTag = "e2e"
29
+ runnerImage = Img (runnerImageRepo , runnerImageTag )
40
30
41
- prebuildImages : = []testing.ContainerImage {
31
+ prebuildImages = []testing.ContainerImage {
42
32
controllerImage ,
43
33
runnerImage ,
44
34
}
45
35
46
- builds : = []testing.DockerBuild {
36
+ builds = []testing.DockerBuild {
47
37
{
48
38
Dockerfile : "../../Dockerfile" ,
49
39
Args : []testing.BuildArg {},
@@ -56,15 +46,35 @@ func TestE2E(t *testing.T) {
56
46
},
57
47
}
58
48
59
- certManagerVersion : = "v1.1.1"
49
+ certManagerVersion = "v1.1.1"
60
50
61
- images : = []testing.ContainerImage {
51
+ images = []testing.ContainerImage {
62
52
Img ("docker" , "dind" ),
63
53
Img ("quay.io/brancz/kube-rbac-proxy" , "v0.10.0" ),
64
54
Img ("quay.io/jetstack/cert-manager-controller" , certManagerVersion ),
65
55
Img ("quay.io/jetstack/cert-manager-cainjector" , certManagerVersion ),
66
56
Img ("quay.io/jetstack/cert-manager-webhook" , certManagerVersion ),
67
57
}
58
+ )
59
+
60
+ // If you're willing to run this test via VS Code "run test" or "debug test",
61
+ // almost certainly you'd want to make the default go test timeout from 30s to longer and enough value.
62
+ // Press Cmd + Shift + P, type "Workspace Settings" and open it, and type "go test timeout" and set e.g. 600s there.
63
+ // See https://github.com/golang/vscode-go/blob/master/docs/settings.md#gotesttimeout for more information.
64
+ //
65
+ // This tests ues testing.Logf extensively for debugging purpose.
66
+ // But messages logged via Logf shows up only when the test failed by default.
67
+ // To always enable logging, do not forget to pass `-test.v` to `go test`.
68
+ // If you're using VS Code, open `Workspace Settings` and search for `go test flags`, edit the `settings.json` and put the below:
69
+ // "go.testFlags": ["-v"]
70
+ //
71
+ // This function requires a few environment variables to be set to provide some test data.
72
+ // If you're using VS Code and wanting to run this test locally,
73
+ // Browse "Workspace Settings" and search for "go test env file" and put e.g. "${workspaceFolder}/.test.env" there.
74
+ func TestE2E (t * testing.T ) {
75
+ if testing .Short () {
76
+ t .Skip ("Skipped as -short is set" )
77
+ }
68
78
69
79
k := testing .Start (t , testing.Cluster {}, testing .Preload (images ... ))
70
80
@@ -88,27 +98,27 @@ func TestE2E(t *testing.T) {
88
98
}
89
99
90
100
t .Run ("install cert-manager" , func (t * testing.T ) {
91
- certmanagerVersion := "v1.1.1"
101
+ applyCfg := testing. KubectlConfig { NoValidate : true , Env : kubectlEnv }
92
102
93
- if err := k .Apply (ctx , fmt .Sprintf ("https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml" , certmanagerVersion ), testing. KubectlConfig { NoValidate : true } ); err != nil {
103
+ if err := k .Apply (ctx , fmt .Sprintf ("https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml" , certManagerVersion ), applyCfg ); err != nil {
94
104
t .Fatal (err )
95
105
}
96
106
97
- certmanagerKubectlCfg := testing.KubectlConfig {
107
+ waitCfg := testing.KubectlConfig {
98
108
Env : kubectlEnv ,
99
109
Namespace : "cert-manager" ,
100
110
Timeout : 90 * time .Second ,
101
111
}
102
112
103
- if err := k .WaitUntilDeployAvailable (ctx , "cert-manager-cainjector" , certmanagerKubectlCfg ); err != nil {
113
+ if err := k .WaitUntilDeployAvailable (ctx , "cert-manager-cainjector" , waitCfg ); err != nil {
104
114
t .Fatal (err )
105
115
}
106
116
107
- if err := k .WaitUntilDeployAvailable (ctx , "cert-manager-webhook" , certmanagerKubectlCfg .WithTimeout (60 * time .Second )); err != nil {
117
+ if err := k .WaitUntilDeployAvailable (ctx , "cert-manager-webhook" , waitCfg .WithTimeout (60 * time .Second )); err != nil {
108
118
t .Fatal (err )
109
119
}
110
120
111
- if err := k .WaitUntilDeployAvailable (ctx , "cert-manager" , certmanagerKubectlCfg .WithTimeout (60 * time .Second )); err != nil {
121
+ if err := k .WaitUntilDeployAvailable (ctx , "cert-manager" , waitCfg .WithTimeout (60 * time .Second )); err != nil {
112
122
t .Fatal (err )
113
123
}
114
124
@@ -117,32 +127,175 @@ func TestE2E(t *testing.T) {
117
127
}
118
128
})
119
129
120
- // If you're using VS Code and wanting to run this test locally,
121
- // Browse "Workspace Settings" and search for "go test env file" and put e.g. "${workspaceFolder}/.test.env" there
122
- githubToken := os .Getenv ("GITHUB_TOKEN" )
123
- if githubToken == "" {
124
- t .Fatal ("GITHUB_TOKEN must be set" )
130
+ t .Run ("make default serviceaccount cluster-admin" , func (t * testing.T ) {
131
+ cfg := testing.KubectlConfig {Env : kubectlEnv }
132
+ bindingName := "default-admin"
133
+ if _ , err := k .GetClusterRoleBinding (ctx , bindingName , cfg ); err != nil {
134
+ if err := k .CreateClusterRoleBindingServiceAccount (ctx , bindingName , "cluster-admin" , "default:default" , cfg ); err != nil {
135
+ t .Fatal (err )
136
+ }
137
+ }
138
+ })
139
+
140
+ cmCfg := testing.KubectlConfig {
141
+ Env : kubectlEnv ,
125
142
}
143
+ testInfoName := "test-info"
126
144
127
- scriptEnv := []string {
128
- "KUBECONFIG=" + k .Kubeconfig (),
129
- "NAME=" + controllerImageRepo ,
130
- "VERSION=" + controllerImageTag ,
131
- "RUNNER_NAME=" + runnerImageRepo ,
132
- "RUNNER_TAG=" + runnerImageTag ,
133
- "TEST_REPO=" + "actions-runner-controller/mumoshu-actions-test" ,
134
- "TEST_ORG=" + "actions-runner-controller" ,
135
- "TEST_ORG_REPO=" + "actions-runner-controller/mumoshu-actions-test-org-runners" ,
136
- "SYNC_PERIOD=" + "10s" ,
137
- "USE_RUNNERSET=" + "1" ,
138
- "ACCEPTANCE_TEST_DEPLOYMENT_TOOL=" + "helm" ,
139
- "ACCEPTANCE_TEST_SECRET_TYPE=token" ,
140
- "GITHUB_TOKEN=" + githubToken ,
145
+ m , _ := k .GetCMLiterals (ctx , testInfoName , cmCfg )
146
+
147
+ t .Run ("Save test ID" , func (t * testing.T ) {
148
+ if m == nil {
149
+ id := RandStringBytesRmndr (10 )
150
+ m = map [string ]string {"id" : id }
151
+ if err := k .CreateCMLiterals (ctx , testInfoName , m , cmCfg ); err != nil {
152
+ t .Fatal (err )
153
+ }
154
+ }
155
+ })
156
+
157
+ id := m ["id" ]
158
+
159
+ runnerLabel := "test-" + id
160
+
161
+ testID := t .Name () + " " + id
162
+
163
+ t .Logf ("Using test id %s" , testID )
164
+
165
+ githubToken := getenv (t , "GITHUB_TOKEN" )
166
+ testRepo := getenv (t , "TEST_REPO" )
167
+ testOrg := getenv (t , "TEST_ORG" )
168
+ testOrgRepo := getenv (t , "TEST_ORG_REPO" )
169
+
170
+ if t .Failed () {
171
+ return
141
172
}
142
173
143
- t .Run ("install actions-runner-controller" , func (t * testing.T ) {
174
+ t .Run ("install actions-runner-controller and runners" , func (t * testing.T ) {
175
+ scriptEnv := []string {
176
+ "KUBECONFIG=" + k .Kubeconfig (),
177
+ "ACCEPTANCE_TEST_DEPLOYMENT_TOOL=" + "helm" ,
178
+ "ACCEPTANCE_TEST_SECRET_TYPE=token" ,
179
+ "NAME=" + controllerImageRepo ,
180
+ "VERSION=" + controllerImageTag ,
181
+ "RUNNER_NAME=" + runnerImageRepo ,
182
+ "RUNNER_TAG=" + runnerImageTag ,
183
+ "TEST_REPO=" + testRepo ,
184
+ "TEST_ORG=" + testOrg ,
185
+ "TEST_ORG_REPO=" + testOrgRepo ,
186
+ "SYNC_PERIOD=" + "10s" ,
187
+ "USE_RUNNERSET=" + "1" ,
188
+ "GITHUB_TOKEN=" + githubToken ,
189
+ "RUNNER_LABEL=" + runnerLabel ,
190
+ }
191
+
144
192
if err := k .RunScript (ctx , "../../acceptance/deploy.sh" , testing.ScriptConfig {Dir : "../.." , Env : scriptEnv }); err != nil {
145
193
t .Fatal (err )
146
194
}
147
195
})
196
+
197
+ testResultCMName := fmt .Sprintf ("test-result-%s" , id )
198
+
199
+ if t .Failed () {
200
+ return
201
+ }
202
+
203
+ t .Run ("Install workflow" , func (t * testing.T ) {
204
+ wfName := "E2E " + testID
205
+ wf := testing.Workflow {
206
+ Name : wfName ,
207
+ On : testing.On {
208
+ Push : & testing.Push {
209
+ Branches : []string {"main" },
210
+ },
211
+ },
212
+ Jobs : map [string ]testing.Job {
213
+ "test" : {
214
+ RunsOn : runnerLabel ,
215
+ Steps : []testing.Step {
216
+ {
217
+ Uses : testing .ActionsCheckoutV2 ,
218
+ },
219
+ {
220
+ Uses : "azure/setup-kubectl@v1" ,
221
+ With : & testing.With {
222
+ Version : "v1.20.2" ,
223
+ },
224
+ },
225
+ {
226
+ Run : "./test.sh" ,
227
+ },
228
+ },
229
+ },
230
+ },
231
+ }
232
+
233
+ wfContent , err := yaml .Marshal (wf )
234
+ if err != nil {
235
+ t .Fatal (err )
236
+ }
237
+
238
+ script := []byte (fmt .Sprintf (`#!/usr/bin/env bash
239
+ set -vx
240
+ echo hello from %s
241
+ kubectl delete cm %s || true
242
+ kubectl create cm %s --from-literal=status=ok
243
+ ` , testID , testResultCMName , testResultCMName ))
244
+
245
+ g := testing.GitRepo {
246
+ Dir : filepath .Join (t .TempDir (), "gitrepo" ),
247
+ Name : testRepo ,
248
+ CommitMessage : wfName ,
249
+ Contents : map [string ][]byte {
250
+ ".github/workflows/workflow.yaml" : wfContent ,
251
+ "test.sh" : script ,
252
+ },
253
+ }
254
+
255
+ if err := g .Sync (ctx ); err != nil {
256
+ t .Fatal (err )
257
+ }
258
+ })
259
+
260
+ if t .Failed () {
261
+ return
262
+ }
263
+
264
+ t .Run ("Verify workflow run result" , func (t * testing.T ) {
265
+ gomega .NewGomegaWithT (t ).Eventually (func () (string , error ) {
266
+ m , err := k .GetCMLiterals (ctx , testResultCMName , cmCfg )
267
+ if err != nil {
268
+ return "" , err
269
+ }
270
+
271
+ result := m ["status" ]
272
+
273
+ return result , nil
274
+ }, 60 * time .Second , 10 * time .Second ).Should (gomega .Equal ("ok" ))
275
+ })
276
+ }
277
+
278
+ func getenv (t * testing.T , name string ) string {
279
+ t .Helper ()
280
+
281
+ v := os .Getenv (name )
282
+ if v == "" {
283
+ t .Fatal (name + " must be set" )
284
+ }
285
+ return v
286
+ }
287
+
288
+ func init () {
289
+ rand .Seed (time .Now ().UnixNano ())
290
+ }
291
+
292
+ const letterBytes = "abcdefghijklmnopqrstuvwxyz"
293
+
294
+ // Copied from https://stackoverflow.com/a/31832326 with thanks
295
+ func RandStringBytesRmndr (n int ) string {
296
+ b := make ([]byte , n )
297
+ for i := range b {
298
+ b [i ] = letterBytes [rand .Int63 ()% int64 (len (letterBytes ))]
299
+ }
300
+ return string (b )
148
301
}
0 commit comments