Skip to content

Commit

Permalink
manifest,zstd: give priority to zstd compressed images
Browse files Browse the repository at this point in the history
While perform a pull from manifest list of type
`application/vnd.oci.image.index.v1+json` make sure that if more
than one image exists for the same platform then give priority to the
one compressed with `zstd`.

Annotation `io.github.containers.compression.zstd` is expected to be set
for the image compressed with `zstd`.

Signed-off-by: Aditya R <arajan@redhat.com>
  • Loading branch information
flouthoc committed Jan 13, 2023
1 parent 5ef8a4f commit 2284e25
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 2 deletions.
66 changes: 66 additions & 0 deletions internal/image/fixtures/schemazstdselection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74a9522510",
"size": 758,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:ac9bbf71dacfad2bfbe48f7d46ca279b1b3b351a6c814db760030015167405b8",
"size": 772,
"annotations": {
"io.github.containers.compression.zstd": "true"
},
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74a9522511",
"size": 758,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74z9522511",
"size": 758,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74z9522511",
"size": 758,
"platform": {
"architecture": "s390x",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:ac9bbf71dacfad2bfbe48m7d46ca279b1b3b351a6c814db760030015167405b8",
"size": 772,
"annotations": {
"io.github.containers.compression.zstd": "true"
},
"platform": {
"architecture": "amd64",
"os": "linux"
}
}
]
}
57 changes: 57 additions & 0 deletions internal/image/fixtures/schemazstdselection2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74a9522510",
"size": 758,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74a9522513",
"size": 759,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:ac9bbf71dacfad2bfbe48f7d46ca279b1b3b351a6c814db760030015167405b8",
"size": 772,
"annotations": {
"io.github.containers.compression.zstd": "true"
},
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74a9522514",
"size": 759,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:ac9bbf71dacfad2bfbe48f7d46ca279b1b3b351a6c814db760030015167405b6",
"size": 772,
"annotations": {
"io.github.containers.compression.zstd": "true"
},
"platform": {
"architecture": "amd64",
"os": "linux"
}
}
]
}
23 changes: 23 additions & 0 deletions manifest/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ func TestChooseInstance(t *testing.T) {
"unmatched",
},
},
{
listFile: "schemazstdselection.json",
matchedInstances: []expectedMatch{
// out of gzip and zstd in amd64 select the first zstd image
{"amd64", "", "sha256:ac9bbf71dacfad2bfbe48f7d46ca279b1b3b351a6c814db760030015167405b8"},
// out of multiple gzip in arm64 select the first one to ensure original logic is prevented
{"arm64", "", "sha256:88cb27f194cce3b06994b4af2dd8a5642f4f294b71bda5b74a3fbb74a9522511"},
// select a signle gzip s390x image
{"s390x", "", ""},
},
unmatchedInstances: []string{
"unmatched",
},
},
{
listFile: "schemazstdselection2.json",
matchedInstances: []expectedMatch{
{"amd64", "", "sha256:ac9bbf71dacfad2bfbe48f7d46ca279b1b3b351a6c814db760030015167405b8"},
},
unmatchedInstances: []string{
"unmatched",
},
},
{ // Focus on ARM variant field testing
listFile: "schema2list-variants.json",
matchedInstances: []expectedMatch{
Expand Down
42 changes: 40 additions & 2 deletions manifest/oci_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ import (
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
)

const (
// Following annotation is used while performing instance selection.
// If more than one image exists for the same platform then the image
// compressed with `zstd` will be given priority.
OCI1InstanceAnnotationCompressionZSTD = "io.github.containers.compression.zstd"
)

// OCI1Index is just an alias for the OCI index type, but one which we can
// provide methods for.
type OCI1Index struct {
Expand Down Expand Up @@ -76,6 +83,8 @@ func (index *OCI1Index) ChooseInstance(ctx *types.SystemContext) (digest.Digest,
if err != nil {
return "", fmt.Errorf("getting platform information %#v: %w", ctx, err)
}
var matchedDigest digest.Digest
matchedDigest = ""
for _, wantedPlatform := range wantedPlatforms {
for _, d := range index.Manifests {
if d.Platform == nil {
Expand All @@ -89,16 +98,45 @@ func (index *OCI1Index) ChooseInstance(ctx *types.SystemContext) (digest.Digest,
Variant: d.Platform.Variant,
}
if platform.MatchesPlatform(imagePlatform, wantedPlatform) {
return d.Digest, nil
if matchedDigest == "" {
matchedDigest = d.Digest
}
// Always give priority to zstd if more than one image
// exists for the same platform.
// TODO: In future this check will be configurable and
// will be relayed via `ctx`.
if _, ok := d.Annotations[OCI1InstanceAnnotationCompressionZSTD]; ok {
matchedDigest = d.Digest
return matchedDigest, nil
}
}
}
}

if matchedDigest != "" {
return matchedDigest, nil
}

for _, d := range index.Manifests {
if d.Platform == nil {
return d.Digest, nil
if matchedDigest == "" {
matchedDigest = d.Digest
}
// Always give priority to zstd if more than one image
// exists for the same platform.
// TODO: In future this check will be configurable and
// will be relayed via `ctx`.
if _, ok := d.Annotations[OCI1InstanceAnnotationCompressionZSTD]; ok {
matchedDigest = d.Digest
return matchedDigest, nil
}
}
}

if matchedDigest != "" {
return matchedDigest, nil
}

return "", fmt.Errorf("no image found in image index for architecture %s, variant %q, OS %s", wantedPlatforms[0].Architecture, wantedPlatforms[0].Variant, wantedPlatforms[0].OS)
}

Expand Down

0 comments on commit 2284e25

Please sign in to comment.