-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
Copy pathstart.go
564 lines (497 loc) · 26.2 KB
/
start.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
package builds
import (
"context"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"sync"
"time"
g "github.com/onsi/ginkgo/v2"
o "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
e2e "k8s.io/kubernetes/test/e2e/framework"
admissionapi "k8s.io/pod-security-admission/api"
buildv1 "github.com/openshift/api/build/v1"
"github.com/openshift/api/image/docker10"
"github.com/openshift/library-go/pkg/image/imageutil"
exutil "github.com/openshift/origin/test/extended/util"
)
var _ = g.Describe("[sig-builds][Feature:Builds][Slow] starting a build using CLI", func() {
defer g.GinkgoRecover()
var (
buildFixture = exutil.FixturePath("testdata", "builds", "test-build.yaml")
bcWithPRRef = exutil.FixturePath("testdata", "builds", "test-bc-with-pr-ref.yaml")
exampleGemfile = exutil.FixturePath("testdata", "builds", "test-build-app", "Gemfile")
exampleBuild = exutil.FixturePath("testdata", "builds", "test-build-app")
symlinkFixture = exutil.FixturePath("testdata", "builds", "test-symlink-build.yaml")
exampleGemfileURL = "https://raw.githubusercontent.com/openshift/ruby-hello-world/master/Gemfile"
exampleArchiveURL = "https://github.com/openshift/ruby-hello-world/archive/master.zip"
oc = exutil.NewCLIWithPodSecurityLevel("cli-start-build", admissionapi.LevelBaseline)
verifyNodeSelector = func(oc *exutil.CLI, name string) {
pod, err := oc.KubeClient().CoreV1().Pods(oc.Namespace()).Get(context.Background(), name+"-build", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
os, ok := pod.Spec.NodeSelector[corev1.LabelOSStable]
o.Expect(ok).To(o.BeTrue())
o.Expect(os).To(o.Equal("linux"))
}
)
g.Context("", func() {
g.BeforeEach(func() {
exutil.PreTestDump()
})
g.JustBeforeEach(func() {
oc.Run("create").Args("-f", buildFixture).Execute()
})
g.Context("start-build test context", func() {
g.AfterEach(func() {
if g.CurrentSpecReport().Failed() {
exutil.DumpPodStates(oc)
exutil.DumpPodLogsStartingWith("", oc)
}
})
g.Describe("oc start-build --wait", func() {
g.It("should start a build and wait for the build to complete [apigroup:build.openshift.io]", func() {
g.By("starting the build with --wait flag")
br, err := exutil.StartBuildAndWait(oc, "sample-build", "--wait")
o.Expect(err).NotTo(o.HaveOccurred())
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
})
g.It("should start a build and wait for the build to fail [apigroup:build.openshift.io]", func() {
g.By("starting the build with --wait flag but wrong --commit")
br, _ := exutil.StartBuildAndWait(oc, "sample-build", "--wait", "--commit=fffffff")
br.AssertFailure()
o.Expect(br.StartBuildErr).To(o.HaveOccurred()) // start-build should detect the build error with --wait flag
o.Expect(br.StartBuildStdErr).Should(o.ContainSubstring(`status is "Failed"`))
verifyNodeSelector(oc, br.BuildName)
})
})
g.Describe("oc start-build with pr ref", func() {
g.It("should start a build from a PR ref, wait for the build to complete, and confirm the right level was used [apigroup:build.openshift.io][apigroup:image.openshift.io]", func() {
g.By("make sure python imagestream has latest tag")
err := exutil.WaitForAnImageStreamTag(oc.AsAdmin(), "openshift", "python", "latest")
o.Expect(err).NotTo(o.HaveOccurred())
g.By("create build config")
err = oc.Run("create").Args("-f", bcWithPRRef).Execute()
o.Expect(err).NotTo(o.HaveOccurred())
g.By("start the builds, wait for and confirm successful completion")
br, err := exutil.StartBuildAndWait(oc, "bc-with-pr-ref-docker")
o.Expect(err).NotTo(o.HaveOccurred())
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
br, err = exutil.StartBuildAndWait(oc, "bc-with-pr-ref")
o.Expect(err).NotTo(o.HaveOccurred())
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
out, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
// the repo has a dependency 'gunicorn', referenced PR removes this dependency
// from requirements.txt so it should not appear in the output anymore
g.By("confirm the correct commit level was retrieved")
o.Expect(out).Should(o.Not(o.ContainSubstring("gunicorn")))
istag, err := oc.ImageClient().ImageV1().ImageStreamTags(oc.Namespace()).Get(context.Background(), "bc-with-pr-ref:latest", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
err = imageutil.ImageWithMetadata(&istag.Image)
o.Expect(err).NotTo(o.HaveOccurred())
imageutil.ImageWithMetadataOrDie(&istag.Image)
o.Expect(istag.Image.DockerImageMetadata.Object.(*docker10.DockerImage).Config.Labels).To(o.HaveKeyWithValue("io.openshift.build.commit.ref", "refs/pull/121/head"))
o.Expect(istag.Image.DockerImageMetadata.Object.(*docker10.DockerImage).Config.Env).To(o.ContainElement("OPENSHIFT_BUILD_REFERENCE=refs/pull/121/head"))
istag, err = oc.ImageClient().ImageV1().ImageStreamTags(oc.Namespace()).Get(context.Background(), "bc-with-pr-ref-docker:latest", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
err = imageutil.ImageWithMetadata(&istag.Image)
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(istag.Image.DockerImageMetadata.Object.(*docker10.DockerImage).Config.Labels).To(o.HaveKeyWithValue("io.openshift.build.commit.ref", "refs/pull/121/head"))
o.Expect(istag.Image.DockerImageMetadata.Object.(*docker10.DockerImage).Config.Env).To(o.ContainElement("OPENSHIFT_BUILD_REFERENCE=refs/pull/121/head"))
})
})
g.Describe("override environment", func() {
g.It("should accept environment variables [apigroup:build.openshift.io]", func() {
g.By("starting the build with -e FOO=bar,-e VAR=test")
br, err := exutil.StartBuildAndWait(oc, "sample-build", "-e", "FOO=bar", "-e", "VAR=test")
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By(fmt.Sprintf("verifying the build output contains the env vars"))
o.Expect(buildLog).To(o.ContainSubstring("FOO=bar"))
o.Expect(buildLog).To(o.ContainSubstring("VAR=test"))
g.By(fmt.Sprintf("verifying the build output contains inherited env vars"))
// This variable is not set and thus inherited from the original build config
o.Expect(buildLog).To(o.ContainSubstring("BAR=test"))
})
g.It("BUILD_LOGLEVEL in buildconfig should create verbose output [apigroup:build.openshift.io]", func() {
g.By("starting the build with buildconfig strategy env BUILD_LOGLEVEL=5")
br, err := exutil.StartBuildAndWait(oc, "sample-verbose-build")
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By(fmt.Sprintf("verifying the build output is verbose"))
o.Expect(buildLog).To(o.ContainSubstring("Creating a new S2I builder"))
o.Expect(buildLog).To(o.MatchRegexp("openshift-builder [1-9v]"))
// Bug 1694871: logging before flag.Parse error
g.By(fmt.Sprintf("verifying the build output has no error about flag.Parse"))
o.Expect(buildLog).NotTo(o.ContainSubstring("ERROR: logging before flag.Parse"))
})
g.It("BUILD_LOGLEVEL in buildconfig can be overridden by build-loglevel [apigroup:build.openshift.io]", func() {
g.By("starting the build with buildconfig strategy env BUILD_LOGLEVEL=5 but build-loglevel=1")
br, err := exutil.StartBuildAndWait(oc, "sample-verbose-build", "--build-loglevel=1")
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By(fmt.Sprintf("verifying the build output is not verbose"))
o.Expect(buildLog).NotTo(o.ContainSubstring("Creating a new S2I builder"))
o.Expect(buildLog).NotTo(o.MatchRegexp("openshift-builder [1-9v]"))
})
})
g.Describe("binary builds", func() {
var commit string
// do a best effort to initialize the repo in case it is a raw checkout or temp dir
tryRepoInit := func(exampleBuild string) {
out, err := exec.Command("bash", "-c", fmt.Sprintf("cd %q; if ! git rev-parse --git-dir; then git init .; git add .; git commit -m 'first'; touch foo; git add .; git commit -m 'second'; fi; true", exampleBuild)).CombinedOutput()
fmt.Fprintf(g.GinkgoWriter, "Tried to init git repo: %v\n%s\n", err, string(out))
}
g.It("should accept --from-file as input [apigroup:build.openshift.io]", func() {
g.By("starting the build with a Dockerfile")
br, err := exutil.StartBuildAndWait(oc, "sample-build", fmt.Sprintf("--from-file=%s", exampleGemfile))
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By(fmt.Sprintf("verifying the build %q status", br.BuildPath))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("Uploading file"))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("as binary input for the build ..."))
o.Expect(buildLog).To(o.ContainSubstring("Build complete"))
})
g.It("should accept --from-dir as input [apigroup:build.openshift.io]", func() {
g.By("starting the build with a directory")
br, err := exutil.StartBuildAndWait(oc, "sample-build", fmt.Sprintf("--from-dir=%s", exampleBuild))
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By(fmt.Sprintf("verifying the build %q status", br.BuildPath))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("Uploading directory"))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("as binary input for the build ..."))
o.Expect(buildLog).To(o.ContainSubstring("Build complete"))
})
g.It("should accept --from-repo as input [apigroup:build.openshift.io]", func() {
g.By("starting the build with a Git repository")
tryRepoInit(exampleBuild)
br, err := exutil.StartBuildAndWait(oc, "sample-build", fmt.Sprintf("--from-repo=%s", exampleBuild))
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("Uploading"))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring(`at commit "HEAD"`))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("as binary input for the build ..."))
o.Expect(buildLog).To(o.ContainSubstring("Build complete"))
})
g.It("should accept --from-repo with --commit as input [apigroup:build.openshift.io]", func() {
g.By("starting the build with a Git repository")
tryRepoInit(exampleBuild)
gitCmd := exec.Command("git", "rev-parse", "HEAD~1")
gitCmd.Dir = exampleBuild
commitByteArray, err := gitCmd.CombinedOutput()
commit = strings.TrimSpace(string(commitByteArray[:]))
o.Expect(err).NotTo(o.HaveOccurred())
br, err := exutil.StartBuildAndWait(oc, "sample-build", fmt.Sprintf("--commit=%s", commit), fmt.Sprintf("--from-repo=%s", exampleBuild))
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("Uploading"))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring(fmt.Sprintf("at commit \"%s\"", commit)))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("as binary input for the build ..."))
o.Expect(buildLog).To(o.ContainSubstring(fmt.Sprintf("\"commit\":\"%s\"", commit)))
o.Expect(buildLog).To(o.ContainSubstring("Build complete"))
})
// run one valid binary build so we can do --from-build later
g.It("should reject binary build requests without a --from-xxxx value [apigroup:build.openshift.io]", func() {
g.Skip("TODO: refactor such that we don't rely on external package managers (i.e. Rubygems)")
g.By("starting a valid build with a directory")
br, err := exutil.StartBuildAndWait(oc, "sample-build-binary", "--follow", fmt.Sprintf("--from-dir=%s", exampleBuild))
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("Uploading directory"))
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("as binary input for the build ..."))
o.Expect(buildLog).To(o.ContainSubstring("Build complete"))
g.By("starting a build without a --from-xxxx value")
br, err = exutil.StartBuildAndWait(oc, "sample-build-binary")
o.Expect(br.StartBuildErr).To(o.HaveOccurred())
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("has no valid source inputs"))
g.By("starting a build from an existing binary build")
br, err = exutil.StartBuildAndWait(oc, "sample-build-binary", fmt.Sprintf("--from-build=%s", "sample-build-binary-1"))
o.Expect(br.StartBuildErr).To(o.HaveOccurred())
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring("has no valid source inputs"))
})
g.It("shoud accept --from-file with https URL as an input [apigroup:build.openshift.io]", func() {
g.By("starting a valid build with input file served by https")
br, err := exutil.StartBuildAndWait(oc, "sample-build", fmt.Sprintf("--from-file=%s", exampleGemfileURL))
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring(fmt.Sprintf("Uploading file from %q as binary input for the build", exampleGemfileURL)))
o.Expect(buildLog).To(o.ContainSubstring("Build complete"))
})
g.It("shoud accept --from-archive with https URL as an input [apigroup:build.openshift.io]", func() {
g.By("starting a valid build with input archive served by https")
// can't use sample-build-binary because we need contextDir due to github archives containing the top-level directory
br, err := exutil.StartBuildAndWait(oc, "sample-build-github-archive", fmt.Sprintf("--from-archive=%s", exampleArchiveURL))
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(br.StartBuildStdErr).To(o.ContainSubstring(fmt.Sprintf("Uploading archive from %q as binary input for the build", exampleArchiveURL)))
o.Expect(buildLog).To(o.ContainSubstring("Build complete"))
})
})
g.Describe("cancel a binary build that doesn't start running in 5 minutes", func() {
g.It("should start a build and wait for the build to be cancelled [apigroup:build.openshift.io]", func() {
g.By("starting a build with a nodeselector that can't be matched")
go func() {
exutil.StartBuild(oc, "sample-build-binary-invalidnodeselector", fmt.Sprintf("--from-file=%s", exampleGemfile))
}()
build := &buildv1.Build{}
cancelFn := func(b *buildv1.Build) bool {
build = b
return exutil.CheckBuildCancelled(b)
}
err := exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), "sample-build-binary-invalidnodeselector-1", nil, nil, cancelFn)
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(build.Status.Phase).To(o.Equal(buildv1.BuildPhaseCancelled))
exutil.CheckForBuildEvent(oc.KubeClient().CoreV1(), build, BuildCancelledEventReason,
BuildCancelledEventMessage)
})
})
g.Describe("cancel a build started by oc start-build --wait", func() {
g.It("should start a build and wait for the build to cancel [apigroup:build.openshift.io]", func() {
g.By("starting the build with --wait flag")
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer g.GinkgoRecover()
defer wg.Done()
_, stderr, err := exutil.StartBuild(oc, "sample-build", "--wait")
o.Expect(err).To(o.HaveOccurred())
o.Expect(stderr).Should(o.ContainSubstring(`status is "Cancelled"`))
}()
g.By("getting the build name")
var buildName string
wait.Poll(time.Duration(100*time.Millisecond), 1*time.Minute, func() (bool, error) {
out, err := oc.Run("get").
Args("build", "--template", "{{ (index .items 0).metadata.name }}").Output()
// Give it second chance in case the build resource was not created yet
if err != nil || len(out) == 0 {
return false, nil
}
buildName = out
return true, nil
})
o.Expect(buildName).ToNot(o.BeEmpty())
build, err := oc.BuildClient().BuildV1().Builds(oc.Namespace()).Get(context.Background(), buildName, metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(build).NotTo(o.BeNil(), "build object should exist")
g.By(fmt.Sprintf("cancelling the build %q", buildName))
err = oc.Run("cancel-build").Args(buildName).Execute()
o.Expect(err).ToNot(o.HaveOccurred())
wg.Wait()
exutil.CheckForBuildEvent(oc.KubeClient().CoreV1(), build, BuildCancelledEventReason,
BuildCancelledEventMessage)
})
})
g.Describe("Setting build-args on Docker builds", func() {
g.It("Should copy build args from BuildConfig to Build [apigroup:build.openshift.io]", func() {
g.By("starting the build without --build-arg flag")
br, _ := exutil.StartBuildAndWait(oc, "sample-build-docker-args-preset")
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By("verifying the build output contains the build args from the BuildConfig.")
o.Expect(buildLog).To(o.ContainSubstring("default"))
})
g.It("Should accept build args that are specified in the Dockerfile [apigroup:build.openshift.io]", func() {
g.By("starting the build with --build-arg flag")
br, _ := exutil.StartBuildAndWait(oc, "sample-build-docker-args", "--build-arg=foofoo=bar")
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By("verifying the build output contains the changes.")
o.Expect(buildLog).To(o.ContainSubstring("bar"))
})
g.It("Should complete with a warning on non-existent build-arg [apigroup:build.openshift.io]", func() {
g.By("starting the build with --build-arg flag")
br, _ := exutil.StartBuildAndWait(oc, "sample-build-docker-args", "--build-arg=bar=foo")
br.AssertSuccess()
verifyNodeSelector(oc, br.BuildName)
buildLog, err := br.Logs()
o.Expect(err).NotTo(o.HaveOccurred())
g.By("verifying the build completed with a warning.")
o.Expect(buildLog).To(o.ContainSubstring("one or more build args were not consumed: [bar]"))
})
})
g.Describe("Trigger builds with branch refs matching directories on master branch", func() {
g.It("Should checkout the config branch, not config directory [apigroup:build.openshift.io]", func() {
g.By("calling oc new-app")
_, err := oc.Run("new-app").Args("https://github.com/openshift/ruby-hello-world#config").Output()
o.Expect(err).NotTo(o.HaveOccurred())
g.By("waiting for the build to complete")
err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), "ruby-hello-world-1", nil, nil, nil)
if err != nil {
exutil.DumpBuildLogs("ruby-hello-world", oc)
}
o.Expect(err).NotTo(o.HaveOccurred())
g.By("get build logs, confirm commit in the config branch is present")
out, err := oc.Run("logs").Args("build/ruby-hello-world-1").Output()
o.Expect(out).To(o.ContainSubstring("Merge pull request #61 from gabemontero/config"))
})
})
g.Describe("start a build via a webhook", func() {
// AUTH-509: Webhooks do not allow unauthenticated requests by default.
// Create a role binding which allows unauthenticated webhooks.
g.BeforeEach(func() {
ctx := context.Background()
adminRoleBindingsClient := oc.AdminKubeClient().RbacV1().RoleBindings(oc.Namespace())
_, err := adminRoleBindingsClient.Get(ctx, "webooks-unauth", metav1.GetOptions{})
if apierrors.IsNotFound(err) {
unauthWebhooksRB := &rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "webooks-unauth",
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: "system:webhook",
},
Subjects: []rbacv1.Subject{
{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Group",
Name: "system:authenticated",
},
{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Group",
Name: "system:unauthenticated",
},
},
}
_, err = adminRoleBindingsClient.Create(ctx, unauthWebhooksRB, metav1.CreateOptions{})
o.Expect(err).NotTo(o.HaveOccurred(), "creating webhook role binding")
return
}
o.Expect(err).NotTo(o.HaveOccurred(), "checking if webhook role binding exists")
})
g.It("should be able to start builds via the webhook with valid secrets and fail with invalid secrets [apigroup:build.openshift.io]", func() {
g.By("clearing existing builds")
_, err := oc.Run("delete").Args("builds", "--all").Output()
o.Expect(err).NotTo(o.HaveOccurred())
builds, err := oc.BuildClient().BuildV1().Builds(oc.Namespace()).List(context.Background(), metav1.ListOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(builds.Items).To(o.BeEmpty())
g.By("getting the api server host")
out, err := oc.WithoutNamespace().Run("status").Args().Output()
o.Expect(err).NotTo(o.HaveOccurred())
e2e.Logf("got status value of: %s", out)
matcher := regexp.MustCompile("https?://.*?443")
apiServer := matcher.FindString(out)
o.Expect(apiServer).NotTo(o.BeEmpty())
out, err = oc.Run("describe").Args("bc", "sample-build").Output()
e2e.Logf("build description: %s", out)
g.By("starting the build via the webhook with the deprecated secret")
curlArgs := []string{"-X",
"POST",
"-k",
fmt.Sprintf("%s/apis/build.openshift.io/v1/namespaces/%s/buildconfigs/sample-build/webhooks/%s/generic",
apiServer, oc.Namespace(), "mysecret"),
}
curlOut, err := exec.Command("curl", curlArgs...).Output()
o.Expect(err).NotTo(o.HaveOccurred())
e2e.Logf("curl cmd: %v, output: %s", curlArgs, string(curlOut))
builds, err = oc.BuildClient().BuildV1().Builds(oc.Namespace()).List(context.Background(), metav1.ListOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(builds.Items).NotTo(o.BeEmpty())
g.By("clearing existing builds")
_, err = oc.Run("delete").Args("builds", "--all").Output()
o.Expect(err).NotTo(o.HaveOccurred())
builds, err = oc.BuildClient().BuildV1().Builds(oc.Namespace()).List(context.Background(), metav1.ListOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(builds.Items).To(o.BeEmpty())
g.By("starting the build via the webhook with the referenced secret")
curlArgs = []string{"-X",
"POST",
"-k",
fmt.Sprintf("%s/apis/build.openshift.io/v1/namespaces/%s/buildconfigs/sample-build/webhooks/%s/generic",
apiServer, oc.Namespace(), "secretvalue1"),
}
curlOut, err = exec.Command("curl", curlArgs...).Output()
o.Expect(err).NotTo(o.HaveOccurred())
e2e.Logf("curl cmd: %s, output: %s", curlArgs, string(curlOut))
builds, err = oc.BuildClient().BuildV1().Builds(oc.Namespace()).List(context.Background(), metav1.ListOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(builds.Items).NotTo(o.BeEmpty())
g.By("clearing existing builds")
_, err = oc.Run("delete").Args("builds", "--all").Output()
o.Expect(err).NotTo(o.HaveOccurred())
builds, err = oc.BuildClient().BuildV1().Builds(oc.Namespace()).List(context.Background(), metav1.ListOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(builds.Items).To(o.BeEmpty())
g.By("starting the build via the webhook with an invalid secret")
curlArgs = []string{"-X",
"POST",
"-k",
fmt.Sprintf("%s/apis/build.openshift.io/v1/namespaces/%s/buildconfigs/sample-build/webhooks/%s/generic",
apiServer, oc.Namespace(), "invalid"),
}
curlOut, err = exec.Command("curl", curlArgs...).Output()
o.Expect(err).NotTo(o.HaveOccurred())
e2e.Logf("curl cmd: %v, output: %s", curlArgs, string(curlOut))
builds, err = oc.BuildClient().BuildV1().Builds(oc.Namespace()).List(context.Background(), metav1.ListOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
o.Expect(builds.Items).To(o.BeEmpty())
})
})
g.Describe("s2i build maintaining symlinks", func() {
g.It(fmt.Sprintf("should s2i build image and maintain symlinks [apigroup:build.openshift.io][apigroup:image.openshift.io]"), func() {
g.By("initializing a local git repo")
repo, err := exutil.NewGitRepo("symlinks")
o.Expect(err).NotTo(o.HaveOccurred())
defer repo.Remove()
err = repo.AddAndCommit("package.json", "{\"scripts\" : {} }")
o.Expect(err).NotTo(o.HaveOccurred())
err = os.Symlink(repo.RepoPath+"/package.json", repo.RepoPath+"/link")
o.Expect(err).NotTo(o.HaveOccurred())
exutil.WaitForOpenShiftNamespaceImageStreams(oc)
g.By(fmt.Sprintf("calling oc create -f %q", symlinkFixture))
err = oc.Run("create").Args("-f", symlinkFixture).Execute()
o.Expect(err).NotTo(o.HaveOccurred())
g.By("starting a build")
err = oc.Run("start-build").Args("symlink-bc", "--from-dir", repo.RepoPath).Execute()
o.Expect(err).NotTo(o.HaveOccurred())
g.By("waiting for build to finish")
err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), "symlink-bc-1", exutil.CheckBuildSuccess, exutil.CheckBuildFailed, nil)
if err != nil {
exutil.DumpBuildLogs("symlink-bc", oc)
}
o.Expect(err).NotTo(o.HaveOccurred())
tag, err := oc.ImageClient().ImageV1().ImageStreamTags(oc.Namespace()).Get(context.Background(), "symlink-is:latest", metav1.GetOptions{})
err = oc.Run("run").Args("-i", "-t", "symlink-test", "--image="+tag.Image.DockerImageReference, "--restart=Never", "--command", "--", "bash", "-c", "if [ ! -L link ]; then ls -ltr; exit 1; fi").Execute()
o.Expect(err).NotTo(o.HaveOccurred())
})
})
})
})
})