Skip to content

Commit 17dcba4

Browse files
committed
Add --replace option to podman artifact add command
This commit implements the --replace functionality for the artifact add command, allowing users to replace existing artifacts without having to manually remove them first. Changes made: - Add Replace field to ArtifactAddOptions entity types - Add --replace CLI flag with validation to prevent conflicts with --append - Implement replace logic in ABI backend to remove existing artifacts before adding - Update API handlers and tunnel implementation for podman-remote support - Add comprehensive documentation and examples to man page - Add e2e and system BATS tests for --replace functionality - Fix code formatting in pkg/bindings/artifacts/types_pull_options.go: * Reorder imports with proper spacing * Fix function declaration spacing * Convert spaces to proper tab indentation * Remove extraneous blank lines The --replace option follows the same pattern as other podman replace options like 'podman container create --replace' and 'podman pod create --replace'. It gracefully handles cases where no existing artifact exists (no error thrown). Usage examples: podman artifact add --replace quay.io/myimage/artifact:latest /path/to/file podman artifact add --replace localhost/test/artifact /tmp/newfile.txt Fixes: Implements requested --replace functionality for artifact add command Signed-off-by: Daniel J Walsh <[email protected]>
1 parent e47ae67 commit 17dcba4

File tree

14 files changed

+352
-12
lines changed

14 files changed

+352
-12
lines changed

