Manifest remove, push
Implements podman manifest remove and podman manifest push. Signed-off-by: Qi Wang <qiwan@redhat.com>
This commit is contained in:
		
							parent
							
								
									0eb905ff2c
								
							
						
					
					
						commit
						5621f5199d
					
				|  | @ -18,7 +18,9 @@ var ( | |||
| 		Example: `podman manifest add mylist:v1.11 image:v1.11-amd64 | ||||
|   podman manifest create localhost/list | ||||
|   podman manifest inspect localhost/list | ||||
|   podman manifest annotate --annotation left=right mylist:v1.11 image:v1.11-amd64`, | ||||
|   podman manifest annotate --annotation left=right mylist:v1.11 image:v1.11-amd64 | ||||
|   podman manifest push mylist:v1.11 quay.io/myimagelist | ||||
|   podman manifest remove mylist:v1.11 sha256:15352d97781ffdf357bf3459c037be3efac4133dc9070c2dce7eca7c05c3e736`, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,66 @@ | |||
| package manifest | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"github.com/containers/common/pkg/auth" | ||||
| 	"github.com/containers/libpod/cmd/podman/registry" | ||||
| 	"github.com/containers/libpod/pkg/domain/entities" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	manifestPushOpts = entities.ManifestPushOptions{} | ||||
| 	pushCmd          = &cobra.Command{ | ||||
| 		Use:     "push [flags] SOURCE DESTINATION", | ||||
| 		Short:   "Push a manifest list or image index to a registry", | ||||
| 		Long:    "Pushes manifest lists and image indexes to registries.", | ||||
| 		RunE:    push, | ||||
| 		Example: `podman manifest push mylist:v1.11 quay.io/myimagelist`, | ||||
| 		Args:    cobra.ExactArgs(2), | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	registry.Commands = append(registry.Commands, registry.CliCommand{ | ||||
| 		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, | ||||
| 		Command: pushCmd, | ||||
| 		Parent:  manifestCmd, | ||||
| 	}) | ||||
| 	flags := pushCmd.Flags() | ||||
| 	flags.BoolVar(&manifestPushOpts.Purge, "purge", false, "remove the manifest list if push succeeds") | ||||
| 	flags.BoolVar(&manifestPushOpts.All, "all", false, "also push the images in the list") | ||||
| 	flags.StringVar(&manifestPushOpts.Authfile, "authfile", auth.GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") | ||||
| 	flags.StringVar(&manifestPushOpts.CertDir, "cert-dir", "", "use certificates at the specified path to access the registry") | ||||
| 	flags.StringVar(&manifestPushOpts.Creds, "creds", "", "use `[username[:password]]` for accessing the registry") | ||||
| 	flags.StringVar(&manifestPushOpts.DigestFile, "digestfile", "", "after copying the image, write the digest of the resulting digest to the file") | ||||
| 	flags.StringVarP(&manifestPushOpts.Format, "format", "f", "", "manifest type (oci or v2s2) to attempt to use when pushing the manifest list (default is manifest type of source)") | ||||
| 	flags.BoolVarP(&manifestPushOpts.RemoveSignatures, "remove-signatures", "", false, "don't copy signatures when pushing images") | ||||
| 	flags.StringVar(&manifestPushOpts.SignBy, "sign-by", "", "sign the image using a GPG key with the specified `FINGERPRINT`") | ||||
| 	flags.BoolVar(&manifestPushOpts.TlsVerify, "tls-verify", true, "require HTTPS and verify certificates when accessing the registry") | ||||
| 	flags.BoolVarP(&manifestPushOpts.Quiet, "quiet", "q", false, "don't output progress information when pushing lists") | ||||
| 	if registry.IsRemote() { | ||||
| 		_ = flags.MarkHidden("authfile") | ||||
| 		_ = flags.MarkHidden("cert-dir") | ||||
| 		_ = flags.MarkHidden("tls-verify") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func push(cmd *cobra.Command, args []string) error { | ||||
| 	if err := auth.CheckAuthFile(manifestPushOpts.Authfile); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	listImageSpec := args[0] | ||||
| 	destSpec := args[1] | ||||
| 	if listImageSpec == "" { | ||||
| 		return errors.Errorf(`invalid image name "%s"`, listImageSpec) | ||||
| 	} | ||||
| 	if destSpec == "" { | ||||
| 		return errors.Errorf(`invalid destination "%s"`, destSpec) | ||||
| 	} | ||||
| 	if err := registry.ImageEngine().ManifestPush(context.Background(), args, manifestPushOpts); err != nil { | ||||
| 		return errors.Wrapf(err, "error pushing manifest %s to %s", listImageSpec, destSpec) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,47 @@ | |||
| package manifest | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/containers/libpod/cmd/podman/registry" | ||||
| 	"github.com/containers/libpod/pkg/domain/entities" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	removeCmd = &cobra.Command{ | ||||
| 		Use:     "remove [flags] LIST IMAGE", | ||||
| 		Short:   "Remove an entry from a manifest list or image index", | ||||
| 		Long:    "Removes an image from a manifest list or image index.", | ||||
| 		RunE:    remove, | ||||
| 		Example: `podman manifest remove mylist:v1.11 sha256:15352d97781ffdf357bf3459c037be3efac4133dc9070c2dce7eca7c05c3e736`, | ||||
| 		Args:    cobra.ExactArgs(2), | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	registry.Commands = append(registry.Commands, registry.CliCommand{ | ||||
| 		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, | ||||
| 		Command: removeCmd, | ||||
| 		Parent:  manifestCmd, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func remove(cmd *cobra.Command, args []string) error { | ||||
| 	listImageSpec := args[0] | ||||
| 	instanceSpec := args[1] | ||||
| 	if listImageSpec == "" { | ||||
| 		return errors.Errorf(`invalid image name "%s"`, listImageSpec) | ||||
| 	} | ||||
| 	if instanceSpec == "" { | ||||
| 		return errors.Errorf(`invalid image digest "%s"`, instanceSpec) | ||||
| 	} | ||||
| 	updatedListID, err := registry.ImageEngine().ManifestRemove(context.Background(), args) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "error removing from manifest list %s", listImageSpec) | ||||
| 	} | ||||
| 	fmt.Printf("%s\n", updatedListID) | ||||
| 	return nil | ||||
| } | ||||
|  | @ -1742,6 +1742,8 @@ _podman_manifest() { | |||
|      add | ||||
|      create | ||||
|      inspect | ||||
|      push | ||||
|      remove | ||||
|     " | ||||
|      __podman_subcommands "$subcommands" && return | ||||
| 
 | ||||
|  | @ -1838,6 +1840,57 @@ _podman_manifest_inspect() { | |||
|     esac | ||||
| } | ||||
| 
 | ||||
| _podman_manifest_push() { | ||||
| 	local options_with_args=" | ||||
|       --authfile | ||||
|       --cert-dir | ||||
|       --creds | ||||
|       --digestfile | ||||
|       --format | ||||
|       -f | ||||
|       --sign-by | ||||
|       --signature-policy, | ||||
|     " | ||||
| 
 | ||||
|     local boolean_options=" | ||||
|       --all | ||||
|       --purge | ||||
|       --help | ||||
|       -h | ||||
|       --remove-signatures | ||||
|       --tls-verify | ||||
|       --quiet | ||||
|     " | ||||
| 
 | ||||
|   _complete_ "$options_with_args" "$boolean_options" | ||||
|     case "$cur" in | ||||
|         -*) | ||||
|             COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur")) | ||||
|             ;; | ||||
|         *) | ||||
|             __podman_complete_images --id | ||||
|             ;; | ||||
|     esac | ||||
| } | ||||
| 
 | ||||
| _podman_manifest_remove() { | ||||
| 	local options_with_args=" | ||||
|     " | ||||
| 
 | ||||
|     local boolean_options=" | ||||
|     " | ||||
| 
 | ||||
|   _complete_ "$options_with_args" "$boolean_options" | ||||
|     case "$cur" in | ||||
|         -*) | ||||
|             COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur")) | ||||
|             ;; | ||||
|         *) | ||||
|             __podman_complete_images --id | ||||
|             ;; | ||||
|     esac | ||||
| } | ||||
| 
 | ||||
| _podman_pull() { | ||||
|     local options_with_args=" | ||||
|     --authfile | ||||
|  |  | |||
|  | @ -73,4 +73,4 @@ podman manifest add --arch arm64 --variant v8 mylist:v1.11 docker://71c201d10fff | |||
| ``` | ||||
| 
 | ||||
| ## SEE ALSO | ||||
| podman(1), podman-manifest(1), podman-manifest-create(1), podman-manifest-inspect(1), podman-rmi(1) | ||||
| podman(1), podman-manifest(1), podman-manifest-create(1), podman-manifest-inspect(1), podman-manifest-push(1), podman-manifest-remove(1), podman-rmi(1) | ||||
|  |  | |||
|  | @ -40,4 +40,4 @@ podman manifest create --all mylist:v1.11 docker://fedora | |||
| ``` | ||||
| 
 | ||||
| ## SEE ALSO | ||||
| podman(1), podman-manifest(1), podman-manifest-add(1), podman-manifest-inspect(1), podman-rmi(1) | ||||
| podman(1), podman-manifest(1), podman-manifest-add(1), podman-manifest-inspect(1), podman-manifest-push(1), podman-manifest-remove(1), podman-rmi(1) | ||||
|  |  | |||
|  | @ -21,4 +21,4 @@ podman manifest inspect mylist:v1.11 | |||
| ``` | ||||
| 
 | ||||
| ## SEE ALSO | ||||
| podman(1), podman-manifest(1), podman-manifest-create(1), podman-manifest-add(1), podman-rmi(1) | ||||
| podman(1), podman-manifest(1), podman-manifest-create(1), podman-manifest-add(1), podman-manifest-push(1), podman-manifest-remove(1), podman-rmi(1) | ||||
|  |  | |||
|  | @ -0,0 +1,72 @@ | |||
| % podman-manifest-push(1) | ||||
| 
 | ||||
| ## NAME | ||||
| podman\-manifest\-push - Push a manifest list or image index to a registry | ||||
| 
 | ||||
| ## SYNOPSIS | ||||
| **podman manifest push** [options...] *listnameorindexname* *transport:details* | ||||
| 
 | ||||
| ## DESCRIPTION | ||||
| Pushes a manifest list or image index to a registry. | ||||
| 
 | ||||
| ## RETURN VALUE | ||||
| The list image's ID and the digest of the image's manifest. | ||||
| 
 | ||||
| ## OPTIONS | ||||
| 
 | ||||
| **--all** | ||||
| 
 | ||||
| Push the images mentioned in the manifest list or image index, in addition to | ||||
| the list or index itself. | ||||
| 
 | ||||
| **--authfile** *path* | ||||
| 
 | ||||
| Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`. | ||||
| If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`. (Not available for remote commands) | ||||
| 
 | ||||
| Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE | ||||
| environment variable. `export REGISTRY_AUTH_FILE=path` | ||||
| 
 | ||||
| **--cert-dir** *path* | ||||
| 
 | ||||
| Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. | ||||
| Default certificates directory is _/etc/containers/certs.d_. (Not available for remote commands) | ||||
| 
 | ||||
| **--creds** *creds* | ||||
| 
 | ||||
| The [username[:password]] to use to authenticate with the registry if required. | ||||
| If one or both values are not supplied, a command line prompt will appear and the | ||||
| value can be entered.  The password is entered without echo. | ||||
| 
 | ||||
| **--digestfile** *Digestfile* | ||||
| 
 | ||||
| After copying the image, write the digest of the resulting image to the file. | ||||
| 
 | ||||
| **--format, -f** | ||||
| 
 | ||||
| Manifest list type (oci or v2s2) to use when pushing the list (default is oci). | ||||
| 
 | ||||
| **--purge** | ||||
| 
 | ||||
| Delete the manifest list or image index from local storage if pushing succeeds. | ||||
| 
 | ||||
| **--remove-signatures** | ||||
| 
 | ||||
| Don't copy signatures when pushing images. | ||||
| 
 | ||||
| **--sign-by** *fingerprint* | ||||
| 
 | ||||
| Sign the pushed images using the GPG key that matches the specified fingerprint. | ||||
| 
 | ||||
| **--tls-verify** *bool-value* | ||||
| 
 | ||||
| Require HTTPS and verify certificates when talking to container registries (defaults to true) (Not available for remote commands) | ||||
| 
 | ||||
| ## EXAMPLE | ||||
| 
 | ||||
| ``` | ||||
| podman manifest push mylist:v1.11 docker://registry.example.org/mylist:v1.11 | ||||
| ``` | ||||
| 
 | ||||
| ## SEE ALSO | ||||
| podman(1), podman-manifest(1), podman-manifest-add(1), podman-manifest-create(1), podman-manifest-inspect(1), podman-manifest-remove(1), podman-rmi(1) | ||||
|  | @ -0,0 +1,23 @@ | |||
| % podman-manifest-remove(1) | ||||
| 
 | ||||
| ## NAME | ||||
| podman\-manifest\-remove - Remove an image from a manifest list or image index | ||||
| 
 | ||||
| ## SYNOPSIS | ||||
| **podman manifest remove** *listnameorindexname* *transport:details* | ||||
| 
 | ||||
| ## DESCRIPTION | ||||
| Removes the image with the specified digest from the specified manifest list or image index. | ||||
| 
 | ||||
| ## RETURN VALUE | ||||
| The list image's ID and the digest of the removed image's manifest. | ||||
| 
 | ||||
| ## EXAMPLE | ||||
| 
 | ||||
| ``` | ||||
| podman manifest remove mylist:v1.11 sha256:cb8a924afdf0229ef7515d9e5b3024e23b3eb03ddbba287f4a19c6ac90b8d221 | ||||
| e604eabaaee4858232761b4fef84e2316ed8f93e15eceafce845966ee3400036 :sha256:cb8a924afdf0229ef7515d9e5b3024e23b3eb03ddbba287f4a19c6ac90b8d221 | ||||
| ``` | ||||
| 
 | ||||
| ## SEE ALSO | ||||
| podman(1), podman-manifest(1), podman-manifest-add(1), podman-manifest-create(1), podman-manifest-inspect(1), podman-manifest-push(1), podman-rmi(1) | ||||
|  | @ -19,6 +19,8 @@ The `podman manifest` command provides subcommands which can be used to: | |||
| | annotate | [podman-manifest-annotate(1)](podman-manifest-annotate.1.md) | Add or update information about an entry in a manifest list or image index. | | ||||
| | create   | [podman-manifest-create(1)](podman-manifest-create.1.md)     | Create a manifest list or image index.                                      | | ||||
| | inspect  | [podman-manifest-inspect(1)](podman-manifest-inspect.1.md)   | Display a manifest list or image index.                                     | | ||||
| | push     | [podman-manifest-push(1)](podman-manifest-push.1.md)         | Push a manifest list or image index to a registry.                          | | ||||
| | remove   | [podman-manifest-remove(1)](podman-manifest-remove.1.md)     | Remove an image from a manifest list or image index.                        | | ||||
| 
 | ||||
| ## SEE ALSO | ||||
| podman(1), podman-manifest-add(1), podman-manifest-annotate(1), podman-manifest-create(1), podman-manifest-inspect(1) | ||||
| podman(1), podman-manifest-add(1), podman-manifest-annotate(1), podman-manifest-create(1), podman-manifest-inspect(1), podman-manifest-push(1), podman-manifest-remove(1) | ||||
|  |  | |||
|  | @ -30,4 +30,6 @@ type ImageEngine interface { | |||
| 	ManifestInspect(ctx context.Context, name string) ([]byte, error) | ||||
| 	ManifestAdd(ctx context.Context, opts ManifestAddOptions) (string, error) | ||||
| 	ManifestAnnotate(ctx context.Context, names []string, opts ManifestAnnotateOptions) (string, error) | ||||
| 	ManifestRemove(ctx context.Context, names []string) (string, error) | ||||
| 	ManifestPush(ctx context.Context, names []string, manifestPushOpts ManifestPushOptions) error | ||||
| } | ||||
|  |  | |||
|  | @ -24,3 +24,8 @@ type ManifestAnnotateOptions struct { | |||
| 	OSVersion  string   `json:"os_version" schema:"os_version"` | ||||
| 	Variant    string   `json:"variant" schema:"variant"` | ||||
| } | ||||
| 
 | ||||
| type ManifestPushOptions struct { | ||||
| 	Purge, Quiet, All, TlsVerify, RemoveSignatures       bool | ||||
| 	Authfile, CertDir, Creds, DigestFile, Format, SignBy string | ||||
| } | ||||
|  |  | |||
|  | @ -6,15 +6,21 @@ import ( | |||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/containers/buildah/manifests" | ||||
| 	buildahUtil "github.com/containers/buildah/util" | ||||
| 	cp "github.com/containers/image/v5/copy" | ||||
| 	"github.com/containers/image/v5/docker" | ||||
| 	"github.com/containers/image/v5/manifest" | ||||
| 	"github.com/containers/image/v5/transports/alltransports" | ||||
| 	libpodImage "github.com/containers/libpod/libpod/image" | ||||
| 	"github.com/containers/libpod/pkg/domain/entities" | ||||
| 	"github.com/containers/libpod/pkg/util" | ||||
| 	"github.com/opencontainers/go-digest" | ||||
| 	imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" | ||||
| 
 | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | @ -137,3 +143,68 @@ func (ir *ImageEngine) ManifestAnnotate(ctx context.Context, names []string, opt | |||
| 	} | ||||
| 	return "", err | ||||
| } | ||||
| 
 | ||||
| // ManifestRemove removes specified digest from the specified manifest list
 | ||||
| func (ir *ImageEngine) ManifestRemove(ctx context.Context, names []string) (string, error) { | ||||
| 	instanceDigest, err := digest.Parse(names[1]) | ||||
| 	if err != nil { | ||||
| 		return "", errors.Errorf(`invalid image digest "%s": %v`, names[1], err) | ||||
| 	} | ||||
| 	listImage, err := ir.Libpod.ImageRuntime().NewFromLocal(names[0]) | ||||
| 	if err != nil { | ||||
| 		return "", errors.Wrapf(err, "error retriving local image from image name %s", names[0]) | ||||
| 	} | ||||
| 	updatedListID, err := listImage.RemoveManifest(instanceDigest) | ||||
| 	if err == nil { | ||||
| 		return fmt.Sprintf("%s :%s\n", updatedListID, instanceDigest.String()), nil | ||||
| 	} | ||||
| 	return "", err | ||||
| } | ||||
| 
 | ||||
| // ManifestPush pushes a manifest list or image index to the destination
 | ||||
| func (ir *ImageEngine) ManifestPush(ctx context.Context, names []string, opts entities.ManifestPushOptions) error { | ||||
| 	listImage, err := ir.Libpod.ImageRuntime().NewFromLocal(names[0]) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "error retriving local image from image name %s", names[0]) | ||||
| 	} | ||||
| 	dest, err := alltransports.ParseImageName(names[1]) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	var manifestType string | ||||
| 	if opts.Format != "" { | ||||
| 		switch opts.Format { | ||||
| 		case "oci": | ||||
| 			manifestType = imgspecv1.MediaTypeImageManifest | ||||
| 		case "v2s2", "docker": | ||||
| 			manifestType = manifest.DockerV2Schema2MediaType | ||||
| 		default: | ||||
| 			return errors.Errorf("unknown format %q. Choose on of the supported formats: 'oci' or 'v2s2'", opts.Format) | ||||
| 		} | ||||
| 	} | ||||
| 	options := manifests.PushOptions{ | ||||
| 		Store:              ir.Libpod.GetStore(), | ||||
| 		SystemContext:      ir.Libpod.SystemContext(), | ||||
| 		ImageListSelection: cp.CopySpecificImages, | ||||
| 		Instances:          nil, | ||||
| 		RemoveSignatures:   opts.RemoveSignatures, | ||||
| 		SignBy:             opts.SignBy, | ||||
| 		ManifestType:       manifestType, | ||||
| 	} | ||||
| 	if opts.All { | ||||
| 		options.ImageListSelection = cp.CopyAllImages | ||||
| 	} | ||||
| 	if !opts.Quiet { | ||||
| 		options.ReportWriter = os.Stderr | ||||
| 	} | ||||
| 	digest, err := listImage.PushManifest(dest, options) | ||||
| 	if err == nil && opts.Purge { | ||||
| 		_, err = ir.Libpod.GetStore().DeleteImage(listImage.ID(), true) | ||||
| 	} | ||||
| 	if opts.DigestFile != "" { | ||||
| 		if err = ioutil.WriteFile(opts.DigestFile, []byte(digest.String()), 0644); err != nil { | ||||
| 			return buildahUtil.GetFailureCause(err, errors.Wrapf(err, "failed to write digest to file %q", opts.DigestFile)) | ||||
| 		} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  |  | |||
|  | @ -91,3 +91,18 @@ func (ir *ImageEngine) ManifestAnnotate(ctx context.Context, names []string, opt | |||
| 	} | ||||
| 	return fmt.Sprintf("%s :%s", updatedListID, names[1]), nil | ||||
| } | ||||
| 
 | ||||
