mirror of https://github.com/containers/podman.git
Add manifest type conversion to kpod push
User can select from 3 manifest types: oci, v2s1, or v2s2 e.g kpod push --format v2s2 alpine dir:my-directory Added "compress" flag to enable compression when true Signed-off-by: umohnani8 <umohnani@redhat.com> Closes: #126 Approved by: rhatdan
This commit is contained in:
parent
bf0d359047
commit
1e7d880b56
|
|
@ -56,7 +56,7 @@ func loginCmd(c *cli.Context) error {
|
|||
server = args[0]
|
||||
}
|
||||
|
||||
sc := common.GetSystemContext("", c.String("authfile"))
|
||||
sc := common.GetSystemContext("", c.String("authfile"), false)
|
||||
|
||||
// username of user logged in to server (if one exists)
|
||||
userFromAuthFile := config.GetUserLoggedIn(sc, server)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func logoutCmd(c *cli.Context) error {
|
|||
server = args[0]
|
||||
}
|
||||
|
||||
sc := common.GetSystemContext("", c.String("authfile"))
|
||||
sc := common.GetSystemContext("", c.String("authfile"), false)
|
||||
|
||||
if c.Bool("all") {
|
||||
if err := config.RemoveAllAuthentication(sc); err != nil {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/libpod/libpod"
|
||||
"github.com/projectatomic/libpod/libpod/common"
|
||||
|
|
@ -29,6 +32,14 @@ var (
|
|||
Name: "cert-dir",
|
||||
Usage: "`pathname` of a directory containing TLS certificates and keys",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "compress",
|
||||
Usage: "compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format, f",
|
||||
Usage: "manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir:' transport (default is manifest type of source)",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "tls-verify",
|
||||
Usage: "require HTTPS and verify certificates when contacting registries (default: true)",
|
||||
|
|
@ -75,8 +86,16 @@ func pushCmd(c *cli.Context) error {
|
|||
if err := validateFlags(c, pushFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
srcName := c.Args().Get(0)
|
||||
destName := c.Args().Get(1)
|
||||
srcName := args[0]
|
||||
destName := args[1]
|
||||
|
||||
// --compress and --format can only be used for the "dir" transport
|
||||
splitArg := strings.SplitN(destName, ":", 2)
|
||||
if c.IsSet("compress") || c.IsSet("format") {
|
||||
if splitArg[0] != libpod.DirTransport {
|
||||
return errors.Errorf("--compress and --format can be set only when pushing to a directory using the 'dir' transport")
|
||||
}
|
||||
}
|
||||
|
||||
registryCredsString := c.String("creds")
|
||||
certPath := c.String("cert-dir")
|
||||
|
|
@ -112,6 +131,20 @@ func pushCmd(c *cli.Context) error {
|
|||
writer = os.Stdout
|
||||
}
|
||||
|
||||
var manifestType string
|
||||
if c.IsSet("format") {
|
||||
switch c.String("format") {
|
||||
case "oci":
|
||||
manifestType = imgspecv1.MediaTypeImageManifest
|
||||
case "v2s1":
|
||||
manifestType = manifest.DockerV2Schema1SignedMediaType
|
||||
case "v2s2", "docker":
|
||||
manifestType = manifest.DockerV2Schema2MediaType
|
||||
default:
|
||||
return fmt.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", c.String("format"))
|
||||
}
|
||||
}
|
||||
|
||||
options := libpod.CopyOptions{
|
||||
Compression: archive.Uncompressed,
|
||||
SignaturePolicyPath: c.String("signature-policy"),
|
||||
|
|
@ -124,8 +157,10 @@ func pushCmd(c *cli.Context) error {
|
|||
RemoveSignatures: removeSignatures,
|
||||
SignBy: signBy,
|
||||
},
|
||||
AuthFile: c.String("authfile"),
|
||||
Writer: writer,
|
||||
AuthFile: c.String("authfile"),
|
||||
Writer: writer,
|
||||
ManifestMIMEType: manifestType,
|
||||
ForceCompress: c.Bool("compress"),
|
||||
}
|
||||
|
||||
return runtime.PushImage(srcName, destName, options)
|
||||
|
|
|
|||
|
|
@ -921,8 +921,7 @@ _kpod_mount() {
|
|||
|
||||
_kpod_push() {
|
||||
local boolean_options="
|
||||
--disable-compression
|
||||
-D
|
||||
--compress
|
||||
--quiet
|
||||
-q
|
||||
--remove-signatures
|
||||
|
|
@ -931,6 +930,7 @@ _kpod_push() {
|
|||
|
||||
local options_with_args="
|
||||
--authfile
|
||||
--format
|
||||
--cert-dir
|
||||
--creds
|
||||
--sign-by
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ kpod push - Push an image from local storage to elsewhere
|
|||
**kpod** **push** [*options* [...]] **imageID** [**destination**]
|
||||
|
||||
## DESCRIPTION
|
||||
Pushes an image from local storage to a specified destination, decompressing
|
||||
and recompressing layers as needed.
|
||||
Pushes an image from local storage to a specified destination.
|
||||
Push is mainly used to push images to registries, however **kpod push**
|
||||
can be used to save images to tarballs and directories using the following
|
||||
transports: **dir:**, **docker-archive:**, **docker-daemon:**, **oci-archive:**, and **ostree:**.
|
||||
|
||||
## imageID
|
||||
Image stored in local container/storage
|
||||
|
|
@ -19,6 +21,8 @@ Image stored in local container/storage
|
|||
|
||||
The DESTINATION is a location to store container images
|
||||
The Image "DESTINATION" uses a "transport":"details" format.
|
||||
If a transport is not given, kpod push will attempt to push
|
||||
to a registry.
|
||||
|
||||
Multiple transports are supported:
|
||||
|
||||
|
|
@ -55,9 +59,15 @@ Credentials (USERNAME:PASSWORD) to use for authenticating to a registry
|
|||
|
||||
Pathname of a directory containing TLS certificates and keys
|
||||
|
||||
**--disable-compression, -D**
|
||||
**--compress**
|
||||
|
||||
Don't compress copies of filesystem layers which will be pushed
|
||||
Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type, compressed or uncompressed, as source)
|
||||
Note: This flag can only be set when using the **dir** transport
|
||||
|
||||
**--format, -f**
|
||||
|
||||
Manifest Type (oci, v2s1, or v2s2) to use when pushing an image to a directory using the 'dir:' transport (default is manifest type of source)
|
||||
Note: This flag can only be set when using the **dir** transport
|
||||
|
||||
**--quiet, -q**
|
||||
|
||||
|
|
@ -113,5 +123,19 @@ Writing manifest to image destination
|
|||
Storing signatures
|
||||
```
|
||||
|
||||
This example pushes the rhel7 image to rhel7-dir with the "oci" manifest type
|
||||
```
|
||||
# kpod push --format oci registry.access.redhat.com/rhel7 dir:rhel7-dir
|
||||
Getting image source signatures
|
||||
Copying blob sha256:9cadd93b16ff2a0c51ac967ea2abfadfac50cfa3af8b5bf983d89b8f8647f3e4
|
||||
71.41 MB / 71.41 MB [======================================================] 9s
|
||||
Copying blob sha256:4aa565ad8b7a87248163ce7dba1dd3894821aac97e846b932ff6b8ef9a8a508a
|
||||
1.21 KB / 1.21 KB [========================================================] 0s
|
||||
Copying config sha256:f1b09a81455c351eaa484b61aacd048ab613c08e4c5d1da80c4c46301b03cf3b
|
||||
3.01 KB / 3.01 KB [========================================================] 0s
|
||||
Writing manifest to image destination
|
||||
Storing signatures
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
kpod(1), kpod-pull(1), crio(8), crio.conf(5), docker-login(1)
|
||||
|
|
|
|||
|
|
@ -16,31 +16,33 @@ var (
|
|||
)
|
||||
|
||||
// GetCopyOptions constructs a new containers/image/copy.Options{} struct from the given parameters
|
||||
func GetCopyOptions(reportWriter io.Writer, signaturePolicyPath string, srcDockerRegistry, destDockerRegistry *DockerRegistryOptions, signing SigningOptions, authFile string) *cp.Options {
|
||||
func GetCopyOptions(reportWriter io.Writer, signaturePolicyPath string, srcDockerRegistry, destDockerRegistry *DockerRegistryOptions, signing SigningOptions, authFile, manifestType string, forceCompress bool) *cp.Options {
|
||||
if srcDockerRegistry == nil {
|
||||
srcDockerRegistry = &DockerRegistryOptions{}
|
||||
}
|
||||
if destDockerRegistry == nil {
|
||||
destDockerRegistry = &DockerRegistryOptions{}
|
||||
}
|
||||
srcContext := srcDockerRegistry.GetSystemContext(signaturePolicyPath, authFile)
|
||||
destContext := destDockerRegistry.GetSystemContext(signaturePolicyPath, authFile)
|
||||
srcContext := srcDockerRegistry.GetSystemContext(signaturePolicyPath, authFile, forceCompress)
|
||||
destContext := destDockerRegistry.GetSystemContext(signaturePolicyPath, authFile, forceCompress)
|
||||
return &cp.Options{
|
||||
RemoveSignatures: signing.RemoveSignatures,
|
||||
SignBy: signing.SignBy,
|
||||
ReportWriter: reportWriter,
|
||||
SourceCtx: srcContext,
|
||||
DestinationCtx: destContext,
|
||||
RemoveSignatures: signing.RemoveSignatures,
|
||||
SignBy: signing.SignBy,
|
||||
ReportWriter: reportWriter,
|
||||
SourceCtx: srcContext,
|
||||
DestinationCtx: destContext,
|
||||
ForceManifestMIMEType: manifestType,
|
||||
}
|
||||
}
|
||||
|
||||
// GetSystemContext Constructs a new containers/image/types.SystemContext{} struct from the given signaturePolicy path
|
||||
func GetSystemContext(signaturePolicyPath, authFilePath string) *types.SystemContext {
|
||||
func GetSystemContext(signaturePolicyPath, authFilePath string, forceCompress bool) *types.SystemContext {
|
||||
sc := &types.SystemContext{}
|
||||
if signaturePolicyPath != "" {
|
||||
sc.SignaturePolicyPath = signaturePolicyPath
|
||||
}
|
||||
sc.AuthFilePath = authFilePath
|
||||
sc.DirForceCompress = forceCompress
|
||||
return sc
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,14 @@ type DockerRegistryOptions struct {
|
|||
|
||||
// GetSystemContext constructs a new system context from the given signaturePolicy path and the
|
||||
// values in the DockerRegistryOptions
|
||||
func (o DockerRegistryOptions) GetSystemContext(signaturePolicyPath, authFile string) *types.SystemContext {
|
||||
func (o DockerRegistryOptions) GetSystemContext(signaturePolicyPath, authFile string, forceCompress bool) *types.SystemContext {
|
||||
sc := &types.SystemContext{
|
||||
SignaturePolicyPath: signaturePolicyPath,
|
||||
DockerAuthConfig: o.DockerRegistryCreds,
|
||||
DockerCertPath: o.DockerCertPath,
|
||||
DockerInsecureSkipTLSVerify: o.DockerInsecureSkipTLSVerify,
|
||||
AuthFilePath: authFile,
|
||||
DirForceCompress: forceCompress,
|
||||
}
|
||||
return sc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ type CopyOptions struct {
|
|||
Reference string
|
||||
// ImageConfig is the Image spec for the image created when a tar archive is imported
|
||||
ImageConfig ociv1.Image
|
||||
// ManifestMIMEType is the manifest type of the image when saving to a directory
|
||||
ManifestMIMEType string
|
||||
// ForceCompress compresses the image layers when saving to a directory using the dir transport if true
|
||||
ForceCompress bool
|
||||
}
|
||||
|
||||
// Image API
|
||||
|
|
@ -643,7 +647,7 @@ func (r *Runtime) PullImage(imgName string, options CopyOptions) (string, error)
|
|||
signaturePolicyPath = options.SignaturePolicyPath
|
||||
}
|
||||
|
||||
sc := common.GetSystemContext(signaturePolicyPath, options.AuthFile)
|
||||
sc := common.GetSystemContext(signaturePolicyPath, options.AuthFile, false)
|
||||
|
||||
srcRef, err := alltransports.ParseImageName(imgName)
|
||||
if err != nil {
|
||||
|
|
@ -664,7 +668,7 @@ func (r *Runtime) PullImage(imgName string, options CopyOptions) (string, error)
|
|||
}
|
||||
defer policyContext.Destroy()
|
||||
|
||||
copyOptions := common.GetCopyOptions(options.Writer, signaturePolicyPath, &options.DockerRegistryOptions, nil, options.SigningOptions, options.AuthFile)
|
||||
copyOptions := common.GetCopyOptions(options.Writer, signaturePolicyPath, &options.DockerRegistryOptions, nil, options.SigningOptions, options.AuthFile, "", false)
|
||||
|
||||
for _, imageInfo := range pullStructs {
|
||||
// Print the following statement only when pulling from a docker or atomic registry
|
||||
|
|
@ -721,7 +725,7 @@ func (r *Runtime) PushImage(source string, destination string, options CopyOptio
|
|||
signaturePolicyPath = options.SignaturePolicyPath
|
||||
}
|
||||
|
||||
sc := common.GetSystemContext(signaturePolicyPath, options.AuthFile)
|
||||
sc := common.GetSystemContext(signaturePolicyPath, options.AuthFile, options.ForceCompress)
|
||||
|
||||
policyContext, err := getPolicyContext(sc)
|
||||
if err != nil {
|
||||
|
|
@ -735,7 +739,7 @@ func (r *Runtime) PushImage(source string, destination string, options CopyOptio
|
|||
return errors.Wrapf(err, "error getting source imageReference for %q", source)
|
||||
}
|
||||
|
||||
copyOptions := common.GetCopyOptions(options.Writer, signaturePolicyPath, nil, &options.DockerRegistryOptions, options.SigningOptions, options.AuthFile)
|
||||
copyOptions := common.GetCopyOptions(options.Writer, signaturePolicyPath, nil, &options.DockerRegistryOptions, options.SigningOptions, options.AuthFile, options.ManifestMIMEType, options.ForceCompress)
|
||||
|
||||
// Copy the image to the remote destination
|
||||
err = cp.Image(policyContext, dest, src, copyOptions)
|
||||
|
|
@ -1004,7 +1008,7 @@ func (r *Runtime) ImportImage(path string, options CopyOptions) error {
|
|||
}
|
||||
|
||||
var reference = options.Reference
|
||||
sc := common.GetSystemContext("", "")
|
||||
sc := common.GetSystemContext("", "", false)
|
||||
|
||||
// if reference not given, get the image digest
|
||||
if reference == "" {
|
||||
|
|
@ -1020,7 +1024,7 @@ func (r *Runtime) ImportImage(path string, options CopyOptions) error {
|
|||
}
|
||||
defer policyContext.Destroy()
|
||||
|
||||
copyOptions := common.GetCopyOptions(os.Stdout, "", nil, nil, common.SigningOptions{}, "")
|
||||
copyOptions := common.GetCopyOptions(os.Stdout, "", nil, nil, common.SigningOptions{}, "", "", false)
|
||||
|
||||
dest, err := is.Transport.ParseStoreReference(r.store, reference)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -84,3 +84,19 @@ function setup() {
|
|||
run ${KPOD_BINARY} $KPOD_OPTIONS rmi "$ALPINE"
|
||||
echo "$output"
|
||||
}
|
||||
|
||||
@test "push with manifest type conversion" {
|
||||
run bash -c "${KPOD_BINARY} $KPOD_OPTIONS push --format oci "${BB}" dir:my-dir"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run bash -c "grep "application/vnd.oci.image.config.v1+json" my-dir/manifest.json"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run bash -c "${KPOD_BINARY} $KPOD_OPTIONS push --compress --format v2s2 "${BB}" dir:my-dir"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
run bash -c "grep "application/vnd.docker.distribution.manifest.v2+json" my-dir/manifest.json"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
rm -rf my-dir
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue