Skip to content

Commit

Permalink
Add podman manifest rm --ignore
Browse files Browse the repository at this point in the history
When removing manifests, users should be allowed to ignore
ones that no longer exists.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
  • Loading branch information
rhatdan committed Nov 25, 2024
1 parent 9d3d0c7 commit 73905dd
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 8 deletions.
9 changes: 7 additions & 2 deletions cmd/podman/manifest/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (

"github.com/containers/podman/v5/cmd/podman/common"
"github.com/containers/podman/v5/cmd/podman/registry"
"github.com/containers/podman/v5/pkg/domain/entities"
"github.com/containers/podman/v5/pkg/errorhandling"
"github.com/spf13/cobra"
)

var (
rmCmd = &cobra.Command{
rmOptions = entities.ImageRemoveOptions{}
rmCmd = &cobra.Command{
Use: "rm LIST [LIST...]",
Short: "Remove manifest list or image index from local storage",
Long: "Remove manifest list or image index from local storage.",
Expand All @@ -27,10 +29,13 @@ func init() {
Command: rmCmd,
Parent: manifestCmd,
})

flags := rmCmd.Flags()
flags.BoolVarP(&rmOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified manifest is missing")
}

func rm(cmd *cobra.Command, args []string) error {
report, rmErrors := registry.ImageEngine().ManifestRm(context.Background(), args)
report, rmErrors := registry.ImageEngine().ManifestRm(context.Background(), args, rmOptions)
if report != nil {
for _, u := range report.Untagged {
fmt.Println("Untagged: " + u)
Expand Down
6 changes: 6 additions & 0 deletions docs/source/markdown/podman-manifest-rm.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ podman\-manifest\-rm - Remove manifest list or image index from local storage
## DESCRIPTION
Removes one or more locally stored manifest lists.

## OPTIONS

#### **--ignore**, **-i**

If a specified manifest does not exist in the local storage, ignore it and do not throw an error.

## EXAMPLE

podman manifest rm `<list>`
Expand Down
31 changes: 31 additions & 0 deletions docs/source/markdown/podman-manifest-rm.1.md.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
% podman-manifest-rm 1

## NAME
podman\-manifest\-rm - Remove manifest list or image index from local storage

## SYNOPSIS
**podman manifest rm** *list-or-index* [...]

## DESCRIPTION
Removes one or more locally stored manifest lists.

## OPTIONS

#### **--ignore**, **-i**

If a specified manifest does not exist in the local storage, ignore it and do not throw an error.

## EXAMPLE

podman manifest rm `<list>`

podman manifest rm listid1 listid2

**storage.conf** (`/etc/containers/storage.conf`)

storage.conf is the storage configuration file for all tools using containers/storage

The storage configuration file specifies all of the available container storage options for tools using shared container storage.

## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-manifest(1)](podman-manifest.1.md)**, **[containers-storage.conf(5)](https://github.com/containers/storage/blob/main/docs/containers-storage.conf.5.md)**
17 changes: 16 additions & 1 deletion pkg/api/handlers/libpod/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -739,16 +739,31 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) {

// ManifestDelete removes a manifest list from storage
func ManifestDelete(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
imageEngine := abi.ImageEngine{Libpod: runtime}

query := struct {
Ignore bool `schema:"ignore"`
}{
// Add defaults here once needed.
}

if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusBadRequest,
fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
return
}
opts := entities.ImageRemoveOptions{}
opts.Ignore = query.Ignore

name := utils.GetName(r)
if _, err := runtime.LibimageRuntime().LookupManifestList(name); err != nil {
utils.Error(w, http.StatusNotFound, err)
return
}

results, errs := imageEngine.ManifestRm(r.Context(), []string{name})
results, errs := imageEngine.ManifestRm(r.Context(), []string{name}, opts)
errsString := errorhandling.ErrorsToStrings(errs)
report := handlers.LibpodImagesRemoveReport{
ImageRemoveReport: *results,
Expand Down
2 changes: 1 addition & 1 deletion pkg/domain/entities/engine_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type ImageEngine interface { //nolint:interfacebloat
ManifestAddArtifact(ctx context.Context, name string, files []string, opts ManifestAddArtifactOptions) (string, error)
ManifestAnnotate(ctx context.Context, names, image string, opts ManifestAnnotateOptions) (string, error)
ManifestRemoveDigest(ctx context.Context, names, image string) (string, error)
ManifestRm(ctx context.Context, names []string) (*ImageRemoveReport, []error)
ManifestRm(ctx context.Context, names []string, imageRmOpts ImageRemoveOptions) (*ImageRemoveReport, []error)
ManifestPush(ctx context.Context, name, destination string, imagePushOpts ImagePushOptions) (string, error)
ManifestListClear(ctx context.Context, name string) (string, error)
Sign(ctx context.Context, names []string, options SignOptions) (*SignReport, error)
Expand Down
4 changes: 2 additions & 2 deletions pkg/domain/infra/abi/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,8 @@ func (ir *ImageEngine) ManifestRemoveDigest(ctx context.Context, name, image str
}

// ManifestRm removes the specified manifest list from storage
func (ir *ImageEngine) ManifestRm(ctx context.Context, names []string) (report *entities.ImageRemoveReport, rmErrors []error) {
return ir.Remove(ctx, names, entities.ImageRemoveOptions{LookupManifest: true})
func (ir *ImageEngine) ManifestRm(ctx context.Context, names []string, opts entities.ImageRemoveOptions) (report *entities.ImageRemoveReport, rmErrors []error) {
return ir.Remove(ctx, names, entities.ImageRemoveOptions{LookupManifest: true, Ignore: opts.Ignore})
}

// ManifestPush pushes a manifest list or image index to the destination
Expand Down
4 changes: 2 additions & 2 deletions pkg/domain/infra/tunnel/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ func (ir *ImageEngine) ManifestRemoveDigest(ctx context.Context, name string, im
}

// ManifestRm removes the specified manifest list from storage
func (ir *ImageEngine) ManifestRm(ctx context.Context, names []string) (*entities.ImageRemoveReport, []error) {
return ir.Remove(ctx, names, entities.ImageRemoveOptions{LookupManifest: true})
func (ir *ImageEngine) ManifestRm(ctx context.Context, names []string, opts entities.ImageRemoveOptions) (report *entities.ImageRemoveReport, rmErrors []error) {
return ir.Remove(ctx, names, entities.ImageRemoveOptions{LookupManifest: true, Ignore: opts.Ignore})
}

// ManifestPush pushes a manifest list or image index to the destination
Expand Down
4 changes: 4 additions & 0 deletions test/system/012-manifest.bats
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ function validate_instance_compression {
--tls-verify=false $mid \
$manifest1
run_podman manifest rm $manifest1
run_podman 1 manifest rm $manifest1
is "$output" "Error: $manifest1: image not known" "Missing manifest is reported"
run_podman manifest rm --ignore $manifest1
is "$output" "" "Missing manifest is ignored"

# Default is to require TLS; also test explicit opts
for opt in '' '--insecure=false' '--tls-verify=true' "--authfile=$authfile"; do
Expand Down

0 comments on commit 73905dd

Please sign in to comment.