cmd/podman/artifact/add.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ func init() {
5353
appendFlagName := "append"
5454
flags.BoolVarP(&addOpts.Append, appendFlagName, "a", false, "Append files to an existing artifact")
5555

56+
replaceFlagName := "replace"
57+
flags.BoolVar(&addOpts.Replace, replaceFlagName, false, "Replace an existing artifact")
58+
5659
fileMIMETypeFlagName := "file-type"
5760
flags.StringVarP(&addOpts.FileMIMEType, fileMIMETypeFlagName, "", "", "Set file type to use for the artifact (layer)")
5861
_ = addCmd.RegisterFlagCompletionFunc(fileMIMETypeFlagName, completion.AutocompleteNone)
@@ -62,6 +65,10 @@ func add(_ *cobra.Command, args []string) error {
6265
artifactName := args[0]
6366
blobs := args[1:]
6467

68+
if addOpts.Append && addOpts.Replace {
69+
return fmt.Errorf("--append and --replace options cannot be used together")
70+
}
71+
6572
annots, err := utils.ParseAnnotations(addOpts.AnnotationsCLI)
6673
if err != nil {
6774
return err
@@ -72,6 +79,7 @@ func add(_ *cobra.Command, args []string) error {
7279
ArtifactMIMEType: addOpts.ArtifactMIMEType,
7380
Append: addOpts.Append,
7481
FileMIMEType: addOpts.FileMIMEType,
82+
Replace: addOpts.Replace,
7583
}
7684

7785
artifactBlobs := make([]entities.ArtifactBlob, 0, len(blobs))

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

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
% podman-artifact-add 1
22

33
## NAME
4-
podman\-artifact\-add - Add an OCI artifact to the local store
4+
podman\-artifact\-add - Add an OCI artifact to local artifact store
55

66
## SYNOPSIS
7-
**podman artifact add** *name* *file* [*file*]...
7+
**podman artifact add** [*options*] *artifact-name* *file* [*file* ...]
88

99
## DESCRIPTION
1010

@@ -35,6 +35,11 @@ Set the media type of the artifact file instead of allowing detection to determi
3535

3636
Print usage statement.
3737

38+
#### **--replace**
39+
40+
If an artifact with the same name already exists, replace and remove it. The default is **false**.
41+
This option cannot be used with the **--append** option.
42+
3843
#### **--type**
3944

4045
Set a type for the artifact being added.
@@ -48,25 +53,29 @@ $ podman artifact add quay.io/myartifact/myml:latest /tmp/foobar.ml
4853
0fe1488ecdef8cc4093e11a55bc048d9fc3e13a4ba846efd24b5a715006c95b3
4954
```
5055

51-
Add multiple files to an artifact
56+
Add OCI artifact to the store with type:
57+
5258
```
53-
$ podman artifact add quay.io/myartifact/myml:latest /tmp/foobar1.ml /tmp/foobar2.ml
54-
1487acae11b5a30948c50762882036b41ac91a7b9514be8012d98015c95ddb78
59+
$ podman artifact add --artifact-type application/com.example.ai --file-type application/vnd.gguf quay.io/myimage/myartifact:latest /home/user/model.gguf
5560
```
5661

57-
Set an annotation for an artifact
62+
Replace an existing artifact with the same name
63+
5864
```
59-
$ podman artifact add --annotation date=2025-01-30 quay.io/myartifact/myml:latest /tmp/foobar1.ml
65+
$ podman artifact add quay.io/myartifact/myml:latest /tmp/foobar.ml
66+
0fe1488ecdef8cc4093e11a55bc048d9fc3e13a4ba846efd24b5a715006c95b3
6067
```
6168

62-
Append a file to an existing artifact
69+
Add multiple files to an artifact
6370
```
64-
$ podman artifact add --append quay.io/myartifact/tarballs:latest /tmp/foobar.tar.gz
71+
$ podman artifact add quay.io/myartifact/myml:latest /tmp/foobar1.ml /tmp/foobar2.ml
72+
1487acae11b5a30948c50762882036b41ac91a7b9514be8012d98015c95ddb78
6573
```
6674

67-
Override the media type of the artifact being added
75+
Add files to an existing OCI artifact
76+
6877
```
69-
$ podman artifact add --file-type text/yaml quay.io/myartifact/descriptors:latest /tmp/info.yaml
78+
$ podman artifact add --append quay.io/myimage/myartifact:latest /home/user/config.yaml
7079
```
7180

7281

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ from its local "artifact store".
1717

1818
| Command | Man Page | Description |
1919
|---------|------------------------------------------------------------|--------------------------------------------------------------|
20-
| add | [podman-artifact-add(1)](podman-artifact-add.1.md) | Add an OCI artifact to the local store |
20+
| add | [podman-artifact-add(1)](podman-artifact-add.1.md) | Add an OCI artifact to local artifact store |
2121
| extract | [podman-artifact-extract(1)](podman-artifact-extract.1.md) | Extract an OCI artifact to a local path |
2222
| inspect | [podman-artifact-inspect(1)](podman-artifact-inspect.1.md) | Inspect an OCI artifact |
2323
| ls | [podman-artifact-ls(1)](podman-artifact-ls.1.md) | List OCI artifacts in local store |

pkg/api/handlers/libpod/artifacts.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ func AddArtifact(w http.ResponseWriter, r *http.Request) {
217217
Annotations []string `schema:"annotations"`
218218
ArtifactMIMEType string `schema:"artifactMIMEType"`
219219
Append bool `schema:"append"`
220+
Replace bool `schema:"replace"`
220221
}{}
221222

222223
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
@@ -240,6 +241,7 @@ func AddArtifact(w http.ResponseWriter, r *http.Request) {
240241
Annotations: annotations,
241242
ArtifactMIMEType: query.ArtifactMIMEType,
242243
FileMIMEType: query.FileMIMEType,
244+
Replace: query.Replace,
243245
}
244246

245247
artifactBlobs := []entities.ArtifactBlob{{

pkg/api/server/register_artifacts.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ func (s *APIServer) registerArtifactHandlers(r *mux.Router) error {
187187
// description: Append files to an existing artifact
188188
// type: boolean
189189
// default: false
190+
// - name: replace
191+
// in: query
192+
// description: Replace an existing artifact with the same name
193+
// type: boolean
194+
// default: false
190195
// - name: inputStream
191196
// in: body
192197
// description: Binary stream of the file to add to an artifact

pkg/bindings/artifacts/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type AddOptions struct {
6262
ArtifactMIMEType *string
6363
Append *bool
6464
FileMIMEType *string
65+
Replace *bool
6566
}
6667

6768
// ExtractOptions

pkg/bindings/artifacts/types_add_options.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/domain/entities/artifact.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ type ArtifactAddOptions struct {
1313
ArtifactMIMEType string
1414
Append bool
1515
FileMIMEType string
16+
Replace bool
1617
}
1718

1819
type ArtifactAddReport = entitiesTypes.ArtifactAddReport

pkg/domain/infra/abi/artifact.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package abi
44

55
import (
66
"context"
7+
"errors"
78
"fmt"
89
"io"
910
"os"
@@ -12,6 +13,7 @@ import (
1213
"github.com/containers/podman/v5/pkg/domain/entities"
1314
"github.com/containers/podman/v5/pkg/libartifact/types"
1415
"github.com/opencontainers/go-digest"
16+
"github.com/sirupsen/logrus"
1517
"go.podman.io/common/libimage"
1618
)
1719

@@ -203,11 +205,19 @@ func (ir *ImageEngine) ArtifactAdd(ctx context.Context, name string, artifactBlo
203205
return nil, err
204206
}
205207

208+
// If replace is true, try to remove existing artifact (ignore errors if it doesn't exist)
209+
if opts.Replace {
210+
if _, err = artStore.Remove(ctx, name); err != nil && !errors.Is(err, types.ErrArtifactNotExist) {
211+
logrus.Debugf("Artifact %q removal failed: %s", name, err)
212+
}
213+
}
214+
206215
addOptions := types.AddOptions{
207216
Annotations: opts.Annotations,
208217
ArtifactMIMEType: opts.ArtifactMIMEType,
209218
Append: opts.Append,
210219
FileMIMEType: opts.FileMIMEType,
220+
Replace: opts.Replace,
211221
}
212222

213223
artifactDigest, err := artStore.Add(ctx, name, artifactBlobs, &addOptions)

pkg/domain/infra/tunnel/artifact.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func (ir *ImageEngine) ArtifactAdd(_ context.Context, name string, artifactBlob
8888
Append: &opts.Append,
8989
ArtifactMIMEType: &opts.ArtifactMIMEType,
9090
FileMIMEType: &opts.FileMIMEType,
91+
Replace: &opts.Replace,
9192
}
9293

9394
for k, v := range opts.Annotations {

0 commit comments

Comments
 (0)