// buildAndPushImage tries to build an image. The image is stored as an image stream tag <name>:<tag>. If // shouldBeDenied is true, a build will be expected to fail with a denied error. func buildAndPushImage(oc *exutil.CLI, namespace, name, tag string, shouldBeDenied bool) { istName := name if tag != "" { istName += ":" + tag } g.By(fmt.Sprintf("building an image %q", istName)) bc, err := oc.REST().BuildConfigs(namespace).Get(name) if err == nil { g.By(fmt.Sprintf("changing build config %s to store result into %s", name, istName)) o.Expect(bc.Spec.BuildSpec.Output.To.Kind).To(o.Equal("ImageStreamTag")) bc.Spec.BuildSpec.Output.To.Name = istName _, err := oc.REST().BuildConfigs(namespace).Update(bc) o.Expect(err).NotTo(o.HaveOccurred()) } else { g.By(fmt.Sprintf("creating a new build config %s with output to %s ", name, istName)) err = oc.Run("new-build").Args( "--binary", "--name", name, "--to", istName).Execute() o.Expect(err).NotTo(o.HaveOccurred()) } tempDir, err := ioutil.TempDir("", "name-build") o.Expect(err).NotTo(o.HaveOccurred()) err = createRandomBlob(path.Join(tempDir, "data"), imageSize) o.Expect(err).NotTo(o.HaveOccurred()) err = ioutil.WriteFile(path.Join(tempDir, "Dockerfile"), []byte("FROM scratch\nCOPY data /data\n"), 0644) o.Expect(err).NotTo(o.HaveOccurred()) err = oc.Run("start-build").Args(name, "--from-dir", tempDir, "--wait").Execute() if shouldBeDenied { o.Expect(err).To(o.HaveOccurred()) out, err := oc.Run("logs").Args("bc/" + name).Output() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).Should(o.MatchRegexp("(?i)Failed to push image:.*denied")) } else { o.Expect(err).NotTo(o.HaveOccurred()) } }
func matcherToGomegaMatcher(matcher interface{}) (types.GomegaMatcher, error) { switch x := matcher.(type) { case string, int, bool, float64: return gomega.Equal(x), nil case []interface{}: var matchers []types.GomegaMatcher for _, valueI := range x { if subMatcher, ok := valueI.(types.GomegaMatcher); ok { matchers = append(matchers, subMatcher) } else { matchers = append(matchers, gomega.ContainElement(valueI)) } } return gomega.And(matchers...), nil } matcher = sanitizeExpectedValue(matcher) if matcher == nil { return nil, fmt.Errorf("Missing Required Attribute") } matcherMap, ok := matcher.(map[string]interface{}) if !ok { panic(fmt.Sprintf("Unexpected matcher type: %T\n\n", matcher)) } var matchType string var value interface{} for matchType, value = range matcherMap { break } switch matchType { case "have-prefix": return gomega.HavePrefix(value.(string)), nil case "have-suffix": return gomega.HaveSuffix(value.(string)), nil case "match-regexp": return gomega.MatchRegexp(value.(string)), nil case "have-len": value = sanitizeExpectedValue(value) return gomega.HaveLen(value.(int)), nil case "contain-element": subMatcher, err := matcherToGomegaMatcher(value) if err != nil { return nil, err } return gomega.ContainElement(subMatcher), nil case "not": subMatcher, err := matcherToGomegaMatcher(value) if err != nil { return nil, err } return gomega.Not(subMatcher), nil case "consist-of": subMatchers, err := sliceToGomega(value) if err != nil { return nil, err } var interfaceSlice []interface{} for _, d := range subMatchers { interfaceSlice = append(interfaceSlice, d) } return gomega.ConsistOf(interfaceSlice...), nil case "and": subMatchers, err := sliceToGomega(value) if err != nil { return nil, err } return gomega.And(subMatchers...), nil case "or": subMatchers, err := sliceToGomega(value) if err != nil { return nil, err } return gomega.Or(subMatchers...), nil case "gt", "ge", "lt", "le": // Golang json escapes '>', '<' symbols, so we use 'gt', 'le' instead comparator := map[string]string{ "gt": ">", "ge": ">=", "lt": "<", "le": "<=", }[matchType] return gomega.BeNumerically(comparator, value), nil default: return nil, fmt.Errorf("Unknown matcher: %s", matchType) } }
Spec: kapi.ResourceQuotaSpec{Hard: kapi.ResourceList{imageapi.ResourceImages: resource.MustParse("0")}}, } g.By(fmt.Sprintf("creating resource quota with a limit %s=%d", imageapi.ResourceImages, 0)) _, err = oc.AdminKubeREST().ResourceQuotas(oc.Namespace()).Create(rq) o.Expect(err).NotTo(o.HaveOccurred()) waitForLimitSync(oc, quotaName, rq.Spec.Hard) g.By("waiting for resource quota to get in sync") err = waitForLimitSync(oc, quotaName, rq.Spec.Hard) o.Expect(err).NotTo(o.HaveOccurred()) g.By(fmt.Sprintf("trying to tag an image exceeding %s=%d quota", imageapi.ResourceImages, 0)) out, err := oc.Run("tag").Args(sharedProjectName+"/src:1", "is:1").Output() o.Expect(err).To(o.HaveOccurred()) o.Expect(out).Should(o.MatchRegexp("(?i)exceeded quota")) o.Expect(out).Should(o.ContainSubstring(string(imageapi.ResourceImages))) g.By(fmt.Sprintf("bump the %s quota to %d", imageapi.ResourceImages, 1)) rq, err = oc.AdminKubeREST().ResourceQuotas(oc.Namespace()).Get(quotaName) o.Expect(err).NotTo(o.HaveOccurred()) rq.Spec.Hard[imageapi.ResourceImages] = resource.MustParse("1") _, err = oc.AdminKubeREST().ResourceQuotas(oc.Namespace()).Update(rq) o.Expect(err).NotTo(o.HaveOccurred()) err = waitForLimitSync(oc, quotaName, rq.Spec.Hard) o.Expect(err).NotTo(o.HaveOccurred()) g.By(fmt.Sprintf("trying to tag an image below %s=%d quota", imageapi.ResourceImages, 1)) out, err = oc.Run("tag").Args(sharedProjectName+"/src:1", "is:1").Output() o.Expect(err).NotTo(o.HaveOccurred()) used, err := waitForResourceQuotaSync(oc, quotaName, rq.Spec.Hard)
want: gomega.BeNumerically("<=", float64(1)), }, // String { in: `{"have-prefix": "foo"}`, want: gomega.HavePrefix("foo"), }, { in: `{"have-suffix": "foo"}`, want: gomega.HaveSuffix("foo"), }, // Regex support is based on golangs regex engine https://golang.org/pkg/regexp/syntax/ { in: `{"match-regexp": "foo"}`, want: gomega.MatchRegexp("foo"), }, // Collection { in: `{"consist-of": ["foo"]}`, want: gomega.ConsistOf(gomega.Equal("foo")), }, { in: `{"contain-element": "foo"}`, want: gomega.ContainElement(gomega.Equal("foo")), }, { in: `{"have-len": 3}`, want: gomega.HaveLen(3), },