From 8879931937c9e32ff3a7cf51016b4913ac69ce3c Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Fri, 26 May 2023 19:10:57 +0000 Subject: [PATCH 1/2] conformance: always run but warn if empty layer manifest not supported As per image-spec, since this is a SHOULD (hence recommended) and now turned off by default. https://raw.githubusercontent.com/opencontainers/image-spec/main/manifest.md === layers array of objects Each item in the array MUST be a descriptor. For portability, layers SHOULD have at least one entry. === One can enable this test by setting env var: OCI_SKIP_EMPTY_LAYER_PUSH_TEST=0 Signed-off-by: Ramkumar Chinchani --- conformance/02_push_test.go | 11 +++++++---- conformance/setup.go | 13 ++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/conformance/02_push_test.go b/conformance/02_push_test.go index 94b53bcf..45f169c5 100644 --- a/conformance/02_push_test.go +++ b/conformance/02_push_test.go @@ -350,16 +350,19 @@ var test02Push = func() { g.Specify("Registry should accept a manifest upload with no layers", func() { SkipIfDisabled(push) - RunOnlyIfNot(skipEmptyLayerTest) req := client.NewRequest(reggie.PUT, "/v2//manifests/", reggie.WithReference(emptyLayerTestTag)). SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). SetBody(emptyLayerManifestContent) resp, err := client.Do(req) Expect(err).To(BeNil()) - location := resp.Header().Get("Location") - Expect(location).ToNot(BeEmpty()) - Expect(resp.StatusCode()).To(Equal(http.StatusCreated)) + if resp.StatusCode() == http.StatusCreated { + location := resp.Header().Get("Location") + Expect(location).ToNot(BeEmpty()) + Expect(resp.StatusCode()).To(Equal(http.StatusCreated)) + } else { + Warn("image manifest with no layers is not supported") + } }) g.Specify("GET request to manifest URL (digest) should yield 200 response", func() { diff --git a/conformance/setup.go b/conformance/setup.go index 379e4850..3d8d9ff0 100644 --- a/conformance/setup.go +++ b/conformance/setup.go @@ -10,11 +10,13 @@ import ( "math/big" mathrand "math/rand" "os" + "runtime" "strconv" "github.com/bloodorangeio/reggie" "github.com/google/uuid" g "github.com/onsi/ginkgo" + "github.com/onsi/ginkgo/formatter" godigest "github.com/opencontainers/go-digest" ) @@ -128,7 +130,6 @@ var ( runPushSetup bool runContentDiscoverySetup bool runContentManagementSetup bool - skipEmptyLayerTest bool deleteManifestBeforeBlobs bool runAutomaticCrossmountTest bool automaticCrossmountEnabled bool @@ -309,7 +310,6 @@ func init() { runPushSetup = true runContentDiscoverySetup = true runContentManagementSetup = true - skipEmptyLayerTest = false deleteManifestBeforeBlobs = true if os.Getenv(envVarTagName) != "" && @@ -322,7 +322,6 @@ func init() { runContentDiscoverySetup = false } - skipEmptyLayerTest, _ = strconv.ParseBool(os.Getenv(envVarPushEmptyLayer)) if v, ok := os.LookupEnv(envVarDeleteManifestBeforeBlobs); ok { deleteManifestBeforeBlobs, _ = strconv.ParseBool(v) } @@ -354,6 +353,14 @@ func RunOnlyIfNot(v bool) { } } +func Warn(message string) { + // print message + fmt.Fprint(os.Stderr, formatter.Fi(2, "\n{{magenta}}WARNING: %s\n{{/}}", message)) + // print file:line + _, file, line, _ := runtime.Caller(1) + fmt.Fprint(os.Stderr, formatter.Fi(2, "\n%s:%d\n", file, line)) +} + func generateSkipReport() string { buf := new(bytes.Buffer) fmt.Fprintf(buf, "you have skipped this test; if this is an error, check your environment variable settings:\n") From 1ea7ad4aac48566eb239e9a7e1141746551144c9 Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Sat, 17 Jun 2023 05:01:32 +0000 Subject: [PATCH 2/2] conformance: delete the empty manifest in teardown emptyLayerManifest is being pushed but not deleted during teardown Signed-off-by: Ramkumar Chinchani --- conformance/02_push_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/conformance/02_push_test.go b/conformance/02_push_test.go index 45f169c5..12013a10 100644 --- a/conformance/02_push_test.go +++ b/conformance/02_push_test.go @@ -15,6 +15,7 @@ var test02Push = func() { g.Context(titlePush, func() { var lastResponse, prevResponse *reggie.Response + var emptyLayerManifestRef string g.Context("Setup", func() { // No setup required at this time for push tests @@ -358,6 +359,7 @@ var test02Push = func() { Expect(err).To(BeNil()) if resp.StatusCode() == http.StatusCreated { location := resp.Header().Get("Location") + emptyLayerManifestRef = location Expect(location).ToNot(BeEmpty()) Expect(resp.StatusCode()).To(Equal(http.StatusCreated)) } else { @@ -390,6 +392,18 @@ var test02Push = func() { ), Equal(http.StatusMethodNotAllowed), )) + if emptyLayerManifestRef != "" { + req = client.NewRequest(reggie.DELETE, emptyLayerManifestRef) + resp, err = client.Do(req) + Expect(err).To(BeNil()) + Expect(resp.StatusCode()).To(SatisfyAny( + SatisfyAll( + BeNumerically(">=", 200), + BeNumerically("<", 300), + ), + Equal(http.StatusMethodNotAllowed), + )) + } }) } @@ -437,6 +451,18 @@ var test02Push = func() { ), Equal(http.StatusMethodNotAllowed), )) + if emptyLayerManifestRef != "" { + req = client.NewRequest(reggie.DELETE, emptyLayerManifestRef) + resp, err = client.Do(req) + Expect(err).To(BeNil()) + Expect(resp.StatusCode()).To(SatisfyAny( + SatisfyAll( + BeNumerically(">=", 200), + BeNumerically("<", 300), + ), + Equal(http.StatusMethodNotAllowed), + )) + } }) } })