0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-23 22:27:35 -05:00
zot/pkg/compliance/v1_0_0/check.go

521 lines
18 KiB
Go
Raw Normal View History

2019-10-09 13:50:10 -05:00
//nolint (dupl)
package v1_0_0
2019-06-20 18:36:40 -05:00
import (
"bytes"
"encoding/json"
"fmt"
"io"
"os"
"strings"
2019-06-20 18:36:40 -05:00
"testing"
"github.com/anuvu/zot/pkg/api"
2019-10-09 13:50:10 -05:00
"github.com/anuvu/zot/pkg/compliance"
2019-06-20 18:36:40 -05:00
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
"github.com/smartystreets/goconvey/convey/reporting"
2019-06-20 18:36:40 -05:00
"gopkg.in/resty.v1"
)
2019-10-09 13:50:10 -05:00
func CheckWorkflows(t *testing.T, config *compliance.Config) {
if config == nil || config.Address == "" || config.Port == "" {
panic("insufficient config")
}
if config.OutputJSON {
outputJSONEnter()
defer outputJSONExit()
}
2019-10-09 13:50:10 -05:00
baseURL := fmt.Sprintf("http://%s:%s", config.Address, config.Port)
fmt.Println("------------------------------")
fmt.Println("Checking for v1.0.0 compliance")
fmt.Println("------------------------------")
2019-06-20 18:36:40 -05:00
Convey("Make API calls to the controller", t, func(c C) {
2019-10-09 13:50:10 -05:00
Convey("Check version", func() {
Print("\nCheck version")
resp, err := resty.R().Get(baseURL + "/v2/")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
})
Convey("Get repository catalog", func() {
2019-10-09 13:50:10 -05:00
Print("\nGet repository catalog")
resp, err := resty.R().Get(baseURL + "/v2/_catalog")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
So(resp.String(), ShouldNotBeEmpty)
2019-10-09 13:50:10 -05:00
So(resp.Header().Get("Content-Type"), ShouldEqual, api.DefaultMediaType)
2019-06-20 18:36:40 -05:00
var repoList api.RepositoryList
err = json.Unmarshal(resp.Body(), &repoList)
So(err, ShouldBeNil)
So(len(repoList.Repositories), ShouldEqual, 0)
2019-08-29 15:39:32 -05:00
// after newly created upload should succeed
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Post(baseURL + "/v2/z/blobs/uploads/")
2019-08-29 15:39:32 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
// after newly created upload should succeed
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Post(baseURL + "/v2/a/b/c/d/blobs/uploads/")
2019-08-29 15:39:32 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().SetResult(&api.RepositoryList{}).Get(baseURL + "/v2/_catalog")
2019-08-29 15:39:32 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
So(resp.String(), ShouldNotBeEmpty)
r := resp.Result().(*api.RepositoryList)
2019-10-09 13:50:10 -05:00
So(len(r.Repositories), ShouldBeGreaterThan, 0)
2019-08-29 15:39:32 -05:00
So(r.Repositories[0], ShouldEqual, "a/b/c/d")
So(r.Repositories[1], ShouldEqual, "z")
2019-06-20 18:36:40 -05:00
})
Convey("Get images in a repository", func() {
2019-10-09 13:50:10 -05:00
Print("\nGet images in a repository")
2019-06-20 18:36:40 -05:00
// non-existent repository should fail
2019-10-09 13:50:10 -05:00
resp, err := resty.R().Get(baseURL + "/v2/repo/tags/list")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
So(resp.String(), ShouldNotBeEmpty)
// after newly created upload should succeed
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Post(baseURL + "/v2/repo/blobs/uploads/")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + "/v2/repo/tags/list")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
So(resp.String(), ShouldNotBeEmpty)
})
Convey("Monolithic blob upload", func() {
2019-10-09 13:50:10 -05:00
Print("\nMonolithic blob upload")
resp, err := resty.R().Post(baseURL + "/v2/repo/blobs/uploads/")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
loc := resp.Header().Get("Location")
So(loc, ShouldNotBeEmpty)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 204)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + "/v2/repo/tags/list")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
So(resp.String(), ShouldNotBeEmpty)
// without a "?digest=<>" should fail
content := []byte("this is a blob")
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Put(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
// without the Content-Length should fail
2019-10-09 13:50:10 -05:00
resp, err = resty.R().SetQueryParam("digest", digest.String()).Put(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
// without any data to send, should fail
resp, err = resty.R().SetQueryParam("digest", digest.String()).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").Put(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
// monolithic blob upload: success
resp, err = resty.R().SetQueryParam("digest", digest.String()).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
blobLoc := resp.Header().Get("Location")
So(blobLoc, ShouldNotBeEmpty)
So(resp.Header().Get("Content-Length"), ShouldEqual, "0")
So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty)
// upload reference should now be removed
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
// blob reference should be accessible
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + blobLoc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
})
Convey("Monolithic blob upload with multiple name components", func() {
2019-10-09 13:50:10 -05:00
Print("\nMonolithic blob upload with multiple name components")
resp, err := resty.R().Post(baseURL + "/v2/repo1/repo2/repo3/blobs/uploads/")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
loc := resp.Header().Get("Location")
So(loc, ShouldNotBeEmpty)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 204)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + "/v2/repo1/repo2/repo3/tags/list")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
So(resp.String(), ShouldNotBeEmpty)
// without a "?digest=<>" should fail
content := []byte("this is a blob")
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Put(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
// without the Content-Length should fail
2019-10-09 13:50:10 -05:00
resp, err = resty.R().SetQueryParam("digest", digest.String()).Put(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
// without any data to send, should fail
resp, err = resty.R().SetQueryParam("digest", digest.String()).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").Put(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
// monolithic blob upload: success
resp, err = resty.R().SetQueryParam("digest", digest.String()).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
blobLoc := resp.Header().Get("Location")
So(blobLoc, ShouldNotBeEmpty)
So(resp.Header().Get("Content-Length"), ShouldEqual, "0")
So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty)
// upload reference should now be removed
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
// blob reference should be accessible
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + blobLoc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
})
2019-06-20 18:36:40 -05:00
Convey("Chunked blob upload", func() {
2019-10-09 13:50:10 -05:00
Print("\nChunked blob upload")
resp, err := resty.R().Post(baseURL + "/v2/repo/blobs/uploads/")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
loc := resp.Header().Get("Location")
So(loc, ShouldNotBeEmpty)
var buf bytes.Buffer
chunk1 := []byte("this is the first chunk")
n, err := buf.Write(chunk1)
So(n, ShouldEqual, len(chunk1))
So(err, ShouldBeNil)
// write first chunk
contentRange := fmt.Sprintf("%d-%d", 0, len(chunk1))
resp, err = resty.R().SetHeader("Content-Type", "application/octet-stream").
2019-10-09 13:50:10 -05:00
SetHeader("Content-Range", contentRange).SetBody(chunk1).Patch(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
// check progress
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 204)
r := resp.Header().Get("Range")
So(r, ShouldNotBeEmpty)
So(r, ShouldEqual, "bytes="+contentRange)
// write same chunk should fail
contentRange = fmt.Sprintf("%d-%d", 0, len(chunk1))
resp, err = resty.R().SetHeader("Content-Type", "application/octet-stream").
2019-10-09 13:50:10 -05:00
SetHeader("Content-Range", contentRange).SetBody(chunk1).Patch(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
So(resp.String(), ShouldNotBeEmpty)
chunk2 := []byte("this is the second chunk")
n, err = buf.Write(chunk2)
So(n, ShouldEqual, len(chunk2))
So(err, ShouldBeNil)
digest := godigest.FromBytes(buf.Bytes())
So(digest, ShouldNotBeNil)
// write final chunk
contentRange = fmt.Sprintf("%d-%d", len(chunk1), len(buf.Bytes()))
resp, err = resty.R().SetQueryParam("digest", digest.String()).
SetHeader("Content-Range", contentRange).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").SetBody(chunk2).Put(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
blobLoc := resp.Header().Get("Location")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
So(blobLoc, ShouldNotBeEmpty)
So(resp.Header().Get("Content-Length"), ShouldEqual, "0")
So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty)
// upload reference should now be removed
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
// blob reference should be accessible
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + blobLoc)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
})
Convey("Chunked blob upload with multiple name components", func() {
2019-10-09 13:50:10 -05:00
Print("\nChunked blob upload with multiple name components")
resp, err := resty.R().Post(baseURL + "/v2/repo4/repo5/repo6/blobs/uploads/")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
loc := resp.Header().Get("Location")
So(loc, ShouldNotBeEmpty)
var buf bytes.Buffer
chunk1 := []byte("this is the first chunk")
n, err := buf.Write(chunk1)
So(n, ShouldEqual, len(chunk1))
So(err, ShouldBeNil)
2019-06-20 18:36:40 -05:00
// write first chunk
contentRange := fmt.Sprintf("%d-%d", 0, len(chunk1))
resp, err = resty.R().SetHeader("Content-Type", "application/octet-stream").
2019-10-09 13:50:10 -05:00
SetHeader("Content-Range", contentRange).SetBody(chunk1).Patch(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
// check progress
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 204)
r := resp.Header().Get("Range")
So(r, ShouldNotBeEmpty)
So(r, ShouldEqual, "bytes="+contentRange)
// write same chunk should fail
contentRange = fmt.Sprintf("%d-%d", 0, len(chunk1))
resp, err = resty.R().SetHeader("Content-Type", "application/octet-stream").
2019-10-09 13:50:10 -05:00
SetHeader("Content-Range", contentRange).SetBody(chunk1).Patch(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 400)
So(resp.String(), ShouldNotBeEmpty)
chunk2 := []byte("this is the second chunk")
n, err = buf.Write(chunk2)
So(n, ShouldEqual, len(chunk2))
So(err, ShouldBeNil)
digest := godigest.FromBytes(buf.Bytes())
So(digest, ShouldNotBeNil)
// write final chunk
contentRange = fmt.Sprintf("%d-%d", len(chunk1), len(buf.Bytes()))
resp, err = resty.R().SetQueryParam("digest", digest.String()).
SetHeader("Content-Range", contentRange).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").SetBody(chunk2).Put(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
blobLoc := resp.Header().Get("Location")
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
So(blobLoc, ShouldNotBeEmpty)
So(resp.Header().Get("Content-Length"), ShouldEqual, "0")
So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty)
// upload reference should now be removed
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
// blob reference should be accessible
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + blobLoc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
})
Convey("Create and delete uploads", func() {
2019-10-09 13:50:10 -05:00
Print("\nCreate and delete uploads")
2019-06-20 18:36:40 -05:00
// create a upload
2019-10-09 13:50:10 -05:00
resp, err := resty.R().Post(baseURL + "/v2/repo/blobs/uploads/")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
loc := resp.Header().Get("Location")
So(loc, ShouldNotBeEmpty)
// delete this upload
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Delete(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
})
Convey("Create and delete blobs", func() {
2019-10-09 13:50:10 -05:00
Print("\nCreate and delete blobs")
2019-06-20 18:36:40 -05:00
// create a upload
2019-10-09 13:50:10 -05:00
resp, err := resty.R().Post(baseURL + "/v2/repo/blobs/uploads/")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
loc := resp.Header().Get("Location")
So(loc, ShouldNotBeEmpty)
content := []byte("this is a blob")
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
// monolithic blob upload
resp, err = resty.R().SetQueryParam("digest", digest.String()).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
blobLoc := resp.Header().Get("Location")
So(blobLoc, ShouldNotBeEmpty)
So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty)
// delete this blob
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Delete(baseURL + blobLoc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
So(resp.Header().Get("Content-Length"), ShouldEqual, "0")
})
Convey("Manifests", func() {
2019-10-09 13:50:10 -05:00
Print("\nManifests")
2019-06-20 18:36:40 -05:00
// create a blob/layer
2019-10-09 13:50:10 -05:00
resp, err := resty.R().Post(baseURL + "/v2/repo/blobs/uploads/")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 202)
loc := resp.Header().Get("Location")
So(loc, ShouldNotBeEmpty)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 204)
content := []byte("this is a blob")
digest := godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
// monolithic blob upload: success
resp, err = resty.R().SetQueryParam("digest", digest.String()).
2019-10-09 13:50:10 -05:00
SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(baseURL + loc)
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
blobLoc := resp.Header().Get("Location")
So(blobLoc, ShouldNotBeEmpty)
So(resp.Header().Get("Content-Length"), ShouldEqual, "0")
So(resp.Header().Get(api.DistContentDigestKey), ShouldNotBeEmpty)
// create a manifest
m := ispec.Manifest{Layers: []ispec.Descriptor{{Digest: digest}}}
content, err = json.Marshal(m)
So(err, ShouldBeNil)
digest = godigest.FromBytes(content)
So(digest, ShouldNotBeNil)
resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
2019-10-09 13:50:10 -05:00
SetBody(content).Put(baseURL + "/v2/repo/manifests/test:1.0")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 201)
d := resp.Header().Get(api.DistContentDigestKey)
So(d, ShouldNotBeEmpty)
So(d, ShouldEqual, digest.String())
// check/get by tag
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Head(baseURL + "/v2/repo/manifests/test:1.0")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + "/v2/repo/manifests/test:1.0")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
So(resp.Body(), ShouldNotBeEmpty)
// check/get by reference
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Head(baseURL + "/v2/repo/manifests/" + digest.String())
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + "/v2/repo/manifests/" + digest.String())
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
So(resp.Body(), ShouldNotBeEmpty)
// delete manifest
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Delete(baseURL + "/v2/repo/manifests/test:1.0")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
// delete again should fail
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Delete(baseURL + "/v2/repo/manifests/" + digest.String())
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
// check/get by tag
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Head(baseURL + "/v2/repo/manifests/test:1.0")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + "/v2/repo/manifests/test:1.0")
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
So(resp.Body(), ShouldNotBeEmpty)
// check/get by reference
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Head(baseURL + "/v2/repo/manifests/" + digest.String())
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
2019-10-09 13:50:10 -05:00
resp, err = resty.R().Get(baseURL + "/v2/repo/manifests/" + digest.String())
2019-06-20 18:36:40 -05:00
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 404)
So(resp.Body(), ShouldNotBeEmpty)
})
})
}
var (
old *os.File
r *os.File
w *os.File
outC chan string
)
func outputJSONEnter() {
// this env var instructs goconvey to output results to JSON (stdout)
os.Setenv("GOCONVEY_REPORTER", "json")
// stdout capture copied from: https://stackoverflow.com/a/29339052
old = os.Stdout
// keep backup of the real stdout
r, w, _ = os.Pipe()
outC = make(chan string)
os.Stdout = w
// copy the output in a separate goroutine so printing can't block indefinitely
go func() {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
}()
}
func outputJSONExit() {
// back to normal state
w.Close()
os.Stdout = old // restoring the real stdout
out := <-outC
// The output of JSON is combined with regular output, so we look for the
// first occurrence of the "{" character and take everything after that
rawJSON := "[{" + strings.Join(strings.Split(out, "{")[1:], "{")
rawJSON = strings.Replace(rawJSON, reporting.OpenJson, "", 1)
rawJSON = strings.Replace(rawJSON, reporting.CloseJson, "", 1)
tmp := strings.Split(rawJSON, ",")
rawJSON = strings.Join(tmp[0:len(tmp)-1], ",") + "]"
rawJSONMinified := validateMinifyRawJSON(rawJSON)
fmt.Println(rawJSONMinified)
}
func validateMinifyRawJSON(rawJSON string) string {
var j interface{}
err := json.Unmarshal([]byte(rawJSON), &j)
if err != nil {
panic(err)
}
rawJSONBytesMinified, err := json.Marshal(j)
if err != nil {
panic(err)
}
return string(rawJSONBytesMinified)
}