| // ManifestRemove removes the digest from manifest list
 | ||||
| func (ir *ImageEngine) ManifestRemove(ctx context.Context, names []string) (string, error) { | ||||
| 	updatedListID, err := manifests.Remove(ctx, names[0], names[1]) | ||||
| 	if err != nil { | ||||
| 		return updatedListID, errors.Wrapf(err, "error removing from manifest %s", names[0]) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%s :%s\n", updatedListID, names[1]), nil | ||||
| } | ||||
| 
 | ||||
| // ManifestPush pushes a manifest list or image index to the destination
 | ||||
| func (ir *ImageEngine) ManifestPush(ctx context.Context, names []string, opts entities.ManifestPushOptions) error { | ||||
| 	_, err := manifests.Push(ctx, names[0], &names[1], &opts.All) | ||||
| 	return err | ||||
| } | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ package integration | |||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	. "github.com/containers/libpod/test/utils" | ||||
| 	. "github.com/onsi/ginkgo" | ||||
|  | @ -114,4 +116,90 @@ var _ = Describe("Podman manifest", func() { | |||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		Expect(session.OutputToString()).To(ContainSubstring(`"architecture": "bar"`)) | ||||
| 	}) | ||||
| 
 | ||||
| 	It("podman manifest remove", func() { | ||||
| 		session := podmanTest.Podman([]string{"manifest", "create", "foo"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "add", "--all", "foo", imageList}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "inspect", "foo"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		Expect(session.OutputToString()).To(ContainSubstring(imageListARM64InstanceDigest)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "remove", "foo", imageListARM64InstanceDigest}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "inspect", "foo"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		Expect(session.OutputToString()).To(ContainSubstring(imageListAMD64InstanceDigest)) | ||||
| 		Expect(session.OutputToString()).To(ContainSubstring(imageListARMInstanceDigest)) | ||||
| 		Expect(session.OutputToString()).To(ContainSubstring(imageListPPC64LEInstanceDigest)) | ||||
| 		Expect(session.OutputToString()).To(ContainSubstring(imageListS390XInstanceDigest)) | ||||
| 		Expect(session.OutputToString()).To(Not(ContainSubstring(imageListARM64InstanceDigest))) | ||||
| 	}) | ||||
| 
 | ||||
| 	It("podman manifest remove not-found", func() { | ||||
| 		session := podmanTest.Podman([]string{"manifest", "create", "foo"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "add", "foo", imageList}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "remove", "foo", "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Not(Equal(0))) | ||||
| 	}) | ||||
| 
 | ||||
| 	It("podman manifest push", func() { | ||||
| 		session := podmanTest.Podman([]string{"manifest", "create", "foo"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "add", "--all", "foo", imageList}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		dest := filepath.Join(podmanTest.TempDir, "pushed") | ||||
| 		err := os.MkdirAll(dest, os.ModePerm) | ||||
| 		Expect(err).To(BeNil()) | ||||
| 		defer func() { | ||||
| 			os.RemoveAll(dest) | ||||
| 		}() | ||||
| 		session = podmanTest.Podman([]string{"manifest", "push", "--all", "foo", "dir:" + dest}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		files, err := filepath.Glob(dest + string(os.PathSeparator) + "*") | ||||
| 		Expect(err).To(BeNil()) | ||||
| 		check := SystemExec("sha256sum", files) | ||||
| 		check.WaitWithDefaultTimeout() | ||||
| 		Expect(check.ExitCode()).To(Equal(0)) | ||||
| 		prefix := "sha256:" | ||||
| 		Expect(check.OutputToString()).To(ContainSubstring(strings.TrimPrefix(imageListAMD64InstanceDigest, prefix))) | ||||
| 		Expect(check.OutputToString()).To(ContainSubstring(strings.TrimPrefix(imageListARMInstanceDigest, prefix))) | ||||
| 		Expect(check.OutputToString()).To(ContainSubstring(strings.TrimPrefix(imageListPPC64LEInstanceDigest, prefix))) | ||||
| 		Expect(check.OutputToString()).To(ContainSubstring(strings.TrimPrefix(imageListS390XInstanceDigest, prefix))) | ||||
| 		Expect(check.OutputToString()).To(ContainSubstring(strings.TrimPrefix(imageListARM64InstanceDigest, prefix))) | ||||
| 	}) | ||||
| 
 | ||||
| 	It("podman manifest push purge", func() { | ||||
| 		session := podmanTest.Podman([]string{"manifest", "create", "foo"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "add", "foo", imageList}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		dest := filepath.Join(podmanTest.TempDir, "pushed") | ||||
| 		err := os.MkdirAll(dest, os.ModePerm) | ||||
| 		Expect(err).To(BeNil()) | ||||
| 		defer func() { | ||||
| 			os.RemoveAll(dest) | ||||
| 		}() | ||||
| 		session = podmanTest.Podman([]string{"manifest", "push", "--purge", "foo", "dir:" + dest}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| 		session = podmanTest.Podman([]string{"manifest", "inspect", "foo"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Not(Equal(0))) | ||||
| 	}) | ||||
| }) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue