Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support editing ArtifactType, preserve it in lists #2304

Merged
merged 1 commit into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions copy/multiple.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type instanceCopy struct {

// Fields which can be used by callers when operation
// is `instanceCopyClone`
cloneArtifactType string
cloneCompressionVariant OptionCompressionVariant
clonePlatform *imgspecv1.Platform
cloneAnnotations map[string]string
Expand Down Expand Up @@ -142,6 +143,7 @@ func prepareInstanceCopies(list internalManifest.List, instanceDigests []digest.
res = append(res, instanceCopy{
op: instanceCopyClone,
sourceDigest: instanceDigest,
cloneArtifactType: instanceDetails.ReadOnly.ArtifactType,
cloneCompressionVariant: compressionVariant,
clonePlatform: instanceDetails.ReadOnly.Platform,
cloneAnnotations: maps.Clone(instanceDetails.ReadOnly.Annotations),
Expand Down Expand Up @@ -268,6 +270,7 @@ func (c *copier) copyMultipleImages(ctx context.Context) (copiedManifest []byte,
AddDigest: updated.manifestDigest,
AddSize: int64(len(updated.manifest)),
AddMediaType: updated.manifestMIMEType,
AddArtifactType: instance.cloneArtifactType,
AddPlatform: instance.clonePlatform,
AddAnnotations: instance.cloneAnnotations,
AddCompressionAlgorithms: updated.compressionAlgorithms,
Expand Down
2 changes: 2 additions & 0 deletions internal/manifest/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type ListUpdate struct {
Platform *imgspecv1.Platform
Annotations map[string]string
CompressionAlgorithmNames []string
ArtifactType string
}
}

Expand Down Expand Up @@ -101,6 +102,7 @@ type ListEdit struct {
AddDigest digest.Digest
AddSize int64
AddMediaType string
AddArtifactType string
AddPlatform *imgspecv1.Platform
AddAnnotations map[string]string
AddCompressionAlgorithms []compression.Algorithm
Expand Down
26 changes: 15 additions & 11 deletions internal/manifest/oci_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func (index *OCI1IndexPublic) Instance(instanceDigest digest.Digest) (ListUpdate
ret.ReadOnly.Platform = manifest.Platform
ret.ReadOnly.Annotations = manifest.Annotations
ret.ReadOnly.CompressionAlgorithmNames = annotationsToCompressionAlgorithmNames(manifest.Annotations)
ret.ReadOnly.ArtifactType = manifest.ArtifactType
return ret, nil
}
}
Expand Down Expand Up @@ -157,11 +158,13 @@ func (index *OCI1IndexPublic) editInstances(editInstances []ListEdit) error {
}
addCompressionAnnotations(editInstance.AddCompressionAlgorithms, &annotations)
addedEntries = append(addedEntries, imgspecv1.Descriptor{
MediaType: editInstance.AddMediaType,
Size: editInstance.AddSize,
Digest: editInstance.AddDigest,
Platform: editInstance.AddPlatform,
Annotations: annotations})
MediaType: editInstance.AddMediaType,
ArtifactType: editInstance.AddArtifactType,
Size: editInstance.AddSize,
Digest: editInstance.AddDigest,
Platform: editInstance.AddPlatform,
Annotations: annotations,
})
default:
return fmt.Errorf("internal error: invalid operation: %d", editInstance.ListOperation)
}
Expand Down Expand Up @@ -299,12 +302,13 @@ func OCI1IndexPublicFromComponents(components []imgspecv1.Descriptor, annotation
platform = &platformCopy
}
m := imgspecv1.Descriptor{
MediaType: component.MediaType,
Size: component.Size,
Digest: component.Digest,
URLs: slices.Clone(component.URLs),
Annotations: maps.Clone(component.Annotations),
Platform: platform,
MediaType: component.MediaType,
ArtifactType: component.ArtifactType,
Size: component.Size,
Digest: component.Digest,
URLs: slices.Clone(component.URLs),
Annotations: maps.Clone(component.Annotations),
Platform: platform,
}
index.Manifests[i] = m
}
Expand Down
45 changes: 38 additions & 7 deletions internal/manifest/oci_index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ func TestOCI1EditInstances(t *testing.T) {
UpdateDigest: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
UpdateSize: 32,
UpdateMediaType: "something",
ListOperation: ListOpUpdate})
ListOperation: ListOpUpdate,
})
err = list.EditInstances(editInstances)
require.NoError(t, err)

Expand Down Expand Up @@ -98,12 +99,14 @@ func TestOCI1EditInstances(t *testing.T) {
ListOperation: ListOpAdd})
// with zstd
editInstances = append(editInstances, ListEdit{
AddDigest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
AddSize: 32,
AddMediaType: "application/vnd.oci.image.manifest.v1+json",
AddPlatform: &imgspecv1.Platform{Architecture: "amd64", OS: "linux", OSFeatures: []string{"sse4"}},
AddAnnotations: annotations,
ListOperation: ListOpAdd})
AddDigest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
AddSize: 32,
AddMediaType: "application/vnd.oci.image.manifest.v1+json",
AddArtifactType: "application/x-tar",
AddPlatform: &imgspecv1.Platform{Architecture: "amd64", OS: "linux", OSFeatures: []string{"sse4"}},
AddAnnotations: annotations,
ListOperation: ListOpAdd,
})
// with zstd but with compression, annotation must be added automatically
editInstances = append(editInstances, ListEdit{
AddDigest: "sha256:hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
Expand Down Expand Up @@ -138,6 +141,8 @@ func TestOCI1EditInstances(t *testing.T) {
require.NoError(t, err)
// Verify if annotations are preserved and correctly set in ReadOnly field.
assert.Equal(t, annotations, instance.ReadOnly.Annotations)
// Verify artifactType is preserved.
assert.Equal(t, "application/x-tar", instance.ReadOnly.ArtifactType)
// Verify compression of an instance is added to the ReadOnly CompressionAlgorithmNames where compression name
// is internally derived from the appropriate annotations.
assert.Equal(t, []string{compressionTypes.ZstdAlgorithmName}, instance.ReadOnly.CompressionAlgorithmNames)
Expand All @@ -157,6 +162,32 @@ func TestOCI1EditInstances(t *testing.T) {
// Digest `ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff` should be re-ordered on update.
assert.Equal(t, list.Instances(), []digest.Digest{digest.Digest("sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f"), digest.Digest("sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270"), digest.Digest("sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), digest.Digest("sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"), digest.Digest("sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), digest.Digest("sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"), digest.Digest("sha256:hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")})

instance, err = list.Instance(digest.Digest("sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"))
require.NoError(t, err)
// Verify if annotations are preserved and correctly set in ReadOnly field.
assert.Equal(t, annotations, instance.ReadOnly.Annotations)

// Create a fresh list
artifactBearingManifest, err := os.ReadFile(filepath.Join("testdata", "oci1index.json"))
require.NoError(t, err)
list, err = ListFromBlob(artifactBearingManifest, GuessMIMEType(artifactBearingManifest))
require.NoError(t, err)
// Edit the parts of the instance that we can change.
editInstances = []ListEdit{{
ListOperation: ListOpUpdate,
UpdateOldDigest: digest.Digest("sha256:615e8db5ae085b39e9cd24e5bc887d03fbd30ee4f55f5fedf9b697fafea4fbdd"),
UpdateDigest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
UpdateSize: 32,
UpdateMediaType: "application/vnd.oci.image.manifest.v1+json",
UpdateAffectAnnotations: true,
UpdateAnnotations: map[string]string{},
}}
err = list.EditInstances(editInstances)
require.NoError(t, err)
// Verify that the artifactType wasn't lost.
instance, err = list.Instance(digest.Digest("sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
require.NoError(t, err)
assert.Equal(t, "application/x-tar", instance.ReadOnly.ArtifactType)
}

func TestOCI1IndexChooseInstanceByCompression(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions internal/manifest/testdata/oci1index.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@
"sse4"
]
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/x-tar",
"size": 8221,
"digest": "sha256:615e8db5ae085b39e9cd24e5bc887d03fbd30ee4f55f5fedf9b697fafea4fbdd",
mtrmac marked this conversation as resolved.
Show resolved Hide resolved
"platform": {
"architecture": "arm64",
"os": "linux"
}
}
],
"annotations": {
Expand Down