mirror of
https://github.com/containers/podman.git
synced 2025-10-20 04:34:01 +08:00
Allow artifact add to override org.opencontainers.image.title annotation
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -21,7 +21,8 @@ the `--append` option, the original creation timestamp is preserved.
|
||||
|
||||
@@option annotation.manifest
|
||||
|
||||
Note: Set annotations for each file being added.
|
||||
Note: Set annotations for each file being added. The annotation "org.opencontainers.image.title" is used
|
||||
to name the layer when mounted into a container, this title must be unigue for each artifact layer.
|
||||
|
||||
#### **--append**, **-a**
|
||||
|
||||
@ -78,6 +79,13 @@ Add files to an existing OCI artifact
|
||||
$ podman artifact add --append quay.io/myimage/myartifact:latest /home/user/config.yaml
|
||||
```
|
||||
|
||||
Create artifact with the layer title name being replaced, and then mount into a container.
|
||||
|
||||
```
|
||||
podman artifact add --annotation org.opencontainers.image.title=smollm2 quay.io/myreg/smollm2:latest blobs/sha256-4d2396b16114669389d7555c15a1592aad584750310f648edad5ca8c4eccda17
|
||||
podman run --mount type=artifact,source=quay.io/myreg/smollm2:latest,destination=/mnt fedora ls -l /mnt
|
||||
smollm2
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
**[podman(1)](podman.1.md)**, **[podman-artifact(1)](podman-artifact.1.md)**
|
||||
|
@ -27,7 +27,7 @@ const (
|
||||
artifactRegistry = "quay.io"
|
||||
artifactRepo = "podman"
|
||||
artifactImageName = "machine-os"
|
||||
artifactOriginalName = "org.opencontainers.image.title"
|
||||
artifactOriginalName = specV1.AnnotationTitle
|
||||
machineOS = "linux"
|
||||
)
|
||||
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/containers/podman/v5/utils"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
imgspec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -99,8 +100,12 @@ var _ = Describe("Podman artifact", func() {
|
||||
It("podman artifact add with options", func() {
|
||||
yamlType := "text/yaml"
|
||||
artifact1Name := "localhost/test/artifact1"
|
||||
artifact2Name := "localhost/test/artifact2"
|
||||
artifact3Name := "localhost/test/artifact3"
|
||||
artifact1File, err := createArtifactFile(1024)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
artifact2File, err := createArtifactFile(1024)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
artifactType := "octet/foobar"
|
||||
annotation1 := "color=blue"
|
||||
@ -115,9 +120,26 @@ var _ = Describe("Podman artifact", func() {
|
||||
Expect(a.Manifest.Layers[0].Annotations["flavor"]).To(Equal("lemon"))
|
||||
Expect(a.Manifest.Layers[0].MediaType).To(Equal(yamlType))
|
||||
|
||||
failSession := podmanTest.Podman([]string{"artifact", "add", "--annotation", "org.opencontainers.image.title=foobar", "foobar", artifact1File})
|
||||
title := RandomString(12)
|
||||
annotation3 := fmt.Sprintf("%s=%s", imgspec.AnnotationTitle, title)
|
||||
podmanTest.PodmanExitCleanly("artifact", "add", "--annotation", annotation3, artifact2Name, artifact1File)
|
||||
a = podmanTest.InspectArtifact(artifact2Name)
|
||||
Expect(a.Manifest.Layers[0].Annotations[imgspec.AnnotationTitle]).To(Equal(title))
|
||||
|
||||
failSession := podmanTest.Podman([]string{"artifact", "add", "--append", "--annotation", annotation3, artifact2Name, artifact2File})
|
||||
failSession.WaitWithDefaultTimeout()
|
||||
Expect(failSession).Should(ExitWithError(125, "Error: cannot override filename with org.opencontainers.image.title annotation"))
|
||||
Expect(failSession).Should(ExitWithError(125, "Error: duplicate layers org.opencontainers.image.title labels within an artifact not allowed"))
|
||||
|
||||
title = RandomString(12)
|
||||
annotation3 = fmt.Sprintf("%s=%s", imgspec.AnnotationTitle, title)
|
||||
podmanTest.PodmanExitCleanly("artifact", "add", "--append", "--annotation", annotation3, artifact2Name, artifact2File)
|
||||
a = podmanTest.InspectArtifact(artifact2Name)
|
||||
Expect(a.Manifest.Layers[1].Annotations[imgspec.AnnotationTitle]).To(Equal(title))
|
||||
|
||||
failSession = podmanTest.Podman([]string{"artifact", "add", "--annotation", annotation3, artifact3Name, artifact1File, artifact2File})
|
||||
failSession.WaitWithDefaultTimeout()
|
||||
Expect(failSession).Should(ExitWithError(125, "Error: duplicate layers org.opencontainers.image.title labels within an artifact not allowed"))
|
||||
|
||||
})
|
||||
|
||||
It("podman artifact add multiple", func() {
|
||||
@ -480,9 +502,9 @@ var _ = Describe("Podman artifact", func() {
|
||||
Expect(a.Manifest.Layers).To(HaveLen(3))
|
||||
|
||||
for _, l := range a.Manifest.Layers {
|
||||
layersNames[l.Annotations["org.opencontainers.image.title"]] += 1
|
||||
layersNames[l.Annotations[imgspec.AnnotationTitle]] += 1
|
||||
|
||||
if l.Annotations["org.opencontainers.image.title"] == filepath.Base(artifact3File) {
|
||||
if l.Annotations[imgspec.AnnotationTitle] == filepath.Base(artifact3File) {
|
||||
Expect(l.Annotations["color"]).To(Equal("blue"))
|
||||
} else {
|
||||
Expect(l.Annotations).To(HaveLen(1))
|
||||
|
24
vendor/go.podman.io/common/pkg/libartifact/store/store.go
generated
vendored
24
vendor/go.podman.io/common/pkg/libartifact/store/store.go
generated
vendored
@ -218,13 +218,6 @@ func (as ArtifactStore) Add(ctx context.Context, dest string, artifactBlobs []li
|
||||
return nil, errors.New("append option is not compatible with type option")
|
||||
}
|
||||
|
||||
// currently we don't allow override of the filename ; if a user requirement emerges,
|
||||
// we could seemingly accommodate but broadens possibilities of something bad happening
|
||||
// for things like `artifact extract`
|
||||
if _, hasTitle := options.Annotations[specV1.AnnotationTitle]; hasTitle {
|
||||
return nil, fmt.Errorf("cannot override filename with %s annotation", specV1.AnnotationTitle)
|
||||
}
|
||||
|
||||
locked := true
|
||||
as.lock.Lock()
|
||||
defer func() {
|
||||
@ -317,7 +310,17 @@ func (as ArtifactStore) Add(ctx context.Context, dest string, artifactBlobs []li
|
||||
}
|
||||
|
||||
annotations := maps.Clone(options.Annotations)
|
||||
annotations[specV1.AnnotationTitle] = artifactBlob.FileName
|
||||
if title, ok := annotations[specV1.AnnotationTitle]; ok {
|
||||
// Verify a duplicate AnnotationTitle is not in use in a different layer.
|
||||
for _, layer := range artifactManifest.Layers {
|
||||
if title == layer.Annotations[specV1.AnnotationTitle] {
|
||||
return nil, fmt.Errorf("duplicate layers %s labels within an artifact not allowed", specV1.AnnotationTitle)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Only override if the user did not specify the Title
|
||||
annotations[specV1.AnnotationTitle] = artifactBlob.FileName
|
||||
}
|
||||
|
||||
newLayer := specV1.Descriptor{
|
||||
MediaType: options.FileMIMEType,
|
||||
@ -469,6 +472,11 @@ func (as ArtifactStore) BlobMountPaths(ctx context.Context, nameOrDigest string,
|
||||
mountPaths := make([]libartTypes.BlobMountPath, 0, len(arty.Manifest.Layers))
|
||||
for _, l := range arty.Manifest.Layers {
|
||||
title := l.Annotations[specV1.AnnotationTitle]
|
||||
for _, mp := range mountPaths {
|
||||
if title == mp.Name {
|
||||
return nil, fmt.Errorf("annotation %q:%q is used in multiple different layers within artifact", specV1.AnnotationTitle, title)
|
||||
}
|
||||
}
|
||||
filename, err := generateArtifactBlobName(title, l.Digest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
Reference in New Issue
Block a user