aboutsummaryrefslogtreecommitdiff
path: root/cmd/podman/push.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/push.go')
-rw-r--r--cmd/podman/push.go167
1 files changed, 167 insertions, 0 deletions
diff --git a/cmd/podman/push.go b/cmd/podman/push.go
new file mode 100644
index 000000000..69d6e6629
--- /dev/null
+++ b/cmd/podman/push.go
@@ -0,0 +1,167 @@
+package main
+
+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"
+ "github.com/urfave/cli"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+var (
+ pushFlags = []cli.Flag{
+ cli.StringFlag{
+ Name: "signature-policy",
+ Usage: "`pathname` of signature policy file (not usually used)",
+ Hidden: true,
+ },
+ cli.StringFlag{
+ Name: "creds",
+ Usage: "`credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
+ },
+ cli.StringFlag{
+ 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)",
+ },
+ cli.BoolFlag{
+ Name: "remove-signatures",
+ Usage: "discard any pre-existing signatures in the image",
+ },
+ cli.StringFlag{
+ Name: "sign-by",
+ Usage: "add a signature at the destination using the specified key",
+ },
+ cli.BoolFlag{
+ Name: "quiet, q",
+ Usage: "don't output progress information when pushing images",
+ },
+ cli.StringFlag{
+ Name: "authfile",
+ Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json",
+ },
+ }
+ pushDescription = fmt.Sprintf(`
+ Pushes an image to a specified location.
+ The Image "DESTINATION" uses a "transport":"details" format.
+ See podman-push(1) section "DESTINATION" for the expected format`)
+
+ pushCommand = cli.Command{
+ Name: "push",
+ Usage: "push an image to a specified destination",
+ Description: pushDescription,
+ Flags: pushFlags,
+ Action: pushCmd,
+ ArgsUsage: "IMAGE DESTINATION",
+ }
+)
+
+func pushCmd(c *cli.Context) error {
+ var registryCreds *types.DockerAuthConfig
+
+ args := c.Args()
+ if len(args) < 2 {
+ return errors.New("podman push requires exactly 2 arguments")
+ }
+ if err := validateFlags(c, pushFlags); err != nil {
+ return err
+ }
+ 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")
+ skipVerify := !c.BoolT("tls-verify")
+ removeSignatures := c.Bool("remove-signatures")
+ signBy := c.String("sign-by")
+
+ if registryCredsString != "" {
+ creds, err := common.ParseRegistryCreds(registryCredsString)
+ if err != nil {
+ if err == common.ErrNoPassword {
+ fmt.Print("Password: ")
+ password, err := terminal.ReadPassword(0)
+ if err != nil {
+ return errors.Wrapf(err, "could not read password from terminal")
+ }
+ creds.Password = string(password)
+ } else {
+ return err
+ }
+ }
+ registryCreds = creds
+ }
+
+ runtime, err := getRuntime(c)
+ if err != nil {
+ return errors.Wrapf(err, "could not create runtime")
+ }
+ defer runtime.Shutdown(false)
+
+ var writer io.Writer
+ if !c.Bool("quiet") {
+ 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"),
+ DockerRegistryOptions: common.DockerRegistryOptions{
+ DockerRegistryCreds: registryCreds,
+ DockerCertPath: certPath,
+ DockerInsecureSkipTLSVerify: skipVerify,
+ },
+ SigningOptions: common.SigningOptions{
+ RemoveSignatures: removeSignatures,
+ SignBy: signBy,
+ },
+ AuthFile: c.String("authfile"),
+ Writer: writer,
+ ManifestMIMEType: manifestType,
+ ForceCompress: c.Bool("compress"),
+ }
+
+ return runtime.PushImage(srcName, destName, options)
+}