1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
package main
import (
"fmt"
"io"
"os"
"strings"
"github.com/containers/image/directory"
"github.com/containers/image/manifest"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/util"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var (
pushCommand cliconfig.PushValues
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 = &cobra.Command{
Use: "push [flags] IMAGE REGISTRY",
Short: "Push an image to a specified destination",
Long: pushDescription,
RunE: func(cmd *cobra.Command, args []string) error {
pushCommand.InputArgs = args
pushCommand.GlobalFlags = MainGlobalOpts
return pushCmd(&pushCommand)
},
Example: `podman push imageID docker://registry.example.com/repository:tag
podman push imageID oci-archive:/path/to/layout:image:tag
podman push --authfile temp-auths/myauths.json alpine docker://docker.io/myrepo/alpine`,
}
)
func init() {
pushCommand.Command = _pushCommand
pushCommand.SetHelpTemplate(HelpTemplate())
pushCommand.SetUsageTemplate(UsageTemplate())
flags := pushCommand.Flags()
flags.MarkHidden("signature-policy")
flags.StringVar(&pushCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&pushCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.BoolVar(&pushCommand.Compress, "compress", false, "Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)")
flags.StringVar(&pushCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.StringVarP(&pushCommand.Format, "format", "f", "", "Manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir:' transport (default is manifest type of source)")
flags.BoolVarP(&pushCommand.Quiet, "quiet", "q", false, "Don't output progress information when pushing images")
flags.BoolVar(&pushCommand.RemoveSignatures, "remove-signatures", false, "Discard any pre-existing signatures in the image")
flags.StringVar(&pushCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.StringVar(&pushCommand.SignBy, "sign-by", "", "Add a signature at the destination using the specified key")
flags.BoolVar(&pushCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
}
func pushCmd(c *cliconfig.PushValues) error {
var (
registryCreds *types.DockerAuthConfig
destName string
)
args := c.InputArgs
if len(args) == 0 || len(args) > 2 {
return errors.New("podman push requires at least one image name, and optionally a second to specify a different destination name")
}
srcName := args[0]
switch len(args) {
case 1:
destName = args[0]
case 2:
destName = args[1]
}
// --compress and --format can only be used for the "dir" transport
splitArg := strings.SplitN(destName, ":", 2)
if c.Flag("compress").Changed || c.Flag("format").Changed {
if splitArg[0] != directory.Transport.Name() {
return errors.Errorf("--compress and --format can be set only when pushing to a directory using the 'dir' transport")
}
}
certPath := c.CertDir
removeSignatures := c.RemoveSignatures
signBy := c.SignBy
if c.Flag("creds").Changed {
creds, err := util.ParseRegistryCreds(c.Creds)
if err != nil {
return err
}
registryCreds = creds
}
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not create runtime")
}
defer runtime.Shutdown(false)
var writer io.Writer
if !c.Quiet {
writer = os.Stderr
}
var manifestType string
if c.Flag("format").Changed {
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"))
}
}
dockerRegistryOptions := image.DockerRegistryOptions{
DockerRegistryCreds: registryCreds,
DockerCertPath: certPath,
}
if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
so := image.SigningOptions{
RemoveSignatures: removeSignatures,
SignBy: signBy,
}
authfile := getAuthFile(c.Authfile)
return runtime.Push(getContext(), srcName, destName, manifestType, authfile, c.SignaturePolicy, writer, c.Compress, so, &dockerRegistryOptions, nil)
}
|