Skip to content

Commit 6138492

Browse files
committed
Allow artifact add to override org.opencontainers.image.title annotation
Signed-off-by: Daniel J Walsh <[email protected]>
1 parent 685a448 commit 6138492

File tree

4 files changed

+52
-14
lines changed

4 files changed

+52
-14
lines changed

docs/source/markdown/podman-artifact-add.1.md.in

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ the `--append` option, the original creation timestamp is preserved.
2121

2222
@@option annotation.manifest
2323

24-
Note: Set annotations for each file being added.
24+
Note: Set annotations for each file being added. The annotation "org.opencontainers.image.title" is used
25+
to name the layer when mounted into a container, this title must be unigue for each artifact layer.
2526

2627
#### **--append**, **-a**
2728

@@ -78,6 +79,13 @@ Add files to an existing OCI artifact
7879
$ podman artifact add --append quay.io/myimage/myartifact:latest /home/user/config.yaml
7980
```
8081

82+
Create artifact with the layer title name being replaced, and then mount into a container.
83+
84+
```
85+
podman artifact add --annotation org.opencontainers.image.title=smollm2 quay.io/myreg/smollm2:latest blobs/sha256-4d2396b16114669389d7555c15a1592aad584750310f648edad5ca8c4eccda17
86+
podman run --mount type=artifact,source=quay.io/myreg/smollm2:latest,destination=/mnt fedora ls -l /mnt
87+
smollm2
88+
```
8189

8290
## SEE ALSO
8391
**[podman(1)](podman.1.md)**, **[podman-artifact(1)](podman-artifact.1.md)**

pkg/libartifact/store/store.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,6 @@ func (as ArtifactStore) Add(ctx context.Context, dest string, artifactBlobs []en
221221
return nil, errors.New("append option is not compatible with type option")
222222
}
223223

224-
// currently we don't allow override of the filename ; if a user requirement emerges,
225-
// we could seemingly accommodate but broadens possibilities of something bad happening
226-
// for things like `artifact extract`
227-
if _, hasTitle := options.Annotations[specV1.AnnotationTitle]; hasTitle {
228-
return nil, fmt.Errorf("cannot override filename with %s annotation", specV1.AnnotationTitle)
229-
}
230-
231224
locked := true
232225
as.lock.Lock()
233226
defer func() {
@@ -320,7 +313,17 @@ func (as ArtifactStore) Add(ctx context.Context, dest string, artifactBlobs []en
320313
}
321314

322315
annotations := maps.Clone(options.Annotations)
323-
annotations[specV1.AnnotationTitle] = artifactBlob.FileName
316+
if title, ok := annotations[specV1.AnnotationTitle]; ok {
317+
// Verify a duplicate AnnotationTitle is not in use in a different layer.
318+
for _, layer := range artifactManifest.Layers {
319+
if title == layer.Annotations[specV1.AnnotationTitle] {
320+
return nil, fmt.Errorf("duplicate layers %s labels within an artifact not allowed", specV1.AnnotationTitle)
321+
}
322+
}
323+
} else {
324+
// Only override if the user did not specify the Title
325+
annotations[specV1.AnnotationTitle] = artifactBlob.FileName
326+
}
324327

325328
newLayer := specV1.Descriptor{
326329
MediaType: options.FileMIMEType,
@@ -472,6 +475,11 @@ func (as ArtifactStore) BlobMountPaths(ctx context.Context, nameOrDigest string,
472475
mountPaths := make([]libartTypes.BlobMountPath, 0, len(arty.Manifest.Layers))
473476
for _, l := range arty.Manifest.Layers {
474477
title := l.Annotations[specV1.AnnotationTitle]
478+
for _, mp := range mountPaths {
479+
if title == mp.Name {
480+
return nil, fmt.Errorf("annotation %q:%q is used in multiple different layers within artifact", specV1.AnnotationTitle, title)
481+
}
482+
}
475483
filename, err := generateArtifactBlobName(title, l.Digest)
476484
if err != nil {
477485
return nil, err

pkg/machine/ocipull/ociartifact.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const (
2727
artifactRegistry = "quay.io"
2828
artifactRepo = "podman"
2929
artifactImageName = "machine-os"
30-
artifactOriginalName = "org.opencontainers.image.title"
30+
artifactOriginalName = specV1.AnnotationTitle
3131
machineOS = "linux"
3232
)
3333

test/e2e/artifact_test.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/containers/podman/v5/utils"
1515
. "github.com/onsi/ginkgo/v2"
1616
. "github.com/onsi/gomega"
17+
imgspec "github.com/opencontainers/image-spec/specs-go/v1"
1718
)
1819

1920
const (
@@ -99,8 +100,12 @@ var _ = Describe("Podman artifact", func() {
99100
It("podman artifact add with options", func() {
100101
yamlType := "text/yaml"
101102
artifact1Name := "localhost/test/artifact1"
103+
artifact2Name := "localhost/test/artifact2"
104+
artifact3Name := "localhost/test/artifact3"
102105
artifact1File, err := createArtifactFile(1024)
103106
Expect(err).ToNot(HaveOccurred())
107+
artifact2File, err := createArtifactFile(1024)
108+
Expect(err).ToNot(HaveOccurred())
104109

105110
artifactType := "octet/foobar"
106111
annotation1 := "color=blue"
@@ -115,9 +120,26 @@ var _ = Describe("Podman artifact", func() {
115120
Expect(a.Manifest.Layers[0].Annotations["flavor"]).To(Equal("lemon"))
116121
Expect(a.Manifest.Layers[0].MediaType).To(Equal(yamlType))
117122

118-
failSession := podmanTest.Podman([]string{"artifact", "add", "--annotation", "org.opencontainers.image.title=foobar", "foobar", artifact1File})
123+
title := RandomString(12)
124+
annotation3 := fmt.Sprintf("%s=%s", imgspec.AnnotationTitle, title)
125+
podmanTest.PodmanExitCleanly("artifact", "add", "--annotation", annotation3, artifact2Name, artifact1File)
126+
a = podmanTest.InspectArtifact(artifact2Name)
127+
Expect(a.Manifest.Layers[0].Annotations[imgspec.AnnotationTitle]).To(Equal(title))
128+
129+
failSession := podmanTest.Podman([]string{"artifact", "add", "--append", "--annotation", annotation3, artifact2Name, artifact2File})
119130
failSession.WaitWithDefaultTimeout()
120-
Expect(failSession).Should(ExitWithError(125, "Error: cannot override filename with org.opencontainers.image.title annotation"))
131+
Expect(failSession).Should(ExitWithError(125, "Error: duplicate layers org.opencontainers.image.title labels within an artifact not allowed"))
132+
133+
title = RandomString(12)
134+
annotation3 = fmt.Sprintf("%s=%s", imgspec.AnnotationTitle, title)
135+
podmanTest.PodmanExitCleanly("artifact", "add", "--append", "--annotation", annotation3, artifact2Name, artifact2File)
136+
a = podmanTest.InspectArtifact(artifact2Name)
137+
Expect(a.Manifest.Layers[1].Annotations[imgspec.AnnotationTitle]).To(Equal(title))
138+
139+
failSession = podmanTest.Podman([]string{"artifact", "add", "--annotation", annotation3, artifact3Name, artifact1File, artifact2File})
140+
failSession.WaitWithDefaultTimeout()
141+
Expect(failSession).Should(ExitWithError(125, "Error: duplicate layers org.opencontainers.image.title labels within an artifact not allowed"))
142+
121143
})
122144

123145
It("podman artifact add multiple", func() {
@@ -480,9 +502,9 @@ var _ = Describe("Podman artifact", func() {
480502
Expect(a.Manifest.Layers).To(HaveLen(3))
481503

482504
for _, l := range a.Manifest.Layers {
483-
layersNames[l.Annotations["org.opencontainers.image.title"]] += 1
505+
layersNames[l.Annotations[imgspec.AnnotationTitle]] += 1
484506

485-
if l.Annotations["org.opencontainers.image.title"] == filepath.Base(artifact3File) {
507+
if l.Annotations[imgspec.AnnotationTitle] == filepath.Base(artifact3File) {
486508
Expect(l.Annotations["color"]).To(Equal("blue"))
487509
} else {
488510
Expect(l.Annotations).To(HaveLen(1))

0 commit comments

Comments
 (0)