diff --git a/pkg/image/apis/image/docker10/conversion.go b/pkg/image/apis/image/docker10/conversion.go index a05009d825..f4342e6971 100644 --- a/pkg/image/apis/image/docker10/conversion.go +++ b/pkg/image/apis/image/docker10/conversion.go @@ -3,61 +3,9 @@ package docker10 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/openshift/api/image/docker10" - "github.com/openshift/openshift-apiserver/pkg/image/apis/image" ) -// Convert_DockerV1CompatibilityImage_to_DockerImageConfig takes a container image registry digest -// (schema 2.1) and converts it to the external API version of Image. -func Convert_DockerV1CompatibilityImage_to_DockerImageConfig(in *DockerV1CompatibilityImage, out *DockerImageConfig) error { - *out = DockerImageConfig{ - ID: in.ID, - Parent: in.Parent, - Comment: in.Comment, - Created: in.Created, - Container: in.Container, - DockerVersion: in.DockerVersion, - Author: in.Author, - Architecture: in.Architecture, - Size: in.Size, - OS: "linux", - ContainerConfig: in.ContainerConfig, - } - if in.Config != nil { - out.Config = &docker10.DockerConfig{} - *out.Config = *in.Config - } - return nil -} - -// Convert_DockerV1CompatibilityImage_to_image_DockerImage takes a container -// image registry digest (schema 2.1) and converts it to the internal API -// version of Image. -func Convert_DockerV1CompatibilityImage_to_image_DockerImage(in *DockerV1CompatibilityImage, out *image.DockerImage) error { - *out = image.DockerImage{ - ID: in.ID, - Parent: in.Parent, - Comment: in.Comment, - Created: metav1.Time{Time: in.Created}, - Container: in.Container, - DockerVersion: in.DockerVersion, - Author: in.Author, - Architecture: in.Architecture, - Size: in.Size, - } - if err := Convert_docker10_DockerConfig_To_image_DockerConfig(&in.ContainerConfig, &out.ContainerConfig, nil); err != nil { - return err - } - if in.Config != nil { - out.Config = &image.DockerConfig{} - if err := Convert_docker10_DockerConfig_To_image_DockerConfig(in.Config, out.Config, nil); err != nil { - return err - } - } - return nil -} - // Convert_DockerImageConfig_to_image_DockerImage takes a container image // registry digest (schema 2.2) and converts it to the internal API version of // Image. diff --git a/pkg/image/apis/image/docker10/types.go b/pkg/image/apis/image/docker10/types.go index 232e894299..3b4a45256a 100644 --- a/pkg/image/apis/image/docker10/types.go +++ b/pkg/image/apis/image/docker10/types.go @@ -28,53 +28,11 @@ type DockerImageManifest struct { SchemaVersion int `json:"schemaVersion"` MediaType string `json:"mediaType,omitempty"` - // schema1 - Name string `json:"name"` - Tag string `json:"tag"` - Architecture string `json:"architecture"` - FSLayers []DockerFSLayer `json:"fsLayers"` - History []DockerHistory `json:"history"` - // schema2 Layers []Descriptor `json:"layers"` Config Descriptor `json:"config"` } -// DockerFSLayer is a container struct for BlobSums defined in an image manifest -type DockerFSLayer struct { - // DockerBlobSum is the tarsum of the referenced filesystem image layer - // TODO make this digest.Digest once distribution/distribution/v3 is in Godeps - DockerBlobSum string `json:"blobSum"` -} - -// DockerHistory stores unstructured v1 compatibility information -type DockerHistory struct { - // DockerV1Compatibility is the raw v1 compatibility information - DockerV1Compatibility string `json:"v1Compatibility"` -} - -// DockerV1CompatibilityImage represents the structured v1 -// compatibility information. -type DockerV1CompatibilityImage struct { - ID string `json:"id"` - Parent string `json:"parent,omitempty"` - Comment string `json:"comment,omitempty"` - Created time.Time `json:"created"` - Container string `json:"container,omitempty"` - ContainerConfig docker10.DockerConfig `json:"container_config,omitempty"` - DockerVersion string `json:"docker_version,omitempty"` - Author string `json:"author,omitempty"` - Config *docker10.DockerConfig `json:"config,omitempty"` - Architecture string `json:"architecture,omitempty"` - Size int64 `json:"size,omitempty"` -} - -// DockerV1CompatibilityImageSize represents the structured v1 -// compatibility information for size -type DockerV1CompatibilityImageSize struct { - Size int64 `json:"size,omitempty"` -} - // DockerImageConfig stores the image configuration type DockerImageConfig struct { ID string `json:"id"` diff --git a/pkg/image/apiserver/admission/limitrange/admission_test.go b/pkg/image/apiserver/admission/limitrange/admission_test.go index 42fb02c30c..b8e8c54e2b 100644 --- a/pkg/image/apiserver/admission/limitrange/admission_test.go +++ b/pkg/image/apiserver/admission/limitrange/admission_test.go @@ -19,7 +19,7 @@ import ( imagev1 "github.com/openshift/api/image/v1" "github.com/openshift/openshift-apiserver/pkg/api/legacy" imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" - "github.com/openshift/openshift-apiserver/pkg/image/apiserver/testutil" + "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/testutil" ) func TestAdmitImageStreamMapping(t *testing.T) { @@ -36,7 +36,7 @@ func TestAdmitImageStreamMapping(t *testing.T) { }, "new ism, under limit range": { imageStreamMapping: getImageStreamMapping(), - limitRange: getLimitRange("1Ki"), + limitRange: getLimitRange("2Mi"), operation: admission.Create, shouldAdmit: true, }, @@ -246,6 +246,7 @@ func getBaseImageWith1Layer() imageapi.Image { }, DockerImageReference: fmt.Sprintf("registry.example.org/%s/%s", "test", testutil.BaseImageWith1LayerDigest), DockerImageManifest: testutil.BaseImageWith1Layer, + DockerImageConfig: testutil.BaseImageWith1LayerConfig, } } diff --git a/pkg/image/apiserver/admission/limitrange/imagestream_limits_test.go b/pkg/image/apiserver/admission/limitrange/imagestream_limits_test.go index d137127f89..6b12fcc6e7 100644 --- a/pkg/image/apiserver/admission/limitrange/imagestream_limits_test.go +++ b/pkg/image/apiserver/admission/limitrange/imagestream_limits_test.go @@ -13,7 +13,7 @@ import ( "github.com/openshift/library-go/pkg/quota/quotautil" imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" - imagetest "github.com/openshift/openshift-apiserver/pkg/image/apiserver/testutil" + imagetest "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/testutil" ) func TestGetMaxLimits(t *testing.T) { diff --git a/pkg/image/apiserver/admission/limitrange/usage_test.go b/pkg/image/apiserver/admission/limitrange/usage_test.go index f546191a02..4a3ed7dc20 100644 --- a/pkg/image/apiserver/admission/limitrange/usage_test.go +++ b/pkg/image/apiserver/admission/limitrange/usage_test.go @@ -13,7 +13,7 @@ import ( imagev1 "github.com/openshift/api/image/v1" "github.com/openshift/library-go/pkg/image/imageutil" imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" - imagetest "github.com/openshift/openshift-apiserver/pkg/image/apiserver/testutil" + imagetest "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/testutil" ) func TestGetImageReferenceForObjectReference(t *testing.T) { diff --git a/pkg/image/apiserver/importer/image.go b/pkg/image/apiserver/importer/image.go index 969f97a6ba..ad10ed1036 100644 --- a/pkg/image/apiserver/importer/image.go +++ b/pkg/image/apiserver/importer/image.go @@ -6,7 +6,6 @@ import ( "github.com/distribution/distribution/v3" "github.com/distribution/distribution/v3/manifest/manifestlist" - "github.com/distribution/distribution/v3/manifest/schema1" "github.com/distribution/distribution/v3/registry/api/errcode" godigest "github.com/opencontainers/go-digest" @@ -18,41 +17,6 @@ import ( imagedockerpre012 "github.com/openshift/openshift-apiserver/pkg/image/apis/image/dockerpre012" ) -func schema1ToImage(manifest *schema1.SignedManifest, d godigest.Digest) (*imageapi.Image, error) { - if len(manifest.History) == 0 { - return nil, fmt.Errorf("image has no v1Compatibility history and cannot be used") - } - dockerImage, err := unmarshalDockerImage([]byte(manifest.History[0].V1Compatibility)) - if err != nil { - return nil, err - } - mediatype, payload, err := manifest.Payload() - if err != nil { - return nil, err - } - - if len(manifest.Canonical) == 0 { - return nil, fmt.Errorf("unable to load canonical representation from schema1 manifest") - } - payloadDigest := godigest.FromBytes(manifest.Canonical) - if len(d) > 0 && payloadDigest != d { - return nil, fmt.Errorf("content integrity error: the schema 1 manifest retrieved with digest %s does not match the digest calculated from the content %s", d, payloadDigest) - } - dockerImage.ID = payloadDigest.String() - - image := &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{ - Name: dockerImage.ID, - }, - DockerImageMetadata: *dockerImage, - DockerImageManifest: string(payload), - DockerImageManifestMediaType: mediatype, - DockerImageMetadataVersion: "1.0", - } - - return image, nil -} - // schema2OrOCIToImage converts a docker schema 2 or an oci schema manifest into an Image. func schema2OrOCIToImage(manifest distribution.Manifest, imageConfig []byte, d godigest.Digest) (*imageapi.Image, error) { mediatype, payload, err := manifest.Payload() diff --git a/pkg/image/apiserver/importer/importer.go b/pkg/image/apiserver/importer/importer.go index baadf15dd6..07d2a611df 100644 --- a/pkg/image/apiserver/importer/importer.go +++ b/pkg/image/apiserver/importer/importer.go @@ -12,7 +12,6 @@ import ( "github.com/distribution/distribution/v3" "github.com/distribution/distribution/v3/manifest/manifestlist" "github.com/distribution/distribution/v3/manifest/ocischema" - "github.com/distribution/distribution/v3/manifest/schema1" "github.com/distribution/distribution/v3/manifest/schema2" "github.com/distribution/distribution/v3/reference" "github.com/distribution/distribution/v3/registry/api/errcode" @@ -743,8 +742,6 @@ func (imp *ImageStreamImporter) importManifest( if isManifestList && !legacyManifestListImport { image, err = manifestListToImage(manifestList, d) return - } else if signedManifest, isSchema1 := manifest.(*schema1.SignedManifest); isSchema1 { - image, err = schema1ToImage(signedManifest, d) } else if deserializedManifest, isSchema2 := manifest.(*schema2.DeserializedManifest); isSchema2 { imageConfig, getImportConfigErr := b.Get(ctx, deserializedManifest.Config.Digest) if getImportConfigErr != nil { diff --git a/pkg/image/apiserver/importer/importer_test.go b/pkg/image/apiserver/importer/importer_test.go index 38770081c5..5a3b080b55 100644 --- a/pkg/image/apiserver/importer/importer_test.go +++ b/pkg/image/apiserver/importer/importer_test.go @@ -2,7 +2,6 @@ package importer import ( "context" - "encoding/json" "fmt" "net/http" "net/url" @@ -11,7 +10,6 @@ import ( "github.com/containers/image/v5/pkg/sysregistriesv2" "github.com/distribution/distribution/v3" - "github.com/distribution/distribution/v3/manifest/schema1" "github.com/distribution/distribution/v3/manifest/schema2" "github.com/distribution/distribution/v3/reference" godigest "github.com/opencontainers/go-digest" @@ -169,20 +167,6 @@ func (r *mockTagService) Lookup(ctx context.Context, digest distribution.Descrip return nil, fmt.Errorf("not implemented") } -func TestSchema1ToImage(t *testing.T) { - m := &schema1.SignedManifest{} - if err := json.Unmarshal([]byte(etcdManifest), m); err != nil { - t.Fatal(err) - } - image, err := schema1ToImage(m, godigest.Digest("sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238")) - if err != nil { - t.Fatal(err) - } - if image.DockerImageMetadata.ID != "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238" { - t.Errorf("unexpected image: %#v", image.DockerImageMetadata.ID) - } -} - func TestImportNothing(t *testing.T) { ctx := NewStaticCredentialsContext( http.DefaultTransport, http.DefaultTransport, nil, @@ -202,11 +186,6 @@ func expectStatusError(status metav1.Status, message string) bool { } func TestImport(t *testing.T) { - etcdManifestSchema1 := &schema1.SignedManifest{} - if err := json.Unmarshal([]byte(etcdManifest), etcdManifestSchema1); err != nil { - t.Fatal(err) - } - t.Logf("etcd manifest schema 1 digest: %q", godigest.FromBytes([]byte(etcdManifest))) busyboxManifestSchema2 := &schema2.DeserializedManifest{} if err := busyboxManifestSchema2.UnmarshalJSON([]byte(busyboxManifest)); err != nil { t.Fatal(err) @@ -312,12 +291,21 @@ func TestImport(t *testing.T) { }, }, { - name: "successfull import by tag and digest", - retriever: &mockRetriever{repo: &mockRepository{manifest: etcdManifestSchema1}}, + name: "successful import by tag and digest", + retriever: &mockRetriever{ + repo: &mockRepository{ + blobs: &mockBlobStore{ + blobs: map[godigest.Digest][]byte{ + busyboxConfigDigest: []byte(busyboxManifestConfig), + }, + }, + manifest: busyboxManifestSchema2, + }, + }, isi: imageapi.ImageStreamImport{ Spec: imageapi.ImageStreamImportSpec{ Images: []imageapi.ImageImportSpec{ - {From: kapi.ObjectReference{Kind: "DockerImage", Name: "test@sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238"}}, + {From: kapi.ObjectReference{Kind: "DockerImage", Name: "test@" + busyboxDigest}}, {From: kapi.ObjectReference{Kind: "DockerImage", Name: "test:tag"}}, }, }, @@ -331,13 +319,17 @@ func TestImport(t *testing.T) { if image.Status.Status != metav1.StatusSuccess { t.Errorf("unexpected status %d: %#v", i, image.Status) } - // the image name is always the sha256, and size is calculated - if image.Image == nil || image.Image.Name != "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238" || image.Image.DockerImageMetadata.Size != 28643712 { - t.Errorf("unexpected image %d: %#v", i, image.Image.Name) - } - // the most specific reference is returned - if image.Image.DockerImageReference != "test@sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238" { - t.Errorf("unexpected ref %d: %#v", i, image.Image.DockerImageReference) + if image.Image == nil { + t.Errorf("unexpected nil image: %#v", image) + } else { + // the image name is always the sha256, and size is calculated + if image.Image.Name != busyboxDigest || image.Image.DockerImageMetadata.Size != 669049 { + t.Errorf("unexpected image %d: %#v (size %d)", i, image.Image.Name, image.Image.DockerImageMetadata.Size) + } + // the most specific reference is returned + if image.Image.DockerImageReference != "test@"+busyboxDigest { + t.Errorf("unexpected ref %d: %#v", i, image.Image.DockerImageReference) + } } if image.Tag != expectedTags[i] { t.Errorf("unexpected tag of status %d (%s != %s)", i, image.Tag, expectedTags[i]) @@ -392,14 +384,14 @@ func TestImport(t *testing.T) { name: "import repository with additional tags", retriever: &mockRetriever{ repo: &mockRepository{ - manifest: etcdManifestSchema1, + manifest: busyboxManifestSchema2, tags: map[string]string{ - "v1": "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", - "other": "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", - "v2": "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", - "3": "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", - "3.1": "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", - "abc": "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", + "v1": busyboxDigest, + "other": busyboxDigest, + "v2": busyboxDigest, + "3": busyboxDigest, + "3.1": busyboxDigest, + "abc": busyboxDigest, }, getTagErr: fmt.Errorf("no such tag"), getByTagErr: fmt.Errorf("no such manifest tag"), @@ -640,56 +632,6 @@ func TestImportFromMirror(t *testing.T) { }) } -const etcdManifest = ` -{ - "schemaVersion": 1, - "tag": "latest", - "name": "coreos/etcd", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:2560187847cadddef806eaf244b7755af247a9dbabb90ca953dd2703cf423766" - }, - { - "blobSum": "sha256:744b46d0ac8636c45870a03830d8d82c20b75fbfb9bc937d5e61005d23ad4cfe" - } - ], - "history": [ - { - "v1Compatibility": "{\"id\":\"fe50ac14986497fa6b5d2cc24feb4a561d01767bc64413752c0988cb70b0b8b9\",\"parent\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"created\":\"2015-12-30T22:29:13.967754365Z\",\"container\":\"c8d0f1a274b5f52fa5beb280775ef07cf18ec0f95e5ae42fbad01157e2614d42\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT \\u0026{[\\\"/etcd\\\"]}\"],\"Image\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/etcd\"],\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/etcd\"],\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\"}" - }, - { - "v1Compatibility": "{\"id\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"parent\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"created\":\"2015-12-30T22:29:13.504159783Z\",\"container\":\"080708d544f85052a46fab72e701b4358c1b96cb4b805a5b2d66276fc2aaf85d\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) EXPOSE 2379/tcp 2380/tcp 4001/tcp 7001/tcp\"],\"Image\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\"}" - }, - { - "v1Compatibility": "{\"id\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"parent\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"created\":\"2015-12-30T22:29:12.912813629Z\",\"container\":\"f28be899c9b8680d4cf8585e663ad20b35019db062526844e7cfef117ce9037f\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:e330b1da49d993059975e46560b3bd360691498b0f2f6e00f39fc160cf8d4ec3 in /\"],\"Image\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":13502144}" - }, - { - "v1Compatibility": "{\"id\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"created\":\"2015-12-30T22:29:12.346834862Z\",\"container\":\"1b97abade59e4b5b935aede236980a54fb500cd9ee5bd4323c832c6d7b3ffc6e\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:74912593c6783292c4520514f5cc9313acbd1da0f46edee0fdbed2a24a264d6f in /\"],\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":15141568}" - } - ], - "signatures": [ - { - "header": { - "alg": "RS256", - "jwk": { - "e": "AQAB", - "kty": "RSA", - "n": "yB40ou1GMvIxYs1jhxWaeoDiw3oa0_Q2UJThUPtArvO0tRzaun9FnSphhOEHIGcezfq95jy-3MN-FIjmsWgbPHY8lVDS38fF75aCw6qkholwqjmMtUIgPNYoMrg0rLUE5RRyJ84-hKf9Fk7V3fItp1mvCTGKaS3ze-y5dTTrfbNGE7qG638Dla2Fuz-9CNgRQj0JH54o547WkKJC-pG-j0jTDr8lzsXhrZC7lJas4yc-vpt3D60iG4cW_mkdtIj52ZFEgHZ56sUj7AhnNVly0ZP9W1hmw4xEHDn9WLjlt7ivwARVeb2qzsNdguUitcI5hUQNwpOVZ_O3f1rUIL_kRw" - } - }, - "protected": "eyJmb3JtYXRUYWlsIjogIkNuMCIsICJmb3JtYXRMZW5ndGgiOiA1OTI2LCAidGltZSI6ICIyMDE2LTAxLTAyVDAyOjAxOjMzWiJ9", - "signature": "DrQ43UWeit-thDoRGTCP0Gd2wL5K2ecyPhHo_au0FoXwuKODja0tfwHexB9ypvFWngk-ijXuwO02x3aRIZqkWpvKLxxzxwkrZnPSje4o_VrFU4z5zwmN8sJw52ODkQlW38PURIVksOxCrb0zRl87yTAAsUAJ_4UUPNltZSLnhwy-qPb2NQ8ghgsONcBxRQrhPFiWNkxDKZ3kjvzYyrXDxTcvwK3Kk_YagZ4rCOhH1B7mAdVSiSHIvvNV5grPshw_ipAoqL2iNMsxWxLjYZl9xSJQI2asaq3fvh8G8cZ7T-OahDUos_GyhnIj39C-9ouqdJqMUYFETqbzRCR6d36CpQ" - } - ] -}` - const busyboxDigest = "sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6" const busyboxManifest = `{ diff --git a/pkg/image/apiserver/internal/imageutil/helpers.go b/pkg/image/apiserver/internal/imageutil/helpers.go index 64eaa03cd5..a2b27b73a0 100644 --- a/pkg/image/apiserver/internal/imageutil/helpers.go +++ b/pkg/image/apiserver/internal/imageutil/helpers.go @@ -7,7 +7,6 @@ import ( "github.com/distribution/distribution/v3/manifest/manifestlist" "github.com/distribution/distribution/v3/manifest/ocischema" - "github.com/distribution/distribution/v3/manifest/schema1" "github.com/distribution/distribution/v3/manifest/schema2" godigest "github.com/opencontainers/go-digest" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -58,22 +57,6 @@ func InternalImageWithMetadata(image *imageapi.Image) error { } switch manifest.SchemaVersion { - case 1: - image.DockerImageManifestMediaType = schema1.MediaTypeManifest - - if len(manifest.History) == 0 { - // It should never have an empty history, but just in case. - return fmt.Errorf("the image %s (%s) has a schema 1 manifest, but it doesn't have history", image.Name, image.DockerImageReference) - } - - v1Metadata := dockerapi10.DockerV1CompatibilityImage{} - if err := json.Unmarshal([]byte(manifest.History[0].DockerV1Compatibility), &v1Metadata); err != nil { - return err - } - - if err := dockerapi10.Convert_DockerV1CompatibilityImage_to_image_DockerImage(&v1Metadata, &image.DockerImageMetadata); err != nil { - return err - } case 2: if manifest.MediaType != "" { image.DockerImageManifestMediaType = manifest.MediaType @@ -127,30 +110,6 @@ func fillImageLayers(image *imageapi.Image, manifest dockerapi10.DockerImageMani } switch manifest.SchemaVersion { - case 1: - if len(manifest.History) != len(manifest.FSLayers) { - return fmt.Errorf("the image %s (%s) has mismatched history and fslayer cardinality (%d != %d)", image.Name, image.DockerImageReference, len(manifest.History), len(manifest.FSLayers)) - } - - image.DockerImageLayers = make([]imageapi.ImageLayer, len(manifest.FSLayers)) - for i, obj := range manifest.History { - layer := manifest.FSLayers[i] - - var size dockerapi10.DockerV1CompatibilityImageSize - if err := json.Unmarshal([]byte(obj.DockerV1Compatibility), &size); err != nil { - size.Size = 0 - } - - // reverse order of the layers: in schema1 manifests the - // first layer is the youngest (base layers are at the - // end), but we want to store layers in the Image resource - // in order from the oldest to the youngest. - revidx := (len(manifest.History) - 1) - i // n-1, n-2, ..., 1, 0 - - image.DockerImageLayers[revidx].Name = layer.DockerBlobSum - image.DockerImageLayers[revidx].LayerSize = size.Size - image.DockerImageLayers[revidx].MediaType = schema1.MediaTypeManifestLayer - } case 2: // The layer list is ordered starting from the base image (opposite order of schema1). // So, we do not need to change the order of layers. @@ -182,8 +141,6 @@ func reorderImageLayers(image *imageapi.Image) { layersOrder, ok := image.Annotations[imagev1.DockerImageLayersOrderAnnotation] if !ok { switch image.DockerImageManifestMediaType { - case schema1.MediaTypeManifest, schema1.MediaTypeSignedManifest: - layersOrder = imagev1.DockerImageLayersOrderAscending case schema2.MediaTypeManifest, imgspecv1.MediaTypeImageManifest: layersOrder = imagev1.DockerImageLayersOrderDescending default: @@ -232,12 +189,6 @@ func ManifestMatchesImage(image *imageapi.Image, newManifest []byte) (bool, erro if err != nil { return false, err } - case schema1.MediaTypeManifest, "": - var m schema1.SignedManifest - if err := json.Unmarshal(newManifest, &m); err != nil { - return false, err - } - canonical = m.Canonical default: return false, fmt.Errorf("unsupported manifest mediatype: %s", image.DockerImageManifestMediaType) } diff --git a/pkg/image/apiserver/internal/imageutil/helpers_test.go b/pkg/image/apiserver/internal/imageutil/helpers_test.go index 0cdb8b7263..6bfad4700d 100644 --- a/pkg/image/apiserver/internal/imageutil/helpers_test.go +++ b/pkg/image/apiserver/internal/imageutil/helpers_test.go @@ -6,10 +6,10 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/diff" coreapi "k8s.io/kubernetes/pkg/apis/core" - kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" imagev1 "github.com/openshift/api/image/v1" imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" @@ -41,14 +41,8 @@ func TestImageWithMetadata(t *testing.T) { }, expectError: true, }, - "error unmarshalling v1 compat": { - image: imageapi.Image{ - DockerImageManifest: "{\"name\": \"library/ubuntu\", \"tag\": \"latest\", \"history\": [\"v1Compatibility\": \"{ not valid {{ json\" }", - }, - expectError: true, - }, - "happy path": { - image: validImageWithManifestData(), + "happy path schema v2": { + image: validImageWithManifestV2Data(), expectedImage: imageapi.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "id", @@ -56,23 +50,27 @@ func TestImageWithMetadata(t *testing.T) { imagev1.DockerImageLayersOrderAnnotation: imagev1.DockerImageLayersOrderAscending, }, }, - DockerImageManifest: validImageWithManifestData().DockerImageManifest, + DockerImageConfig: validImageWithManifestV2Data().DockerImageConfig, + DockerImageManifest: validImageWithManifestV2Data().DockerImageManifest, + DockerImageManifestMediaType: "application/vnd.docker.distribution.manifest.v2+json", DockerImageLayers: []imageapi.ImageLayer{ - {Name: "tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", MediaType: "application/vnd.docker.container.image.rootfs.diff+x-gtar", LayerSize: 0}, - {Name: "tarsum.dev+sha256:2aaacc362ac6be2b9e9ae8c6029f6f616bb50aec63746521858e47841b90fabd", MediaType: "application/vnd.docker.container.image.rootfs.diff+x-gtar", LayerSize: 188097705}, - {Name: "tarsum.dev+sha256:c937c4bb1c1a21cc6d94340812262c6472092028972ae69b551b1a70d4276171", MediaType: "application/vnd.docker.container.image.rootfs.diff+x-gtar", LayerSize: 194533}, - {Name: "tarsum.dev+sha256:b194de3772ebbcdc8f244f663669799ac1cb141834b7cb8b69100285d357a2b0", MediaType: "application/vnd.docker.container.image.rootfs.diff+x-gtar", LayerSize: 1895}, - {Name: "tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", MediaType: "application/vnd.docker.container.image.rootfs.diff+x-gtar", LayerSize: 0}, + {Name: "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 5312}, + {Name: "sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 235231}, + {Name: "sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 235231}, + {Name: "sha256:b4ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 639152}, }, - DockerImageManifestMediaType: "application/vnd.docker.distribution.manifest.v1+json", DockerImageMetadata: imageapi.DockerImage{ - ID: "2d24f826cb16146e2016ff349a8a33ed5830f3b938d45c0f82943f4ab8c097e7", - Parent: "117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c", - Comment: "", - Created: metav1.Date(2015, 2, 21, 2, 11, 6, 735146646, time.UTC), - Container: "c9a3eda5951d28aa8dbe5933be94c523790721e4f80886d0a8e7a710132a38ec", + ID: "sha256:815d06b56f4138afacd0009b8e3799fcdce79f0507bf8d0588e219b93ab6fd4d", + Parent: "", + Comment: "", + Created: metav1.Date(2015, 2, 21, 2, 11, 6, 735146646, time.UTC), + Container: "e91032eb0403a61bfe085ff5a5a48e3659e5a6deae9f4d678daa2ae399d5a001", + DockerVersion: "1.9.0-dev", + Author: "", + Architecture: "amd64", + Size: 882848, ContainerConfig: imageapi.DockerConfig{ - Hostname: "43bd710ec89a", + Hostname: "23304fc829f9", Domainname: "", User: "", Memory: 0, @@ -87,20 +85,19 @@ func TestImageWithMetadata(t *testing.T) { Tty: false, OpenStdin: false, StdinOnce: false, - Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, - Cmd: []string{"/bin/sh", "-c", "#(nop) CMD [/bin/bash]"}, - Image: "117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c", + Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "derived=true", "asdf=true"}, + Cmd: []string{"/bin/sh", "-c", "#(nop) CMD [\"/bin/sh\" \"-c\" \"echo hi\"]"}, + Image: "sha256:4ab15c48b859c2920dd5224f92aabcd39a52794c5b3cf088fb3bbb438756c246", Volumes: nil, WorkingDir: "", Entrypoint: nil, NetworkDisabled: false, SecurityOpts: nil, OnBuild: []string{}, + Labels: map[string]string{}, }, - DockerVersion: "1.4.1", - Author: "", Config: &imageapi.DockerConfig{ - Hostname: "43bd710ec89a", + Hostname: "23304fc829f9", Domainname: "", User: "", Memory: 0, @@ -115,22 +112,21 @@ func TestImageWithMetadata(t *testing.T) { Tty: false, OpenStdin: false, StdinOnce: false, - Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, - Cmd: []string{"/bin/bash"}, - Image: "117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c", + Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "derived=true", "asdf=true"}, + Cmd: []string{"/bin/sh", "-c", "echo hi"}, + Image: "sha256:4ab15c48b859c2920dd5224f92aabcd39a52794c5b3cf088fb3bbb438756c246", Volumes: nil, WorkingDir: "", Entrypoint: nil, NetworkDisabled: false, OnBuild: []string{}, + Labels: map[string]string{}, }, - Architecture: "amd64", - Size: 188294133, }, }, }, - "valid metadata size": { - image: validImageWithManifestV2Data(), + "happy path OCI": { + image: validImageWithManifestOCIData(), expectedImage: imageapi.Image{ ObjectMeta: metav1.ObjectMeta{ Name: "id", @@ -138,27 +134,28 @@ func TestImageWithMetadata(t *testing.T) { imagev1.DockerImageLayersOrderAnnotation: imagev1.DockerImageLayersOrderAscending, }, }, - DockerImageConfig: validImageWithManifestV2Data().DockerImageConfig, - DockerImageManifest: validImageWithManifestV2Data().DockerImageManifest, - DockerImageManifestMediaType: "application/vnd.docker.distribution.manifest.v2+json", + DockerImageConfig: validImageWithManifestOCIData().DockerImageConfig, + DockerImageManifest: validImageWithManifestOCIData().DockerImageManifest, + DockerImageManifestMediaType: "application/vnd.oci.image.manifest.v1+json", DockerImageLayers: []imageapi.ImageLayer{ - {Name: "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 5312}, - {Name: "sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 235231}, - {Name: "sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 235231}, - {Name: "sha256:b4ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4", MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", LayerSize: 639152}, + { + Name: "sha256:d9d352c11bbd3880007953ed6eec1cbace76898828f3434984a0ca60672fdf5a", + LayerSize: 29715337, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, }, DockerImageMetadata: imageapi.DockerImage{ - ID: "sha256:815d06b56f4138afacd0009b8e3799fcdce79f0507bf8d0588e219b93ab6fd4d", + ID: "sha256:bf16bdcff9c96b76a6d417bd8f0a3abe0e55c0ed9bdb3549e906834e2592fd5f", Parent: "", Comment: "", - Created: metav1.Date(2015, 2, 21, 2, 11, 6, 735146646, time.UTC), - Container: "e91032eb0403a61bfe085ff5a5a48e3659e5a6deae9f4d678daa2ae399d5a001", - DockerVersion: "1.9.0-dev", + Created: metav1.Date(2025, 5, 29, 4, 21, 1, 971275965, time.UTC), + Container: "57d2303e19c80641e487894fdb01e8e26ab42726f45e72624efe9d812e1c8889", + DockerVersion: "24.0.7", Author: "", Architecture: "amd64", - Size: 882848, + Size: 29718508, ContainerConfig: imageapi.DockerConfig{ - Hostname: "23304fc829f9", + Hostname: "57d2303e19c8", Domainname: "", User: "", Memory: 0, @@ -173,18 +170,22 @@ func TestImageWithMetadata(t *testing.T) { Tty: false, OpenStdin: false, StdinOnce: false, - Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "derived=true", "asdf=true"}, - Cmd: []string{"/bin/sh", "-c", "#(nop) CMD [\"/bin/sh\" \"-c\" \"echo hi\"]"}, - Image: "sha256:4ab15c48b859c2920dd5224f92aabcd39a52794c5b3cf088fb3bbb438756c246", + Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, + Cmd: []string{"/bin/sh", "-c", "#(nop) ", `CMD ["/bin/bash"]`}, + Image: "sha256:825befda5d2b1a76b71f4e1d6d31f5d82d4488b8337b1ad42e29b1340d766647", Volumes: nil, WorkingDir: "", Entrypoint: nil, NetworkDisabled: false, SecurityOpts: nil, - OnBuild: []string{}, + OnBuild: nil, + Labels: map[string]string{ + "org.opencontainers.image.ref.name": "ubuntu", + "org.opencontainers.image.version": "24.04", + }, }, Config: &imageapi.DockerConfig{ - Hostname: "23304fc829f9", + Hostname: "", Domainname: "", User: "", Memory: 0, @@ -199,14 +200,112 @@ func TestImageWithMetadata(t *testing.T) { Tty: false, OpenStdin: false, StdinOnce: false, - Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "derived=true", "asdf=true"}, - Cmd: []string{"/bin/sh", "-c", "echo hi"}, - Image: "sha256:4ab15c48b859c2920dd5224f92aabcd39a52794c5b3cf088fb3bbb438756c246", + Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, + Cmd: []string{"/bin/bash"}, + Image: "sha256:825befda5d2b1a76b71f4e1d6d31f5d82d4488b8337b1ad42e29b1340d766647", Volumes: nil, WorkingDir: "", Entrypoint: nil, NetworkDisabled: false, - OnBuild: []string{}, + OnBuild: nil, + Labels: map[string]string{ + "org.opencontainers.image.ref.name": "ubuntu", + "org.opencontainers.image.version": "24.04", + }, + }, + }, + }, + }, + "happy path OCI multiple layers": { + image: validImageWithManifestOCIDataMultipleLayers(), + expectedImage: imageapi.Image{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sha256:99a93c48631257c32751cc64aaa73adc2bcc1e95ef5011d975f71a04b970646b", + Annotations: map[string]string{ + imagev1.DockerImageLayersOrderAnnotation: imagev1.DockerImageLayersOrderAscending, + }, + }, + DockerImageConfig: validImageWithManifestOCIDataMultipleLayers().DockerImageConfig, + DockerImageManifest: validImageWithManifestOCIDataMultipleLayers().DockerImageManifest, + DockerImageManifestMediaType: "application/vnd.oci.image.manifest.v1+json", + DockerImageLayers: []imageapi.ImageLayer{ + { + Name: "sha256:0c01110621e0ec1eded421406c9f117f7ae5486c8f7b0a0d1a37cc7bc9317226", + LayerSize: 48494272, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, + { + Name: "sha256:3b1eb73e993990490aa137c00e60ff4ca9d1715bafb8e888dbb0986275edb13f", + LayerSize: 24015708, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, + { + Name: "sha256:b1b8a0660a31403a35d70b276c3c86b1200b8683e83cd77a92ec98744017684a", + LayerSize: 64399794, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, + { + Name: "sha256:420c602e8633734081b143b180e927a7c4b2993e514b8b19d91b935983d0dc88", + LayerSize: 92355229, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, + { + Name: "sha256:a8f67fead7e33763b5fa924cb2e4644bbf5332ed056eb32ba0bcd3bdb68eea3b", + LayerSize: 78981811, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, + { + Name: "sha256:1f64d3b080beb286622037cab1eea6b66361f7824c5935c00e96deac1a3dadbc", + LayerSize: 125, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, + { + Name: "sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1", + LayerSize: 32, + MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", + }, + }, + DockerImageMetadata: imageapi.DockerImage{ + ID: "sha256:99a93c48631257c32751cc64aaa73adc2bcc1e95ef5011d975f71a04b970646b", + Parent: "", + Comment: "", + Created: metav1.Date(2025, 6, 5, 18, 53, 13, 0, time.UTC), + Container: "", + DockerVersion: "", + Author: "", + Architecture: "amd64", + Size: 308250765, + ContainerConfig: imageapi.DockerConfig{}, + Config: &imageapi.DockerConfig{ + Hostname: "", + Domainname: "", + User: "", + Memory: 0, + MemorySwap: 0, + CPUShares: 0, + CPUSet: "", + AttachStdin: false, + AttachStdout: false, + AttachStderr: false, + PortSpecs: nil, + ExposedPorts: nil, + Tty: false, + OpenStdin: false, + StdinOnce: false, + Env: []string{ + "PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "GOLANG_VERSION=1.24.4", + "GOTOOLCHAIN=local", + "GOPATH=/go", + }, + Cmd: []string{"bash"}, + Image: "", + Volumes: nil, + WorkingDir: "/go", + Entrypoint: nil, + NetworkDisabled: false, + OnBuild: nil, + Labels: nil, }, }, }, @@ -224,8 +323,8 @@ func TestImageWithMetadata(t *testing.T) { if test.expectError { return } - if e, a := test.expectedImage, imageWithMetadata; !kapihelper.Semantic.DeepEqual(e, a) { - t.Errorf("image: %s", diff.ObjectDiff(e, a)) + if e, a := test.expectedImage, imageWithMetadata; !cmp.Equal(e, a) { + t.Errorf("image: %s", cmp.Diff(e, a)) } }) } @@ -248,70 +347,6 @@ func TestImageWithMetadataWithManifestList(t *testing.T) { } } -func validImageWithManifestData() imageapi.Image { - return imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{ - Name: "id", - }, - DockerImageManifest: `{ - "name": "library/ubuntu", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - }, - { - "blobSum": "tarsum.dev+sha256:b194de3772ebbcdc8f244f663669799ac1cb141834b7cb8b69100285d357a2b0" - }, - { - "blobSum": "tarsum.dev+sha256:c937c4bb1c1a21cc6d94340812262c6472092028972ae69b551b1a70d4276171" - }, - { - "blobSum": "tarsum.dev+sha256:2aaacc362ac6be2b9e9ae8c6029f6f616bb50aec63746521858e47841b90fabd" - }, - { - "blobSum": "tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - } - ], - "history": [ - { - "v1Compatibility": "{\"id\":\"2d24f826cb16146e2016ff349a8a33ed5830f3b938d45c0f82943f4ab8c097e7\",\"parent\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"created\":\"2015-02-21T02:11:06.735146646Z\",\"container\":\"c9a3eda5951d28aa8dbe5933be94c523790721e4f80886d0a8e7a710132a38ec\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [/bin/bash]\"],\"Image\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"Size\":0}\n" - }, - { - "v1Compatibility": "{\"id\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"parent\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"created\":\"2015-02-21T02:11:02.473113442Z\",\"container\":\"b4d4c42c196081cdb8e032446e9db92c0ce8ddeeeb1ef4e582b0275ad62b9af2\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"sed -i 's/^#\\\\s*\\\\(deb.*universe\\\\)$/\\\\1/g' /etc/apt/sources.list\"],\"Image\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:b194de3772ebbcdc8f244f663669799ac1cb141834b7cb8b69100285d357a2b0\",\"Size\":1895}\n" - }, - { - "v1Compatibility": "{\"id\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"parent\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"created\":\"2015-02-21T02:10:56.648624065Z\",\"container\":\"d6323d4f92bf13dd2a7d2957e8970c8dc8ba3c2df08ffebdf4a04b4b658c83fb\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"echo '#!/bin/sh' \\u003e /usr/sbin/policy-rc.d \\u0009\\u0026\\u0026 echo 'exit 101' \\u003e\\u003e /usr/sbin/policy-rc.d \\u0009\\u0026\\u0026 chmod +x /usr/sbin/policy-rc.d \\u0009\\u0009\\u0026\\u0026 dpkg-divert --local --rename --add /sbin/initctl \\u0009\\u0026\\u0026 cp -a /usr/sbin/policy-rc.d /sbin/initctl \\u0009\\u0026\\u0026 sed -i 's/^exit.*/exit 0/' /sbin/initctl \\u0009\\u0009\\u0026\\u0026 echo 'force-unsafe-io' \\u003e /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \\u0009\\u0009\\u0026\\u0026 echo 'DPkg::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e /etc/apt/apt.conf.d/docker-clean \\u0009\\u0026\\u0026 echo 'APT::Update::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\u0009\\u0026\\u0026 echo 'Dir::Cache::pkgcache \\\"\\\"; Dir::Cache::srcpkgcache \\\"\\\";' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\u0009\\u0009\\u0026\\u0026 echo 'Acquire::Languages \\\"none\\\";' \\u003e /etc/apt/apt.conf.d/docker-no-languages \\u0009\\u0009\\u0026\\u0026 echo 'Acquire::GzipIndexes \\\"true\\\"; Acquire::CompressionTypes::Order:: \\\"gz\\\";' \\u003e /etc/apt/apt.conf.d/docker-gzip-indexes\"],\"Image\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:c937c4bb1c1a21cc6d94340812262c6472092028972ae69b551b1a70d4276171\",\"Size\":194533}\n" - }, - { - "v1Compatibility": "{\"id\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"parent\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"created\":\"2015-02-21T02:10:48.627646094Z\",\"container\":\"43bd710ec89aa1d61685c5ddb8737b315f2152d04c9e127ea2a9cf79f950fa5d\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:0018ff77d038472f52512fd66ae2466e6325e5d91289e10a6b324f40582298df in /\"],\"Image\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:2aaacc362ac6be2b9e9ae8c6029f6f616bb50aec63746521858e47841b90fabd\",\"Size\":188097705}\n" - }, - { - "v1Compatibility": "{\"id\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"comment\":\"Imported from -\",\"created\":\"2013-06-13T14:03:50.821769-07:00\",\"container_config\":{\"Hostname\":\"\",\"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\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null},\"docker_version\":\"0.4.0\",\"architecture\":\"x86_64\",\"checksum\":\"tarsum.dev+sha256:324d4cf44ee7daa46266c1df830c61a7df615c0632176a339e7310e34723d67a\",\"Size\":0}\n" - } - ], - "schemaVersion": 1, - "signatures": [ - { - "header": { - "jwk": { - "crv": "P-256", - "kid": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4", - "kty": "EC", - "x": "Cu_UyxwLgHzE9rvlYSmvVdqYCXY42E9eNhBb0xNv0SQ", - "y": "zUsjWJkeKQ5tv7S-hl1Tg71cd-CqnrtiiLxSi6N_yc8" - }, - "alg": "ES256" - }, - "signature": "JafVC022gLJbK8fEp9UrW-GWAi53nD4Xf0-fmb766nV6zGTq7g9RutSWHcpv3OqhV8t5b-4j-bXhvnGBjXA7Yg", - "protected": "eyJmb3JtYXRMZW5ndGgiOjEwMDc2LCJmb3JtYXRUYWlsIjoiQ24wIiwidGltZSI6IjIwMTUtMDMtMDdUMTI6Mzk6MjJaIn0" - } - ] -}`, - } -} - func validImageWithManifestV2Data() imageapi.Image { return imageapi.Image{ ObjectMeta: metav1.ObjectMeta{ @@ -449,6 +484,283 @@ func validImageWithManifestV2Data() imageapi.Image { } } +func validImageWithManifestOCIData() imageapi.Image { + return imageapi.Image{ + ObjectMeta: metav1.ObjectMeta{ + Name: "id", + }, + DockerImageConfig: `{ + "architecture": "amd64", + "config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/bash" + ], + "Image": "sha256:825befda5d2b1a76b71f4e1d6d31f5d82d4488b8337b1ad42e29b1340d766647", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": { + "org.opencontainers.image.ref.name": "ubuntu", + "org.opencontainers.image.version": "24.04" + } + }, + "container": "57d2303e19c80641e487894fdb01e8e26ab42726f45e72624efe9d812e1c8889", + "container_config": { + "Hostname": "57d2303e19c8", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ", + "CMD [\"/bin/bash\"]" + ], + "Image": "sha256:825befda5d2b1a76b71f4e1d6d31f5d82d4488b8337b1ad42e29b1340d766647", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": { + "org.opencontainers.image.ref.name": "ubuntu", + "org.opencontainers.image.version": "24.04" + } + }, + "created": "2025-05-29T04:21:01.971275965Z", + "docker_version": "24.0.7", + "history": [ + { + "created": "2025-05-29T04:20:59.390476489Z", + "created_by": "/bin/sh -c #(nop) ARG RELEASE", + "empty_layer": true + }, + { + "created": "2025-05-29T04:20:59.425928067Z", + "created_by": "/bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH", + "empty_layer": true + }, + { + "created": "2025-05-29T04:20:59.461048974Z", + "created_by": "/bin/sh -c #(nop) LABEL org.opencontainers.image.ref.name=ubuntu", + "empty_layer": true + }, + { + "created": "2025-05-29T04:20:59.498669132Z", + "created_by": "/bin/sh -c #(nop) LABEL org.opencontainers.image.version=24.04", + "empty_layer": true + }, + { + "created": "2025-05-29T04:21:01.6549815Z", + "created_by": "/bin/sh -c #(nop) ADD file:598ca0108009b5c2e9e6f4fc4bd19a6bcd604fccb5b9376fac14a75522a5cfa3 in / " + }, + { + "created": "2025-05-29T04:21:01.971275965Z", + "created_by": "/bin/sh -c #(nop) CMD [\"/bin/bash\"]", + "empty_layer": true + } + ], + "os": "linux", + "rootfs": { + "type": "layers", + "diff_ids": [ + "sha256:a8346d259389bc6221b4f3c61bad4e48087c5b82308e8f53ce703cfc8333c7b3" + ] + } +}`, + DockerImageManifest: `{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "config": { + "mediaType": "application/vnd.oci.image.config.v1+json", + "size": 2295, + "digest": "sha256:bf16bdcff9c96b76a6d417bd8f0a3abe0e55c0ed9bdb3549e906834e2592fd5f" + }, + "layers": [ + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "size": 29715337, + "digest": "sha256:d9d352c11bbd3880007953ed6eec1cbace76898828f3434984a0ca60672fdf5a" + } + ] +}`, + } +} + +func validImageWithManifestOCIDataMultipleLayers() imageapi.Image { + return imageapi.Image{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sha256:99a93c48631257c32751cc64aaa73adc2bcc1e95ef5011d975f71a04b970646b", + }, + DockerImageConfig: `{ + "architecture": "amd64", + "config": { + "Env": [ + "PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "GOLANG_VERSION=1.24.4", + "GOTOOLCHAIN=local", + "GOPATH=/go" + ], + "Cmd": [ + "bash" + ], + "WorkingDir": "/go" + }, + "created": "2025-06-05T18:53:13Z", + "history": [ + { + "created": "2023-05-10T23:29:59Z", + "created_by": "# debian.sh --arch 'amd64' out/ 'bookworm' '@1749513600'", + "comment": "debuerreotype 0.15" + }, + { + "created": "2023-05-10T23:29:59Z", + "created_by": "RUN /bin/sh -c set -eux; \tapt-get update; \tapt-get install -y --no-install-recommends \t\tca-certificates \t\tcurl \t\tgnupg \t\tnetbase \t\tsq \t\twget \t; \trm -rf /var/lib/apt/lists/* # buildkit", + "comment": "buildkit.dockerfile.v0" + }, + { + "created": "2024-01-09T01:14:25Z", + "created_by": "RUN /bin/sh -c set -eux; \tapt-get update; \tapt-get install -y --no-install-recommends \t\tgit \t\tmercurial \t\topenssh-client \t\tsubversion \t\t\t\tprocps \t; \trm -rf /var/lib/apt/lists/* # buildkit", + "comment": "buildkit.dockerfile.v0" + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "RUN /bin/sh -c set -eux; \tapt-get update; \tapt-get install -y --no-install-recommends \t\tg++ \t\tgcc \t\tlibc6-dev \t\tmake \t\tpkg-config \t; \trm -rf /var/lib/apt/lists/* # buildkit", + "comment": "buildkit.dockerfile.v0" + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "ENV GOLANG_VERSION=1.24.4", + "comment": "buildkit.dockerfile.v0", + "empty_layer": true + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "ENV GOTOOLCHAIN=local", + "comment": "buildkit.dockerfile.v0", + "empty_layer": true + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "ENV GOPATH=/go", + "comment": "buildkit.dockerfile.v0", + "empty_layer": true + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "ENV PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "comment": "buildkit.dockerfile.v0", + "empty_layer": true + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "COPY /target/ / # buildkit", + "comment": "buildkit.dockerfile.v0" + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "RUN /bin/sh -c mkdir -p \"$GOPATH/src\" \"$GOPATH/bin\" && chmod -R 1777 \"$GOPATH\" # buildkit", + "comment": "buildkit.dockerfile.v0" + }, + { + "created": "2025-06-05T18:53:13Z", + "created_by": "WORKDIR /go", + "comment": "buildkit.dockerfile.v0" + } + ], + "os": "linux", + "rootfs": { + "type": "layers", + "diff_ids": [ + "sha256:8f003894a7efc4178494f1e133497ed2f325ae53b6a65869e54c04d1c51d588f", + "sha256:f5b8fb1def00d5f185660b75bac1eed1fce467d44cebd868dae2f344711321ef", + "sha256:1c49688bd8ebe54298be2b61f7d5efd32467862f115b5439b87c19e56e57c6b4", + "sha256:c291adf4681b803d1a3fdd12233811fb566c89cf1d423bd62f853d35aeb2c32f", + "sha256:86d0740ea51f822cea0316cc9b0aaf705545175ab281342f460f0f14e8742502", + "sha256:7c5761aef9e0522152cc129c12b38d65073013ae75888975e1b8469556f3af70", + "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" + ] + } +}`, + DockerImageManifest: `{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "config": { + "mediaType": "application/vnd.oci.image.config.v1+json", + "digest": "sha256:99a93c48631257c32751cc64aaa73adc2bcc1e95ef5011d975f71a04b970646b", + "size": 2803 + }, + "layers": [ + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:0c01110621e0ec1eded421406c9f117f7ae5486c8f7b0a0d1a37cc7bc9317226", + "size": 48494272 + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:3b1eb73e993990490aa137c00e60ff4ca9d1715bafb8e888dbb0986275edb13f", + "size": 24015708 + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:b1b8a0660a31403a35d70b276c3c86b1200b8683e83cd77a92ec98744017684a", + "size": 64399794 + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:420c602e8633734081b143b180e927a7c4b2993e514b8b19d91b935983d0dc88", + "size": 92355229 + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:a8f67fead7e33763b5fa924cb2e4644bbf5332ed056eb32ba0bcd3bdb68eea3b", + "size": 78981811 + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:1f64d3b080beb286622037cab1eea6b66361f7824c5935c00e96deac1a3dadbc", + "size": 125 + }, + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", + "digest": "sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1", + "size": 32 + } + ], + "annotations": { + "com.docker.official-images.bashbrew.arch": "amd64", + "org.opencontainers.image.base.digest": "sha256:fab1b6389a07a117b06169a1c2bc5a4a3d3f5d7315dea5ebf4d7ad49606d7f32", + "org.opencontainers.image.base.name": "buildpack-deps:bookworm-scm", + "org.opencontainers.image.created": "2025-06-05T18:53:13Z", + "org.opencontainers.image.revision": "205cf586b0d0c7200e0fd642feaf738ddb382da0", + "org.opencontainers.image.source": "https://github.com/docker-library/golang.git#205cf586b0d0c7200e0fd642feaf738ddb382da0:1.24/bookworm", + "org.opencontainers.image.url": "https://hub.docker.com/_/golang", + "org.opencontainers.image.version": "1.24.4-bookworm" + } +}`, + } +} + func validImageWithManifestListData() imageapi.Image { return imageapi.Image{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/image/apiserver/internal/testutil/image.go b/pkg/image/apiserver/internal/testutil/image.go new file mode 100644 index 0000000000..ebb61e9411 --- /dev/null +++ b/pkg/image/apiserver/internal/testutil/image.go @@ -0,0 +1,69 @@ +package testutil + +import ( + imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" + "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/imageutil" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// kindest/node:v1.33.1 +// manifest digest: sha256:14ffd6ee8a3daa20cc934ba786626b181e1797268c5465f2c299a7cf54494c77` + +// KindestManifest is the kindest/node manifest JSON. +const KindestManifest = `{ + "schemaVersion": 2, + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "config": { + "mediaType": "application/vnd.docker.container.image.v1+json", + "size": 1984, + "digest": "sha256:d6b20550c77b11385dd30115ba29dbf9a9bfc98c2f28ff7d162a6ad7c9686251" + }, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 132852852, + "digest": "sha256:dc42dfa52495c90dc5b99c19534d6d4fa9cd37fa439356fcbd73e770c35f2293" + }, + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 318908736, + "digest": "sha256:841483099b542d6aeafc6ffacd59617954c409d3ebc558b7a95f43e05b1701a1" + } + ] +}` + +// KindestConfigDigest is the kindest/node config digest. +const KindestConfigDigest = `sha256:d6b20550c77b11385dd30115ba29dbf9a9bfc98c2f28ff7d162a6ad7c9686251` + +// KindestConfig is the kindest/node config JSON blob. +const KindestConfig = `{"architecture":"amd64","config":{"Hostname":"5e7483a6cf0e","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","container=docker","HTTP_PROXY=","HTTPS_PROXY=","NO_PROXY="],"Cmd":null,"Image":"docker.io/kindest/base:v20250521-31a79fd4","Volumes":null,"WorkingDir":"/","Entrypoint":["/usr/local/bin/entrypoint","/sbin/init"],"OnBuild":null,"Labels":{},"StopSignal":"SIGRTMIN+3"},"container":"5e7483a6cf0e7958e796eee6912d1f6247394a0b914c822e47c7596b54aeac0a","container_config":{"Hostname":"5e7483a6cf0e","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","container=docker"],"Cmd":["infinity"],"Image":"docker.io/kindest/base:v20250521-31a79fd4","Volumes":null,"WorkingDir":"/","Entrypoint":["sleep"],"OnBuild":null,"Labels":{},"StopSignal":"SIGRTMIN+3"},"created":"2025-05-21T01:04:14.093628812Z","docker_version":"20.10.21","history":[{"created":"2025-05-21T00:57:52.347930888Z","created_by":"COPY / / # buildkit","comment":"buildkit.dockerfile.v0"},{"created":"2025-05-21T00:57:52.347930888Z","created_by":"ENV container=docker","comment":"buildkit.dockerfile.v0","empty_layer":true},{"created":"2025-05-21T00:57:52.347930888Z","created_by":"STOPSIGNAL SIGRTMIN+3","comment":"buildkit.dockerfile.v0","empty_layer":true},{"created":"2025-05-21T00:57:52.347930888Z","created_by":"ENTRYPOINT [\"/usr/local/bin/entrypoint\" \"/sbin/init\"]","comment":"buildkit.dockerfile.v0","empty_layer":true},{"created":"2025-05-21T01:04:14.093628812Z","created_by":"infinity"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:f13bb3f5a0b612fa8b3ee54536cff9a57cc76a084b6a399d7762283e52393778","sha256:2f6a2492037574ad66c92893c0d266ff1a74dbab0eeed7771c511a09f909b577"]}}` + +// KindestBareImage returns a kindest/node image without metadata and layers. +func KindestBareImage(hooks ...func(*imageapi.Image)) *imageapi.Image { + img := &imageapi.Image{ + ObjectMeta: metav1.ObjectMeta{ + Name: KindestConfigDigest, + GenerateName: "kindest", + }, + DockerImageReference: "kindest/node:v1.33.1", + DockerImageManifestMediaType: "application/vnd.docker.distribution.manifest.v2+json", + DockerImageManifest: KindestManifest, + DockerImageConfig: KindestConfig, + } + for _, hook := range hooks { + hook(img) + } + return img +} + +// MustKindestCompleteImage returns a kindest/node image fully filled in. +func MustKindestCompleteImage(hooks ...func(*imageapi.Image)) *imageapi.Image { + img := KindestBareImage() + for _, hook := range hooks { + hook(img) + } + if err := imageutil.InternalImageWithMetadata(img); err != nil { + panic(err) + } + return img +} diff --git a/pkg/image/apiserver/internal/testutil/util.go b/pkg/image/apiserver/internal/testutil/util.go new file mode 100644 index 0000000000..5f40f86e7c --- /dev/null +++ b/pkg/image/apiserver/internal/testutil/util.go @@ -0,0 +1,167 @@ +package testutil + +import ( + "fmt" +) + +// InternalRegistryURL is an url of internal container image registry for testing purposes. +const InternalRegistryURL = "172.30.12.34:5000" + +// MakeDockerImageReference makes a container image reference string referencing testing internal docker +// registry. +func MakeDockerImageReference(ns, isName, imageID string) string { + return fmt.Sprintf("%s/%s/%s@%s", InternalRegistryURL, ns, isName, imageID) +} + +// BaseImageWith1Layer contains a single layer. +const BaseImageWith1Layer = `{ + "schemaVersion": 2, + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "config": { + "mediaType": "application/vnd.docker.container.image.v1+json", + "size": 1512, + "digest": "sha256:6c6084ed97e5851b5d216b20ed1852301278584c3c6aff915272b231593f6f98" + }, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 1970140, + "digest": "sha256:550fe1bea624a5c62551cf09f3aa10886eed133794844af1dfb775118309387e" + } + ] +}` + +// BaseImageWith1LayerDigest is the digest associated with BaseImageWith1Layer. +// +// This is actually docksal/empty. +const BaseImageWith1LayerDigest = `sha256:f853843b26903da94dd1cdf9e39ff7e2ba7a754388341895d557dbe913f5a915` + +// BaseImageWith1LayerConfig is the config associated with BaseImageWith1Layer. +const BaseImageWith1LayerConfig = `{ + "architecture": "amd64", + "config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh" + ], + "ArgsEscaped": true, + "Image": "sha256:01b85c6717c3b1f5379864199c541cecabb81be758b4fec6ef0b66cbfb6e11a5", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": null + }, + "container": "f8a4df32c288f30c6d641c3945c88b64490e1e029be516209955023786cf1727", + "container_config": { + "Hostname": "f8a4df32c288", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ", + "CMD [\"/bin/sh\"]" + ], + "ArgsEscaped": true, + "Image": "sha256:01b85c6717c3b1f5379864199c541cecabb81be758b4fec6ef0b66cbfb6e11a5", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": {} + }, + "created": "2018-01-09T21:13:01.402230769Z", + "docker_version": "17.06.2-ce", + "history": [ + { + "created": "2018-01-09T21:13:01.165340448Z", + "created_by": "/bin/sh -c #(nop) ADD file:df48d6d6df42a01380557aebd4ca02807fc08a76a1d1b36d957e59a41c69db0b in / " + }, + { + "created": "2018-01-09T21:13:01.402230769Z", + "created_by": "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", + "empty_layer": true + } + ], + "os": "linux", + "rootfs": { + "type": "layers", + "diff_ids": [ + "sha256:d39d92664027be502c35cf1bf464c726d15b8ead0e3084be6e252a161730bc82" + ] + } +}` + +// The following digests are actually random SHA256 hashes. + +const BaseImageWith2LayersDigest = "sha256:5bb720a64ecc8f5285cda9d899db4a79f2fc73b4533e4d7d7ffd9b7b6720c159" + +const ChildImageWith2LayersDigest = "sha256:4ec0a236b636e898d557205b01683560c07ce0edc949706c03e7cb2e7037093e" + +const ChildImageWith3LayersDigest = "sha256:9237f69ed1eb6221da9d28569669ae5e73173d6a67f88265726d2fad47e31df2" + +const MiscImageDigest = "sha256:e07072af8e05843efde5e4f2f23ee12b96029cf6d5685fa9f4cbc45f2196011e" + +const ManifestList = `{ + "manifests": [ + { + "digest": "sha256:96a76fa48db5fca24271fe1565d88a4453e759b365dbaaeeb5a4e41049293e77", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "amd64", + "os": "linux" + }, + "size": 429 + }, + { + "digest": "sha256:6c3d8fec1c50ff78997e13a8352b030d4b290f656081c974373753fd5a3496f1", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "arm64", + "os": "linux" + }, + "size": 429 + }, + { + "digest": "sha256:520a368f78807947b96ea773cc62b14e380f4af08bbfd8ed18f0ebc70dedef68", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "ppc64le", + "os": "linux" + }, + "size": 429 + }, + { + "digest": "sha256:50b0c55990fe1b48c4b026fb6b49b4377e36c52b291d434977793dc0c8998ba4", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "s390x", + "os": "linux" + }, + "size": 429 + } + ], + "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", + "schemaVersion": 2 +}` diff --git a/pkg/image/apiserver/registry/image/etcd/etcd_test.go b/pkg/image/apiserver/registry/image/etcd/etcd_test.go index 72ce047325..1501a486b6 100644 --- a/pkg/image/apiserver/registry/image/etcd/etcd_test.go +++ b/pkg/image/apiserver/registry/image/etcd/etcd_test.go @@ -17,6 +17,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" + "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/testutil" "github.com/openshift/openshift-apiserver/pkg/image/apiserver/registry/image" // install all APIs @@ -40,16 +41,6 @@ func TestStorage(t *testing.T) { image.NewRegistry(storage) } -func validImage() *imageapi.Image { - return &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - GenerateName: "foo", - }, - DockerImageReference: "openshift/origin", - } -} - func TestCreate(t *testing.T) { storage, server := newStorage(t) defer server.Terminate(t) @@ -146,300 +137,169 @@ func TestWatch(t *testing.T) { ) } -const etcdManifest = `{ - "schemaVersion": 1, - "tag": "latest", - "name": "coreos/etcd", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:2560187847cadddef806eaf244b7755af247a9dbabb90ca953dd2703cf423766" - }, - { - "blobSum": "sha256:744b46d0ac8636c45870a03830d8d82c20b75fbfb9bc937d5e61005d23ad4cfe" - } - ], - "history": [ - { - "v1Compatibility": "{\"id\":\"fe50ac14986497fa6b5d2cc24feb4a561d01767bc64413752c0988cb70b0b8b9\",\"parent\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"created\":\"2015-12-30T22:29:13.967754365Z\",\"container\":\"c8d0f1a274b5f52fa5beb280775ef07cf18ec0f95e5ae42fbad01157e2614d42\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT \\u0026{[\\\"/etcd\\\"]}\"],\"Image\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/etcd\"],\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/etcd\"],\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\"}" - }, - { - "v1Compatibility": "{\"id\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"parent\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"created\":\"2015-12-30T22:29:13.504159783Z\",\"container\":\"080708d544f85052a46fab72e701b4358c1b96cb4b805a5b2d66276fc2aaf85d\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) EXPOSE 2379/tcp 2380/tcp 4001/tcp 7001/tcp\"],\"Image\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\"}" - }, - { - "v1Compatibility": "{\"id\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"parent\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"created\":\"2015-12-30T22:29:12.912813629Z\",\"container\":\"f28be899c9b8680d4cf8585e663ad20b35019db062526844e7cfef117ce9037f\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:e330b1da49d993059975e46560b3bd360691498b0f2f6e00f39fc160cf8d4ec3 in /\"],\"Image\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":13502144}" - }, - { - "v1Compatibility": "{\"id\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"created\":\"2015-12-30T22:29:12.346834862Z\",\"container\":\"1b97abade59e4b5b935aede236980a54fb500cd9ee5bd4323c832c6d7b3ffc6e\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:74912593c6783292c4520514f5cc9313acbd1da0f46edee0fdbed2a24a264d6f in /\"],\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":15141568}" - } - ], - "signatures": [ - { - "header": { - "alg": "RS256", - "jwk": { - "e": "AQAB", - "kty": "RSA", - "n": "yB40ou1GMvIxYs1jhxWaeoDiw3oa0_Q2UJThUPtArvO0tRzaun9FnSphhOEHIGcezfq95jy-3MN-FIjmsWgbPHY8lVDS38fF75aCw6qkholwqjmMtUIgPNYoMrg0rLUE5RRyJ84-hKf9Fk7V3fItp1mvCTGKaS3ze-y5dTTrfbNGE7qG638Dla2Fuz-9CNgRQj0JH54o547WkKJC-pG-j0jTDr8lzsXhrZC7lJas4yc-vpt3D60iG4cW_mkdtIj52ZFEgHZ56sUj7AhnNVly0ZP9W1hmw4xEHDn9WLjlt7ivwARVeb2qzsNdguUitcI5hUQNwpOVZ_O3f1rUIL_kRw" - } - }, - "protected": "eyJmb3JtYXRUYWlsIjogIkNuMCIsICJmb3JtYXRMZW5ndGgiOiA1OTI2LCAidGltZSI6ICIyMDE2LTAxLTAyVDAyOjAxOjMzWiJ9", - "signature": "DrQ43UWeit-thDoRGTCP0Gd2wL5K2ecyPhHo_au0FoXwuKODja0tfwHexB9ypvFWngk-ijXuwO02x3aRIZqkWpvKLxxzxwkrZnPSje4o_VrFU4z5zwmN8sJw52ODkQlW38PURIVksOxCrb0zRl87yTAAsUAJ_4UUPNltZSLnhwy-qPb2NQ8ghgsONcBxRQrhPFiWNkxDKZ3kjvzYyrXDxTcvwK3Kk_YagZ4rCOhH1B7mAdVSiSHIvvNV5grPshw_ipAoqL2iNMsxWxLjYZl9xSJQI2asaq3fvh8G8cZ7T-OahDUos_GyhnIj39C-9ouqdJqMUYFETqbzRCR6d36CpQ" - } - ] -}` - -const etcdManifestNoSignature = `{ - "schemaVersion": 1, - "tag": "latest", - "name": "coreos/etcd", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:2560187847cadddef806eaf244b7755af247a9dbabb90ca953dd2703cf423766" - }, - { - "blobSum": "sha256:744b46d0ac8636c45870a03830d8d82c20b75fbfb9bc937d5e61005d23ad4cfe" - } - ], - "history": [ - { - "v1Compatibility": "{\"id\":\"fe50ac14986497fa6b5d2cc24feb4a561d01767bc64413752c0988cb70b0b8b9\",\"parent\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"created\":\"2015-12-30T22:29:13.967754365Z\",\"container\":\"c8d0f1a274b5f52fa5beb280775ef07cf18ec0f95e5ae42fbad01157e2614d42\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ENTRYPOINT \\u0026{[\\\"/etcd\\\"]}\"],\"Image\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/etcd\"],\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/etcd\"],\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\"}" - }, - { - "v1Compatibility": "{\"id\":\"a5a18474fa96a3c6e240bc88e41de2afd236520caf904356ad9d5f8d875c3481\",\"parent\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"created\":\"2015-12-30T22:29:13.504159783Z\",\"container\":\"080708d544f85052a46fab72e701b4358c1b96cb4b805a5b2d66276fc2aaf85d\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) EXPOSE 2379/tcp 2380/tcp 4001/tcp 7001/tcp\"],\"Image\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"2379/tcp\":{},\"2380/tcp\":{},\"4001/tcp\":{},\"7001/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\"}" - }, - { - "v1Compatibility": "{\"id\":\"796d581500e960cc02095dcdeccf55db215b8e54c57e3a0b11392145ffe60cf6\",\"parent\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"created\":\"2015-12-30T22:29:12.912813629Z\",\"container\":\"f28be899c9b8680d4cf8585e663ad20b35019db062526844e7cfef117ce9037f\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:e330b1da49d993059975e46560b3bd360691498b0f2f6e00f39fc160cf8d4ec3 in /\"],\"Image\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":13502144}" - }, - { - "v1Compatibility": "{\"id\":\"309c960c7f875411ae2ee2bfb97b86eee5058f3dad77206dd0df4f97df8a77fa\",\"created\":\"2015-12-30T22:29:12.346834862Z\",\"container\":\"1b97abade59e4b5b935aede236980a54fb500cd9ee5bd4323c832c6d7b3ffc6e\",\"container_config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:74912593c6783292c4520514f5cc9313acbd1da0f46edee0fdbed2a24a264d6f in /\"],\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.9.1\",\"config\":{\"Hostname\":\"1b97abade59e\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":15141568}" - } - ] -}` - func TestCreateSetsMetadata(t *testing.T) { testCases := []struct { + name string image *imageapi.Image expect func(*imageapi.Image) bool }{ { - image: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - DockerImageReference: "openshift/ruby-19-centos", - }, - }, - { + name: "image schema v2", expect: func(image *imageapi.Image) bool { - if image.DockerImageMetadata.Size != 28643712 { + ok := true + if image.DockerImageMetadata.Size != 451763572 { t.Errorf("image had size %d", image.DockerImageMetadata.Size) - return false + ok = false } - if len(image.DockerImageLayers) != 4 || image.DockerImageLayers[0].Name != "sha256:744b46d0ac8636c45870a03830d8d82c20b75fbfb9bc937d5e61005d23ad4cfe" || image.DockerImageLayers[0].LayerSize != 15141568 { + if len(image.DockerImageLayers) != 2 || image.DockerImageLayers[0].Name != "sha256:dc42dfa52495c90dc5b99c19534d6d4fa9cd37fa439356fcbd73e770c35f2293" || image.DockerImageLayers[0].LayerSize != 132852852 { t.Errorf("unexpected layers: %#v", image.DockerImageLayers) - return false + ok = false } - return true - }, - image: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - DockerImageReference: "openshift/ruby-19-centos", - DockerImageManifest: etcdManifest, + return ok }, + image: testutil.MustKindestCompleteImage(), }, } for i, test := range testCases { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() + t.Run(test.name, func(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() - obj, err := storage.Create(apirequest.NewDefaultContext(), test.image, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if obj == nil { - t.Errorf("%d: Expected nil obj, got %v", i, obj) - continue - } - if err != nil { - t.Errorf("%d: Unexpected non-nil error: %#v", i, err) - continue - } - image, ok := obj.(*imageapi.Image) - if !ok { - t.Errorf("%d: Expected image type, got: %#v", i, obj) - continue - } - if test.expect != nil && !test.expect(image) { - t.Errorf("%d: Unexpected image: %#v", i, obj) - } + obj, err := storage.Create(apirequest.NewDefaultContext(), test.image, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) + if obj == nil { + t.Errorf("%d: Expected nil obj, got %v", i, obj) + return + } + if err != nil { + t.Errorf("%d: Unexpected non-nil error: %#v", i, err) + return + } + image, ok := obj.(*imageapi.Image) + if !ok { + t.Errorf("%d: Expected image type, got: %#v", i, obj) + return + } + if test.expect != nil && !test.expect(image) { + t.Errorf("%d: Unexpected image: %#v", i, obj) + } + }) } } func TestUpdateResetsMetadata(t *testing.T) { testCases := []struct { + name string image *imageapi.Image existing *imageapi.Image expect func(*imageapi.Image) bool }{ - // manifest changes are ignored { + name: "labels and Docker image reference updated", expect: func(image *imageapi.Image) bool { + ok := true if image.Labels["a"] != "b" { t.Errorf("unexpected labels: %s", image.Labels) - return false + ok = false } - if image.DockerImageManifest != "" { - t.Errorf("unexpected manifest: %s", image.DockerImageManifest) - return false - } - if image.DockerImageMetadata.ID != "foo" { + if image.DockerImageMetadata.ID != testutil.KindestConfigDigest { t.Errorf("unexpected container image: %#v", image.DockerImageMetadata) - return false + ok = false } - if image.DockerImageReference == "openshift/ruby-19-centos-2" { + if image.DockerImageReference != "kindest/node-updated" { t.Errorf("image reference not changed: %s", image.DockerImageReference) - return false + ok = false } - if image.DockerImageMetadata.Size != 0 { + if image.DockerImageMetadata.Size != 451763572 { t.Errorf("image had size %d", image.DockerImageMetadata.Size) - return false + ok = false } - if len(image.DockerImageLayers) != 1 && image.DockerImageLayers[0].LayerSize != 10 { + if len(image.DockerImageLayers) != 2 || image.DockerImageLayers[0].LayerSize != 132852852 { t.Errorf("unexpected layers: %#v", image.DockerImageLayers) - return false + ok = false } - return true - }, - existing: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - DockerImageReference: "openshift/ruby-19-centos-2", - DockerImageLayers: []imageapi.ImageLayer{{Name: "test", LayerSize: 10}}, - DockerImageMetadata: imageapi.DockerImage{ID: "foo"}, - }, - image: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1", Labels: map[string]string{"a": "b"}}, - DockerImageReference: "openshift/ruby-19-centos", - DockerImageManifest: etcdManifest, + return ok }, + existing: testutil.MustKindestCompleteImage(), + image: testutil.MustKindestCompleteImage(func(img *imageapi.Image) { + img.Labels = map[string]string{"a": "b"} + img.DockerImageReference = "kindest/node-updated" + }), }, - // existing manifest is preserved, and unpacked { + name: "manifest is preserved and unpacked", expect: func(image *imageapi.Image) bool { if len(image.DockerImageManifest) != 0 { t.Errorf("unexpected not empty manifest") return false } - if image.DockerImageMetadata.ID != "fe50ac14986497fa6b5d2cc24feb4a561d01767bc64413752c0988cb70b0b8b9" { + if image.DockerImageMetadata.ID != testutil.KindestConfigDigest { t.Errorf("unexpected container image: %#v", image.DockerImageMetadata) return false } - if image.DockerImageReference != "openshift/ruby-19-centos" { + if image.DockerImageReference != "kindest/node-updated" { t.Errorf("image reference not changed: %s", image.DockerImageReference) return false } - if image.DockerImageMetadata.Size != 28643712 { + if image.DockerImageMetadata.Size != 451763572 { t.Errorf("image had size %d", image.DockerImageMetadata.Size) return false } - if len(image.DockerImageLayers) != 4 || image.DockerImageLayers[0].Name != "sha256:744b46d0ac8636c45870a03830d8d82c20b75fbfb9bc937d5e61005d23ad4cfe" || image.DockerImageLayers[0].LayerSize != 15141568 { + if len(image.DockerImageLayers) != 2 || image.DockerImageLayers[0].Name != "sha256:dc42dfa52495c90dc5b99c19534d6d4fa9cd37fa439356fcbd73e770c35f2293" || image.DockerImageLayers[0].LayerSize != 132852852 { t.Errorf("unexpected layers: %#v", image.DockerImageLayers) return false } return true }, - existing: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - DockerImageReference: "openshift/ruby-19-centos-2", - DockerImageLayers: []imageapi.ImageLayer{}, - DockerImageManifest: etcdManifest, - }, + existing: testutil.MustKindestCompleteImage(), image: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - DockerImageReference: "openshift/ruby-19-centos", - DockerImageMetadata: imageapi.DockerImage{ID: "foo"}, + ObjectMeta: metav1.ObjectMeta{ + Name: testutil.KindestConfigDigest, + GenerateName: "kindest", + }, + DockerImageReference: "kindest/node-updated", }, }, - // old manifest is replaced because the new manifest matches the digest - { - expect: func(image *imageapi.Image) bool { - if image.DockerImageManifest != etcdManifest { - t.Errorf("unexpected manifest: %s", image.DockerImageManifest) - return false - } - if image.DockerImageMetadata.ID != "fe50ac14986497fa6b5d2cc24feb4a561d01767bc64413752c0988cb70b0b8b9" { - t.Errorf("unexpected container image: %#v", image.DockerImageMetadata) - return false - } - if image.DockerImageReference != "openshift/ruby-19-centos" { - t.Errorf("image reference not changed: %s", image.DockerImageReference) - return false - } - if image.DockerImageMetadata.Size != 28643712 { - t.Errorf("image had size %d", image.DockerImageMetadata.Size) - return false - } - if len(image.DockerImageLayers) != 4 || image.DockerImageLayers[0].Name != "sha256:744b46d0ac8636c45870a03830d8d82c20b75fbfb9bc937d5e61005d23ad4cfe" || image.DockerImageLayers[0].LayerSize != 15141568 { - t.Errorf("unexpected layers: %#v", image.DockerImageLayers) - return false - } - return true - }, - existing: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", ResourceVersion: "1"}, - DockerImageReference: "openshift/ruby-19-centos-2", - DockerImageLayers: []imageapi.ImageLayer{}, - DockerImageManifest: etcdManifestNoSignature, - }, - image: &imageapi.Image{ - ObjectMeta: metav1.ObjectMeta{Name: "sha256:958608f8ecc1dc62c93b6c610f3a834dae4220c9642e6e8b4e0f2b3ad7cbd238", ResourceVersion: "1"}, - DockerImageReference: "openshift/ruby-19-centos", - DockerImageMetadata: imageapi.DockerImage{ID: "foo"}, - DockerImageManifest: etcdManifest, - }, - }} + } for i, test := range testCases { - storage, server := newStorage(t) - defer server.Terminate(t) - defer storage.Store.DestroyFunc() + t.Run(test.name, func(t *testing.T) { + storage, server := newStorage(t) + defer server.Terminate(t) + defer storage.Store.DestroyFunc() - // Clear the resource version before creating - test.existing.ResourceVersion = "" - created, err := storage.Create(apirequest.NewDefaultContext(), test.existing, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if err != nil { - t.Errorf("%d: Unexpected non-nil error: %#v", i, err) - continue - } + // Clear the resource version before creating + test.existing.ResourceVersion = "" + created, err := storage.Create(apirequest.NewDefaultContext(), test.existing, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) + if err != nil { + t.Errorf("%d: Unexpected non-nil error: %#v", i, err) + return + } - // Copy the resource version into our update object - test.image.ResourceVersion = created.(*imageapi.Image).ResourceVersion - obj, _, err := storage.Update(apirequest.NewDefaultContext(), test.image.Name, rest.DefaultUpdatedObjectInfo(test.image), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}) - if err != nil { - t.Errorf("%d: Unexpected non-nil error: %#v", i, err) - continue - } - if obj == nil { - t.Errorf("%d: Expected nil obj, got %v", i, obj) - continue - } - image, ok := obj.(*imageapi.Image) - if !ok { - t.Errorf("%d: Expected image type, got: %#v", i, obj) - continue - } - if test.expect != nil && !test.expect(image) { - t.Errorf("%d: Unexpected image: %#v", i, obj) - } + // Copy the resource version into our update object + test.image.ResourceVersion = created.(*imageapi.Image).ResourceVersion + obj, _, err := storage.Update(apirequest.NewDefaultContext(), test.image.Name, rest.DefaultUpdatedObjectInfo(test.image), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}) + if err != nil { + t.Errorf("%d: Unexpected non-nil error: %#v", i, err) + return + } + if obj == nil { + t.Errorf("%d: Expected nil obj, got %v", i, obj) + return + } + image, ok := obj.(*imageapi.Image) + if !ok { + t.Errorf("%d: Expected image type, got: %#v", i, obj) + return + } + if test.expect != nil && !test.expect(image) { + t.Errorf("%d: Unexpected image: %#v", i, obj) + } + }) } } + +func validImage() *imageapi.Image { + return testutil.KindestBareImage() +} diff --git a/pkg/image/apiserver/registry/image/strategy_test.go b/pkg/image/apiserver/registry/image/strategy_test.go index 45d28bf849..6bc97c73e5 100644 --- a/pkg/image/apiserver/registry/image/strategy_test.go +++ b/pkg/image/apiserver/registry/image/strategy_test.go @@ -18,7 +18,7 @@ import ( kapitesting "k8s.io/kubernetes/pkg/api/testing" imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" - "github.com/openshift/openshift-apiserver/pkg/image/apiserver/testutil" + "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/testutil" ) func fuzzImage(t *testing.T, image *imageapi.Image, seed int64) *imageapi.Image { diff --git a/pkg/image/apiserver/registry/imagestream/strategy_test.go b/pkg/image/apiserver/registry/imagestream/strategy_test.go index 89edc52fb9..f56d116a12 100644 --- a/pkg/image/apiserver/registry/imagestream/strategy_test.go +++ b/pkg/image/apiserver/registry/imagestream/strategy_test.go @@ -29,8 +29,8 @@ import ( "github.com/openshift/openshift-apiserver/pkg/image/apis/image/validation/fake" admfake "github.com/openshift/openshift-apiserver/pkg/image/apiserver/admission/fake" "github.com/openshift/openshift-apiserver/pkg/image/apiserver/admission/limitrange" + "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/testutil" "github.com/openshift/openshift-apiserver/pkg/image/apiserver/registryhostname" - "github.com/openshift/openshift-apiserver/pkg/image/apiserver/testutil" ) type fakeUser struct{} diff --git a/pkg/image/apiserver/registry/imagestreamimage/rest_test.go b/pkg/image/apiserver/registry/imagestreamimage/rest_test.go index 644282b8bb..d02ea942ee 100644 --- a/pkg/image/apiserver/registry/imagestreamimage/rest_test.go +++ b/pkg/image/apiserver/registry/imagestreamimage/rest_test.go @@ -21,6 +21,7 @@ import ( imageapi "github.com/openshift/openshift-apiserver/pkg/image/apis/image" "github.com/openshift/openshift-apiserver/pkg/image/apis/image/validation/fake" admfake "github.com/openshift/openshift-apiserver/pkg/image/apiserver/admission/fake" + "github.com/openshift/openshift-apiserver/pkg/image/apiserver/internal/testutil" "github.com/openshift/openshift-apiserver/pkg/image/apiserver/registry/image" imageetcd "github.com/openshift/openshift-apiserver/pkg/image/apiserver/registry/image/etcd" "github.com/openshift/openshift-apiserver/pkg/image/apiserver/registry/imagestream" @@ -95,7 +96,7 @@ func TestGet(t *testing.T) { expectError: true, }, "happy path": { - input: "repo@id", + input: "repo@" + testutil.KindestConfigDigest, repo: &imageapi.ImageStream{ ObjectMeta: metav1.ObjectMeta{ Namespace: "ns", @@ -107,76 +108,16 @@ func TestGet(t *testing.T) { Items: []imageapi.TagEvent{ {Image: "anotherid"}, {Image: "anotherid2"}, - {Image: "id"}, + {Image: testutil.KindestConfigDigest}, }, }, }, }, }, - expectedImageMetadataID: "2d24f826cb16146e2016ff349a8a33ed5830f3b938d45c0f82943f4ab8c097e7", - expectedConfigHostname: "43bd710ec89a", + expectedImageMetadataID: testutil.KindestConfigDigest, + expectedConfigHostname: "5e7483a6cf0e", images: []*imageapi.Image{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "id", - }, - DockerImageManifest: `{ - "name": "library/ubuntu", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - }, - { - "blobSum": "tarsum.dev+sha256:b194de3772ebbcdc8f244f663669799ac1cb141834b7cb8b69100285d357a2b0" - }, - { - "blobSum": "tarsum.dev+sha256:c937c4bb1c1a21cc6d94340812262c6472092028972ae69b551b1a70d4276171" - }, - { - "blobSum": "tarsum.dev+sha256:2aaacc362ac6be2b9e9ae8c6029f6f616bb50aec63746521858e47841b90fabd" - }, - { - "blobSum": "tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - } - ], - "history": [ - { - "v1Compatibility": "{\"id\":\"2d24f826cb16146e2016ff349a8a33ed5830f3b938d45c0f82943f4ab8c097e7\",\"parent\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"created\":\"2015-02-21T02:11:06.735146646Z\",\"container\":\"c9a3eda5951d28aa8dbe5933be94c523790721e4f80886d0a8e7a710132a38ec\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [/bin/bash]\"],\"Image\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/bash\"],\"Image\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\"Size\":0}\n" - }, - { - "v1Compatibility": "{\"id\":\"117ee323aaa9d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c\",\"parent\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"created\":\"2015-02-21T02:11:02.473113442Z\",\"container\":\"b4d4c42c196081cdb8e032446e9db92c0ce8ddeeeb1ef4e582b0275ad62b9af2\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"sed -i 's/^#\\\\s*\\\\(deb.*universe\\\\)$/\\\\1/g' /etc/apt/sources.list\"],\"Image\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:b194de3772ebbcdc8f244f663669799ac1cb141834b7cb8b69100285d357a2b0\",\"Size\":1895}\n" - }, - { - "v1Compatibility": "{\"id\":\"1c8294cc516082dfbb731f062806b76b82679ce38864dd87635f08869c993e45\",\"parent\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"created\":\"2015-02-21T02:10:56.648624065Z\",\"container\":\"d6323d4f92bf13dd2a7d2957e8970c8dc8ba3c2df08ffebdf4a04b4b658c83fb\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"echo '#!/bin/sh' \\u003e /usr/sbin/policy-rc.d \\u0009\\u0026\\u0026 echo 'exit 101' \\u003e\\u003e /usr/sbin/policy-rc.d \\u0009\\u0026\\u0026 chmod +x /usr/sbin/policy-rc.d \\u0009\\u0009\\u0026\\u0026 dpkg-divert --local --rename --add /sbin/initctl \\u0009\\u0026\\u0026 cp -a /usr/sbin/policy-rc.d /sbin/initctl \\u0009\\u0026\\u0026 sed -i 's/^exit.*/exit 0/' /sbin/initctl \\u0009\\u0009\\u0026\\u0026 echo 'force-unsafe-io' \\u003e /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \\u0009\\u0009\\u0026\\u0026 echo 'DPkg::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e /etc/apt/apt.conf.d/docker-clean \\u0009\\u0026\\u0026 echo 'APT::Update::Post-Invoke { \\\"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true\\\"; };' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\u0009\\u0026\\u0026 echo 'Dir::Cache::pkgcache \\\"\\\"; Dir::Cache::srcpkgcache \\\"\\\";' \\u003e\\u003e /etc/apt/apt.conf.d/docker-clean \\u0009\\u0009\\u0026\\u0026 echo 'Acquire::Languages \\\"none\\\";' \\u003e /etc/apt/apt.conf.d/docker-no-languages \\u0009\\u0009\\u0026\\u0026 echo 'Acquire::GzipIndexes \\\"true\\\"; Acquire::CompressionTypes::Order:: \\\"gz\\\";' \\u003e /etc/apt/apt.conf.d/docker-gzip-indexes\"],\"Image\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:c937c4bb1c1a21cc6d94340812262c6472092028972ae69b551b1a70d4276171\",\"Size\":194533}\n" - }, - { - "v1Compatibility": "{\"id\":\"fa4fd76b09ce9b87bfdc96515f9a5dd5121c01cc996cf5379050d8e13d4a864b\",\"parent\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"created\":\"2015-02-21T02:10:48.627646094Z\",\"container\":\"43bd710ec89aa1d61685c5ddb8737b315f2152d04c9e127ea2a9cf79f950fa5d\",\"container_config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:0018ff77d038472f52512fd66ae2466e6325e5d91289e10a6b324f40582298df in /\"],\"Image\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"43bd710ec89a\",\"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=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[]},\"architecture\":\"amd64\",\"os\":\"linux\",\"checksum\":\"tarsum.dev+sha256:2aaacc362ac6be2b9e9ae8c6029f6f616bb50aec63746521858e47841b90fabd\",\"Size\":188097705}\n" - }, - { - "v1Compatibility": "{\"id\":\"511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158\",\"comment\":\"Imported from -\",\"created\":\"2013-06-13T14:03:50.821769-07:00\",\"container_config\":{\"Hostname\":\"\",\"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\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":null},\"docker_version\":\"0.4.0\",\"architecture\":\"x86_64\",\"checksum\":\"tarsum.dev+sha256:324d4cf44ee7daa46266c1df830c61a7df615c0632176a339e7310e34723d67a\",\"Size\":0}\n" - } - ], - "schemaVersion": 1, - "signatures": [ - { - "header": { - "jwk": { - "crv": "P-256", - "kid": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4", - "kty": "EC", - "x": "Cu_UyxwLgHzE9rvlYSmvVdqYCXY42E9eNhBb0xNv0SQ", - "y": "zUsjWJkeKQ5tv7S-hl1Tg71cd-CqnrtiiLxSi6N_yc8" - }, - "alg": "ES256" - }, - "signature": "JafVC022gLJbK8fEp9UrW-GWAi53nD4Xf0-fmb766nV6zGTq7g9RutSWHcpv3OqhV8t5b-4j-bXhvnGBjXA7Yg", - "protected": "eyJmb3JtYXRMZW5ndGgiOjEwMDc2LCJmb3JtYXRUYWlsIjoiQ24wIiwidGltZSI6IjIwMTUtMDMtMDdUMTI6Mzk6MjJaIn0" - } - ] -}`, - }, + testutil.MustKindestCompleteImage(), }, }, "uses annotations from image stream": { diff --git a/pkg/image/apiserver/testutil/util.go b/pkg/image/apiserver/testutil/util.go deleted file mode 100644 index cb5044aa0b..0000000000 --- a/pkg/image/apiserver/testutil/util.go +++ /dev/null @@ -1,223 +0,0 @@ -package testutil - -import ( - "fmt" -) - -// InternalRegistryURL is an url of internal container image registry for testing purposes. -const InternalRegistryURL = "172.30.12.34:5000" - -// MakeDockerImageReference makes a container image reference string referencing testing internal docker -// registry. -func MakeDockerImageReference(ns, isName, imageID string) string { - return fmt.Sprintf("%s/%s/%s@%s", InternalRegistryURL, ns, isName, imageID) -} - -// 1 data layer of 128 B -const BaseImageWith1LayerDigest = `sha256:c5207ce0f38da269ad2e58f143b5ea4b314c75ce1121384369f0db9015e10e82` - -const BaseImageWith1Layer = `{ - "schemaVersion": 1, - "name": "miminar/baseImageWith1Layer", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:2d099e04ef6c850542d8ab916df2e9417cc799d39b78f64440e51402f1261a36" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - } - ], - "history": [ - { - "v1Compatibility": "{\"architecture\":\"amd64\",\"author\":\"miminar@redhat.com\",\"config\":{\"Hostname\":\"d7b63ae1152b\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"sha256:d4994ff5bda31913c54af389d68d27418b294cde415cb41282b513900bd11f1e\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"container\":\"99664df33257d325a5d3c082e72a5b6bf86adf1d4e75af6c5a5c4cdaab1fac58\",\"container_config\":{\"Hostname\":\"d7b63ae1152b\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) COPY file:90583fd8c765e40f7f2070c55da446e138b019b0712dee898d8193b66b05d48d in /data1\"],\"Image\":\"sha256:d4994ff5bda31913c54af389d68d27418b294cde415cb41282b513900bd11f1e\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"created\":\"2016-02-15T07:30:37.655693399Z\",\"docker_version\":\"1.10.0\",\"id\":\"3303329125f4954da646b116f6e4a7e40d03656d4802340d46aca8a473d9c3e4\",\"os\":\"linux\",\"parent\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"size\":128}" - }, - { - "v1Compatibility": "{\"id\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"created\":\"2016-02-15T07:30:37.531741167Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) MAINTAINER miminar@redhat.com\"]},\"throwaway\":true}" - } - ] -}` - -// 2 data layers, the first is shared with baseImageWith1Layer, total size of 240 B -const BaseImageWith2LayersDigest = "sha256:77371f61c054608a4bb1a96b99f9be69f0868340f5c924ecd8813172f7cf853d" - -const BaseImageWith2Layers = `{ - "schemaVersion": 1, - "name": "miminar/baseImageWith2Layers", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:e7900a2e6943680b384950859a0616089757cae4d8c6e98db9cfec6c41fe2834" - }, - { - "blobSum": "sha256:2d099e04ef6c850542d8ab916df2e9417cc799d39b78f64440e51402f1261a36" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - } - ], - "history": [ - { - "v1Compatibility": "{\"architecture\":\"amd64\",\"author\":\"miminar@redhat.com\",\"config\":{\"Hostname\":\"686b99d75c4a\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"sha256:356b1cbd1af67cfa316c7066895954a69865b972abe680942c123e8bfbbd7458\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"container\":\"686b99d75c4a744420c9a6bf9d3ba2548e72462e4719c8202878315f48083b2c\",\"container_config\":{\"Hostname\":\"686b99d75c4a\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) COPY file:23d2e6ff1c67ff4caee900c71d58df6e37bfb9defe46085018c4ba29c3d2de5a in /data2\"],\"Image\":\"sha256:356b1cbd1af67cfa316c7066895954a69865b972abe680942c123e8bfbbd7458\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":{}},\"created\":\"2016-02-15T07:31:50.390272025Z\",\"docker_version\":\"1.10.0\",\"id\":\"61c8a7f2be3a9b6fcd46f24da46eedfd37200b0d067d487595942b5b8bacbce7\",\"os\":\"linux\",\"parent\":\"1620fdccc2424391c3422467cec611bc32767d5bfae5bd8a2fb53c795e2a3e86\",\"size\":112}" - }, - { - "v1Compatibility": "{\"id\":\"1620fdccc2424391c3422467cec611bc32767d5bfae5bd8a2fb53c795e2a3e86\",\"parent\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"created\":\"2016-02-15T07:30:37.655693399Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) COPY file:90583fd8c765e40f7f2070c55da446e138b019b0712dee898d8193b66b05d48d in /data1\"]},\"size\":128}" - }, - { - "v1Compatibility": "{\"id\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"created\":\"2016-02-15T07:30:37.531741167Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) MAINTAINER miminar@redhat.com\"]},\"throwaway\":true}" - } - ] -}` - -// based on baseImageWith1Layer, it adds a new data layer of 126 B -const ChildImageWith2LayersDigest = "sha256:a9f073fbf2c9835711acd09081d87f5b7129ac6269e0df834240000f48abecd4" - -const ChildImageWith2Layers = `{ - "schemaVersion": 1, - "name": "miminar/childImageWith2Layers", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:766b6e9134dc2819fae9c5e67d39e14272948bc8967df9a119418cca84cab089" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:2d099e04ef6c850542d8ab916df2e9417cc799d39b78f64440e51402f1261a36" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - } - ], - "history": [ - { - "v1Compatibility": "{\"architecture\":\"amd64\",\"author\":\"miminar@redhat.com\",\"config\":{\"Hostname\":\"d7b63ae1152b\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"sha256:27bc5bf237c48c2b41b0636a3876960a9adb6c2ac9ff95ac879d56b1046ba5a1\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":[],\"Labels\":{}},\"container\":\"c2d2505e43f4fd479aa21d356270d0791633e838284d7010cba1f61992907c69\",\"container_config\":{\"Hostname\":\"d7b63ae1152b\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) COPY file:859e4175fd5743f276905245e351272b425232cfd3b30a3fc6bff351da308996 in /data3\"],\"Image\":\"sha256:27bc5bf237c48c2b41b0636a3876960a9adb6c2ac9ff95ac879d56b1046ba5a1\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":[],\"Labels\":{}},\"created\":\"2016-02-15T07:33:17.59074814Z\",\"docker_version\":\"1.10.0\",\"id\":\"e6a8e2793d6cad7d503aa5a3b55fd2c19b3b190d480a175b21d5f7b50c86d27b\",\"os\":\"linux\",\"parent\":\"84dc393745ff2631760c4bdbf1168af188fcd4606c1400c6900487fdc75a9ed5\",\"size\":126}" - }, - { - "v1Compatibility": "{\"id\":\"84dc393745ff2631760c4bdbf1168af188fcd4606c1400c6900487fdc75a9ed5\",\"parent\":\"1620fdccc2424391c3422467cec611bc32767d5bfae5bd8a2fb53c795e2a3e86\",\"created\":\"2016-02-15T07:33:17.454934648Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) MAINTAINER miminar@redhat.com\"]},\"throwaway\":true}" - }, - { - "v1Compatibility": "{\"id\":\"1620fdccc2424391c3422467cec611bc32767d5bfae5bd8a2fb53c795e2a3e86\",\"parent\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"created\":\"2016-02-15T07:30:37.655693399Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) COPY file:90583fd8c765e40f7f2070c55da446e138b019b0712dee898d8193b66b05d48d in /data1\"]},\"size\":128}" - }, - { - "v1Compatibility": "{\"id\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"created\":\"2016-02-15T07:30:37.531741167Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) MAINTAINER miminar@redhat.com\"]},\"throwaway\":true}" - } - ] -}` - -// based on baseImageWith2Layers, it adds a new data layer of 70 B -const ChildImageWith3LayersDigest = "sha256:2282a6d553353756fa43ba8672807d3fe81f8fdef54b0f6a360d64aaef2f243a" - -const ChildImageWith3Layers = `{ - "schemaVersion": 1, - "name": "miminar/childImageWith3Layers", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:77ef66f4abb43c5e17bcacdfe744f6959365f6244b66a6565470083fbdd15178" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:e7900a2e6943680b384950859a0616089757cae4d8c6e98db9cfec6c41fe2834" - }, - { - "blobSum": "sha256:2d099e04ef6c850542d8ab916df2e9417cc799d39b78f64440e51402f1261a36" - }, - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - } - ], - "history": [ - { - "v1Compatibility": "{\"architecture\":\"amd64\",\"author\":\"miminar@redhat.com\",\"config\":{\"Hostname\":\"686b99d75c4a\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"sha256:8b0241d44c66c1bcf48c66d0465ee6bf6ac2117e9936a9ec2337122e08d109ef\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":[],\"Labels\":{}},\"container\":\"61c9522f27b7052081b61b72d70dd71ce7050566812f050158e03954b493e446\",\"container_config\":{\"Hostname\":\"686b99d75c4a\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) COPY file:7781db9ed3a36b0607009b073a99802a9ad834bbb5e3bcbcf83a7d27146a1a5b in /data4\"],\"Image\":\"sha256:8b0241d44c66c1bcf48c66d0465ee6bf6ac2117e9936a9ec2337122e08d109ef\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":[],\"Labels\":{}},\"created\":\"2016-02-15T07:36:13.703778299Z\",\"docker_version\":\"1.10.0\",\"id\":\"8e7b1ec73ed1d21747991c2101d1db51e97c4f62931bbaa575aeba11286d6748\",\"os\":\"linux\",\"parent\":\"fbe31426cd0e8c5545ddc5c8318499682d52ff96118e36e49616ac3aee32c47c\",\"size\":70}" - }, - { - "v1Compatibility": "{\"id\":\"fbe31426cd0e8c5545ddc5c8318499682d52ff96118e36e49616ac3aee32c47c\",\"parent\":\"9b1154060650718a3850e625464addb217c1064f18dd693cf635dfcabdc9de50\",\"created\":\"2016-02-15T07:36:13.585345649Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) MAINTAINER miminar@redhat.com\"]},\"throwaway\":true}" - }, - { - "v1Compatibility": "{\"id\":\"9b1154060650718a3850e625464addb217c1064f18dd693cf635dfcabdc9de50\",\"parent\":\"1620fdccc2424391c3422467cec611bc32767d5bfae5bd8a2fb53c795e2a3e86\",\"created\":\"2016-02-15T07:31:50.390272025Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) COPY file:23d2e6ff1c67ff4caee900c71d58df6e37bfb9defe46085018c4ba29c3d2de5a in /data2\"]},\"size\":112}" - }, - { - "v1Compatibility": "{\"id\":\"1620fdccc2424391c3422467cec611bc32767d5bfae5bd8a2fb53c795e2a3e86\",\"parent\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"created\":\"2016-02-15T07:30:37.655693399Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) COPY file:90583fd8c765e40f7f2070c55da446e138b019b0712dee898d8193b66b05d48d in /data1\"]},\"size\":128}" - }, - { - "v1Compatibility": "{\"id\":\"3690474eb5b4b26fdfbd89c6e159e8cc376ca76ef48032a30fa6aafd56337880\",\"created\":\"2016-02-15T07:30:37.531741167Z\",\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) MAINTAINER miminar@redhat.com\"]},\"throwaway\":true}" - } - ] -}` - -// another base image with unique data layer of 554 B -const MiscImageDigest = "sha256:2643199e5ed5047eeed22da854748ed88b3a63ba0497601ba75852f7b92d4640" - -const MiscImage = `{ - "schemaVersion": 1, - "name": "miminar/misc", - "tag": "latest", - "architecture": "amd64", - "fsLayers": [ - { - "blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4" - }, - { - "blobSum": "sha256:eeee0535bf3cec7a24bff2c6e97481afa3d37e2cdeff277c57cb5cbdb2fa9e92" - } - ], - "history": [ - { - "v1Compatibility": "{\"id\":\"964092b7f3e54185d3f425880be0b022bfc9a706701390e0ceab527c84dea3e3\",\"parent\":\"9e77fef7a1c9f989988c06620dabc4020c607885b959a2cbd7c2283c91da3e33\",\"created\":\"2016-01-15T18:06:41.282540103Z\",\"container\":\"4e937d31f242d087cce0ec5b9fdbceaf1a13b40704e9147962cc80947e4ab86b\",\"container_config\":{\"Hostname\":\"aded96b43f48\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [\\\"sh\\\"]\"],\"Image\":\"9e77fef7a1c9f989988c06620dabc4020c607885b959a2cbd7c2283c91da3e33\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.8.3\",\"config\":{\"Hostname\":\"aded96b43f48\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"sh\"],\"Image\":\"9e77fef7a1c9f989988c06620dabc4020c607885b959a2cbd7c2283c91da3e33\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\"}" - }, - { - "v1Compatibility": "{\"id\":\"9e77fef7a1c9f989988c06620dabc4020c607885b959a2cbd7c2283c91da3e33\",\"created\":\"2016-01-15T18:06:40.707908287Z\",\"container\":\"aded96b43f48d94eb80642c210b89f119ab2a233c1c7c7055104fb052937f12c\",\"container_config\":{\"Hostname\":\"aded96b43f48\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) ADD file:a62b361be92f978752150570261ddc6fc21b025e3a28418820a1f39b7db7498c in /\"],\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"1.8.3\",\"config\":{\"Hostname\":\"aded96b43f48\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"OnBuild\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":554}" - } - ] -}` - -const ManifestList = `{ - "manifests": [ - { - "digest": "sha256:96a76fa48db5fca24271fe1565d88a4453e759b365dbaaeeb5a4e41049293e77", - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "platform": { - "architecture": "amd64", - "os": "linux" - }, - "size": 429 - }, - { - "digest": "sha256:6c3d8fec1c50ff78997e13a8352b030d4b290f656081c974373753fd5a3496f1", - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "platform": { - "architecture": "arm64", - "os": "linux" - }, - "size": 429 - }, - { - "digest": "sha256:520a368f78807947b96ea773cc62b14e380f4af08bbfd8ed18f0ebc70dedef68", - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "platform": { - "architecture": "ppc64le", - "os": "linux" - }, - "size": 429 - }, - { - "digest": "sha256:50b0c55990fe1b48c4b026fb6b49b4377e36c52b291d434977793dc0c8998ba4", - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "platform": { - "architecture": "s390x", - "os": "linux" - }, - "size": 429 - } - ], - "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", - "schemaVersion": 2 -}`