diff --git a/Dockerfile b/Dockerfile index f2720b2fe0..4a192118a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,41 +53,8 @@ RUN --mount=type=cache,sharing=locked,id=moby-criu-aptlib,target=/var/lib/apt \ && /build/criu --version # registry -FROM base AS registry-src -WORKDIR /usr/src/registry -RUN git init . && git remote add origin "https://github.com/distribution/distribution.git" - -FROM base AS registry -WORKDIR /go/src/github.com/docker/distribution - -# REGISTRY_VERSION_SCHEMA1 specifies the version of the registry to build and -# install from the https://github.com/docker/distribution repository. This is -# an older (pre v2.3.0) version of the registry that only supports schema1 -# manifests. This version of the registry is not working on arm64, so installation -# is skipped on that architecture. -ARG REGISTRY_VERSION_SCHEMA1=v2.1.0 -ARG TARGETPLATFORM -RUN --mount=from=registry-src,src=/usr/src/registry,rw \ - --mount=type=cache,target=/root/.cache/go-build,id=registry-build-$TARGETPLATFORM \ - --mount=type=cache,target=/go/pkg/mod \ - --mount=type=tmpfs,target=/go/src <= 0; i-- { - blobSum := verifiedManifest.FSLayers[i].BlobSum - if err = blobSum.Validate(); err != nil { - return "", "", errors.Wrapf(err, "could not validate layer digest %q", blobSum) - } - - var throwAway struct { - ThrowAway bool `json:"throwaway,omitempty"` - } - if err := json.Unmarshal([]byte(verifiedManifest.History[i].V1Compatibility), &throwAway); err != nil { - return "", "", err - } - - h, err := v1.HistoryFromConfig([]byte(verifiedManifest.History[i].V1Compatibility), throwAway.ThrowAway) - if err != nil { - return "", "", err - } - history = append(history, h) - - if throwAway.ThrowAway { - continue - } - - layerDescriptor := &layerDescriptor{ - digest: blobSum, - repoInfo: p.repoInfo, - repo: p.repo, - metadataService: p.metadataService, - } - - descriptors = append(descriptors, layerDescriptor) - } - - resultRootFS, release, err := p.config.DownloadManager.Download(ctx, *rootFS, descriptors, p.config.ProgressOutput) - if err != nil { - return "", "", err - } - defer release() - - config, err := v1.MakeConfigFromV1Config([]byte(verifiedManifest.History[0].V1Compatibility), &resultRootFS, history) - if err != nil { - return "", "", err - } - - imageID, err := p.config.ImageStore.Put(ctx, config) - if err != nil { - return "", "", err - } - - manifestDigest = digest.FromBytes(unverifiedManifest.Canonical) - - return imageID, manifestDigest, nil -} - func checkSupportedMediaType(mediaType string) error { lowerMt := strings.ToLower(mediaType) for _, mt := range supportedMediaTypes { @@ -860,18 +764,7 @@ func (p *puller) pullManifestList(ctx context.Context, ref reference.Named, mfst switch v := manifest.(type) { case *schema1.SignedManifest: - err := DeprecatedSchema1ImageError(ref) - log.G(ctx).Warn(err.Error()) - if os.Getenv("DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE") == "" { - return "", "", err - } - progress.Message(p.config.ProgressOutput, "", err.Error()) - - platform := toOCIPlatform(match.Platform) - id, _, err = p.pullSchema1(ctx, manifestRef, v, platform) - if err != nil { - return "", "", err - } + return "", "", DeprecatedSchema1ImageError(ref) case *schema2.DeserializedManifest: platform := toOCIPlatform(match.Platform) id, _, err = p.pullSchema2(ctx, manifestRef, v, platform) @@ -990,83 +883,6 @@ func schema2ManifestDigest(ref reference.Named, mfst distribution.Manifest) (dig return digest.FromBytes(canonical), nil } -func verifySchema1Manifest(signedManifest *schema1.SignedManifest, ref reference.Reference) (m *schema1.Manifest, err error) { - // If pull by digest, then verify the manifest digest. NOTE: It is - // important to do this first, before any other content validation. If the - // digest cannot be verified, don't even bother with those other things. - if digested, isCanonical := ref.(reference.Canonical); isCanonical { - verifier := digested.Digest().Verifier() - if _, err := verifier.Write(signedManifest.Canonical); err != nil { - return nil, err - } - if !verifier.Verified() { - err := fmt.Errorf("image verification failed for digest %s", digested.Digest()) - log.G(context.TODO()).Error(err) - return nil, err - } - } - m = &signedManifest.Manifest - - if m.SchemaVersion != 1 { - return nil, fmt.Errorf("unsupported schema version %d for %q", m.SchemaVersion, reference.FamiliarString(ref)) - } - if len(m.FSLayers) != len(m.History) { - return nil, fmt.Errorf("length of history not equal to number of layers for %q", reference.FamiliarString(ref)) - } - if len(m.FSLayers) == 0 { - return nil, fmt.Errorf("no FSLayers in manifest for %q", reference.FamiliarString(ref)) - } - return m, nil -} - -// fixManifestLayers removes repeated layers from the manifest and checks the -// correctness of the parent chain. -func fixManifestLayers(m *schema1.Manifest) error { - imgs := make([]*image.V1Image, len(m.FSLayers)) - for i := range m.FSLayers { - img := &image.V1Image{} - - if err := json.Unmarshal([]byte(m.History[i].V1Compatibility), img); err != nil { - return err - } - - imgs[i] = img - if err := v1.ValidateID(img.ID); err != nil { - return err - } - } - - if imgs[len(imgs)-1].Parent != "" && runtime.GOOS != "windows" { - // Windows base layer can point to a base layer parent that is not in manifest. - return errors.New("invalid parent ID in the base layer of the image") - } - - // check general duplicates to error instead of a deadlock - idmap := make(map[string]struct{}) - - var lastID string - for _, img := range imgs { - // skip IDs that appear after each other, we handle those later - if _, exists := idmap[img.ID]; img.ID != lastID && exists { - return fmt.Errorf("ID %+v appears multiple times in manifest", img.ID) - } - lastID = img.ID - idmap[lastID] = struct{}{} - } - - // backwards loop so that we keep the remaining indexes after removing items - for i := len(imgs) - 2; i >= 0; i-- { - if imgs[i].ID == imgs[i+1].ID { // repeated ID. remove and continue - m.FSLayers = append(m.FSLayers[:i], m.FSLayers[i+1:]...) - m.History = append(m.History[:i], m.History[i+1:]...) - } else if imgs[i].Parent != imgs[i+1].ID { - return fmt.Errorf("invalid parent ID. Expected %v, got %v", imgs[i+1].ID, imgs[i].Parent) - } - } - - return nil -} - func createDownloadFile() (*os.File, error) { return os.CreateTemp("", "GetImageBlob") } diff --git a/distribution/pull_v2_test.go b/distribution/pull_v2_test.go index df09c04465..e151216ad1 100644 --- a/distribution/pull_v2_test.go +++ b/distribution/pull_v2_test.go @@ -2,12 +2,9 @@ package distribution // import "github.com/docker/docker/distribution" import ( "context" - "encoding/json" "net/http" "net/http/httptest" "net/url" - "os" - "reflect" "regexp" "runtime" "strings" @@ -15,184 +12,13 @@ import ( "testing" "github.com/distribution/reference" - "github.com/docker/distribution/manifest/schema1" registrytypes "github.com/docker/docker/api/types/registry" "github.com/docker/docker/image" "github.com/docker/docker/registry" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" ) -// TestFixManifestLayers checks that fixManifestLayers removes a duplicate -// layer, and that it makes no changes to the manifest when called a second -// time, after the duplicate is removed. -func TestFixManifestLayers(t *testing.T) { - duplicateLayerManifest := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - duplicateLayerManifestExpectedOutput := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - if err := fixManifestLayers(&duplicateLayerManifest); err != nil { - t.Fatalf("unexpected error from fixManifestLayers: %v", err) - } - - if !reflect.DeepEqual(duplicateLayerManifest, duplicateLayerManifestExpectedOutput) { - t.Fatal("incorrect output from fixManifestLayers on duplicate layer manifest") - } - - // Run fixManifestLayers again and confirm that it doesn't change the - // manifest (which no longer has duplicate layers). - if err := fixManifestLayers(&duplicateLayerManifest); err != nil { - t.Fatalf("unexpected error from fixManifestLayers: %v", err) - } - - if !reflect.DeepEqual(duplicateLayerManifest, duplicateLayerManifestExpectedOutput) { - t.Fatal("incorrect output from fixManifestLayers on duplicate layer manifest (second pass)") - } -} - -// TestFixManifestLayersBaseLayerParent makes sure that fixManifestLayers fails -// if the base layer configuration specifies a parent. -func TestFixManifestLayersBaseLayerParent(t *testing.T) { - // TODO Windows: Fix this unit text - if runtime.GOOS == "windows" { - t.Skip("Needs fixing on Windows") - } - duplicateLayerManifest := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"parent\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - if err := fixManifestLayers(&duplicateLayerManifest); err == nil || !strings.Contains(err.Error(), "invalid parent ID in the base layer of the image") { - t.Fatalf("expected an invalid parent ID error from fixManifestLayers") - } -} - -// TestFixManifestLayersBadParent makes sure that fixManifestLayers fails -// if an image configuration specifies a parent that doesn't directly follow -// that (deduplicated) image in the image history. -func TestFixManifestLayersBadParent(t *testing.T) { - duplicateLayerManifest := schema1.Manifest{ - FSLayers: []schema1.FSLayer{ - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4")}, - {BlobSum: digest.Digest("sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa")}, - }, - History: []schema1.History{ - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ac3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"3b38edc92eb7c074812e217b41a6ade66888531009d6286a6f5f36a06f9841b9\",\"parent\":\"ac3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:11.368300679Z\",\"container\":\"d91be3479d5b1e84b0c00d18eea9dc777ca0ad166d51174b24283e2e6f104253\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT [\\\"/go/bin/dnsdock\\\"]\"],\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":null,\"Image\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":[\"/go/bin/dnsdock\"],\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"}, - {V1Compatibility: "{\"id\":\"ec3025ca8cc9bcab039e193e20ec647c2da3c53a74020f2ba611601f9b2c6c02\",\"created\":\"2015-08-19T16:49:07.568027497Z\",\"container\":\"fe9e5a5264a843c9292d17b736c92dd19bdb49986a8782d7389964ddaff887cc\",\"container_config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"cd /go/src/github.com/tonistiigi/dnsdock \\u0026\\u0026 go get -v github.com/tools/godep \\u0026\\u0026 godep restore \\u0026\\u0026 go install -ldflags \\\"-X main.version `git describe --tags HEAD``if [[ -n $(command git status --porcelain --untracked-files=no 2\\u003e/dev/null) ]]; then echo \\\"-dirty\\\"; fi`\\\" ./...\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"docker_version\":\"1.6.2\",\"config\":{\"Hostname\":\"03797203757d\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/go/bin:/usr/src/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"GOLANG_VERSION=1.4.1\",\"GOPATH=/go\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"e3b0ff09e647595dafee15c54cd632c900df9e82b1d4d313b1e20639a1461779\",\"Volumes\":null,\"WorkingDir\":\"/go\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":118430532}\n"}, - }, - } - - err := fixManifestLayers(&duplicateLayerManifest) - assert.Check(t, is.ErrorContains(err, "invalid parent ID")) -} - -// TestValidateManifest verifies the validateManifest function -func TestValidateManifest(t *testing.T) { - // TODO Windows: Fix this unit text - if runtime.GOOS == "windows" { - t.Skip("Needs fixing on Windows") - } - expectedDigest, err := reference.ParseNormalizedNamed("repo@sha256:02fee8c3220ba806531f606525eceb83f4feb654f62b207191b1c9209188dedd") - if err != nil { - t.Fatal("could not parse reference") - } - expectedFSLayer0 := digest.Digest("sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4") - - // Good manifest - - goodManifestBytes, err := os.ReadFile("fixtures/validate_manifest/good_manifest") - if err != nil { - t.Fatal("error reading fixture:", err) - } - - var goodSignedManifest schema1.SignedManifest - err = json.Unmarshal(goodManifestBytes, &goodSignedManifest) - if err != nil { - t.Fatal("error unmarshaling manifest:", err) - } - - verifiedManifest, err := verifySchema1Manifest(&goodSignedManifest, expectedDigest) - if err != nil { - t.Fatal("validateManifest failed:", err) - } - - if verifiedManifest.FSLayers[0].BlobSum != expectedFSLayer0 { - t.Fatal("unexpected FSLayer in good manifest") - } - - // "Extra data" manifest - - extraDataManifestBytes, err := os.ReadFile("fixtures/validate_manifest/extra_data_manifest") - if err != nil { - t.Fatal("error reading fixture:", err) - } - - var extraDataSignedManifest schema1.SignedManifest - err = json.Unmarshal(extraDataManifestBytes, &extraDataSignedManifest) - if err != nil { - t.Fatal("error unmarshaling manifest:", err) - } - - verifiedManifest, err = verifySchema1Manifest(&extraDataSignedManifest, expectedDigest) - if err != nil { - t.Fatal("validateManifest failed:", err) - } - - if verifiedManifest.FSLayers[0].BlobSum != expectedFSLayer0 { - t.Fatal("unexpected FSLayer in extra data manifest") - } - - // Bad manifest - - badManifestBytes, err := os.ReadFile("fixtures/validate_manifest/bad_manifest") - if err != nil { - t.Fatal("error reading fixture:", err) - } - - var badSignedManifest schema1.SignedManifest - err = json.Unmarshal(badManifestBytes, &badSignedManifest) - if err != nil { - t.Fatal("error unmarshaling manifest:", err) - } - - _, err = verifySchema1Manifest(&badSignedManifest, expectedDigest) - if err == nil || !strings.HasPrefix(err.Error(), "image verification failed for digest") { - t.Fatal("expected validateManifest to fail with digest error") - } -} - func TestFormatPlatform(t *testing.T) { var platform ocispec.Platform result := formatPlatform(platform) diff --git a/hack/make/.integration-daemon-start b/hack/make/.integration-daemon-start index 9d3d04817f..5e3e058bd6 100644 --- a/hack/make/.integration-daemon-start +++ b/hack/make/.integration-daemon-start @@ -40,15 +40,9 @@ fi # intentionally open a couple bogus file descriptors to help test that they get scrubbed in containers exec 41>&1 42>&2 -# Allow pushing manifest v2 schema 1 images, as they're used to push -# images to our test-registries for testing _pulling_ schema 2v1 images. -export DOCKER_ALLOW_SCHEMA1_PUSH_DONOTUSE=1 export DOCKER_GRAPHDRIVER=${DOCKER_GRAPHDRIVER:-vfs} export DOCKER_USERLANDPROXY=${DOCKER_USERLANDPROXY:-true} -# Allow testing push/pull of legacy image formats -export DOCKER_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1 - # example usage: DOCKER_STORAGE_OPTS="dm.basesize=20G,dm.loopdatasize=200G" storage_params="" if [ -n "$DOCKER_STORAGE_OPTS" ]; then diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go index 407bb28a12..5eba88220a 100644 --- a/integration-cli/check_test.go +++ b/integration-cli/check_test.go @@ -28,7 +28,6 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "gotest.tools/v3/assert" - "gotest.tools/v3/skip" ) const ( @@ -364,13 +363,6 @@ func TestDockerRegistrySuite(t *testing.T) { suite.Run(ctx, t, &DockerRegistrySuite{ds: &DockerSuite{}}) } -func TestDockerSchema1RegistrySuite(t *testing.T) { - skip.If(t, testEnv.UsingSnapshotter()) - ctx := testutil.StartSpan(baseContext, t) - ensureTestEnvSetup(ctx, t) - suite.Run(ctx, t, &DockerSchema1RegistrySuite{ds: &DockerSuite{}}) -} - func TestDockerRegistryAuthHtpasswdSuite(t *testing.T) { ctx := testutil.StartSpan(baseContext, t) ensureTestEnvSetup(ctx, t) @@ -478,33 +470,6 @@ func (s *DockerRegistrySuite) TearDownTest(ctx context.Context, c *testing.T) { s.ds.TearDownTest(ctx, c) } -type DockerSchema1RegistrySuite struct { - ds *DockerSuite - reg *registry.V2 - d *daemon.Daemon -} - -func (s *DockerSchema1RegistrySuite) OnTimeout(c *testing.T) { - s.d.DumpStackAndQuit() -} - -func (s *DockerSchema1RegistrySuite) SetUpTest(ctx context.Context, c *testing.T) { - testRequires(c, DaemonIsLinux, RegistryHosting, NotArm64, testEnv.IsLocalDaemon) - s.reg = registry.NewV2(c, registry.Schema1) - s.reg.WaitReady(c) - s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) -} - -func (s *DockerSchema1RegistrySuite) TearDownTest(ctx context.Context, c *testing.T) { - if s.reg != nil { - s.reg.Close() - } - if s.d != nil { - s.d.Stop(c) - } - s.ds.TearDownTest(ctx, c) -} - type DockerRegistryAuthHtpasswdSuite struct { ds *DockerSuite reg *registry.V2 diff --git a/integration-cli/docker_cli_by_digest_test.go b/integration-cli/docker_cli_by_digest_test.go index e6037827ce..9c642860a1 100644 --- a/integration-cli/docker_cli_by_digest_test.go +++ b/integration-cli/docker_cli_by_digest_test.go @@ -9,7 +9,6 @@ import ( "strings" "testing" - "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" "github.com/docker/docker/api/types" "github.com/docker/docker/integration-cli/cli" @@ -62,7 +61,7 @@ func setupImageWithTag(c *testing.T, tag string) (digest.Digest, error) { return digest.Digest(pushDigest), nil } -func testPullByTagDisplaysDigest(c *testing.T) { +func (s *DockerRegistrySuite) TestPullByTagDisplaysDigest(c *testing.T) { testRequires(c, DaemonIsLinux) pushDigest, err := setupImage(c) assert.NilError(c, err, "error setting up image") @@ -79,15 +78,7 @@ func testPullByTagDisplaysDigest(c *testing.T) { assert.Equal(c, pushDigest.String(), pullDigest) } -func (s *DockerRegistrySuite) TestPullByTagDisplaysDigest(c *testing.T) { - testPullByTagDisplaysDigest(c) -} - -func (s *DockerSchema1RegistrySuite) TestPullByTagDisplaysDigest(c *testing.T) { - testPullByTagDisplaysDigest(c) -} - -func testPullByDigest(c *testing.T) { +func (s *DockerRegistrySuite) TestPullByDigest(c *testing.T) { testRequires(c, DaemonIsLinux) pushDigest, err := setupImage(c) assert.NilError(c, err, "error setting up image") @@ -105,15 +96,7 @@ func testPullByDigest(c *testing.T) { assert.Equal(c, pushDigest.String(), pullDigest) } -func (s *DockerRegistrySuite) TestPullByDigest(c *testing.T) { - testPullByDigest(c) -} - -func (s *DockerSchema1RegistrySuite) TestPullByDigest(c *testing.T) { - testPullByDigest(c) -} - -func testPullByDigestNoFallback(c *testing.T) { +func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *testing.T) { testRequires(c, DaemonIsLinux) // pull from the registry using the @ reference imageReference := fmt.Sprintf("%s@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", repoName) @@ -128,14 +111,6 @@ func testPullByDigestNoFallback(c *testing.T) { assert.Check(c, is.Contains(out, expectedMsg), "expected non-zero exit status and correct error message when pulling non-existing image") } -func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *testing.T) { - testPullByDigestNoFallback(c) -} - -func (s *DockerSchema1RegistrySuite) TestPullByDigestNoFallback(c *testing.T) { - testPullByDigestNoFallback(c) -} - func (s *DockerRegistrySuite) TestCreateByDigest(c *testing.T) { pushDigest, err := setupImage(c) assert.NilError(c, err, "error setting up image") @@ -580,48 +555,6 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *testing.T) { } } -// TestPullFailsWithAlteredManifest tests that a `docker pull` fails when -// we have modified a manifest blob and its digest cannot be verified. -// This is the schema1 version of the test. -func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredManifest(c *testing.T) { - testRequires(c, DaemonIsLinux) - manifestDigest, err := setupImage(c) - assert.Assert(c, err == nil, "error setting up image") - - // Load the target manifest blob. - manifestBlob := s.reg.ReadBlobContents(c, manifestDigest) - - var imgManifest schema1.Manifest - err = json.Unmarshal(manifestBlob, &imgManifest) - assert.Assert(c, err == nil, "unable to decode image manifest from blob") - - // Change a layer in the manifest. - imgManifest.FSLayers[0] = schema1.FSLayer{ - BlobSum: digest.Digest("sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), - } - - // Move the existing data file aside, so that we can replace it with a - // malicious blob of data. NOTE: we defer the returned undo func. - undo := s.reg.TempMoveBlobData(c, manifestDigest) - defer undo() - - alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ") - assert.Assert(c, err == nil, "unable to encode altered image manifest to JSON") - - s.reg.WriteBlobContents(c, manifestDigest, alteredManifestBlob) - - // Now try pulling that image by digest. We should get an error about - // digest verification for the manifest digest. - - // Pull from the registry using the @ reference. - imageReference := fmt.Sprintf("%s@%s", repoName, manifestDigest) - out, exitStatus, _ := dockerCmdWithError("pull", imageReference) - assert.Assert(c, exitStatus != 0) - - expectedErrorMsg := fmt.Sprintf("image verification failed for digest %s", manifestDigest) - assert.Assert(c, strings.Contains(out, expectedErrorMsg)) -} - // TestPullFailsWithAlteredLayer tests that a `docker pull` fails when // we have modified a layer blob and its digest cannot be verified. // This is the schema2 version of the test. @@ -666,46 +599,3 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredLayer(c *testing.T) { expectedErrorMsg := fmt.Sprintf("filesystem layer verification failed for digest %s", targetLayerDigest) assert.Assert(c, strings.Contains(out, expectedErrorMsg), "expected error message in output: %s", out) } - -// TestPullFailsWithAlteredLayer tests that a `docker pull` fails when -// we have modified a layer blob and its digest cannot be verified. -// This is the schema1 version of the test. -func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredLayer(c *testing.T) { - testRequires(c, DaemonIsLinux) - manifestDigest, err := setupImage(c) - assert.Assert(c, err == nil) - - // Load the target manifest blob. - manifestBlob := s.reg.ReadBlobContents(c, manifestDigest) - - var imgManifest schema1.Manifest - err = json.Unmarshal(manifestBlob, &imgManifest) - assert.Assert(c, err == nil) - - // Next, get the digest of one of the layers from the manifest. - targetLayerDigest := imgManifest.FSLayers[0].BlobSum - - // Move the existing data file aside, so that we can replace it with a - // malicious blob of data. NOTE: we defer the returned undo func. - undo := s.reg.TempMoveBlobData(c, targetLayerDigest) - defer undo() - - // Now make a fake data blob in this directory. - s.reg.WriteBlobContents(c, targetLayerDigest, []byte("This is not the data you are looking for.")) - - // Now try pulling that image by digest. We should get an error about - // digest verification for the target layer digest. - - // Remove distribution cache to force a re-pull of the blobs - if err := os.RemoveAll(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "image", s.d.StorageDriver(), "distribution")); err != nil { - c.Fatalf("error clearing distribution cache: %v", err) - } - - // Pull from the registry using the @ reference. - imageReference := fmt.Sprintf("%s@%s", repoName, manifestDigest) - out, exitStatus, _ := dockerCmdWithError("pull", imageReference) - assert.Assert(c, exitStatus != 0, "expected a non-zero exit status") - - expectedErrorMsg := fmt.Sprintf("filesystem layer verification failed for digest %s", targetLayerDigest) - assert.Assert(c, strings.Contains(out, expectedErrorMsg), "expected error message in output: %s", out) -} diff --git a/integration-cli/docker_cli_pull_local_test.go b/integration-cli/docker_cli_pull_local_test.go index fbf72d1ebb..4fadcc4ebc 100644 --- a/integration-cli/docker_cli_pull_local_test.go +++ b/integration-cli/docker_cli_pull_local_test.go @@ -25,7 +25,7 @@ import ( // tags for the same image) are not also pulled down. // // Ref: docker/docker#8141 -func testPullImageWithAliases(c *testing.T) { +func (s *DockerRegistrySuite) TestPullImageWithAliases(c *testing.T) { const imgRepo = privateRegistryURL + "/dockercli/busybox" var repos []string @@ -52,16 +52,8 @@ func testPullImageWithAliases(c *testing.T) { } } -func (s *DockerRegistrySuite) TestPullImageWithAliases(c *testing.T) { - testPullImageWithAliases(c) -} - -func (s *DockerSchema1RegistrySuite) TestPullImageWithAliases(c *testing.T) { - testPullImageWithAliases(c) -} - -// testConcurrentPullWholeRepo pulls the same repo concurrently. -func testConcurrentPullWholeRepo(c *testing.T) { +// TestConcurrentPullWholeRepo pulls the same repo concurrently. +func (s *DockerRegistrySuite) TestConcurrentPullWholeRepo(c *testing.T) { const imgRepo = privateRegistryURL + "/dockercli/busybox" var repos []string @@ -108,16 +100,8 @@ func testConcurrentPullWholeRepo(c *testing.T) { } } -func (s *DockerRegistrySuite) TestConcurrentPullWholeRepo(c *testing.T) { - testConcurrentPullWholeRepo(c) -} - -func (s *DockerSchema1RegistrySuite) TestConcurrentPullWholeRepo(c *testing.T) { - testConcurrentPullWholeRepo(c) -} - -// testConcurrentFailingPull tries a concurrent pull that doesn't succeed. -func testConcurrentFailingPull(c *testing.T) { +// TestConcurrentFailingPull tries a concurrent pull that doesn't succeed. +func (s *DockerRegistrySuite) TestConcurrentFailingPull(c *testing.T) { const imgRepo = privateRegistryURL + "/dockercli/busybox" // Run multiple pulls concurrently @@ -139,17 +123,9 @@ func testConcurrentFailingPull(c *testing.T) { } } -func (s *DockerRegistrySuite) TestConcurrentFailingPull(c *testing.T) { - testConcurrentFailingPull(c) -} - -func (s *DockerSchema1RegistrySuite) TestConcurrentFailingPull(c *testing.T) { - testConcurrentFailingPull(c) -} - -// testConcurrentPullMultipleTags pulls multiple tags from the same repo +// TestConcurrentPullMultipleTags pulls multiple tags from the same repo // concurrently. -func testConcurrentPullMultipleTags(c *testing.T) { +func (s *DockerRegistrySuite) TestConcurrentPullMultipleTags(c *testing.T) { const imgRepo = privateRegistryURL + "/dockercli/busybox" var repos []string @@ -195,17 +171,9 @@ func testConcurrentPullMultipleTags(c *testing.T) { } } -func (s *DockerRegistrySuite) TestConcurrentPullMultipleTags(c *testing.T) { - testConcurrentPullMultipleTags(c) -} - -func (s *DockerSchema1RegistrySuite) TestConcurrentPullMultipleTags(c *testing.T) { - testConcurrentPullMultipleTags(c) -} - -// testPullIDStability verifies that pushing an image and pulling it back +// TestPullIDStability verifies that pushing an image and pulling it back // preserves the image ID. -func testPullIDStability(c *testing.T) { +func (s *DockerRegistrySuite) TestPullIDStability(c *testing.T) { const derivedImage = privateRegistryURL + "/dockercli/id-stability" const baseImage = "busybox" @@ -255,16 +223,8 @@ func testPullIDStability(c *testing.T) { } } -func (s *DockerRegistrySuite) TestPullIDStability(c *testing.T) { - testPullIDStability(c) -} - -func (s *DockerSchema1RegistrySuite) TestPullIDStability(c *testing.T) { - testPullIDStability(c) -} - // #21213 -func testPullNoLayers(c *testing.T) { +func (s *DockerRegistrySuite) TestPullNoLayers(c *testing.T) { const imgRepo = privateRegistryURL + "/dockercli/scratch" buildImageSuccessfully(c, imgRepo, build.WithDockerfile(` @@ -275,14 +235,6 @@ func testPullNoLayers(c *testing.T) { cli.DockerCmd(c, "pull", imgRepo) } -func (s *DockerRegistrySuite) TestPullNoLayers(c *testing.T) { - testPullNoLayers(c) -} - -func (s *DockerSchema1RegistrySuite) TestPullNoLayers(c *testing.T) { - testPullNoLayers(c) -} - func (s *DockerRegistrySuite) TestPullManifestList(c *testing.T) { skip.If(c, testEnv.UsingSnapshotter(), "containerd knows how to pull manifest lists") pushDigest, err := setupImage(c) diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go index e16c21233d..6ffb898e23 100644 --- a/integration-cli/requirements_test.go +++ b/integration-cli/requirements_test.go @@ -43,10 +43,6 @@ func IsAmd64() bool { return testEnv.DaemonVersion.Arch == "amd64" } -func NotArm64() bool { - return testEnv.DaemonVersion.Arch != "arm64" -} - func NotPpc64le() bool { return testEnv.DaemonVersion.Arch != "ppc64le" } diff --git a/integration/daemon/daemon_test.go b/integration/daemon/daemon_test.go index 040e1253b5..cbccc9e474 100644 --- a/integration/daemon/daemon_test.go +++ b/integration/daemon/daemon_test.go @@ -58,6 +58,18 @@ func TestConfigDaemonID(t *testing.T) { info = d.Info(t) assert.Equal(t, info.ID, engineID) d.Stop(t) + + // Verify that engine-id file is created if it doesn't exist + err = os.Remove(idFile) + assert.NilError(t, err) + + d.Start(t, "--iptables=false") + id, err := os.ReadFile(idFile) + assert.NilError(t, err) + + info = d.Info(t) + assert.Equal(t, string(id), info.ID) + d.Stop(t) } func TestDaemonConfigValidation(t *testing.T) { diff --git a/testutil/registry/ops.go b/testutil/registry/ops.go index 7357d5f509..c72c5cb303 100644 --- a/testutil/registry/ops.go +++ b/testutil/registry/ops.go @@ -2,11 +2,6 @@ package registry import "io" -// Schema1 sets the registry to serve v1 api -func Schema1(c *Config) { - c.schema1 = true -} - // Htpasswd sets the auth method with htpasswd func Htpasswd(c *Config) { c.auth = "htpasswd" diff --git a/testutil/registry/registry.go b/testutil/registry/registry.go index 7cc3370de4..7e29329329 100644 --- a/testutil/registry/registry.go +++ b/testutil/registry/registry.go @@ -16,9 +16,7 @@ import ( const ( // V2binary is the name of the registry v2 binary - V2binary = "registry-v2" - // V2binarySchema1 is the name of the registry that serve schema1 - V2binarySchema1 = "registry-v2-schema1" + V2binary = "registry" // DefaultURL is the default url that will be used by the registry (if not specified otherwise) DefaultURL = "127.0.0.1:5000" ) @@ -36,7 +34,6 @@ type V2 struct { // Config contains the test registry configuration type Config struct { - schema1 bool auth string tokenURL string registryURL string @@ -106,13 +103,7 @@ http: t.Fatal(err) } - binary := V2binary - args := []string{"serve", confPath} - if c.schema1 { - binary = V2binarySchema1 - args = []string{confPath} - } - cmd := exec.Command(binary, args...) + cmd := exec.Command(V2binary, "serve", confPath) cmd.Stdout = c.stdout cmd.Stderr = c.stderr if err := cmd.Start(); err != nil { diff --git a/vendor.mod b/vendor.mod index f0424cfce5..50aef8ae68 100644 --- a/vendor.mod +++ b/vendor.mod @@ -40,7 +40,6 @@ require ( github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c github.com/docker/go-metrics v0.0.1 github.com/docker/go-units v0.5.0 - github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4 github.com/fluent/fluent-logger-golang v1.9.0 github.com/godbus/dbus/v5 v5.1.0 github.com/gogo/protobuf v1.3.2 @@ -148,6 +147,7 @@ require ( github.com/containernetworking/plugins v1.4.0 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fernet/fernet-go v0.0.0-20211208181803-9f70042a33ee // indirect