Skip to content

Commit ad1abd3

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 af65d46 commit ad1abd3

File tree

17 files changed

+512
-31
lines changed

17 files changed

+512
-31
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(cmd *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(cmd *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))
Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,73 @@
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

1111
Add an OCI artifact to the local store from the local filesystem. You must
1212
provide at least one file to create the artifact, but several can also be
1313
added.
1414

15+
Artifacts automatically include a creation timestamp in the
16+
`org.opencontainers.image.created` annotation using RFC3339Nano format. When using
17+
the `--append` option, the original creation timestamp is preserved.
18+
1519

1620
## OPTIONS
1721

1822
@@option annotation.manifest
1923

20-
Note: Set annotations for each file being added.
24+
@@option arch
2125

22-
#### **--append**, **-a**
26+
#### **--append**
2327

24-
Append files to an existing artifact. This option cannot be used with the **--type** option.
28+
Add files to an existing OCI Artifact. The default is **false**.
2529

26-
#### **--file-type**
30+
#### **--artifact-type**
2731

28-
Set the media type of the artifact file instead of allowing detection to determine the type
32+
Set the MIME type for the artifact config. This will be set in the media type of the artifact manifest. Setting the type for an artifact makes it easier to search and filter on the artifact type.
2933

30-
#### **--help**
34+
#### **--file-type**
3135

32-
Print usage statement.
36+
Set the MIME type for each of the added files. The default of the filesystem adds files as (application/octet-stream).
3337

34-
#### **--type**
38+
#### **--replace**
3539

36-
Set a type for the artifact being added.
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.
3742

3843
## EXAMPLES
3944

40-
Add a single file to an artifact
45+
Add artifact to the store with path:
4146

4247
```
43-
$ podman artifact add quay.io/myartifact/myml:latest /tmp/foobar.ml
44-
0fe1488ecdef8cc4093e11a55bc048d9fc3e13a4ba846efd24b5a715006c95b3
48+
$ podman artifact add quay.io/myimage/myartifact:latest /home/user/model.gguf
4549
```
4650

47-
Add multiple files to an artifact
48-
```
49-
$ podman artifact add quay.io/myartifact/myml:latest /tmp/foobar1.ml /tmp/foobar2.ml
50-
1487acae11b5a30948c50762882036b41ac91a7b9514be8012d98015c95ddb78
51-
```
51+
Add OCI artifact to the store with type:
5252

53-
Set an annotation for an artifact
5453
```
55-
$ podman artifact add --annotation date=2025-01-30 quay.io/myartifact/myml:latest /tmp/foobar1.ml
54+
$ podman artifact add --artifact-type application/com.example.ai --file-type application/vnd.gguf quay.io/myimage/myartifact:latest /home/user/model.gguf
5655
```
5756

58-
Append a file to an existing artifact
57+
Replace an existing artifact with the same name
58+
5959
```
60-
$ podman artifact add --append quay.io/myartifact/tarballs:latest /tmp/foobar.tar.gz
60+
$ podman artifact add --replace quay.io/myartifact/myml:latest /tmp/newfoobar.ml
6161
```
6262

63-
Override the media type of the artifact being added
63+
Add files to an existing OCI artifact
64+
6465
```
65-
$ podman artifact add --file-type text/yaml quay.io/myartifact/descriptors:latest /tmp/info.yaml
66+
$ podman artifact add --append quay.io/myimage/myartifact:latest /home/user/config.yaml
6667
```
6768

68-
6969
## SEE ALSO
7070
**[podman(1)](podman.1.md)**, **[podman-artifact(1)](podman-artifact.1.md)**
7171

7272
## HISTORY
73-
Jan 2025, Originally compiled by Brent Baude <[email protected]>
73+
Sept 2024, Originally compiled by Brent Baude <[email protected]>

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ podman\-artifact\-inspect - Inspect an OCI artifact
88

99
## DESCRIPTION
1010

11-
Inspect an artifact in the local store. The artifact can be referred to with either:
11+
Inspect an artifact in the local store and output the results in JSON format.
12+
The artifact can be referred to with either:
1213

1314
1. Fully qualified artifact name
1415
2. Full or partial digest of the artifact's manifest
1516

17+
The inspect output includes the artifact manifest with annotations. All artifacts
18+
automatically include a creation timestamp in the `org.opencontainers.image.created`
19+
annotation using RFC3339Nano format, showing when the artifact was initially created.
20+
1621
## OPTIONS
1722

1823
#### **--help**

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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,17 @@ func (ir *ImageEngine) ArtifactAdd(ctx context.Context, name string, artifactBlo
203203
return nil, err
204204
}
205205

206+
// If replace is true, try to remove existing artifact (ignore errors if it doesn't exist)
207+
if opts.Replace {
208+
_, _ = artStore.Remove(ctx, name)
209+
}
210+
206211
addOptions := types.AddOptions{
207212
Annotations: opts.Annotations,
208213
ArtifactMIMEType: opts.ArtifactMIMEType,
209214
Append: opts.Append,
210215
FileMIMEType: opts.FileMIMEType,
216+
Replace: opts.Replace,
211217
}
212218

213219
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)