mirror of
https://github.com/containers/podman
synced 2024-10-19 16:54:07 +00:00
Migrate to cobra CLI
We intend to migrate to the cobra cli from urfave/cli because the project is more well maintained. There are also some technical reasons as well which extend into our remote client work. Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
parent
962850c6e0
commit
25a3923b61
3
Makefile
3
Makefile
|
@ -352,7 +352,8 @@ vendor: .install.vndr
|
|||
$(GOPATH)/bin/vndr \
|
||||
-whitelist "github.com/varlink/go" \
|
||||
-whitelist "github.com/onsi/ginkgo" \
|
||||
-whitelist "github.com/onsi/gomega"
|
||||
-whitelist "github.com/onsi/gomega" \
|
||||
-whitelist "gopkg.in/fsnotify.v1"
|
||||
|
||||
.PHONY: \
|
||||
.gopathok \
|
||||
|
|
|
@ -3,57 +3,56 @@ package main
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
attachFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "detach-keys",
|
||||
Usage: "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-stdin",
|
||||
Usage: "Do not attach STDIN. The default is false.",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "sig-proxy",
|
||||
Usage: "Proxy received signals to the process (default true)",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
attachCommand cliconfig.AttachValues
|
||||
attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively."
|
||||
attachCommand = cli.Command{
|
||||
Name: "attach",
|
||||
Usage: "Attach to a running container",
|
||||
Description: attachDescription,
|
||||
Flags: sortFlags(attachFlags),
|
||||
Action: attachCmd,
|
||||
ArgsUsage: "",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_attachCommand = &cobra.Command{
|
||||
Use: "attach",
|
||||
Short: "Attach to a running container",
|
||||
Long: attachDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
attachCommand.InputArgs = args
|
||||
attachCommand.GlobalFlags = MainGlobalOpts
|
||||
return attachCmd(&attachCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func attachCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func init() {
|
||||
attachCommand.Command = _attachCommand
|
||||
flags := attachCommand.Flags()
|
||||
flags.StringVar(&attachCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
|
||||
flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false")
|
||||
flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true)")
|
||||
|
||||
flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
|
||||
rootCmd.AddCommand(attachCommand.Command)
|
||||
}
|
||||
|
||||
func attachCmd(c *cliconfig.AttachValues) error {
|
||||
args := c.InputArgs
|
||||
var ctr *libpod.Container
|
||||
if err := validateFlags(c, attachFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(c.Args()) > 1 || (len(c.Args()) == 0 && !c.Bool("latest")) {
|
||||
|
||||
if len(c.InputArgs) > 1 || (len(c.InputArgs) == 0 && !c.Latest) {
|
||||
return errors.Errorf("attach requires the name or id of one running container or the latest flag")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
ctr, err = runtime.GetLatestContainer()
|
||||
} else {
|
||||
ctr, err = runtime.LookupContainer(args[0])
|
||||
|
@ -72,11 +71,11 @@ func attachCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
inputStream := os.Stdin
|
||||
if c.Bool("no-stdin") {
|
||||
if c.NoStdin {
|
||||
inputStream = nil
|
||||
}
|
||||
|
||||
if err := startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.String("detach-keys"), c.BoolT("sig-proxy"), false); err != nil {
|
||||
if err := startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, c.SigProxy, false); err != nil {
|
||||
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
|
||||
}
|
||||
|
||||
|
|
|
@ -10,38 +10,58 @@ import (
|
|||
"github.com/containers/buildah/imagebuildah"
|
||||
buildahcli "github.com/containers/buildah/pkg/cli"
|
||||
"github.com/containers/buildah/pkg/parse"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
layerFlags = []cli.Flag{
|
||||
cli.BoolTFlag{
|
||||
Name: "force-rm",
|
||||
Usage: "Always remove intermediate containers after a build, even if the build is unsuccessful. (default true)",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "layers",
|
||||
Usage: "Cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. ",
|
||||
},
|
||||
}
|
||||
buildCommand cliconfig.BuildValues
|
||||
buildDescription = "Builds an OCI or Docker image using instructions from one\n" +
|
||||
"or more Dockerfiles and a specified build context directory."
|
||||
buildCommand = cli.Command{
|
||||
Name: "build",
|
||||
Usage: "Build an image using instructions from Dockerfiles",
|
||||
Description: buildDescription,
|
||||
Flags: sortFlags(append(append(buildahcli.BudFlags, layerFlags...), buildahcli.FromAndBudFlags...)),
|
||||
Action: buildCmd,
|
||||
ArgsUsage: "CONTEXT-DIRECTORY | URL",
|
||||
SkipArgReorder: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
layerValues buildahcli.LayerResults
|
||||
budFlagsValues buildahcli.BudResults
|
||||
fromAndBudValues buildahcli.FromAndBudResults
|
||||
userNSValues buildahcli.UserNSResults
|
||||
namespaceValues buildahcli.NameSpaceResults
|
||||
|
||||
_buildCommand = &cobra.Command{
|
||||
Use: "build",
|
||||
Short: "Build an image using instructions from Dockerfiles",
|
||||
Long: buildDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
buildCommand.InputArgs = args
|
||||
buildCommand.GlobalFlags = MainGlobalOpts
|
||||
buildCommand.BudResults = &budFlagsValues
|
||||
buildCommand.UserNSResults = &userNSValues
|
||||
buildCommand.FromAndBudResults = &fromAndBudValues
|
||||
buildCommand.LayerResults = &layerValues
|
||||
buildCommand.NameSpaceResults = &namespaceValues
|
||||
return buildCmd(&buildCommand)
|
||||
},
|
||||
Example: "CONTEXT-DIRECTORY | URL",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
buildCommand.Command = _buildCommand
|
||||
flags := buildCommand.Flags()
|
||||
flags.SetInterspersed(false)
|
||||
|
||||
flags.BoolVar(&layerValues.ForceRm, "force-rm", true, "Always remove intermediate containers after a build, even if the build is unsuccessful. (default true)")
|
||||
flags.BoolVar(&layerValues.Layers, "layers", true, "Cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override")
|
||||
budFlags := buildahcli.GetBudFlags(&budFlagsValues)
|
||||
fromAndBugFlags := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues)
|
||||
|
||||
flags.AddFlagSet(&budFlags)
|
||||
flags.AddFlagSet(&fromAndBugFlags)
|
||||
|
||||
rootCmd.AddCommand(buildCommand.Command)
|
||||
}
|
||||
|
||||
func getDockerfiles(files []string) []string {
|
||||
var dockerfiles []string
|
||||
for _, f := range files {
|
||||
|
@ -54,30 +74,30 @@ func getDockerfiles(files []string) []string {
|
|||
return dockerfiles
|
||||
}
|
||||
|
||||
func buildCmd(c *cli.Context) error {
|
||||
func buildCmd(c *cliconfig.BuildValues) error {
|
||||
// The following was taken directly from containers/buildah/cmd/bud.go
|
||||
// TODO Find a away to vendor more of this in rather than copy from bud
|
||||
|
||||
output := ""
|
||||
tags := []string{}
|
||||
if c.IsSet("tag") || c.IsSet("t") {
|
||||
tags = c.StringSlice("tag")
|
||||
if c.Flag("tag").Changed {
|
||||
tags = c.Tag
|
||||
if len(tags) > 0 {
|
||||
output = tags[0]
|
||||
tags = tags[1:]
|
||||
}
|
||||
}
|
||||
pullPolicy := imagebuildah.PullNever
|
||||
if c.BoolT("pull") {
|
||||
if c.Pull {
|
||||
pullPolicy = imagebuildah.PullIfMissing
|
||||
}
|
||||
if c.Bool("pull-always") {
|
||||
if c.PullAlways {
|
||||
pullPolicy = imagebuildah.PullAlways
|
||||
}
|
||||
|
||||
args := make(map[string]string)
|
||||
if c.IsSet("build-arg") {
|
||||
for _, arg := range c.StringSlice("build-arg") {
|
||||
if c.Flag("build-arg").Changed {
|
||||
for _, arg := range c.BuildArg {
|
||||
av := strings.SplitN(arg, "=", 2)
|
||||
if len(av) > 1 {
|
||||
args[av[0]] = av[1]
|
||||
|
@ -87,15 +107,15 @@ func buildCmd(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
dockerfiles := getDockerfiles(c.StringSlice("file"))
|
||||
format, err := getFormat(c)
|
||||
dockerfiles := getDockerfiles(c.File)
|
||||
format, err := getFormat(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
contextDir := ""
|
||||
cliArgs := c.Args()
|
||||
cliArgs := c.InputArgs
|
||||
|
||||
layers := c.BoolT("layers") // layers for podman defaults to true
|
||||
layers := c.Layers // layers for podman defaults to true
|
||||
// Check to see if the BUILDAH_LAYERS environment variable is set and override command-line
|
||||
if _, ok := os.LookupEnv("BUILDAH_LAYERS"); ok {
|
||||
layers = buildahcli.UseLayers()
|
||||
|
@ -124,7 +144,7 @@ func buildCmd(c *cli.Context) error {
|
|||
}
|
||||
contextDir = absDir
|
||||
}
|
||||
cliArgs = cliArgs.Tail()
|
||||
cliArgs = Tail(cliArgs)
|
||||
} else {
|
||||
// No context directory or URL was specified. Try to use the
|
||||
// home of the first locally-available Dockerfile.
|
||||
|
@ -153,17 +173,14 @@ func buildCmd(c *cli.Context) error {
|
|||
if len(dockerfiles) == 0 {
|
||||
dockerfiles = append(dockerfiles, filepath.Join(contextDir, "Dockerfile"))
|
||||
}
|
||||
if err := parse.ValidateFlags(c, buildahcli.BudFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtimeFlags := []string{}
|
||||
for _, arg := range c.StringSlice("runtime-flag") {
|
||||
for _, arg := range c.RuntimeOpts {
|
||||
runtimeFlags = append(runtimeFlags, "--"+arg)
|
||||
}
|
||||
// end from buildah
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -173,10 +190,10 @@ func buildCmd(c *cli.Context) error {
|
|||
stdout = os.Stdout
|
||||
stderr = os.Stderr
|
||||
reporter = os.Stderr
|
||||
if c.IsSet("logfile") {
|
||||
f, err := os.OpenFile(c.String("logfile"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if c.Flag("logfile").Changed {
|
||||
f, err := os.OpenFile(c.Logfile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return errors.Errorf("error opening logfile %q: %v", c.String("logfile"), err)
|
||||
return errors.Errorf("error opening logfile %q: %v", c.Logfile, err)
|
||||
}
|
||||
defer f.Close()
|
||||
logrus.SetOutput(f)
|
||||
|
@ -185,36 +202,36 @@ func buildCmd(c *cli.Context) error {
|
|||
reporter = f
|
||||
}
|
||||
|
||||
systemContext, err := parse.SystemContextFromOptions(c)
|
||||
systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error building system context")
|
||||
}
|
||||
systemContext.AuthFilePath = getAuthFile(c.String("authfile"))
|
||||
commonOpts, err := parse.CommonBuildOptions(c)
|
||||
systemContext.AuthFilePath = getAuthFile(c.Authfile)
|
||||
commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c)
|
||||
namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error parsing namespace-related options")
|
||||
}
|
||||
usernsOption, idmappingOptions, err := parse.IDMappingOptions(c)
|
||||
usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error parsing ID mapping options")
|
||||
}
|
||||
namespaceOptions.AddOrReplace(usernsOption...)
|
||||
|
||||
ociruntime := runtime.GetOCIRuntimePath()
|
||||
if c.IsSet("runtime") {
|
||||
ociruntime = c.String("runtime")
|
||||
if c.Flag("runtime").Changed {
|
||||
ociruntime = c.Runtime
|
||||
}
|
||||
options := imagebuildah.BuildOptions{
|
||||
ContextDirectory: contextDir,
|
||||
PullPolicy: pullPolicy,
|
||||
Compression: imagebuildah.Gzip,
|
||||
Quiet: c.Bool("quiet"),
|
||||
SignaturePolicyPath: c.String("signature-policy"),
|
||||
Quiet: c.Quiet,
|
||||
SignaturePolicyPath: c.SignaturePolicy,
|
||||
Args: args,
|
||||
Output: output,
|
||||
AdditionalTags: tags,
|
||||
|
@ -227,22 +244,22 @@ func buildCmd(c *cli.Context) error {
|
|||
SystemContext: systemContext,
|
||||
NamespaceOptions: namespaceOptions,
|
||||
ConfigureNetwork: networkPolicy,
|
||||
CNIPluginPath: c.String("cni-plugin-path"),
|
||||
CNIConfigDir: c.String("cni-config-dir"),
|
||||
CNIPluginPath: c.CNIPlugInPath,
|
||||
CNIConfigDir: c.CNIConfigDir,
|
||||
IDMappingOptions: idmappingOptions,
|
||||
CommonBuildOpts: commonOpts,
|
||||
DefaultMountsFilePath: c.GlobalString("default-mounts-file"),
|
||||
IIDFile: c.String("iidfile"),
|
||||
Squash: c.Bool("squash"),
|
||||
Labels: c.StringSlice("label"),
|
||||
Annotations: c.StringSlice("annotation"),
|
||||
DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile,
|
||||
IIDFile: c.Iidfile,
|
||||
Squash: c.Squash,
|
||||
Labels: c.Label,
|
||||
Annotations: c.Annotation,
|
||||
Layers: layers,
|
||||
NoCache: c.Bool("no-cache"),
|
||||
RemoveIntermediateCtrs: c.BoolT("rm"),
|
||||
ForceRmIntermediateCtrs: c.BoolT("force-rm"),
|
||||
NoCache: c.NoCache,
|
||||
RemoveIntermediateCtrs: c.Rm,
|
||||
ForceRmIntermediateCtrs: c.ForceRm,
|
||||
}
|
||||
|
||||
if c.Bool("quiet") {
|
||||
if c.Quiet {
|
||||
options.ReportWriter = ioutil.Discard
|
||||
}
|
||||
|
||||
|
@ -252,3 +269,13 @@ func buildCmd(c *cli.Context) error {
|
|||
|
||||
return runtime.Build(getContext(), options, dockerfiles...)
|
||||
}
|
||||
|
||||
// Tail returns a string slice after the first element unless there are
|
||||
// not enough elements, then it returns an empty slice. This is to replace
|
||||
// the urfavecli Tail method for args
|
||||
func Tail(a []string) []string {
|
||||
if len(a) >= 2 {
|
||||
return []string(a)[1:]
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
|
|
@ -5,70 +5,67 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
checkpointCommand cliconfig.CheckpointValues
|
||||
checkpointDescription = `
|
||||
podman container checkpoint
|
||||
|
||||
Checkpoints one or more running containers. The container name or ID can be used.
|
||||
`
|
||||
checkpointFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "keep, k",
|
||||
Usage: "Keep all temporary checkpoint files",
|
||||
_checkpointCommand = &cobra.Command{
|
||||
Use: "checkpoint",
|
||||
Short: "Checkpoints one or more containers",
|
||||
Long: checkpointDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
checkpointCommand.InputArgs = args
|
||||
checkpointCommand.GlobalFlags = MainGlobalOpts
|
||||
return checkpointCmd(&checkpointCommand)
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "leave-running, R",
|
||||
Usage: "Leave the container running after writing checkpoint to disk",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "tcp-established",
|
||||
Usage: "Checkpoint a container with established TCP connections",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Checkpoint all running containers",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
checkpointCommand = cli.Command{
|
||||
Name: "checkpoint",
|
||||
Usage: "Checkpoints one or more containers",
|
||||
Description: checkpointDescription,
|
||||
Flags: sortFlags(checkpointFlags),
|
||||
Action: checkpointCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func checkpointCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
checkpointCommand.Command = _checkpointCommand
|
||||
|
||||
flags := checkpointCommand.Flags()
|
||||
flags.BoolVarP(&checkpointCommand.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
|
||||
flags.BoolVarP(&checkpointCommand.LeaveRunning, "leave-running", "R", false, "Leave the container running after writing checkpoint to disk")
|
||||
flags.BoolVar(&checkpointCommand.TcpEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
|
||||
flags.BoolVarP(&checkpointCommand.All, "all", "a", false, "Checkpoint all running containers")
|
||||
flags.BoolVarP(&checkpointCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
}
|
||||
|
||||
func checkpointCmd(c *cliconfig.CheckpointValues) error {
|
||||
if rootless.IsRootless() {
|
||||
return errors.New("checkpointing a container requires root")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
options := libpod.ContainerCheckpointOptions{
|
||||
Keep: c.Bool("keep"),
|
||||
KeepRunning: c.Bool("leave-running"),
|
||||
TCPEstablished: c.Bool("tcp-established"),
|
||||
Keep: c.Keep,
|
||||
KeepRunning: c.LeaveRunning,
|
||||
TCPEstablished: c.TcpEstablished,
|
||||
}
|
||||
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
|
||||
containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
|
||||
|
||||
for _, ctr := range containers {
|
||||
if err = ctr.Checkpoint(context.TODO(), options); err != nil {
|
||||
|
|
|
@ -4,50 +4,52 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
cleanupFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Cleans up all containers",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
cleanupCommand cliconfig.CleanupValues
|
||||
cleanupDescription = `
|
||||
podman container cleanup
|
||||
|
||||
Cleans up mount points and network stacks on one or more containers from the host. The container name or ID can be used. This command is used internally when running containers, but can also be used if container cleanup has failed when a container exits.
|
||||
`
|
||||
cleanupCommand = cli.Command{
|
||||
Name: "cleanup",
|
||||
Usage: "Cleanup network and mountpoints of one or more containers",
|
||||
Description: cleanupDescription,
|
||||
Flags: sortFlags(cleanupFlags),
|
||||
Action: cleanupCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_cleanupCommand = &cobra.Command{
|
||||
Use: "cleanup",
|
||||
Short: "Cleanup network and mountpoints of one or more containers",
|
||||
Long: cleanupDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cleanupCommand.InputArgs = args
|
||||
cleanupCommand.GlobalFlags = MainGlobalOpts
|
||||
return cleanupCmd(&cleanupCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func cleanupCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, cleanupFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
func init() {
|
||||
cleanupCommand.Command = _cleanupCommand
|
||||
flags := cleanupCommand.Flags()
|
||||
|
||||
flags.BoolVarP(&cleanupCommand.All, "all", "a", false, "Cleans up all containers")
|
||||
flags.BoolVarP(&cleanupCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
}
|
||||
|
||||
func cleanupCmd(c *cliconfig.CleanupValues) error {
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cleanupContainers, lastError := getAllOrLatestContainers(c, runtime, -1, "all")
|
||||
cleanupContainers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
|
||||
|
||||
ctx := getContext()
|
||||
|
||||
|
|
109
cmd/podman/cliconfig/commands.go
Normal file
109
cmd/podman/cliconfig/commands.go
Normal file
|
@ -0,0 +1,109 @@
|
|||
package cliconfig
|
||||
|
||||
// GlobalIsSet is a compatibility method for urfave
|
||||
func (p *PodmanCommand) GlobalIsSet(opt string) bool {
|
||||
flag := p.PersistentFlags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return false
|
||||
}
|
||||
return flag.Changed
|
||||
}
|
||||
|
||||
// IsSet is a compatibility method for urfave
|
||||
func (p *PodmanCommand) IsSet(opt string) bool {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return false
|
||||
}
|
||||
return flag.Changed
|
||||
}
|
||||
|
||||
// Bool is a compatibility method for urfave
|
||||
func (p *PodmanCommand) Bool(opt string) bool {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return false
|
||||
}
|
||||
val, _ := p.Flags().GetBool(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// String is a compatibility method for urfave
|
||||
func (p *PodmanCommand) String(opt string) string {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return ""
|
||||
}
|
||||
val, _ := p.Flags().GetString(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// StringArray is a compatibility method for urfave
|
||||
func (p *PodmanCommand) StringArray(opt string) []string {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return []string{}
|
||||
}
|
||||
val, _ := p.Flags().GetStringArray(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// StringSlice is a compatibility method for urfave
|
||||
func (p *PodmanCommand) StringSlice(opt string) []string {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return []string{}
|
||||
}
|
||||
val, _ := p.Flags().GetStringSlice(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// Int is a compatibility method for urfave
|
||||
func (p *PodmanCommand) Int(opt string) int {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return 0
|
||||
}
|
||||
val, _ := p.Flags().GetInt(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// Unt is a compatibility method for urfave
|
||||
func (p *PodmanCommand) Uint(opt string) uint {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return 0
|
||||
}
|
||||
val, _ := p.Flags().GetUint(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// Int64 is a compatibility method for urfave
|
||||
func (p *PodmanCommand) Int64(opt string) int64 {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return 0
|
||||
}
|
||||
val, _ := p.Flags().GetInt64(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// Unt64 is a compatibility method for urfave
|
||||
func (p *PodmanCommand) Uint64(opt string) uint64 {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return 0
|
||||
}
|
||||
val, _ := p.Flags().GetUint64(opt)
|
||||
return val
|
||||
}
|
||||
|
||||
// Float64 is a compatibility method for urfave
|
||||
func (p *PodmanCommand) Float64(opt string) float64 {
|
||||
flag := p.Flags().Lookup(opt)
|
||||
if flag == nil {
|
||||
return 0
|
||||
}
|
||||
val, _ := p.Flags().GetFloat64(opt)
|
||||
return val
|
||||
}
|
541
cmd/podman/cliconfig/config.go
Normal file
541
cmd/podman/cliconfig/config.go
Normal file
|
@ -0,0 +1,541 @@
|
|||
package cliconfig
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type PodmanCommand struct {
|
||||
*cobra.Command
|
||||
InputArgs []string
|
||||
GlobalFlags MainFlags
|
||||
}
|
||||
|
||||
type MainFlags struct {
|
||||
CGroupManager string
|
||||
CniConfigDir string
|
||||
ConmonPath string
|
||||
DefaultMountsFile string
|
||||
HooksDir []string
|
||||
MaxWorks int
|
||||
Namespace string
|
||||
Root string
|
||||
Runroot string
|
||||
Runtime string
|
||||
StorageDriver string
|
||||
StorageOpts []string
|
||||
Syslog bool
|
||||
|
||||
Config string
|
||||
CpuProfile string
|
||||
LogLevel string
|
||||
TmpDir string
|
||||
}
|
||||
|
||||
type AttachValues struct {
|
||||
PodmanCommand
|
||||
DetachKeys string
|
||||
Latest bool
|
||||
NoStdin bool
|
||||
SigProxy bool
|
||||
}
|
||||
|
||||
type ImagesValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Digests bool
|
||||
Filter []string
|
||||
Format string
|
||||
Noheading bool
|
||||
NoTrunc bool
|
||||
Quiet bool
|
||||
Sort string
|
||||
}
|
||||
|
||||
type TagValues struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type WaitValues struct {
|
||||
PodmanCommand
|
||||
Interval uint
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type CheckpointValues struct {
|
||||
PodmanCommand
|
||||
Keep bool
|
||||
LeaveRunning bool
|
||||
TcpEstablished bool
|
||||
All bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type CommitValues struct {
|
||||
PodmanCommand
|
||||
Change []string
|
||||
Format string
|
||||
Message string
|
||||
Author string
|
||||
Pause bool
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
type ContainersPrune struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type DiffValues struct {
|
||||
PodmanCommand
|
||||
Archive bool
|
||||
Format string
|
||||
}
|
||||
|
||||
type ExecValues struct {
|
||||
PodmanCommand
|
||||
Env []string
|
||||
Privileged bool
|
||||
Interfactive bool
|
||||
Tty bool
|
||||
User string
|
||||
Latest bool
|
||||
Workdir string
|
||||
}
|
||||
|
||||
type ImageExistsValues struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type ContainerExistsValues struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type PodExistsValues struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type ExportValues struct {
|
||||
PodmanCommand
|
||||
Output string
|
||||
}
|
||||
|
||||
type GenerateKubeValues struct {
|
||||
PodmanCommand
|
||||
Service bool
|
||||
}
|
||||
|
||||
type HistoryValues struct {
|
||||
PodmanCommand
|
||||
Human bool
|
||||
NoTrunc bool
|
||||
Quiet bool
|
||||
Format string
|
||||
}
|
||||
type PruneImagesValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
}
|
||||
|
||||
type ImportValues struct {
|
||||
PodmanCommand
|
||||
Change []string
|
||||
Message string
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
type InfoValues struct {
|
||||
PodmanCommand
|
||||
Debug bool
|
||||
Format string
|
||||
}
|
||||
|
||||
type InspectValues struct {
|
||||
PodmanCommand
|
||||
TypeObject string
|
||||
Format string
|
||||
Size bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type KillValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Signal string
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type LoadValues struct {
|
||||
PodmanCommand
|
||||
Input string
|
||||
Quiet bool
|
||||
SignaturePolicy string
|
||||
}
|
||||
|
||||
type LoginValues struct {
|
||||
PodmanCommand
|
||||
Password string
|
||||
Username string
|
||||
Authfile string
|
||||
CertDir string
|
||||
GetLogin bool
|
||||
TlsVerify bool
|
||||
}
|
||||
|
||||
type LogoutValues struct {
|
||||
PodmanCommand
|
||||
Authfile string
|
||||
All bool
|
||||
}
|
||||
|
||||
type LogsValues struct {
|
||||
PodmanCommand
|
||||
Details bool
|
||||
Follow bool
|
||||
Since string
|
||||
Tail uint64
|
||||
Timestamps bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type MountValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Format string
|
||||
NoTrunc bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PauseValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
}
|
||||
|
||||
type KubePlayValues struct {
|
||||
PodmanCommand
|
||||
Authfile string
|
||||
CertDir string
|
||||
Creds string
|
||||
Quiet bool
|
||||
SignaturePolicy string
|
||||
TlsVerify bool
|
||||
}
|
||||
|
||||
type PodCreateValues struct {
|
||||
PodmanCommand
|
||||
CgroupParent string
|
||||
Infra bool
|
||||
InfraImage string
|
||||
InfraCommand string
|
||||
LabelFile []string
|
||||
Labels []string
|
||||
Name string
|
||||
PodIDFile string
|
||||
Publish []string
|
||||
Share string
|
||||
}
|
||||
|
||||
type PodInspectValues struct {
|
||||
PodmanCommand
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PodKillValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Signal string
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PodPauseValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PodPsValues struct {
|
||||
PodmanCommand
|
||||
CtrNames bool
|
||||
CtrIDs bool
|
||||
CtrStatus bool
|
||||
Filter string
|
||||
Format string
|
||||
Latest bool
|
||||
Namespace bool
|
||||
NoTrunc bool
|
||||
Quiet bool
|
||||
Sort string
|
||||
}
|
||||
|
||||
type PodRestartValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PodRmValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Force bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PodStartValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
}
|
||||
type PodStatsValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
NoStream bool
|
||||
NoReset bool
|
||||
Format string
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PodStopValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
Timeout uint
|
||||
}
|
||||
|
||||
type PodTopValues struct {
|
||||
PodmanCommand
|
||||
Latest bool
|
||||
ListDescriptors bool
|
||||
}
|
||||
type PodUnpauseValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PortValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type PsValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Filter []string
|
||||
Format string
|
||||
Last int
|
||||
Latest bool
|
||||
Namespace bool
|
||||
NoTrunct bool
|
||||
Pod bool
|
||||
Quiet bool
|
||||
Size bool
|
||||
Sort string
|
||||
Sync bool
|
||||
}
|
||||
|
||||
type PullValues struct {
|
||||
PodmanCommand
|
||||
Authfile string
|
||||
CertDir string
|
||||
Creds string
|
||||
Quiet bool
|
||||
SignaturePolicy string
|
||||
TlsVerify bool
|
||||
}
|
||||
|
||||
type PushValues struct {
|
||||
PodmanCommand
|
||||
Authfile string
|
||||
CertDir string
|
||||
Compress bool
|
||||
Creds string
|
||||
Format string
|
||||
Quiet bool
|
||||
RemoveSignatures bool
|
||||
SignBy string
|
||||
SignaturePolicy string
|
||||
TlsVerify bool
|
||||
}
|
||||
|
||||
type RefreshValues struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type RestartValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
Running bool
|
||||
Timeout uint
|
||||
}
|
||||
|
||||
type RestoreValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Keep bool
|
||||
Latest bool
|
||||
TcpEstablished bool
|
||||
}
|
||||
|
||||
type RmValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Force bool
|
||||
Latest bool
|
||||
Volumes bool
|
||||
}
|
||||
|
||||
type RmiValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Force bool
|
||||
}
|
||||
|
||||
type RunlabelValues struct {
|
||||
PodmanCommand
|
||||
Authfile string
|
||||
Display bool
|
||||
CertDir string
|
||||
Creds string
|
||||
Name string
|
||||
Opt1 string
|
||||
Opt2 string
|
||||
Opt3 string
|
||||
Quiet bool
|
||||
Pull bool
|
||||
SignaturePolicy string
|
||||
TlsVerify bool
|
||||
}
|
||||
type SaveValues struct {
|
||||
PodmanCommand
|
||||
Compress bool
|
||||
Format string
|
||||
Output string
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
type SearchValues struct {
|
||||
PodmanCommand
|
||||
Authfile string
|
||||
Filter []string
|
||||
Format string
|
||||
Limit int
|
||||
NoTrunc bool
|
||||
TlsVerify bool
|
||||
}
|
||||
|
||||
type SignValues struct {
|
||||
PodmanCommand
|
||||
Directory string
|
||||
SignBy string
|
||||
}
|
||||
|
||||
type StartValues struct {
|
||||
PodmanCommand
|
||||
Attach bool
|
||||
DetachKeys string
|
||||
Interactive bool
|
||||
Latest bool
|
||||
SigProxy bool
|
||||
}
|
||||
|
||||
type StatsValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Format string
|
||||
Latest bool
|
||||
NoReset bool
|
||||
NoStream bool
|
||||
}
|
||||
|
||||
type StopValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
Timeout uint
|
||||
}
|
||||
|
||||
type TopValues struct {
|
||||
PodmanCommand
|
||||
Latest bool
|
||||
ListDescriptors bool
|
||||
}
|
||||
|
||||
type UmountValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Force bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type UnpauseValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
}
|
||||
|
||||
type VarlinkValues struct {
|
||||
PodmanCommand
|
||||
Timeout int64
|
||||
}
|
||||
|
||||
type SetTrustValues struct {
|
||||
PodmanCommand
|
||||
PolicyPath string
|
||||
PubKeysFile []string
|
||||
TrustType string
|
||||
}
|
||||
|
||||
type ShowTrustValues struct {
|
||||
PodmanCommand
|
||||
Json bool
|
||||
PolicyPath string
|
||||
Raw bool
|
||||
RegistryPath string
|
||||
}
|
||||
|
||||
type VersionValues struct {
|
||||
PodmanCommand
|
||||
Format string
|
||||
}
|
||||
|
||||
type VolumeCreateValues struct {
|
||||
PodmanCommand
|
||||
Driver string
|
||||
Label []string
|
||||
Opt []string
|
||||
}
|
||||
type VolumeInspectValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Format string
|
||||
}
|
||||
|
||||
type VolumeLsValues struct {
|
||||
PodmanCommand
|
||||
Filter string
|
||||
Format string
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
type VolumePruneValues struct {
|
||||
PodmanCommand
|
||||
Force bool
|
||||
}
|
||||
|
||||
type VolumeRmValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Force bool
|
||||
}
|
||||
|
||||
type CleanupValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Latest bool
|
||||
}
|
||||
|
||||
type SystemPruneValues struct {
|
||||
PodmanCommand
|
||||
All bool
|
||||
Force bool
|
||||
Volume bool
|
||||
}
|
22
cmd/podman/cliconfig/create.go
Normal file
22
cmd/podman/cliconfig/create.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package cliconfig
|
||||
|
||||
import (
|
||||
buildahcli "github.com/containers/buildah/pkg/cli"
|
||||
)
|
||||
|
||||
type CreateValues struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type RunValues struct {
|
||||
PodmanCommand
|
||||
}
|
||||
|
||||
type BuildValues struct {
|
||||
PodmanCommand
|
||||
*buildahcli.BudResults
|
||||
*buildahcli.UserNSResults
|
||||
*buildahcli.FromAndBudResults
|
||||
*buildahcli.NameSpaceResults
|
||||
*buildahcli.LayerResults
|
||||
}
|
|
@ -2,151 +2,106 @@
|
|||
|
||||
package main
|
||||
|
||||
import "github.com/urfave/cli"
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func getAppCommands() []cli.Command {
|
||||
return []cli.Command{
|
||||
attachCommand,
|
||||
commitCommand,
|
||||
buildCommand,
|
||||
createCommand,
|
||||
diffCommand,
|
||||
execCommand,
|
||||
killCommand,
|
||||
kubeCommand,
|
||||
loadCommand,
|
||||
loginCommand,
|
||||
logoutCommand,
|
||||
logsCommand,
|
||||
mountCommand,
|
||||
pauseCommand,
|
||||
psCommand,
|
||||
podCommand,
|
||||
portCommand,
|
||||
pushCommand,
|
||||
playCommand,
|
||||
restartCommand,
|
||||
rmCommand,
|
||||
runCommand,
|
||||
saveCommand,
|
||||
searchCommand,
|
||||
startCommand,
|
||||
statsCommand,
|
||||
stopCommand,
|
||||
topCommand,
|
||||
umountCommand,
|
||||
unpauseCommand,
|
||||
volumeCommand,
|
||||
waitCommand,
|
||||
func getImageSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_buildCommand,
|
||||
_importCommand,
|
||||
_loadCommand,
|
||||
_pullCommand,
|
||||
_rmiCommand,
|
||||
_saveCommand,
|
||||
_signCommand,
|
||||
}
|
||||
}
|
||||
|
||||
func getImageSubCommands() []cli.Command {
|
||||
return []cli.Command{
|
||||
buildCommand,
|
||||
importCommand,
|
||||
loadCommand,
|
||||
pullCommand,
|
||||
saveCommand,
|
||||
trustCommand,
|
||||
signCommand,
|
||||
func getContainerSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_attachCommand,
|
||||
_checkpointCommand,
|
||||
_cleanupCommand,
|
||||
_containerExistsCommand,
|
||||
_commitCommand,
|
||||
_createCommand,
|
||||
_diffCommand,
|
||||
_execCommand,
|
||||
_exportCommand,
|
||||
_killCommand,
|
||||
_logsCommand,
|
||||
_psCommand,
|
||||
_mountCommand,
|
||||
_pauseCommand,
|
||||
_portCommand,
|
||||
_pruneContainersCommand,
|
||||
_refreshCommand,
|
||||
_restartCommand,
|
||||
_restoreCommand,
|
||||
_rmCommand,
|
||||
_runCommmand,
|
||||
_runlabelCommand,
|
||||
_startCommand,
|
||||
_statsCommand,
|
||||
_stopCommand,
|
||||
_topCommand,
|
||||
_umountCommand,
|
||||
_unpauseCommand,
|
||||
_waitCommand,
|
||||
}
|
||||
}
|
||||
|
||||
func getSystemSubCommands() []cli.Command {
|
||||
return []cli.Command{infoCommand}
|
||||
func getPodSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_podCreateCommand,
|
||||
_podExistsCommand,
|
||||
_podInspectCommand,
|
||||
_podKillCommand,
|
||||
_podPauseCommand,
|
||||
_podPsCommand,
|
||||
_podRestartCommand,
|
||||
_podRmCommand,
|
||||
_podStartCommand,
|
||||
_podStatsCommand,
|
||||
_podStopCommand,
|
||||
_podTopCommand,
|
||||
_podUnpauseCommand,
|
||||
}
|
||||
}
|
||||
|
||||
func getContainerSubCommands() []cli.Command {
|
||||
return []cli.Command{
|
||||
attachCommand,
|
||||
checkpointCommand,
|
||||
cleanupCommand,
|
||||
containerExistsCommand,
|
||||
commitCommand,
|
||||
createCommand,
|
||||
diffCommand,
|
||||
execCommand,
|
||||
exportCommand,
|
||||
killCommand,
|
||||
logsCommand,
|
||||
psCommand,
|
||||
mountCommand,
|
||||
pauseCommand,
|
||||
portCommand,
|
||||
pruneContainersCommand,
|
||||
refreshCommand,
|
||||
restartCommand,
|
||||
restoreCommand,
|
||||
rmCommand,
|
||||
runCommand,
|
||||
runlabelCommand,
|
||||
startCommand,
|
||||
statsCommand,
|
||||
stopCommand,
|
||||
topCommand,
|
||||
umountCommand,
|
||||
unpauseCommand,
|
||||
// updateCommand,
|
||||
waitCommand,
|
||||
func getVolumeSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_volumeCreateCommand,
|
||||
_volumeLsCommand,
|
||||
_volumeRmCommand,
|
||||
_volumeInspectCommand,
|
||||
_volumePruneCommand,
|
||||
}
|
||||
}
|
||||
func getMainAppFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "cgroup-manager",
|
||||
Usage: "Cgroup manager to use (cgroupfs or systemd, default systemd)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cni-config-dir",
|
||||
Usage: "Path of the configuration directory for CNI networks",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "conmon",
|
||||
Usage: "Path of the conmon binary",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "default-mounts-file",
|
||||
Usage: "Path to default mounts file",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "hooks-dir",
|
||||
Usage: "Set the OCI hooks directory path (may be set multiple times)",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "max-workers",
|
||||
Usage: "The maximum number of workers for parallel operations",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "namespace",
|
||||
Usage: "Set the libpod namespace, used to create separate views of the containers and pods on the system",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "root",
|
||||
Usage: "Path to the root directory in which data, including images, is stored",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "runroot",
|
||||
Usage: "Path to the 'run directory' where all state information is stored",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "runtime",
|
||||
Usage: "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "storage-driver, s",
|
||||
Usage: "Select which storage driver is used to manage storage of images and containers (default is overlay)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "storage-opt",
|
||||
Usage: "Used to pass an option to the storage driver",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "syslog",
|
||||
Usage: "Output logging information to syslog as well as the console",
|
||||
},
|
||||
|
||||
func getGenerateSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_containerKubeCommand,
|
||||
}
|
||||
}
|
||||
|
||||
func getPlaySubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_playKubeCommand,
|
||||
}
|
||||
}
|
||||
|
||||
func getTrustSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_setTrustCommand,
|
||||
_showTrustCommand,
|
||||
}
|
||||
}
|
||||
|
||||
func getSystemSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_infoCommand,
|
||||
_pruneSystemCommand,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,24 +2,47 @@
|
|||
|
||||
package main
|
||||
|
||||
import "github.com/urfave/cli"
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func getAppCommands() []cli.Command {
|
||||
return []cli.Command{}
|
||||
//import "github.com/urfave/cli"
|
||||
//
|
||||
func getAppCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
func getImageSubCommands() []cli.Command {
|
||||
return []cli.Command{}
|
||||
func getImageSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
func getContainerSubCommands() []cli.Command {
|
||||
return []cli.Command{}
|
||||
func getContainerSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
func getSystemSubCommands() []cli.Command {
|
||||
return []cli.Command{}
|
||||
func getPodSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
func getMainAppFlags() []cli.Flag {
|
||||
return []cli.Flag{}
|
||||
func getVolumeSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
func getGenerateSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
func getPlaySubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
func getTrustSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
||||
//func getMainAppFlags() []cli.Flag {
|
||||
// return []cli.Flag{}
|
||||
//}
|
||||
func getSystemSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -13,57 +15,43 @@ import (
|
|||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
commitFlags = []cli.Flag{
|
||||
cli.StringSliceFlag{
|
||||
Name: "change, c",
|
||||
Usage: fmt.Sprintf("Apply the following possible instructions to the created image (default []): %s", strings.Join(libpod.ChangeCmds, " | ")),
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format, f",
|
||||
Usage: "`format` of the image manifest and metadata",
|
||||
Value: "oci",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "message, m",
|
||||
Usage: "Set commit message for imported image",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "author, a",
|
||||
Usage: "Set the author for the image committed",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "pause, p",
|
||||
Usage: "Pause container during commit",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress output",
|
||||
},
|
||||
}
|
||||
commitCommand cliconfig.CommitValues
|
||||
commitDescription = `Create an image from a container's changes.
|
||||
Optionally tag the image created, set the author with the --author flag,
|
||||
set the commit message with the --message flag,
|
||||
and make changes to the instructions with the --change flag.`
|
||||
commitCommand = cli.Command{
|
||||
Name: "commit",
|
||||
Usage: "Create new image based on the changed container",
|
||||
Description: commitDescription,
|
||||
Flags: sortFlags(commitFlags),
|
||||
Action: commitCmd,
|
||||
ArgsUsage: "CONTAINER [REPOSITORY[:TAG]]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
|
||||
_commitCommand = &cobra.Command{
|
||||
Use: "commit",
|
||||
Short: "Create new image based on the changed container",
|
||||
Long: commitDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
commitCommand.InputArgs = args
|
||||
commitCommand.GlobalFlags = MainGlobalOpts
|
||||
return commitCmd(&commitCommand)
|
||||
},
|
||||
Example: "CONTAINER [REPOSITORY[:TAG]]",
|
||||
}
|
||||
)
|
||||
|
||||
func commitCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, commitFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
func init() {
|
||||
commitCommand.Command = _commitCommand
|
||||
flags := commitCommand.Flags()
|
||||
flags.StringSliceVarP(&commitCommand.Change, "change", "c", []string{}, fmt.Sprintf("Apply the following possible instructions to the created image (default []): %s", strings.Join(libpod.ChangeCmds, " | ")))
|
||||
flags.StringVarP(&commitCommand.Format, "format", "f", "oci", "`Format` of the image manifest and metadata")
|
||||
flags.StringVarP(&commitCommand.Message, "message", "m", "", "Set commit message for imported image")
|
||||
flags.StringVarP(&commitCommand.Author, "author", "a", "", "Set the author for the image committed")
|
||||
flags.BoolVarP(&commitCommand.Pause, "pause", "p", false, "Pause container during commit")
|
||||
flags.BoolVarP(&commitCommand.Quiet, "quiet", "q", false, "Suppress output")
|
||||
|
||||
rootCmd.AddCommand(commitCommand.Command)
|
||||
}
|
||||
|
||||
func commitCmd(c *cliconfig.CommitValues) error {
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -73,26 +61,26 @@ func commitCmd(c *cli.Context) error {
|
|||
writer io.Writer
|
||||
mimeType string
|
||||
)
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) != 2 {
|
||||
return errors.Errorf("you must provide a container name or ID and a target image name")
|
||||
}
|
||||
|
||||
switch c.String("format") {
|
||||
switch c.Format {
|
||||
case "oci":
|
||||
mimeType = buildah.OCIv1ImageManifest
|
||||
if c.IsSet("message") || c.IsSet("m") {
|
||||
if c.Flag("message").Changed {
|
||||
return errors.Errorf("messages are only compatible with the docker image format (-f docker)")
|
||||
}
|
||||
case "docker":
|
||||
mimeType = manifest.DockerV2Schema2MediaType
|
||||
default:
|
||||
return errors.Errorf("unrecognized image format %q", c.String("format"))
|
||||
return errors.Errorf("unrecognized image format %q", c.Format)
|
||||
}
|
||||
container := args[0]
|
||||
reference := args[1]
|
||||
if c.IsSet("change") || c.IsSet("c") {
|
||||
for _, change := range c.StringSlice("change") {
|
||||
if c.Flag("change").Changed {
|
||||
for _, change := range c.Change {
|
||||
splitChange := strings.Split(strings.ToUpper(change), "=")
|
||||
if !util.StringInSlice(splitChange[0], libpod.ChangeCmds) {
|
||||
return errors.Errorf("invalid syntax for --change: %s", change)
|
||||
|
@ -100,7 +88,7 @@ func commitCmd(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
if !c.Bool("quiet") {
|
||||
if !c.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
ctr, err := runtime.LookupContainer(container)
|
||||
|
@ -117,10 +105,10 @@ func commitCmd(c *cli.Context) error {
|
|||
}
|
||||
options := libpod.ContainerCommitOptions{
|
||||
CommitOptions: coptions,
|
||||
Pause: c.Bool("pause"),
|
||||
Message: c.String("message"),
|
||||
Changes: c.StringSlice("change"),
|
||||
Author: c.String("author"),
|
||||
Pause: c.Pause,
|
||||
Message: c.Message,
|
||||
Changes: c.Change,
|
||||
Author: c.Author,
|
||||
}
|
||||
newImage, err := ctr.Commit(getContext(), reference, options)
|
||||
if err != nil {
|
||||
|
|
|
@ -4,34 +4,19 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/containers/storage"
|
||||
"github.com/fatih/camelcase"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
stores = make(map[storage.Store]struct{})
|
||||
LatestFlag = cli.BoolFlag{
|
||||
Name: "latest, l",
|
||||
Usage: "Act on the latest container podman is aware of",
|
||||
}
|
||||
LatestPodFlag = cli.BoolFlag{
|
||||
Name: "latest, l",
|
||||
Usage: "Act on the latest pod podman is aware of",
|
||||
}
|
||||
WorkDirFlag = cli.StringFlag{
|
||||
Name: "workdir, w",
|
||||
Usage: "Working directory inside the container",
|
||||
}
|
||||
stores = make(map[storage.Store]struct{})
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -50,53 +35,9 @@ func shortID(id string) string {
|
|||
return id
|
||||
}
|
||||
|
||||
func usageErrorHandler(context *cli.Context, err error, _ bool) error {
|
||||
cmd := context.App.Name
|
||||
if len(context.Command.Name) > 0 {
|
||||
cmd = cmd + " " + context.Command.Name
|
||||
}
|
||||
return fmt.Errorf("%s\nSee '%s --help'.", err, cmd)
|
||||
}
|
||||
|
||||
func commandNotFoundHandler(context *cli.Context, command string) {
|
||||
fmt.Fprintf(os.Stderr, "Command %q not found.\nSee `%s --help`.\n", command, context.App.Name)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
// validateFlags searches for StringFlags or StringSlice flags that never had
|
||||
// a value set. This commonly occurs when the CLI mistakenly takes the next
|
||||
// option and uses it as a value.
|
||||
func validateFlags(c *cli.Context, flags []cli.Flag) error {
|
||||
for _, flag := range flags {
|
||||
switch reflect.TypeOf(flag).String() {
|
||||
case "cli.StringSliceFlag":
|
||||
{
|
||||
f := flag.(cli.StringSliceFlag)
|
||||
name := strings.Split(f.Name, ",")
|
||||
val := c.StringSlice(name[0])
|
||||
for _, v := range val {
|
||||
if ok, _ := regexp.MatchString("^-.+", v); ok {
|
||||
return errors.Errorf("option --%s requires a value", name[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
case "cli.StringFlag":
|
||||
{
|
||||
f := flag.(cli.StringFlag)
|
||||
name := strings.Split(f.Name, ",")
|
||||
val := c.String(name[0])
|
||||
if ok, _ := regexp.MatchString("^-.+", val); ok {
|
||||
return errors.Errorf("option --%s requires a value", name[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkAllAndLatest checks that --all and --latest are used correctly
|
||||
func checkAllAndLatest(c *cli.Context) error {
|
||||
argLen := len(c.Args())
|
||||
func checkAllAndLatest(c *cliconfig.PodmanCommand) error {
|
||||
argLen := len(c.InputArgs)
|
||||
if (c.Bool("all") || c.Bool("latest")) && argLen > 0 {
|
||||
return errors.Errorf("no arguments are needed with --all or --latest")
|
||||
}
|
||||
|
@ -117,7 +58,7 @@ func checkAllAndLatest(c *cli.Context) error {
|
|||
// is desired a -1 can be used to get all containers. For a better
|
||||
// error message, if the filter fails, a corresponding verb can be
|
||||
// specified which will then appear in the error message.
|
||||
func getAllOrLatestContainers(c *cli.Context, runtime *libpod.Runtime, filterState libpod.ContainerStatus, verb string) ([]*libpod.Container, error) {
|
||||
func getAllOrLatestContainers(c *cliconfig.PodmanCommand, runtime *libpod.Runtime, filterState libpod.ContainerStatus, verb string) ([]*libpod.Container, error) {
|
||||
var containers []*libpod.Container
|
||||
var lastError error
|
||||
var err error
|
||||
|
@ -142,7 +83,7 @@ func getAllOrLatestContainers(c *cli.Context, runtime *libpod.Runtime, filterSta
|
|||
}
|
||||
containers = append(containers, lastCtr)
|
||||
} else {
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
for _, i := range args {
|
||||
container, err := runtime.LookupContainer(i)
|
||||
if err != nil {
|
||||
|
@ -173,363 +114,367 @@ func getDefaultNetwork() string {
|
|||
return "bridge"
|
||||
}
|
||||
|
||||
// Common flags shared between commands
|
||||
var createFlags = []cli.Flag{
|
||||
cli.StringSliceFlag{
|
||||
Name: "add-host",
|
||||
Usage: "Add a custom host-to-IP mapping (host:ip) (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "annotation",
|
||||
Usage: "Add annotations to container (key:value) (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "attach, a",
|
||||
Usage: "Attach to STDIN, STDOUT or STDERR (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "blkio-weight",
|
||||
Usage: "Block IO weight (relative weight) accepts a weight value between 10 and 1000.",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "blkio-weight-device",
|
||||
Usage: "Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "cap-add",
|
||||
Usage: "Add capabilities to the container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "cap-drop",
|
||||
Usage: "Drop capabilities from the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cgroup-parent",
|
||||
Usage: "Optional parent cgroup for the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cidfile",
|
||||
Usage: "Write the container ID to the file",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "conmon-pidfile",
|
||||
Usage: "Path to the file that will receive the PID of conmon",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "cpu-period",
|
||||
Usage: "Limit the CPU CFS (Completely Fair Scheduler) period",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-quota",
|
||||
Usage: "Limit the CPU CFS (Completely Fair Scheduler) quota",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "cpu-rt-period",
|
||||
Usage: "Limit the CPU real-time period in microseconds",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-rt-runtime",
|
||||
Usage: "Limit the CPU real-time runtime in microseconds",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "cpu-shares",
|
||||
Usage: "CPU shares (relative weight)",
|
||||
},
|
||||
cli.Float64Flag{
|
||||
Name: "cpus",
|
||||
Usage: "Number of CPUs. The default is 0.000 which means no limit",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpuset-cpus",
|
||||
Usage: "CPUs in which to allow execution (0-3, 0,1)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpuset-mems",
|
||||
Usage: "Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "detach, d",
|
||||
Usage: "Run container in background and print container ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "detach-keys",
|
||||
Usage: "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device",
|
||||
Usage: "Add a host device to the container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-read-bps",
|
||||
Usage: "Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-read-iops",
|
||||
Usage: "Limit read rate (IO per second) from a device (e.g. --device-read-iops=/dev/sda:1000)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-write-bps",
|
||||
Usage: "Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sda:1mb)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-write-iops",
|
||||
Usage: "Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "dns",
|
||||
Usage: "Set custom DNS servers",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "dns-opt",
|
||||
Usage: "Set custom DNS options",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "dns-search",
|
||||
Usage: "Set custom DNS search domains",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "entrypoint",
|
||||
Usage: "Overwrite the default ENTRYPOINT of the image",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "env, e",
|
||||
Usage: "Set environment variables in container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "env-file",
|
||||
Usage: "Read in a file of environment variables",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "expose",
|
||||
Usage: "Expose a port or a range of ports (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "gidmap",
|
||||
Usage: "GID map to use for the user namespace",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "group-add",
|
||||
Usage: "Add additional groups to join (default [])",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "help",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "hostname, h",
|
||||
Usage: "Set container hostname",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "image-volume, builtin-volume",
|
||||
Usage: "Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore' (default 'bind')",
|
||||
Value: "bind",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "init",
|
||||
Usage: "Run an init binary inside the container that forwards signals and reaps processes",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "init-path",
|
||||
// Do not use the Value field for setting the default value to determine user input (i.e., non-empty string)
|
||||
Usage: fmt.Sprintf("Path to the container-init binary (default: %q)", libpod.DefaultInitPath),
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "interactive, i",
|
||||
Usage: "Keep STDIN open even if not attached",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "ip",
|
||||
Usage: "Specify a static IPv4 address for the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "ipc",
|
||||
Usage: "IPC namespace to use",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "kernel-memory",
|
||||
Usage: "Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label",
|
||||
Usage: "Set metadata on container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label-file",
|
||||
Usage: "Read in a line delimited file of labels (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "log-driver",
|
||||
Usage: "Logging driver for the container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "log-opt",
|
||||
Usage: "Logging driver options (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "mac-address",
|
||||
Usage: "Container MAC address (e.g. 92:d0:c6:0a:29:33), not currently supported",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory, m",
|
||||
Usage: "Memory limit (format: <number>[<unit>], where unit = b, k, m or g)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory-reservation",
|
||||
Usage: "Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory-swap",
|
||||
Usage: "Swap limit equal to memory plus swap: '-1' to enable unlimited swap",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "memory-swappiness",
|
||||
Usage: "Tune container memory swappiness (0 to 100) (default -1)",
|
||||
Value: -1,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Assign a name to the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "net, network",
|
||||
Usage: "Connect a container to a network",
|
||||
Value: getDefaultNetwork(),
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "oom-kill-disable",
|
||||
Usage: "Disable OOM Killer",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "oom-score-adj",
|
||||
Usage: "Tune the host's OOM preferences (-1000 to 1000)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pid",
|
||||
Usage: "PID namespace to use",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "pids-limit",
|
||||
Usage: "Tune container pids limit (set -1 for unlimited)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pod",
|
||||
Usage: "Run container in an existing pod",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "privileged",
|
||||
Usage: "Give extended privileges to container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "publish, p",
|
||||
Usage: "Publish a container's port, or a range of ports, to the host (default [])",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "publish-all, P",
|
||||
Usage: "Publish all exposed ports to random ports on the host interface",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress output information when pulling images",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "read-only",
|
||||
Usage: "Make containers root filesystem read-only",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "restart",
|
||||
Usage: "Restart is not supported. Please use a systemd unit file for restart",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "rm",
|
||||
Usage: "Remove container (and pod if created) after exit",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "rootfs",
|
||||
Usage: "The first argument is not an image but the rootfs to the exploded container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "security-opt",
|
||||
Usage: "Security Options (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "shm-size",
|
||||
Usage: "Size of `/dev/shm`. The format is `<number><unit>`.",
|
||||
Value: "65536k",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "stop-signal",
|
||||
Usage: "Signal to stop a container. Default is SIGTERM",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "stop-timeout",
|
||||
Usage: "Timeout (in seconds) to stop a container. Default is 10",
|
||||
Value: libpod.CtrRemoveTimeout,
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "storage-opt",
|
||||
Usage: "Storage driver options per container (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "subgidname",
|
||||
Usage: "Name of range listed in /etc/subgid for use in user namespace",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "subuidname",
|
||||
Usage: "Name of range listed in /etc/subuid for use in user namespace",
|
||||
},
|
||||
func getCreateFlags(c *cliconfig.PodmanCommand) {
|
||||
|
||||
cli.StringSliceFlag{
|
||||
Name: "sysctl",
|
||||
Usage: "Sysctl options (default [])",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "systemd",
|
||||
Usage: "Run container in systemd mode if the command executable is systemd or init",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "tmpfs",
|
||||
Usage: "Mount a temporary filesystem (`tmpfs`) into a container (default [])",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "tty, t",
|
||||
Usage: "Allocate a pseudo-TTY for container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "uidmap",
|
||||
Usage: "UID map to use for the user namespace",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "ulimit",
|
||||
Usage: "Ulimit options (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "user, u",
|
||||
Usage: "Username or UID (format: <name|uid>[:<group|gid>])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "userns",
|
||||
Usage: "User namespace to use",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "uts",
|
||||
Usage: "UTS namespace to use",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "mount",
|
||||
Usage: "Attach a filesystem mount to the container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "volume, v",
|
||||
Usage: "Bind mount a volume into the container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "volumes-from",
|
||||
Usage: "Mount volumes from the specified container(s) (default [])",
|
||||
},
|
||||
WorkDirFlag,
|
||||
createFlags := c.Flags()
|
||||
|
||||
createFlags.StringSlice(
|
||||
"add-host", []string{},
|
||||
"Add a custom host-to-IP mapping (host:ip) (default [])",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"annotation", []string{},
|
||||
"Add annotations to container (key:value) (default [])",
|
||||
)
|
||||
createFlags.StringSliceP(
|
||||
"attach", "a", []string{},
|
||||
"Attach to STDIN, STDOUT or STDERR (default [])",
|
||||
)
|
||||
createFlags.String(
|
||||
"blkio-weight", "",
|
||||
"Block IO weight (relative weight) accepts a weight value between 10 and 1000.",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"blkio-weight-device", []string{},
|
||||
"Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"cap-add", []string{},
|
||||
"Add capabilities to the container",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"cap-drop", []string{},
|
||||
"Drop capabilities from the container",
|
||||
)
|
||||
createFlags.String(
|
||||
"cgroup-parent", "",
|
||||
"Optional parent cgroup for the container",
|
||||
)
|
||||
createFlags.String(
|
||||
"cidfile", "",
|
||||
"Write the container ID to the file",
|
||||
)
|
||||
createFlags.String(
|
||||
"conmon-pidfile", "",
|
||||
"Path to the file that will receive the PID of conmon",
|
||||
)
|
||||
createFlags.Uint64(
|
||||
"cpu-period", 0,
|
||||
"Limit the CPU CFS (Completely Fair Scheduler) period",
|
||||
)
|
||||
createFlags.Int64(
|
||||
"cpu-quota", 0,
|
||||
"Limit the CPU CFS (Completely Fair Scheduler) quota",
|
||||
)
|
||||
createFlags.Uint64(
|
||||
"cpu-rt-period", 0,
|
||||
"Limit the CPU real-time period in microseconds",
|
||||
)
|
||||
createFlags.Int64(
|
||||
"cpu-rt-runtime", 0,
|
||||
"Limit the CPU real-time runtime in microseconds",
|
||||
)
|
||||
createFlags.Uint64(
|
||||
"cpu-shares", 0,
|
||||
"CPU shares (relative weight)",
|
||||
)
|
||||
createFlags.Float64(
|
||||
"cpus", 0,
|
||||
"Number of CPUs. The default is 0.000 which means no limit",
|
||||
)
|
||||
createFlags.String(
|
||||
"cpuset-cpus", "",
|
||||
"CPUs in which to allow execution (0-3, 0,1)",
|
||||
)
|
||||
createFlags.String(
|
||||
"cpuset-mems", "",
|
||||
"Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
|
||||
)
|
||||
createFlags.BoolP(
|
||||
"detach", "d", false,
|
||||
"Run container in background and print container ID",
|
||||
)
|
||||
createFlags.String(
|
||||
"detach-keys", "",
|
||||
"Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"device", []string{},
|
||||
"Add a host device to the container (default [])",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"device-read-bps", []string{},
|
||||
"Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"device-read-iops", []string{},
|
||||
"Limit read rate (IO per second) from a device (e.g. --device-read-iops=/dev/sda:1000)",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"device-write-bps", []string{},
|
||||
"Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sda:1mb)",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"device-write-iops", []string{},
|
||||
"Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"dns", []string{},
|
||||
"Set custom DNS servers",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"dns-opt", []string{},
|
||||
"Set custom DNS options",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"dns-search", []string{},
|
||||
"Set custom DNS search domains",
|
||||
)
|
||||
createFlags.String(
|
||||
"entrypoint", "",
|
||||
"Overwrite the default ENTRYPOINT of the image",
|
||||
)
|
||||
createFlags.StringSliceP(
|
||||
"env", "e", []string{},
|
||||
"Set environment variables in container",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"env-file", []string{},
|
||||
"Read in a file of environment variables",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"expose", []string{},
|
||||
"Expose a port or a range of ports (default [])",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"gidmap", []string{},
|
||||
"GID map to use for the user namespace",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"group-add", []string{},
|
||||
"Add additional groups to join (default [])",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"help", false, "",
|
||||
)
|
||||
|
||||
createFlags.StringP(
|
||||
"hostname", "h", "",
|
||||
"Set container hostname",
|
||||
)
|
||||
createFlags.String(
|
||||
"image-volume", "bind",
|
||||
"Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore' (default 'bind')",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"init", false,
|
||||
"Run an init binary inside the container that forwards signals and reaps processes",
|
||||
)
|
||||
createFlags.String(
|
||||
"init-path", "",
|
||||
// Do not use the Value field for setting the default value to determine user input (i.e., non-empty string)
|
||||
fmt.Sprintf("Path to the container-init binary (default: %q)", libpod.DefaultInitPath),
|
||||
)
|
||||
createFlags.BoolP(
|
||||
"interactive", "i", false,
|
||||
"Keep STDIN open even if not attached",
|
||||
)
|
||||
createFlags.String(
|
||||
"ip", "",
|
||||
"Specify a static IPv4 address for the container",
|
||||
)
|
||||
createFlags.String(
|
||||
"ipc", "",
|
||||
"IPC namespace to use",
|
||||
)
|
||||
createFlags.String(
|
||||
"kernel-memory", "",
|
||||
"Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"label", []string{},
|
||||
"Set metadata on container (default [])",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"label-file", []string{},
|
||||
"Read in a line delimited file of labels (default [])",
|
||||
)
|
||||
createFlags.String(
|
||||
"log-driver", "",
|
||||
"Logging driver for the container",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"log-opt", []string{},
|
||||
"Logging driver options (default [])",
|
||||
)
|
||||
createFlags.String(
|
||||
"mac-address", "",
|
||||
"Container MAC address (e.g. 92:d0:c6:0a:29:33), not currently supported",
|
||||
)
|
||||
createFlags.StringP(
|
||||
"memory", "m", "",
|
||||
"Memory limit (format: <number>[<unit>], where unit = b, k, m or g)",
|
||||
)
|
||||
createFlags.String(
|
||||
"memory-reservation", "",
|
||||
"Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)",
|
||||
)
|
||||
createFlags.String(
|
||||
"memory-swap", "",
|
||||
"Swap limit equal to memory plus swap: '-1' to enable unlimited swap",
|
||||
)
|
||||
createFlags.Int64(
|
||||
"memory-swappiness", -1,
|
||||
"Tune container memory swappiness (0 to 100) (default -1)",
|
||||
)
|
||||
createFlags.String(
|
||||
"name", "",
|
||||
"Assign a name to the container",
|
||||
)
|
||||
createFlags.String(
|
||||
"net", getDefaultNetwork(),
|
||||
"Connect a container to a network",
|
||||
)
|
||||
createFlags.String(
|
||||
"network", getDefaultNetwork(),
|
||||
"Connect a container to a network",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"oom-kill-disable", false,
|
||||
"Disable OOM Killer",
|
||||
)
|
||||
createFlags.Int(
|
||||
"oom-score-adj", 0,
|
||||
"Tune the host's OOM preferences (-1000 to 1000)",
|
||||
)
|
||||
createFlags.String(
|
||||
"pid", "",
|
||||
"PID namespace to use",
|
||||
)
|
||||
createFlags.Int64(
|
||||
"pids-limit", 0,
|
||||
"Tune container pids limit (set -1 for unlimited)",
|
||||
)
|
||||
createFlags.String(
|
||||
"pod", "",
|
||||
"Run container in an existing pod",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"privileged", false,
|
||||
"Give extended privileges to container",
|
||||
)
|
||||
createFlags.StringSliceP(
|
||||
"publish", "p", []string{},
|
||||
"Publish a container's port, or a range of ports, to the host (default [])",
|
||||
)
|
||||
createFlags.BoolP(
|
||||
"publish-all", "P", false,
|
||||
"Publish all exposed ports to random ports on the host interface",
|
||||
)
|
||||
createFlags.BoolP(
|
||||
"quiet", "q", false,
|
||||
"Suppress output information when pulling images",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"read-only", false,
|
||||
"Make containers root filesystem read-only",
|
||||
)
|
||||
createFlags.String(
|
||||
"restart", "",
|
||||
"Restart is not supported. Please use a systemd unit file for restart",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"rm", false,
|
||||
"Remove container (and pod if created) after exit",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"rootfs", false,
|
||||
"The first argument is not an image but the rootfs to the exploded container",
|
||||
)
|
||||
createFlags.StringArray(
|
||||
"security-opt", []string{},
|
||||
"Security Options (default [])",
|
||||
)
|
||||
createFlags.String(
|
||||
"shm-size", "65536k",
|
||||
"Size of `/dev/shm`. The format is `<number><unit>`",
|
||||
)
|
||||
createFlags.String(
|
||||
"stop-signal", "",
|
||||
"Signal to stop a container. Default is SIGTERM",
|
||||
)
|
||||
createFlags.Int(
|
||||
"stop-timeout", libpod.CtrRemoveTimeout,
|
||||
"Timeout (in seconds) to stop a container. Default is 10",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"storage-opt", []string{},
|
||||
"Storage driver options per container (default [])",
|
||||
)
|
||||
createFlags.String(
|
||||
"subgidname", "",
|
||||
"Name of range listed in /etc/subgid for use in user namespace",
|
||||
)
|
||||
createFlags.String(
|
||||
"subuidname", "",
|
||||
"Name of range listed in /etc/subuid for use in user namespace",
|
||||
)
|
||||
|
||||
createFlags.StringSlice(
|
||||
"sysctl", []string{},
|
||||
"Sysctl options (default [])",
|
||||
)
|
||||
createFlags.Bool(
|
||||
"systemd", true,
|
||||
"Run container in systemd mode if the command executable is systemd or init",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"tmpfs", []string{},
|
||||
"Mount a temporary filesystem (`tmpfs`) into a container (default [])",
|
||||
)
|
||||
createFlags.BoolP(
|
||||
"tty", "t", false,
|
||||
"Allocate a pseudo-TTY for container",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"uidmap", []string{},
|
||||
"UID map to use for the user namespace",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"ulimit", []string{},
|
||||
"Ulimit options (default [])",
|
||||
)
|
||||
createFlags.StringP(
|
||||
"user", "u", "",
|
||||
"Username or UID (format: <name|uid>[:<group|gid>])",
|
||||
)
|
||||
createFlags.String(
|
||||
"userns", "",
|
||||
"User namespace to use",
|
||||
)
|
||||
createFlags.String(
|
||||
"uts", "",
|
||||
"UTS namespace to use",
|
||||
)
|
||||
createFlags.StringArray(
|
||||
"mount", []string{},
|
||||
"Attach a filesystem mount to the container (default [])",
|
||||
)
|
||||
createFlags.StringArrayP(
|
||||
"volume", "v", []string{},
|
||||
"Bind mount a volume into the container (default [])",
|
||||
)
|
||||
createFlags.StringSlice(
|
||||
"volumes-from", []string{},
|
||||
"Mount volumes from the specified container(s) (default [])",
|
||||
)
|
||||
createFlags.StringP(
|
||||
"workdir", "w", "",
|
||||
"Working directory inside the container",
|
||||
)
|
||||
}
|
||||
|
||||
func getFormat(c *cli.Context) (string, error) {
|
||||
func getFormat(c *cliconfig.PodmanCommand) (string, error) {
|
||||
format := strings.ToLower(c.String("format"))
|
||||
if strings.HasPrefix(format, buildah.OCI) {
|
||||
return buildah.OCIv1ImageManifest, nil
|
||||
|
@ -541,13 +486,6 @@ func getFormat(c *cli.Context) (string, error) {
|
|||
return "", errors.Errorf("unrecognized image type %q", format)
|
||||
}
|
||||
|
||||
func sortFlags(flags []cli.Flag) []cli.Flag {
|
||||
sort.Slice(flags, func(i, j int) bool {
|
||||
return strings.Compare(flags[i].GetName(), flags[j].GetName()) < 0
|
||||
})
|
||||
return flags
|
||||
}
|
||||
|
||||
func getAuthFile(authfile string) string {
|
||||
if authfile != "" {
|
||||
return authfile
|
||||
|
|
|
@ -1,30 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
containerSubCommands = []cli.Command{
|
||||
exportCommand,
|
||||
inspectCommand,
|
||||
}
|
||||
containerDescription = "Manage containers"
|
||||
containerCommand = cli.Command{
|
||||
Name: "container",
|
||||
Usage: "Manage Containers",
|
||||
Description: containerDescription,
|
||||
ArgsUsage: "",
|
||||
Subcommands: getContainerSubCommandsSorted(),
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
)
|
||||
|
||||
func getContainerSubCommandsSorted() []cli.Command {
|
||||
containerSubCommands = append(containerSubCommands, getContainerSubCommands()...)
|
||||
sort.Sort(commandSortedAlpha{containerSubCommands})
|
||||
return containerSubCommands
|
||||
var containerDescription = "Manage containers"
|
||||
var containerCommand = cliconfig.PodmanCommand{
|
||||
Command: &cobra.Command{
|
||||
Use: "container",
|
||||
Short: "Manage Containers",
|
||||
Long: containerDescription,
|
||||
TraverseChildren: true,
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
containerCommand.AddCommand(getContainerSubCommands()...)
|
||||
rootCmd.AddCommand(containerCommand.Command)
|
||||
}
|
||||
|
|
|
@ -3,30 +3,39 @@ package main
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
pruneContainersCommand cliconfig.ContainersPrune
|
||||
pruneContainersDescription = `
|
||||
podman container prune
|
||||
|
||||
Removes all exited containers
|
||||
`
|
||||
|
||||
pruneContainersCommand = cli.Command{
|
||||
Name: "prune",
|
||||
Usage: "Remove all stopped containers",
|
||||
Description: pruneContainersDescription,
|
||||
Action: pruneContainersCmd,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_pruneContainersCommand = &cobra.Command{
|
||||
Use: "prune",
|
||||
Short: "Remove all stopped containers",
|
||||
Long: pruneContainersDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
pruneContainersCommand.InputArgs = args
|
||||
pruneContainersCommand.GlobalFlags = MainGlobalOpts
|
||||
return pruneContainersCmd(&pruneContainersCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
pruneContainersCommand.Command = _pruneContainersCommand
|
||||
}
|
||||
|
||||
func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWorkers int, force bool) error {
|
||||
var deleteFuncs []shared.ParallelWorkerInput
|
||||
|
||||
|
@ -60,8 +69,8 @@ func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWork
|
|||
return printParallelOutput(deleteErrors, errCount)
|
||||
}
|
||||
|
||||
func pruneContainersCmd(c *cli.Context) error {
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
func pruneContainersCmd(c *cliconfig.ContainersPrune) error {
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -69,7 +78,7 @@ func pruneContainersCmd(c *cli.Context) error {
|
|||
|
||||
maxWorkers := shared.Parallelize("rm")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
|
@ -29,37 +30,46 @@ import (
|
|||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
createCommand cliconfig.CreateValues
|
||||
createDescription = "Creates a new container from the given image or" +
|
||||
" storage and prepares it for running the specified command. The" +
|
||||
" container ID is then printed to stdout. You can then start it at" +
|
||||
" any time with the podman start <container_id> command. The container" +
|
||||
" will be created with the initial state 'created'."
|
||||
_createCommand = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create but do not start a container",
|
||||
Long: createDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
createCommand.InputArgs = args
|
||||
createCommand.GlobalFlags = MainGlobalOpts
|
||||
return createCmd(&createCommand)
|
||||
},
|
||||
Example: "IMAGE [COMMAND [ARG...]]",
|
||||
}
|
||||
|
||||
defaultEnvVariables = map[string]string{
|
||||
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TERM": "xterm",
|
||||
}
|
||||
)
|
||||
|
||||
var createDescription = "Creates a new container from the given image or" +
|
||||
" storage and prepares it for running the specified command. The" +
|
||||
" container ID is then printed to stdout. You can then start it at" +
|
||||
" any time with the podman start <container_id> command. The container" +
|
||||
" will be created with the initial state 'created'."
|
||||
func init() {
|
||||
createCommand.PodmanCommand.Command = _createCommand
|
||||
|
||||
var createCommand = cli.Command{
|
||||
Name: "create",
|
||||
Usage: "Create but do not start a container",
|
||||
Description: createDescription,
|
||||
Flags: sortFlags(createFlags),
|
||||
Action: createCmd,
|
||||
ArgsUsage: "IMAGE [COMMAND [ARG...]]",
|
||||
HideHelp: true,
|
||||
SkipArgReorder: true,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
getCreateFlags(&createCommand.PodmanCommand)
|
||||
flags := createCommand.Flags()
|
||||
flags.SetInterspersed(true)
|
||||
|
||||
rootCmd.AddCommand(createCommand.Command)
|
||||
}
|
||||
|
||||
func createCmd(c *cli.Context) error {
|
||||
if err := createInit(c); err != nil {
|
||||
func createCmd(c *cliconfig.CreateValues) error {
|
||||
if err := createInit(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -67,13 +77,13 @@ func createCmd(c *cli.Context) error {
|
|||
rootless.SetSkipStorageSetup(true)
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
ctr, _, err := createContainer(c, runtime)
|
||||
ctr, _, err := createContainer(&c.PodmanCommand, runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -82,33 +92,24 @@ func createCmd(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func createInit(c *cli.Context) error {
|
||||
// TODO should allow user to create based off a directory on the host not just image
|
||||
// Need CLI support for this
|
||||
|
||||
func createInit(c *cliconfig.PodmanCommand) error {
|
||||
// Docker-compatibility: the "-h" flag for run/create is reserved for
|
||||
// the hostname (see https://github.com/containers/libpod/issues/1367).
|
||||
if c.Bool("help") {
|
||||
cli.ShowCommandHelpAndExit(c, "run", 0)
|
||||
}
|
||||
|
||||
if err := validateFlags(c, createFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(c.Args()) < 1 {
|
||||
if len(c.InputArgs) < 1 {
|
||||
return errors.Errorf("image name or ID is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
|
||||
func createContainer(c *cliconfig.PodmanCommand, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
|
||||
|
||||
rtc := runtime.GetConfig()
|
||||
ctx := getContext()
|
||||
rootfs := ""
|
||||
if c.Bool("rootfs") {
|
||||
rootfs = c.Args()[0]
|
||||
rootfs = c.InputArgs[0]
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -134,7 +135,7 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container
|
|||
writer = os.Stderr
|
||||
}
|
||||
|
||||
newImage, err := runtime.ImageRuntime().New(ctx, c.Args()[0], rtc.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, false, nil)
|
||||
newImage, err := runtime.ImageRuntime().New(ctx, c.InputArgs[0], rtc.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, false, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -264,7 +265,7 @@ func isPortInImagePorts(exposedPorts map[string]struct{}, port string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string {
|
||||
func configureEntrypoint(c *cliconfig.PodmanCommand, data *inspect.ImageData) []string {
|
||||
entrypoint := []string{}
|
||||
if c.IsSet("entrypoint") {
|
||||
// Force entrypoint to ""
|
||||
|
@ -284,7 +285,7 @@ func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string {
|
|||
return entrypoint
|
||||
}
|
||||
|
||||
func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) {
|
||||
func configurePod(c *cliconfig.PodmanCommand, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) {
|
||||
pod, err := runtime.LookupPod(podName)
|
||||
if err != nil {
|
||||
return namespaces, err
|
||||
|
@ -296,7 +297,7 @@ func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string
|
|||
if (namespaces["pid"] == cc.Pod) || (!c.IsSet("pid") && pod.SharesPID()) {
|
||||
namespaces["pid"] = fmt.Sprintf("container:%s", podInfraID)
|
||||
}
|
||||
if (namespaces["net"] == cc.Pod) || (!c.IsSet("net") && pod.SharesNet()) {
|
||||
if (namespaces["net"] == cc.Pod) || (!c.IsSet("net") && !c.IsSet("network") && pod.SharesNet()) {
|
||||
namespaces["net"] = fmt.Sprintf("container:%s", podInfraID)
|
||||
}
|
||||
if (namespaces["user"] == cc.Pod) || (!c.IsSet("user") && pod.SharesUser()) {
|
||||
|
@ -313,7 +314,7 @@ func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string
|
|||
|
||||
// Parses CLI options related to container creation into a config which can be
|
||||
// parsed into an OCI runtime spec
|
||||
func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
|
||||
func parseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
|
||||
var (
|
||||
inputCommand, command []string
|
||||
memoryLimit, memoryReservation, memorySwap, memoryKernel int64
|
||||
|
@ -335,14 +336,14 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
|
||||
imageID := ""
|
||||
|
||||
inputCommand = c.Args()[1:]
|
||||
inputCommand = c.InputArgs[1:]
|
||||
if data != nil {
|
||||
imageID = data.ID
|
||||
}
|
||||
|
||||
rootfs := ""
|
||||
if c.Bool("rootfs") {
|
||||
rootfs = c.Args()[0]
|
||||
rootfs = c.InputArgs[0]
|
||||
}
|
||||
|
||||
sysctl, err := validateSysctl(c.StringSlice("sysctl"))
|
||||
|
@ -382,15 +383,15 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
blkioWeight = uint16(u)
|
||||
}
|
||||
var mountList []spec.Mount
|
||||
if mountList, err = parseMounts(c.StringSlice("mount")); err != nil {
|
||||
if mountList, err = parseMounts(c.StringArray("mount")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = parseVolumes(c.StringSlice("volume")); err != nil {
|
||||
if err = parseVolumes(c.StringArray("volume")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = parseVolumesFrom(c.StringSlice("volumes-from")); err != nil {
|
||||
if err = parseVolumesFrom(c.StringArray("volumes-from")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -399,10 +400,10 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
if c.Bool("detach") && c.Bool("rm") {
|
||||
return nil, errors.Errorf("--rm and --detach cannot be specified together")
|
||||
}
|
||||
if c.Int64("cpu-period") != 0 && c.Float64("cpus") > 0 {
|
||||
if c.Flag("cpu-period").Changed && c.Flag("cpus").Changed {
|
||||
return nil, errors.Errorf("--cpu-period and --cpus cannot be set together")
|
||||
}
|
||||
if c.Int64("cpu-quota") != 0 && c.Float64("cpus") > 0 {
|
||||
if c.Flag("cpu-quota").Changed && c.Flag("cpus").Changed {
|
||||
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
|
||||
}
|
||||
|
||||
|
@ -420,9 +421,13 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
// Instead of integrating here, should be done in libpod
|
||||
// However, that also involves setting up security opts
|
||||
// when the pod's namespace is integrated
|
||||
namespaceNet := c.String("network")
|
||||
if c.Flag("net").Changed {
|
||||
namespaceNet = c.String("net")
|
||||
}
|
||||
namespaces = map[string]string{
|
||||
"pid": c.String("pid"),
|
||||
"net": c.String("net"),
|
||||
"net": namespaceNet,
|
||||
"ipc": c.String("ipc"),
|
||||
"user": c.String("userns"),
|
||||
"uts": c.String("uts"),
|
||||
|
@ -654,7 +659,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
}
|
||||
|
||||
var systemd bool
|
||||
if command != nil && c.BoolT("systemd") && ((filepath.Base(command[0]) == "init") || (filepath.Base(command[0]) == "systemd")) {
|
||||
if command != nil && c.Bool("systemd") && ((filepath.Base(command[0]) == "init") || (filepath.Base(command[0]) == "systemd")) {
|
||||
systemd = true
|
||||
if signalString == "" {
|
||||
stopSignal, err = signal.ParseSignal("RTMIN+3")
|
||||
|
@ -663,7 +668,17 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
}
|
||||
}
|
||||
}
|
||||
// This is done because cobra cannot have two aliased flags. So we have to check
|
||||
// both
|
||||
network := c.String("network")
|
||||
if c.Flag("net").Changed {
|
||||
network = c.String("net")
|
||||
}
|
||||
|
||||
var memorySwappiness int64
|
||||
if c.Flags().Lookup("memory-swappiness") != nil {
|
||||
memorySwappiness, _ = c.Flags().GetInt64("memory-swappiness")
|
||||
}
|
||||
config := &cc.CreateConfig{
|
||||
Runtime: runtime,
|
||||
Annotations: annotations,
|
||||
|
@ -697,7 +712,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
LogDriverOpt: c.StringSlice("log-opt"),
|
||||
MacAddress: c.String("mac-address"),
|
||||
Name: c.String("name"),
|
||||
Network: c.String("network"),
|
||||
Network: network,
|
||||
NetworkAlias: c.StringSlice("network-alias"),
|
||||
IpcMode: ipcMode,
|
||||
NetMode: netMode,
|
||||
|
@ -730,12 +745,11 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
Memory: memoryLimit,
|
||||
MemoryReservation: memoryReservation,
|
||||
MemorySwap: memorySwap,
|
||||
MemorySwappiness: c.Int("memory-swappiness"),
|
||||
MemorySwappiness: int(memorySwappiness),
|
||||
KernelMemory: memoryKernel,
|
||||
OomScoreAdj: c.Int("oom-score-adj"),
|
||||
|
||||
PidsLimit: c.Int64("pids-limit"),
|
||||
Ulimit: c.StringSlice("ulimit"),
|
||||
PidsLimit: c.Int64("pids-limit"),
|
||||
Ulimit: c.StringSlice("ulimit"),
|
||||
},
|
||||
Rm: c.Bool("rm"),
|
||||
StopSignal: stopSignal,
|
||||
|
@ -747,13 +761,12 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
User: user,
|
||||
UsernsMode: usernsMode,
|
||||
Mounts: mountList,
|
||||
Volumes: c.StringSlice("volume"),
|
||||
Volumes: c.StringArray("volume"),
|
||||
WorkDir: workDir,
|
||||
Rootfs: rootfs,
|
||||
VolumesFrom: c.StringSlice("volumes-from"),
|
||||
Syslog: c.GlobalBool("syslog"),
|
||||
Syslog: c.GlobalFlags.Syslog,
|
||||
}
|
||||
|
||||
if c.Bool("init") {
|
||||
initPath := c.String("init-path")
|
||||
if initPath == "" {
|
||||
|
@ -767,11 +780,11 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||
if config.Privileged {
|
||||
config.LabelOpts = label.DisableSecOpt()
|
||||
} else {
|
||||
if err := parseSecurityOpt(config, c.StringSlice("security-opt")); err != nil {
|
||||
if err := parseSecurityOpt(config, c.StringArray("security-opt")); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
config.SecurityOpts = c.StringSlice("security-opt")
|
||||
config.SecurityOpts = c.StringArray("security-opt")
|
||||
warnings, err := verifyContainerResources(config, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -80,19 +80,22 @@ func addWarning(warnings []string, msg string) []string {
|
|||
// podman run --mount type=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
|
||||
// podman run --mount type=tmpfs,target=/dev/shm ..
|
||||
func parseMounts(mounts []string) ([]spec.Mount, error) {
|
||||
// TODO(vrothberg): the manual parsing can be replaced with a regular expression
|
||||
// to allow a more robust parsing of the mount format and to give
|
||||
// precise errors regarding supported format versus suppored options.
|
||||
var mountList []spec.Mount
|
||||
errInvalidSyntax := errors.Errorf("incorrect mount format : should be --mount type=<bind|tmpfs>,[src=<host-dir>,]target=<ctr-dir>,[options]")
|
||||
errInvalidSyntax := errors.Errorf("incorrect mount format: should be --mount type=<bind|tmpfs>,[src=<host-dir>,]target=<ctr-dir>[,options]")
|
||||
for _, mount := range mounts {
|
||||
var tokenCount int
|
||||
var mountInfo spec.Mount
|
||||
|
||||
arr := strings.SplitN(mount, ",", 2)
|
||||
if len(arr) < 2 {
|
||||
return nil, errInvalidSyntax
|
||||
return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
|
||||
}
|
||||
kv := strings.Split(arr[0], "=")
|
||||
if kv[0] != "type" {
|
||||
return nil, errInvalidSyntax
|
||||
return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
|
||||
}
|
||||
switch kv[1] {
|
||||
case "bind":
|
||||
|
@ -168,7 +171,7 @@ func parseVolumes(volumes []string) error {
|
|||
for _, volume := range volumes {
|
||||
arr := strings.SplitN(volume, ":", 3)
|
||||
if len(arr) < 2 {
|
||||
return errors.Errorf("incorrect volume format %q, should be host-dir:ctr-dir:[option]", volume)
|
||||
return errors.Errorf("incorrect volume format %q, should be host-dir:ctr-dir[:option]", volume)
|
||||
}
|
||||
if err := validateVolumeHostDir(arr[0]); err != nil {
|
||||
return err
|
||||
|
|
|
@ -2,12 +2,12 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/storage/pkg/archive"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type diffJSONOutput struct {
|
||||
|
@ -33,31 +33,35 @@ func (so stdoutStruct) Out() error {
|
|||
}
|
||||
|
||||
var (
|
||||
diffFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "archive",
|
||||
Usage: "Save the diff as a tar archive",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Change the output format.",
|
||||
},
|
||||
}
|
||||
diffCommand cliconfig.DiffValues
|
||||
diffDescription = fmt.Sprint(`Displays changes on a container or image's filesystem. The
|
||||
container or image will be compared to its parent layer`)
|
||||
|
||||
diffCommand = cli.Command{
|
||||
Name: "diff",
|
||||
Usage: "Inspect changes on container's file systems",
|
||||
Description: diffDescription,
|
||||
Flags: sortFlags(diffFlags),
|
||||
Action: diffCmd,
|
||||
ArgsUsage: "ID-NAME",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_diffCommand = &cobra.Command{
|
||||
Use: "diff",
|
||||
Short: "Inspect changes on container's file systems",
|
||||
Long: diffDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
diffCommand.InputArgs = args
|
||||
diffCommand.GlobalFlags = MainGlobalOpts
|
||||
return diffCmd(&diffCommand)
|
||||
},
|
||||
Example: "ID-NAME",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
diffCommand.Command = _diffCommand
|
||||
flags := diffCommand.Flags()
|
||||
|
||||
flags.BoolVar(&diffCommand.Archive, "archive", true, "Save the diff as a tar archive")
|
||||
flags.StringVar(&diffCommand.Format, "format", "", "Change the output format")
|
||||
|
||||
flags.MarkHidden("archive")
|
||||
|
||||
rootCmd.AddCommand(diffCommand.Command)
|
||||
|
||||
}
|
||||
func formatJSON(output []diffOutputParams) (diffJSONOutput, error) {
|
||||
jsonStruct := diffJSONOutput{}
|
||||
for _, output := range output {
|
||||
|
@ -75,29 +79,25 @@ func formatJSON(output []diffOutputParams) (diffJSONOutput, error) {
|
|||
return jsonStruct, nil
|
||||
}
|
||||
|
||||
func diffCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, diffFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(c.Args()) != 1 {
|
||||
func diffCmd(c *cliconfig.DiffValues) error {
|
||||
if len(c.InputArgs) != 1 {
|
||||
return errors.Errorf("container, image, or layer name must be specified: podman diff [options [...]] ID-NAME")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
to := c.Args().Get(0)
|
||||
to := c.InputArgs[0]
|
||||
changes, err := runtime.GetDiff("", to)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get changes for %q", to)
|
||||
}
|
||||
|
||||
diffOutput := []diffOutputParams{}
|
||||
outputFormat := c.String("format")
|
||||
outputFormat := c.Format
|
||||
|
||||
for _, change := range changes {
|
||||
|
||||
|
|
|
@ -2,82 +2,76 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
execFlags = []cli.Flag{
|
||||
cli.StringSliceFlag{
|
||||
Name: "env, e",
|
||||
Usage: "Set environment variables",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "privileged",
|
||||
Usage: "Give the process extended Linux capabilities inside the container. The default is false",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "interactive, i",
|
||||
Usage: "Not supported. All exec commands are interactive by default.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "tty, t",
|
||||
Usage: "Allocate a pseudo-TTY. The default is false",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "user, u",
|
||||
Usage: "Sets the username or UID used and optionally the groupname or GID for the specified command",
|
||||
},
|
||||
LatestFlag,
|
||||
WorkDirFlag,
|
||||
}
|
||||
execCommand cliconfig.ExecValues
|
||||
|
||||
execDescription = `
|
||||
podman exec
|
||||
|
||||
Run a command in a running container
|
||||
`
|
||||
|
||||
execCommand = cli.Command{
|
||||
Name: "exec",
|
||||
Usage: "Run a process in a running container",
|
||||
Description: execDescription,
|
||||
Flags: sortFlags(execFlags),
|
||||
Action: execCmd,
|
||||
ArgsUsage: "CONTAINER-NAME",
|
||||
SkipArgReorder: true,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_execCommand = &cobra.Command{
|
||||
Use: "exec",
|
||||
Short: "Run a process in a running container",
|
||||
Long: execDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
execCommand.InputArgs = args
|
||||
execCommand.GlobalFlags = MainGlobalOpts
|
||||
return execCmd(&execCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME",
|
||||
}
|
||||
)
|
||||
|
||||
func execCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func init() {
|
||||
execCommand.Command = _execCommand
|
||||
flags := execCommand.Flags()
|
||||
flags.SetInterspersed(false)
|
||||
flags.StringSliceVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables")
|
||||
flags.BoolVarP(&execCommand.Interfactive, "interactive", "i", false, "Not supported. All exec commands are interactive by default")
|
||||
flags.BoolVarP(&execCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.BoolVar(&execCommand.Privileged, "privileged", false, "Give the process extended Linux capabilities inside the container. The default is false")
|
||||
flags.BoolVarP(&execCommand.Tty, "tty", "t", false, "Allocate a pseudo-TTY. The default is false")
|
||||
flags.StringVarP(&execCommand.User, "user", "u", "", "Sets the username or UID used and optionally the groupname or GID for the specified command")
|
||||
|
||||
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
|
||||
|
||||
rootCmd.AddCommand(execCommand.Command)
|
||||
}
|
||||
|
||||
func execCmd(c *cliconfig.ExecValues) error {
|
||||
args := c.InputArgs
|
||||
var ctr *libpod.Container
|
||||
var err error
|
||||
argStart := 1
|
||||
if len(args) < 1 && !c.Bool("latest") {
|
||||
if len(args) < 1 && !c.Latest {
|
||||
return errors.Errorf("you must provide one container name or id")
|
||||
}
|
||||
if len(args) < 2 && !c.Bool("latest") {
|
||||
if len(args) < 2 && !c.Latest {
|
||||
return errors.Errorf("you must provide a command to exec")
|
||||
}
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
argStart = 0
|
||||
}
|
||||
rootless.SetSkipStorageSetup(true)
|
||||
cmd := args[argStart:]
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
ctr, err = runtime.GetLatestContainer()
|
||||
} else {
|
||||
ctr, err = runtime.LookupContainer(args[0])
|
||||
|
@ -101,7 +95,7 @@ func execCmd(c *cli.Context) error {
|
|||
// ENVIRONMENT VARIABLES
|
||||
env := map[string]string{}
|
||||
|
||||
if err := readKVStrings(env, []string{}, c.StringSlice("env")); err != nil {
|
||||
if err := readKVStrings(env, []string{}, c.Env); err != nil {
|
||||
return errors.Wrapf(err, "unable to process environment variables")
|
||||
}
|
||||
envs := []string{}
|
||||
|
@ -109,5 +103,5 @@ func execCmd(c *cli.Context) error {
|
|||
envs = append(envs, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
|
||||
return ctr.Exec(c.Bool("tty"), c.Bool("privileged"), envs, cmd, c.String("user"), c.String("workdir"))
|
||||
return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
|
@ -8,66 +10,78 @@ import (
|
|||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
imageExistsCommand cliconfig.ImageExistsValues
|
||||
containerExistsCommand cliconfig.ContainerExistsValues
|
||||
podExistsCommand cliconfig.PodExistsValues
|
||||
|
||||
imageExistsDescription = `
|
||||
podman image exists
|
||||
|
||||
Check if an image exists in local storage
|
||||
`
|
||||
|
||||
imageExistsCommand = cli.Command{
|
||||
Name: "exists",
|
||||
Usage: "Check if an image exists in local storage",
|
||||
Description: imageExistsDescription,
|
||||
Action: imageExistsCmd,
|
||||
ArgsUsage: "IMAGE-NAME",
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
containerExistsDescription = `
|
||||
podman container exists
|
||||
|
||||
Check if a container exists in local storage
|
||||
`
|
||||
|
||||
containerExistsCommand = cli.Command{
|
||||
Name: "exists",
|
||||
Usage: "Check if a container exists in local storage",
|
||||
Description: containerExistsDescription,
|
||||
Action: containerExistsCmd,
|
||||
ArgsUsage: "CONTAINER-NAME",
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
podExistsDescription = `
|
||||
podman pod exists
|
||||
|
||||
Check if a pod exists in local storage
|
||||
`
|
||||
_imageExistsCommand = &cobra.Command{
|
||||
Use: "exists",
|
||||
Short: "Check if an image exists in local storage",
|
||||
Long: imageExistsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
imageExistsCommand.InputArgs = args
|
||||
imageExistsCommand.GlobalFlags = MainGlobalOpts
|
||||
return imageExistsCmd(&imageExistsCommand)
|
||||
},
|
||||
Example: "IMAGE-NAME",
|
||||
}
|
||||
|
||||
podExistsCommand = cli.Command{
|
||||
Name: "exists",
|
||||
Usage: "Check if a pod exists in local storage",
|
||||
Description: podExistsDescription,
|
||||
Action: podExistsCmd,
|
||||
ArgsUsage: "POD-NAME",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_containerExistsCommand = &cobra.Command{
|
||||
Use: "exists",
|
||||
Short: "Check if a container exists in local storage",
|
||||
Long: containerExistsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
containerExistsCommand.InputArgs = args
|
||||
containerExistsCommand.GlobalFlags = MainGlobalOpts
|
||||
return containerExistsCmd(&containerExistsCommand)
|
||||
|
||||
},
|
||||
Example: "CONTAINER-NAME",
|
||||
}
|
||||
|
||||
_podExistsCommand = &cobra.Command{
|
||||
Use: "exists",
|
||||
Short: "Check if a pod exists in local storage",
|
||||
Long: podExistsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podExistsCommand.InputArgs = args
|
||||
podExistsCommand.GlobalFlags = MainGlobalOpts
|
||||
return podExistsCmd(&podExistsCommand)
|
||||
},
|
||||
Example: "POD-NAME",
|
||||
}
|
||||
)
|
||||
|
||||
func imageExistsCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func init() {
|
||||
imageExistsCommand.Command = _imageExistsCommand
|
||||
containerExistsCommand.Command = _containerExistsCommand
|
||||
podExistsCommand.Command = _podExistsCommand
|
||||
}
|
||||
|
||||
func imageExistsCmd(c *cliconfig.ImageExistsValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 || len(args) < 1 {
|
||||
return errors.New("you may only check for the existence of one image at a time")
|
||||
}
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -83,12 +97,12 @@ func imageExistsCmd(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func containerExistsCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func containerExistsCmd(c *cliconfig.ContainerExistsValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 || len(args) < 1 {
|
||||
return errors.New("you may only check for the existence of one container at a time")
|
||||
}
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -102,12 +116,12 @@ func containerExistsCmd(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func podExistsCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func podExistsCmd(c *cliconfig.PodExistsValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 || len(args) < 1 {
|
||||
return errors.New("you may only check for the existence of one pod at a time")
|
||||
}
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
|
|
@ -3,50 +3,52 @@ package main
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
exportFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "output, o",
|
||||
Usage: "Write to a file, default is STDOUT",
|
||||
Value: "/dev/stdout",
|
||||
},
|
||||
}
|
||||
exportCommand cliconfig.ExportValues
|
||||
exportDescription = "Exports container's filesystem contents as a tar archive" +
|
||||
" and saves it on the local machine."
|
||||
exportCommand = cli.Command{
|
||||
Name: "export",
|
||||
Usage: "Export container's filesystem contents as a tar archive",
|
||||
Description: exportDescription,
|
||||
Flags: sortFlags(exportFlags),
|
||||
Action: exportCmd,
|
||||
ArgsUsage: "CONTAINER",
|
||||
OnUsageError: usageErrorHandler,
|
||||
|
||||
_exportCommand = &cobra.Command{
|
||||
Use: "export",
|
||||
Short: "Export container's filesystem contents as a tar archive",
|
||||
Long: exportDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
exportCommand.InputArgs = args
|
||||
exportCommand.GlobalFlags = MainGlobalOpts
|
||||
return exportCmd(&exportCommand)
|
||||
},
|
||||
Example: "CONTAINER",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
exportCommand.Command = _exportCommand
|
||||
flags := exportCommand.Flags()
|
||||
flags.StringVarP(&exportCommand.Output, "output", "o", "/dev/stdout", "Write to a file, default is STDOUT")
|
||||
rootCmd.AddCommand(exportCommand.Command)
|
||||
}
|
||||
|
||||
// exportCmd saves a container to a tarball on disk
|
||||
func exportCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, exportFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
func exportCmd(c *cliconfig.ExportValues) error {
|
||||
if os.Geteuid() != 0 {
|
||||
rootless.SetSkipStorageSetup(true)
|
||||
}
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) == 0 {
|
||||
return errors.Errorf("container id must be specified")
|
||||
}
|
||||
|
@ -54,10 +56,11 @@ func exportCmd(c *cli.Context) error {
|
|||
return errors.Errorf("too many arguments given, need 1 at most.")
|
||||
}
|
||||
|
||||
output := c.String("output")
|
||||
output := c.Output
|
||||
if runtime.Remote && (output == "/dev/stdout" || len(output) == 0) {
|
||||
return errors.New("remote client usage must specify an output file (-o)")
|
||||
}
|
||||
|
||||
if output == "/dev/stdout" {
|
||||
file := os.Stdout
|
||||
if logrus.IsTerminal(file) {
|
||||
|
@ -68,5 +71,5 @@ func exportCmd(c *cli.Context) error {
|
|||
if err := validateFileName(output); err != nil {
|
||||
return err
|
||||
}
|
||||
return runtime.Export(args[0], c.String("output"))
|
||||
return runtime.Export(args[0], output)
|
||||
}
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
generateSubCommands = []cli.Command{
|
||||
containerKubeCommand,
|
||||
}
|
||||
var generateDescription = "Generate structured data based for a containers and pods"
|
||||
var generateCommand = cliconfig.PodmanCommand{
|
||||
|
||||
generateDescription = "Generate structured data based for a containers and pods"
|
||||
kubeCommand = cli.Command{
|
||||
Name: "generate",
|
||||
Usage: "Generate structured data",
|
||||
Description: generateDescription,
|
||||
ArgsUsage: "",
|
||||
Subcommands: generateSubCommands,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
Command: &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generated structured data",
|
||||
Long: generateDescription,
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
generateCommand.AddCommand(getGenerateSubCommands()...)
|
||||
rootCmd.AddCommand(generateCommand.Command)
|
||||
}
|
||||
|
|
|
@ -2,38 +2,40 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
podmanVersion "github.com/containers/libpod/version"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
containerKubeFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "service, s",
|
||||
Usage: "Generate YAML for kubernetes service object",
|
||||
},
|
||||
}
|
||||
containerKubeCommand cliconfig.GenerateKubeValues
|
||||
containerKubeDescription = "Generate Kubernetes Pod YAML"
|
||||
containerKubeCommand = cli.Command{
|
||||
Name: "kube",
|
||||
Usage: "Generate Kubernetes pod YAML for a container or pod",
|
||||
Description: containerKubeDescription,
|
||||
Flags: sortFlags(containerKubeFlags),
|
||||
Action: generateKubeYAMLCmd,
|
||||
ArgsUsage: "CONTAINER|POD-NAME",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_containerKubeCommand = &cobra.Command{
|
||||
Use: "kube",
|
||||
Short: "Generate Kubernetes pod YAML for a container or pod",
|
||||
Long: containerKubeDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
containerKubeCommand.InputArgs = args
|
||||
containerKubeCommand.GlobalFlags = MainGlobalOpts
|
||||
return generateKubeYAMLCmd(&containerKubeCommand)
|
||||
},
|
||||
Example: "CONTAINER|POD-NAME",
|
||||
}
|
||||
)
|
||||
|
||||
func generateKubeYAMLCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
containerKubeCommand.Command = _containerKubeCommand
|
||||
flags := containerKubeCommand.Flags()
|
||||
flags.BoolVarP(&containerKubeCommand.Service, "service", "s", false, "Generate YAML for kubernetes service object")
|
||||
}
|
||||
|
||||
func generateKubeYAMLCmd(c *cliconfig.GenerateKubeValues) error {
|
||||
var (
|
||||
podYAML *v1.Pod
|
||||
container *libpod.Container
|
||||
|
@ -48,12 +50,12 @@ func generateKubeYAMLCmd(c *cli.Context) error {
|
|||
if rootless.IsRootless() {
|
||||
return errors.Wrapf(libpod.ErrNotImplemented, "rootless users")
|
||||
}
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 || (len(args) < 1 && !c.Bool("latest")) {
|
||||
return errors.Errorf("you must provide one container|pod ID or name or --latest")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -77,7 +79,7 @@ func generateKubeYAMLCmd(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if c.Bool("service") {
|
||||
if c.Service {
|
||||
serviceYAML := libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts)
|
||||
marshalledService, err = yaml.Marshal(serviceYAML)
|
||||
if err != nil {
|
||||
|
|
|
@ -6,12 +6,13 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const createdByTruncLength = 45
|
||||
|
@ -34,53 +35,44 @@ type historyOptions struct {
|
|||
}
|
||||
|
||||
var (
|
||||
historyFlags = []cli.Flag{
|
||||
cli.BoolTFlag{
|
||||
Name: "human, H",
|
||||
Usage: "Display sizes and dates in human readable format",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-trunc, notruncate",
|
||||
Usage: "Do not truncate the output",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Display the numeric IDs only",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Change the output to JSON or a Go template",
|
||||
},
|
||||
}
|
||||
historyCommand cliconfig.HistoryValues
|
||||
|
||||
historyDescription = "Displays the history of an image. The information can be printed out in an easy to read, " +
|
||||
"or user specified format, and can be truncated."
|
||||
historyCommand = cli.Command{
|
||||
Name: "history",
|
||||
Usage: "Show history of a specified image",
|
||||
Description: historyDescription,
|
||||
Flags: sortFlags(historyFlags),
|
||||
Action: historyCmd,
|
||||
ArgsUsage: "",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_historyCommand = &cobra.Command{
|
||||
Use: "history",
|
||||
Short: "Show history of a specified image",
|
||||
Long: historyDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
historyCommand.InputArgs = args
|
||||
historyCommand.GlobalFlags = MainGlobalOpts
|
||||
return historyCmd(&historyCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func historyCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, historyFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
func init() {
|
||||
historyCommand.Command = _historyCommand
|
||||
flags := historyCommand.Flags()
|
||||
flags.StringVar(&historyCommand.Format, "format", "", "Change the output to JSON or a Go template")
|
||||
flags.BoolVarP(&historyCommand.Human, "human", "H", true, "Display sizes and dates in human readable format")
|
||||
// notrucate needs to be added
|
||||
flags.BoolVar(&historyCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
|
||||
flags.BoolVarP(&historyCommand.Quiet, "quiet", "q", false, "Display the numeric IDs only")
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
rootCmd.AddCommand(historyCommand.Command)
|
||||
|
||||
}
|
||||
func historyCmd(c *cliconfig.HistoryValues) error {
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
format := genHistoryFormat(c.String("format"), c.Bool("quiet"))
|
||||
format := genHistoryFormat(c.Format, c.Quiet)
|
||||
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) == 0 {
|
||||
return errors.Errorf("an image name must be specified")
|
||||
}
|
||||
|
@ -93,9 +85,9 @@ func historyCmd(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
opts := historyOptions{
|
||||
human: c.BoolT("human"),
|
||||
noTrunc: c.Bool("no-trunc"),
|
||||
quiet: c.Bool("quiet"),
|
||||
human: c.Human,
|
||||
noTrunc: c.NoTrunc,
|
||||
quiet: c.Quiet,
|
||||
format: format,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +1,35 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
imageSubCommands = []cli.Command{
|
||||
importCommand,
|
||||
historyCommand,
|
||||
imageExistsCommand,
|
||||
inspectCommand,
|
||||
lsImagesCommand,
|
||||
pruneImagesCommand,
|
||||
pullCommand,
|
||||
rmImageCommand,
|
||||
tagCommand,
|
||||
}
|
||||
imageDescription = "Manage images"
|
||||
imageCommand = cli.Command{
|
||||
Name: "image",
|
||||
Usage: "Manage images",
|
||||
Description: imageDescription,
|
||||
ArgsUsage: "",
|
||||
Subcommands: getImageSubCommandsSorted(),
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
imageCommand = cliconfig.PodmanCommand{
|
||||
Command: &cobra.Command{
|
||||
Use: "image",
|
||||
Short: "Manage images",
|
||||
Long: imageDescription,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func getImageSubCommandsSorted() []cli.Command {
|
||||
imageSubCommands = append(imageSubCommands, getImageSubCommands()...)
|
||||
sort.Sort(commandSortedAlpha{imageSubCommands})
|
||||
return imageSubCommands
|
||||
//imageSubCommands are implemented both in local and remote clients
|
||||
var imageSubCommands = []*cobra.Command{
|
||||
_historyCommand,
|
||||
_imageExistsCommand,
|
||||
_inspectCommand,
|
||||
_imagesCommand,
|
||||
_pruneImagesCommand,
|
||||
_pushCommand,
|
||||
_rmiCommand,
|
||||
_tagCommand,
|
||||
}
|
||||
|
||||
func init() {
|
||||
imageCommand.AddCommand(imageSubCommands...)
|
||||
imageCommand.AddCommand(getImageSubCommands()...)
|
||||
rootCmd.AddCommand(imageCommand.Command)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/imagefilters"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
|
@ -16,7 +17,7 @@ import (
|
|||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type imagesTemplateParams struct {
|
||||
|
@ -83,108 +84,79 @@ func (a imagesSortedSize) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
var (
|
||||
imagesFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Show all images (default hides intermediate images)",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "digests",
|
||||
Usage: "Show digests",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "filter, f",
|
||||
Usage: "Filter output based on conditions provided (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Change the output format to JSON or a Go template",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "noheading, n",
|
||||
Usage: "Do not print column headings",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-trunc, notruncate",
|
||||
Usage: "Do not truncate output",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Display only image IDs",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "sort",
|
||||
Usage: "Sort by created, id, repository, size, or tag",
|
||||
Value: "Created",
|
||||
},
|
||||
}
|
||||
|
||||
imagesCommand cliconfig.ImagesValues
|
||||
imagesDescription = "lists locally stored images."
|
||||
imagesCommand = cli.Command{
|
||||
Name: "images",
|
||||
Usage: "List images in local storage",
|
||||
Description: imagesDescription,
|
||||
Flags: sortFlags(imagesFlags),
|
||||
Action: imagesCmd,
|
||||
ArgsUsage: "",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
lsImagesCommand = cli.Command{
|
||||
Name: "list",
|
||||
Aliases: []string{"ls"},
|
||||
Usage: "List images in local storage",
|
||||
Description: imagesDescription,
|
||||
Flags: imagesFlags,
|
||||
Action: imagesCmd,
|
||||
ArgsUsage: "",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
|
||||
_imagesCommand = &cobra.Command{
|
||||
Use: "images",
|
||||
Short: "List images in local storage",
|
||||
Long: imagesDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
imagesCommand.InputArgs = args
|
||||
imagesCommand.GlobalFlags = MainGlobalOpts
|
||||
return imagesCmd(&imagesCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func imagesCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
imagesCommand.Command = _imagesCommand
|
||||
flags := imagesCommand.Flags()
|
||||
flags.BoolVarP(&imagesCommand.All, "all", "a", false, "Show all images (default hides intermediate images)")
|
||||
flags.BoolVar(&imagesCommand.Digests, "digests", false, "Show digests")
|
||||
flags.StringSliceVarP(&imagesCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
|
||||
flags.StringVar(&imagesCommand.Format, "format", "", "Change the output format to JSON or a Go template")
|
||||
flags.BoolVarP(&imagesCommand.Noheading, "noheading", "n", false, "Do not print column headings")
|
||||
// TODO Need to learn how to deal with second name being a string instead of a char.
|
||||
// This needs to be "no-trunc, notruncate"
|
||||
flags.BoolVar(&imagesCommand.NoTrunc, "no-trunc", false, "Do not truncate output")
|
||||
flags.BoolVarP(&imagesCommand.Quiet, "quiet", "q", false, "Display only image IDs")
|
||||
flags.StringVar(&imagesCommand.Sort, "sort", "created", "Sort by created, id, repository, size, or tag")
|
||||
|
||||
rootCmd.AddCommand(imagesCommand.Command)
|
||||
|
||||
}
|
||||
|
||||
func imagesCmd(c *cliconfig.ImagesValues) error {
|
||||
var (
|
||||
filterFuncs []imagefilters.ResultFilter
|
||||
newImage *adapter.ContainerImage
|
||||
)
|
||||
if err := validateFlags(c, imagesFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
if len(c.Args()) == 1 {
|
||||
newImage, err = runtime.NewImageFromLocal(c.Args().Get(0))
|
||||
if len(c.InputArgs) == 1 {
|
||||
newImage, err = runtime.NewImageFromLocal(c.InputArgs[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.Args()) > 1 {
|
||||
if len(c.InputArgs) > 1 {
|
||||
return errors.New("'podman images' requires at most 1 argument")
|
||||
}
|
||||
|
||||
ctx := getContext()
|
||||
|
||||
if len(c.StringSlice("filter")) > 0 || newImage != nil {
|
||||
filterFuncs, err = CreateFilterFuncs(ctx, runtime, c, newImage)
|
||||
if len(c.Filter) > 0 || newImage != nil {
|
||||
filterFuncs, err = CreateFilterFuncs(ctx, runtime, c.Filter, newImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
opts := imagesOptions{
|
||||
quiet: c.Bool("quiet"),
|
||||
noHeading: c.Bool("noheading"),
|
||||
noTrunc: c.Bool("no-trunc"),
|
||||
digests: c.Bool("digests"),
|
||||
format: c.String("format"),
|
||||
sort: c.String("sort"),
|
||||
all: c.Bool("all"),
|
||||
quiet: c.Quiet,
|
||||
noHeading: c.Noheading,
|
||||
noTrunc: c.NoTrunc,
|
||||
digests: c.Digests,
|
||||
format: c.Format,
|
||||
sort: c.Sort,
|
||||
all: c.All,
|
||||
}
|
||||
|
||||
opts.outputformat = opts.setOutputFormat()
|
||||
|
@ -195,7 +167,7 @@ func imagesCmd(c *cli.Context) error {
|
|||
|
||||
var filteredImages []*adapter.ContainerImage
|
||||
//filter the images
|
||||
if len(c.StringSlice("filter")) > 0 || newImage != nil {
|
||||
if len(c.Filter) > 0 || newImage != nil {
|
||||
filteredImages = imagefilters.FilterImages(images, filterFuncs)
|
||||
} else {
|
||||
filteredImages = images
|
||||
|
@ -368,9 +340,9 @@ func (i *imagesTemplateParams) HeaderMap() map[string]string {
|
|||
|
||||
// CreateFilterFuncs returns an array of filter functions based on the user inputs
|
||||
// and is later used to filter images for output
|
||||
func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, c *cli.Context, img *adapter.ContainerImage) ([]imagefilters.ResultFilter, error) {
|
||||
func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, filters []string, img *adapter.ContainerImage) ([]imagefilters.ResultFilter, error) {
|
||||
var filterFuncs []imagefilters.ResultFilter
|
||||
for _, filter := range c.StringSlice("filter") {
|
||||
for _, filter := range filters {
|
||||
splitFilter := strings.Split(filter, "=")
|
||||
switch splitFilter[0] {
|
||||
case "before":
|
||||
|
|
|
@ -3,35 +3,39 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
pruneImagesCommand cliconfig.PruneImagesValues
|
||||
pruneImagesDescription = `
|
||||
podman image prune
|
||||
|
||||
Removes all unnamed images from local storage
|
||||
`
|
||||
pruneImageFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Remove all unused images, not just dangling ones",
|
||||
_pruneImagesCommand = &cobra.Command{
|
||||
Use: "prune",
|
||||
Short: "Remove unused images",
|
||||
Long: pruneImagesDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
pruneImagesCommand.InputArgs = args
|
||||
pruneImagesCommand.GlobalFlags = MainGlobalOpts
|
||||
return pruneImagesCmd(&pruneImagesCommand)
|
||||
},
|
||||
}
|
||||
pruneImagesCommand = cli.Command{
|
||||
Name: "prune",
|
||||
Usage: "Remove unused images",
|
||||
Description: pruneImagesDescription,
|
||||
Action: pruneImagesCmd,
|
||||
OnUsageError: usageErrorHandler,
|
||||
Flags: pruneImageFlags,
|
||||
}
|
||||
)
|
||||
|
||||
func pruneImagesCmd(c *cli.Context) error {
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
func init() {
|
||||
pruneImagesCommand.Command = _pruneImagesCommand
|
||||
flags := pruneImagesCommand.Flags()
|
||||
flags.BoolVarP(&pruneImagesCommand.All, "all", "a", false, "Remove all unused images, not just dangling ones")
|
||||
}
|
||||
|
||||
func pruneImagesCmd(c *cliconfig.PruneImagesValues) error {
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -39,7 +43,7 @@ func pruneImagesCmd(c *cli.Context) error {
|
|||
|
||||
// Call prune; if any cids are returned, print them and then
|
||||
// return err in case an error also came up
|
||||
pruneCids, err := runtime.PruneImages(c.Bool("all"))
|
||||
pruneCids, err := runtime.PruneImages(c.All)
|
||||
if len(pruneCids) > 0 {
|
||||
for _, cid := range pruneCids {
|
||||
fmt.Println(cid)
|
||||
|
|
|
@ -3,47 +3,44 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
importFlags = []cli.Flag{
|
||||
cli.StringSliceFlag{
|
||||
Name: "change, c",
|
||||
Usage: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "message, m",
|
||||
Usage: "Set commit message for imported image",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress output",
|
||||
},
|
||||
}
|
||||
importCommand cliconfig.ImportValues
|
||||
|
||||
importDescription = `Create a container image from the contents of the specified tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz).
|
||||
Note remote tar balls can be specified, via web address.
|
||||
Optionally tag the image. You can specify the instructions using the --change option.
|
||||
`
|
||||
importCommand = cli.Command{
|
||||
Name: "import",
|
||||
Usage: "Import a tarball to create a filesystem image",
|
||||
Description: importDescription,
|
||||
Flags: sortFlags(importFlags),
|
||||
Action: importCmd,
|
||||
ArgsUsage: "TARBALL [REFERENCE]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_importCommand = &cobra.Command{
|
||||
Use: "import",
|
||||
Short: "Import a tarball to create a filesystem image",
|
||||
Long: importDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
importCommand.InputArgs = args
|
||||
importCommand.GlobalFlags = MainGlobalOpts
|
||||
return importCmd(&importCommand)
|
||||
},
|
||||
Example: "TARBALL [REFERENCE]",
|
||||
}
|
||||
)
|
||||
|
||||
func importCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, importFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
func init() {
|
||||
importCommand.Command = _importCommand
|
||||
flags := importCommand.Flags()
|
||||
flags.StringSliceVarP(&importCommand.Change, "change", "c", []string{}, "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR")
|
||||
flags.StringVarP(&importCommand.Message, "message", "m", "", "Set commit message for imported image")
|
||||
flags.BoolVarP(&importCommand.Quiet, "quiet", "q", false, "Suppress output")
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
rootCmd.AddCommand(importCommand.Command)
|
||||
}
|
||||
|
||||
func importCmd(c *cliconfig.ImportValues) error {
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -54,7 +51,7 @@ func importCmd(c *cli.Context) error {
|
|||
reference string
|
||||
)
|
||||
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
switch len(args) {
|
||||
case 0:
|
||||
return errors.Errorf("need to give the path to the tarball, or must specify a tarball of '-' for stdin")
|
||||
|
@ -71,7 +68,7 @@ func importCmd(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
quiet := c.Bool("quiet")
|
||||
quiet := c.Quiet
|
||||
if runtime.Remote {
|
||||
quiet = false
|
||||
}
|
||||
|
|
|
@ -4,45 +4,47 @@ import (
|
|||
"fmt"
|
||||
rt "runtime"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/containers/libpod/version"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
infoCommand cliconfig.InfoValues
|
||||
|
||||
infoDescription = "Display podman system information"
|
||||
infoCommand = cli.Command{
|
||||
Name: "info",
|
||||
Usage: infoDescription,
|
||||
Description: `Information display here pertain to the host, current storage stats, and build of podman. Useful for the user and when reporting issues.`,
|
||||
Flags: sortFlags(infoFlags),
|
||||
Action: infoCmd,
|
||||
ArgsUsage: "",
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
infoFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "debug, D",
|
||||
Usage: "Display additional debug information",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format, f",
|
||||
Usage: "Change the output format to JSON or a Go template",
|
||||
_infoCommand = &cobra.Command{
|
||||
Use: "info",
|
||||
Long: infoDescription,
|
||||
Short: `Display information pertaining to the host, current storage stats, and build of podman. Useful for the user and when reporting issues.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
infoCommand.InputArgs = args
|
||||
infoCommand.GlobalFlags = MainGlobalOpts
|
||||
return infoCmd(&infoCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func infoCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, infoFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
func init() {
|
||||
infoCommand.Command = _infoCommand
|
||||
flags := infoCommand.Flags()
|
||||
|
||||
flags.BoolVarP(&infoCommand.Debug, "debug", "D", false, "Display additional debug information")
|
||||
flags.StringVarP(&infoCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
|
||||
|
||||
rootCmd.AddCommand(infoCommand.Command)
|
||||
}
|
||||
|
||||
func infoCmd(c *cliconfig.InfoValues) error {
|
||||
info := map[string]interface{}{}
|
||||
remoteClientInfo := map[string]interface{}{}
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -59,7 +61,7 @@ func infoCmd(c *cli.Context) error {
|
|||
infoArr = append(infoArr, libpod.InfoData{Type: "client", Data: remoteClientInfo})
|
||||
}
|
||||
|
||||
if !runtime.Remote && c.Bool("debug") {
|
||||
if !runtime.Remote && c.Debug {
|
||||
debugInfo := debugInfo(c)
|
||||
infoArr = append(infoArr, libpod.InfoData{Type: "debug", Data: debugInfo})
|
||||
}
|
||||
|
@ -69,7 +71,7 @@ func infoCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
var out formats.Writer
|
||||
infoOutputFormat := c.String("format")
|
||||
infoOutputFormat := c.Format
|
||||
switch infoOutputFormat {
|
||||
case formats.JSONString:
|
||||
out = formats.JSONStruct{Output: info}
|
||||
|
@ -85,11 +87,11 @@ func infoCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// top-level "debug" info
|
||||
func debugInfo(c *cli.Context) map[string]interface{} {
|
||||
func debugInfo(c *cliconfig.InfoValues) map[string]interface{} {
|
||||
info := map[string]interface{}{}
|
||||
info["compiler"] = rt.Compiler
|
||||
info["go version"] = rt.Version()
|
||||
info["podman version"] = c.App.Version
|
||||
info["podman version"] = version.Version
|
||||
version, _ := libpod.GetVersion()
|
||||
info["git commit"] = version.GitCommit
|
||||
return info
|
||||
|
|
|
@ -5,13 +5,14 @@ import (
|
|||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
cc "github.com/containers/libpod/pkg/spec"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -21,38 +22,37 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
inspectFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "type, t",
|
||||
Value: inspectAll,
|
||||
Usage: "Return JSON for specified type, (e.g image, container or task)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format, f",
|
||||
Usage: "Change the output format to a Go template",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "size, s",
|
||||
Usage: "Display total file size if the type is container",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
inspectCommand cliconfig.InspectValues
|
||||
|
||||
inspectDescription = "This displays the low-level information on containers and images identified by name or ID. By default, this will render all results in a JSON array. If the container and image have the same name, this will return container JSON for unspecified type."
|
||||
inspectCommand = cli.Command{
|
||||
Name: "inspect",
|
||||
Usage: "Display the configuration of a container or image",
|
||||
Description: inspectDescription,
|
||||
Flags: sortFlags(inspectFlags),
|
||||
Action: inspectCmd,
|
||||
ArgsUsage: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_inspectCommand = &cobra.Command{
|
||||
Use: "inspect",
|
||||
Short: "Display the configuration of a container or image",
|
||||
Long: inspectDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
inspectCommand.InputArgs = args
|
||||
inspectCommand.GlobalFlags = MainGlobalOpts
|
||||
return inspectCmd(&inspectCommand)
|
||||
},
|
||||
Example: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...",
|
||||
}
|
||||
)
|
||||
|
||||
func inspectCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
inspectType := c.String("type")
|
||||
latestContainer := c.Bool("latest")
|
||||
func init() {
|
||||
inspectCommand.Command = _inspectCommand
|
||||
flags := inspectCommand.Flags()
|
||||
flags.StringVarP(&inspectCommand.TypeObject, "type", "t", inspectAll, "Return JSON for specified type, (e.g image, container or task)")
|
||||
flags.StringVarP(&inspectCommand.Format, "format", "f", "", "Change the output format to a Go template")
|
||||
flags.BoolVarP(&inspectCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of if the type is a container")
|
||||
flags.BoolVarP(&inspectCommand.Size, "size", "s", false, "Display total file size if the type is container")
|
||||
|
||||
rootCmd.AddCommand(inspectCommand.Command)
|
||||
}
|
||||
|
||||
func inspectCmd(c *cliconfig.InspectValues) error {
|
||||
args := c.InputArgs
|
||||
inspectType := c.TypeObject
|
||||
latestContainer := c.Latest
|
||||
if len(args) == 0 && !latestContainer {
|
||||
return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name")
|
||||
}
|
||||
|
@ -60,11 +60,8 @@ func inspectCmd(c *cli.Context) error {
|
|||
if len(args) > 0 && latestContainer {
|
||||
return errors.Errorf("you cannot provide additional arguments with --latest")
|
||||
}
|
||||
if err := validateFlags(c, inspectFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
@ -74,7 +71,7 @@ func inspectCmd(c *cli.Context) error {
|
|||
return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
|
||||
}
|
||||
|
||||
outputFormat := c.String("format")
|
||||
outputFormat := c.Format
|
||||
if strings.Contains(outputFormat, "{{.Id}}") {
|
||||
outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1)
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ func inspectCmd(c *cli.Context) error {
|
|||
inspectType = inspectTypeContainer
|
||||
}
|
||||
|
||||
inspectedObjects, iterateErr := iterateInput(getContext(), c, args, runtime, inspectType)
|
||||
inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, args, runtime, inspectType)
|
||||
if iterateErr != nil {
|
||||
return iterateErr
|
||||
}
|
||||
|
@ -105,7 +102,7 @@ func inspectCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// func iterateInput iterates the images|containers the user has requested and returns the inspect data and error
|
||||
func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *adapter.LocalRuntime, inspectType string) ([]interface{}, error) {
|
||||
func iterateInput(ctx context.Context, size bool, args []string, runtime *adapter.LocalRuntime, inspectType string) ([]interface{}, error) {
|
||||
var (
|
||||
data interface{}
|
||||
inspectedItems []interface{}
|
||||
|
@ -120,7 +117,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *a
|
|||
inspectError = errors.Wrapf(err, "error looking up container %q", input)
|
||||
break
|
||||
}
|
||||
libpodInspectData, err := ctr.Inspect(c.Bool("size"))
|
||||
libpodInspectData, err := ctr.Inspect(size)
|
||||
if err != nil {
|
||||
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
|
||||
break
|
||||
|
@ -160,7 +157,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *a
|
|||
break
|
||||
}
|
||||
} else {
|
||||
libpodInspectData, err := ctr.Inspect(c.Bool("size"))
|
||||
libpodInspectData, err := ctr.Inspect(size)
|
||||
if err != nil {
|
||||
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
|
||||
break
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
|
@ -11,68 +12,66 @@ import (
|
|||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
killFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Signal all running containers",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signal, s",
|
||||
Usage: "Signal to send to the container",
|
||||
Value: "KILL",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
killCommand cliconfig.KillValues
|
||||
|
||||
killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal."
|
||||
killCommand = cli.Command{
|
||||
Name: "kill",
|
||||
Usage: "Kill one or more running containers with a specific signal",
|
||||
Description: killDescription,
|
||||
Flags: sortFlags(killFlags),
|
||||
Action: killCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_killCommand = &cobra.Command{
|
||||
Use: "kill",
|
||||
Short: "Kill one or more running containers with a specific signal",
|
||||
Long: killDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
killCommand.InputArgs = args
|
||||
killCommand.GlobalFlags = MainGlobalOpts
|
||||
return killCmd(&killCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
killCommand.Command = _killCommand
|
||||
flags := killCommand.Flags()
|
||||
|
||||
flags.BoolVarP(&killCommand.All, "all", "a", false, "Signal all running containers")
|
||||
flags.StringVarP(&killCommand.Signal, "signal", "s", "KILL", "Signal to send to the container")
|
||||
flags.BoolVarP(&killCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
|
||||
rootCmd.AddCommand(killCommand.Command)
|
||||
}
|
||||
|
||||
// killCmd kills one or more containers with a signal
|
||||
func killCmd(c *cli.Context) error {
|
||||
func killCmd(c *cliconfig.KillValues) error {
|
||||
var (
|
||||
killFuncs []shared.ParallelWorkerInput
|
||||
killSignal uint = uint(syscall.SIGTERM)
|
||||
)
|
||||
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateFlags(c, killFlags); err != nil {
|
||||
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rootless.SetSkipStorageSetup(true)
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if c.String("signal") != "" {
|
||||
if c.Signal != "" {
|
||||
// Check if the signalString provided by the user is valid
|
||||
// Invalid signals will return err
|
||||
sysSignal, err := signal.ParseSignal(c.String("signal"))
|
||||
sysSignal, err := signal.ParseSignal(c.Signal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
killSignal = uint(sysSignal)
|
||||
}
|
||||
|
||||
containers, err := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
|
||||
containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
|
||||
if err != nil {
|
||||
if len(containers) == 0 {
|
||||
return err
|
||||
|
@ -94,7 +93,7 @@ func killCmd(c *cli.Context) error {
|
|||
|
||||
maxWorkers := shared.Parallelize("kill")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package libpodruntime
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// GetRuntime generates a new libpod runtime configured by command line options
|
||||
func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
||||
func GetRuntime(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
|
||||
options := []libpod.RuntimeOption{}
|
||||
|
||||
storageOpts, volumePath, err := util.GetDefaultStoreOptions()
|
||||
|
@ -17,29 +17,39 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if c.IsSet("uidmap") || c.IsSet("gidmap") || c.IsSet("subuidmap") || c.IsSet("subgidmap") {
|
||||
mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap"))
|
||||
uidmapFlag := c.Flags().Lookup("uidmap")
|
||||
gidmapFlag := c.Flags().Lookup("gidmap")
|
||||
subuidname := c.Flags().Lookup("subuidname")
|
||||
subgidname := c.Flags().Lookup("subgidname")
|
||||
if (uidmapFlag != nil && gidmapFlag != nil && subuidname != nil && subgidname != nil) &&
|
||||
(uidmapFlag.Changed || gidmapFlag.Changed || subuidname.Changed || subgidname.Changed) {
|
||||
uidmapVal, _ := c.Flags().GetStringSlice("uidmap")
|
||||
gidmapVal, _ := c.Flags().GetStringSlice("gidmap")
|
||||
subuidVal, _ := c.Flags().GetString("subuidname")
|
||||
subgidVal, _ := c.Flags().GetString("subgidname")
|
||||
mappings, err := util.ParseIDMapping(uidmapVal, gidmapVal, subuidVal, subgidVal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storageOpts.UIDMap = mappings.UIDMap
|
||||
storageOpts.GIDMap = mappings.GIDMap
|
||||
|
||||
}
|
||||
|
||||
if c.GlobalIsSet("root") {
|
||||
storageOpts.GraphRoot = c.GlobalString("root")
|
||||
if c.Flags().Changed("root") {
|
||||
storageOpts.GraphRoot = c.GlobalFlags.Root
|
||||
}
|
||||
if c.GlobalIsSet("runroot") {
|
||||
storageOpts.RunRoot = c.GlobalString("runroot")
|
||||
if c.Flags().Changed("runroot") {
|
||||
storageOpts.RunRoot = c.GlobalFlags.Runroot
|
||||
}
|
||||
if len(storageOpts.RunRoot) > 50 {
|
||||
return nil, errors.New("the specified runroot is longer than 50 characters")
|
||||
}
|
||||
if c.GlobalIsSet("storage-driver") {
|
||||
storageOpts.GraphDriverName = c.GlobalString("storage-driver")
|
||||
if c.Flags().Changed("storage-driver") {
|
||||
storageOpts.GraphDriverName = c.GlobalFlags.StorageDriver
|
||||
}
|
||||
if c.GlobalIsSet("storage-opt") {
|
||||
storageOpts.GraphDriverOptions = c.GlobalStringSlice("storage-opt")
|
||||
if c.Flags().Changed("storage-opt") {
|
||||
storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts
|
||||
}
|
||||
|
||||
options = append(options, libpod.WithStorageConfig(storageOpts))
|
||||
|
@ -47,23 +57,23 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
|||
// TODO CLI flags for image config?
|
||||
// TODO CLI flag for signature policy?
|
||||
|
||||
if c.GlobalIsSet("namespace") {
|
||||
options = append(options, libpod.WithNamespace(c.GlobalString("namespace")))
|
||||
if len(c.GlobalFlags.Namespace) > 0 {
|
||||
options = append(options, libpod.WithNamespace(c.GlobalFlags.Namespace))
|
||||
}
|
||||
|
||||
if c.GlobalIsSet("runtime") {
|
||||
options = append(options, libpod.WithOCIRuntime(c.GlobalString("runtime")))
|
||||
if c.Flags().Changed("runtime") {
|
||||
options = append(options, libpod.WithOCIRuntime(c.GlobalFlags.Runtime))
|
||||
}
|
||||
|
||||
if c.GlobalIsSet("conmon") {
|
||||
options = append(options, libpod.WithConmonPath(c.GlobalString("conmon")))
|
||||
if c.Flags().Changed("conmon") {
|
||||
options = append(options, libpod.WithConmonPath(c.GlobalFlags.ConmonPath))
|
||||
}
|
||||
if c.GlobalIsSet("tmpdir") {
|
||||
options = append(options, libpod.WithTmpDir(c.GlobalString("tmpdir")))
|
||||
if c.Flags().Changed("tmpdir") {
|
||||
options = append(options, libpod.WithTmpDir(c.GlobalFlags.TmpDir))
|
||||
}
|
||||
|
||||
if c.GlobalIsSet("cgroup-manager") {
|
||||
options = append(options, libpod.WithCgroupManager(c.GlobalString("cgroup-manager")))
|
||||
if c.Flags().Changed("cgroup-manager") {
|
||||
options = append(options, libpod.WithCgroupManager(c.GlobalFlags.CGroupManager))
|
||||
} else {
|
||||
if rootless.IsRootless() {
|
||||
options = append(options, libpod.WithCgroupManager("cgroupfs"))
|
||||
|
@ -73,29 +83,37 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
|
|||
// TODO flag to set libpod static dir?
|
||||
// TODO flag to set libpod tmp dir?
|
||||
|
||||
if c.GlobalIsSet("cni-config-dir") {
|
||||
options = append(options, libpod.WithCNIConfigDir(c.GlobalString("cni-config-dir")))
|
||||
if c.Flags().Changed("cni-config-dir") {
|
||||
options = append(options, libpod.WithCNIConfigDir(c.GlobalFlags.CniConfigDir))
|
||||
}
|
||||
if c.GlobalIsSet("default-mounts-file") {
|
||||
options = append(options, libpod.WithDefaultMountsFile(c.GlobalString("default-mounts-file")))
|
||||
if c.Flags().Changed("default-mounts-file") {
|
||||
options = append(options, libpod.WithDefaultMountsFile(c.GlobalFlags.DefaultMountsFile))
|
||||
}
|
||||
if c.GlobalIsSet("hooks-dir") {
|
||||
options = append(options, libpod.WithHooksDir(c.GlobalStringSlice("hooks-dir")...))
|
||||
if c.Flags().Changed("hooks-dir") {
|
||||
options = append(options, libpod.WithHooksDir(c.GlobalFlags.HooksDir...))
|
||||
}
|
||||
|
||||
// TODO flag to set CNI plugins dir?
|
||||
|
||||
// TODO I dont think these belong here?
|
||||
// Will follow up with a different PR to address
|
||||
//
|
||||
// Pod create options
|
||||
if c.IsSet("infra-image") {
|
||||
options = append(options, libpod.WithDefaultInfraImage(c.String("infra-image")))
|
||||
|
||||
infraImageFlag := c.Flags().Lookup("infra-image")
|
||||
if infraImageFlag != nil && infraImageFlag.Changed {
|
||||
infraImage, _ := c.Flags().GetString("infra-image")
|
||||
options = append(options, libpod.WithDefaultInfraImage(infraImage))
|
||||
}
|
||||
|
||||
if c.IsSet("infra-command") {
|
||||
options = append(options, libpod.WithDefaultInfraCommand(c.String("infra-command")))
|
||||
infraCommandFlag := c.Flags().Lookup("infra-command")
|
||||
if infraCommandFlag != nil && infraImageFlag.Changed {
|
||||
infraCommand, _ := c.Flags().GetString("infra-command")
|
||||
options = append(options, libpod.WithDefaultInfraCommand(infraCommand))
|
||||
}
|
||||
options = append(options, libpod.WithVolumePath(volumePath))
|
||||
if c.IsSet("config") {
|
||||
return libpod.NewRuntimeFromConfig(c.String("config"), options...)
|
||||
if c.Flags().Changed("config") {
|
||||
return libpod.NewRuntimeFromConfig(c.GlobalFlags.Config, options...)
|
||||
}
|
||||
return libpod.NewRuntime(options...)
|
||||
}
|
||||
|
|
|
@ -9,45 +9,44 @@ import (
|
|||
"github.com/containers/image/directory"
|
||||
dockerarchive "github.com/containers/image/docker/archive"
|
||||
ociarchive "github.com/containers/image/oci/archive"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
loadFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "input, i",
|
||||
Usage: "Read from archive file, default is STDIN",
|
||||
Value: "/dev/stdin",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress the output",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signature-policy",
|
||||
Usage: "`pathname` of signature policy file (not usually used)",
|
||||
},
|
||||
}
|
||||
loadCommand cliconfig.LoadValues
|
||||
|
||||
loadDescription = "Loads the image from docker-archive stored on the local machine."
|
||||
loadCommand = cli.Command{
|
||||
Name: "load",
|
||||
Usage: "Load an image from docker archive",
|
||||
Description: loadDescription,
|
||||
Flags: sortFlags(loadFlags),
|
||||
Action: loadCmd,
|
||||
ArgsUsage: "",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_loadCommand = &cobra.Command{
|
||||
Use: "load",
|
||||
Short: "Load an image from docker archive",
|
||||
Long: loadDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
loadCommand.InputArgs = args
|
||||
loadCommand.GlobalFlags = MainGlobalOpts
|
||||
return loadCmd(&loadCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
loadCommand.Command = _loadCommand
|
||||
flags := loadCommand.Flags()
|
||||
flags.StringVarP(&loadCommand.Input, "input", "i", "/dev/stdin", "Read from archive file, default is STDIN")
|
||||
flags.BoolVarP(&loadCommand.Quiet, "quiet", "q", false, "Suppress the output")
|
||||
flags.StringVar(&loadCommand.SignaturePolicy, "signature-policy", "", "Pathname of signature policy file (not usually used)")
|
||||
|
||||
rootCmd.AddCommand(loadCommand.Command)
|
||||
}
|
||||
|
||||
// loadCmd gets the image/file to be loaded from the command line
|
||||
// and calls loadImage to load the image to containers-storage
|
||||
func loadCmd(c *cli.Context) error {
|
||||
func loadCmd(c *cliconfig.LoadValues) error {
|
||||
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
var imageName string
|
||||
|
||||
if len(args) == 1 {
|
||||
|
@ -56,17 +55,14 @@ func loadCmd(c *cli.Context) error {
|
|||
if len(args) > 1 {
|
||||
return errors.New("too many arguments. Requires exactly 1")
|
||||
}
|
||||
if err := validateFlags(c, loadFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
input := c.String("input")
|
||||
input := c.Input
|
||||
|
||||
if input == "/dev/stdin" {
|
||||
fi, err := os.Stdin.Stat()
|
||||
|
@ -101,7 +97,7 @@ func loadCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
var writer io.Writer
|
||||
if !c.Bool("quiet") {
|
||||
if !c.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
|
||||
|
@ -110,18 +106,18 @@ func loadCmd(c *cli.Context) error {
|
|||
var newImages []*image.Image
|
||||
src, err := dockerarchive.ParseReference(input) // FIXME? We should add dockerarchive.NewReference()
|
||||
if err == nil {
|
||||
newImages, err = runtime.ImageRuntime().LoadFromArchiveReference(ctx, src, c.String("signature-policy"), writer)
|
||||
newImages, err = runtime.ImageRuntime().LoadFromArchiveReference(ctx, src, c.SignaturePolicy, writer)
|
||||
}
|
||||
if err != nil {
|
||||
// generate full src name with specified image:tag
|
||||
src, err := ociarchive.NewReference(input, imageName) // imageName may be ""
|
||||
if err == nil {
|
||||
newImages, err = runtime.ImageRuntime().LoadFromArchiveReference(ctx, src, c.String("signature-policy"), writer)
|
||||
newImages, err = runtime.ImageRuntime().LoadFromArchiveReference(ctx, src, c.SignaturePolicy, writer)
|
||||
}
|
||||
if err != nil {
|
||||
src, err := directory.NewReference(input)
|
||||
if err == nil {
|
||||
newImages, err = runtime.ImageRuntime().LoadFromArchiveReference(ctx, src, c.String("signature-policy"), writer)
|
||||
newImages, err = runtime.ImageRuntime().LoadFromArchiveReference(ctx, src, c.SignaturePolicy, writer)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error pulling %q", input)
|
||||
|
|
|
@ -9,55 +9,48 @@ import (
|
|||
"github.com/containers/image/docker"
|
||||
"github.com/containers/image/pkg/docker/config"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/common"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
var (
|
||||
loginFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "password, p",
|
||||
Usage: "Password for registry",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "username, u",
|
||||
Usage: "Username for registry",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cert-dir",
|
||||
Usage: "Pathname of a directory containing TLS certificates and keys used to connect to the registry",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "get-login",
|
||||
Usage: "Return the current login user for the registry",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "tls-verify",
|
||||
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
|
||||
},
|
||||
}
|
||||
loginCommand cliconfig.LoginValues
|
||||
|
||||
loginDescription = "Login to a container registry on a specified server."
|
||||
loginCommand = cli.Command{
|
||||
Name: "login",
|
||||
Usage: "Login to a container registry",
|
||||
Description: loginDescription,
|
||||
Flags: sortFlags(loginFlags),
|
||||
Action: loginCmd,
|
||||
ArgsUsage: "REGISTRY",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_loginCommand = &cobra.Command{
|
||||
Use: "login",
|
||||
Short: "Login to a container registry",
|
||||
Long: loginDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
loginCommand.InputArgs = args
|
||||
loginCommand.GlobalFlags = MainGlobalOpts
|
||||
return loginCmd(&loginCommand)
|
||||
},
|
||||
Example: "REGISTRY",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
loginCommand.Command = _loginCommand
|
||||
flags := loginCommand.Flags()
|
||||
|
||||
flags.StringVar(&loginCommand.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(&loginCommand.CertDir, "cert-dir", "", "Pathname of a directory containing TLS certificates and keys used to connect to the registry")
|
||||
flags.BoolVar(&loginCommand.GetLogin, "get-login", true, "Return the current login user for the registry")
|
||||
flags.StringVarP(&loginCommand.Password, "password", "p", "", "Password for registry")
|
||||
flags.BoolVar(&loginCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
|
||||
flags.StringVarP(&loginCommand.Username, "username", "u", "", "Username for registry")
|
||||
|
||||
rootCmd.AddCommand(loginCommand.Command)
|
||||
}
|
||||
|
||||
// loginCmd uses the authentication package to store a user's authenticated credentials
|
||||
// in an auth.json file for future use
|
||||
func loginCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func loginCmd(c *cliconfig.LoginValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 {
|
||||
return errors.Errorf("too many arguments, login takes only 1 argument")
|
||||
}
|
||||
|
@ -65,17 +58,17 @@ func loginCmd(c *cli.Context) error {
|
|||
return errors.Errorf("please specify a registry to login to")
|
||||
}
|
||||
server := registryFromFullName(scrubServer(args[0]))
|
||||
authfile := getAuthFile(c.String("authfile"))
|
||||
authfile := getAuthFile(c.Authfile)
|
||||
|
||||
sc := common.GetSystemContext("", authfile, false)
|
||||
if c.IsSet("tls-verify") {
|
||||
sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
|
||||
if c.Flag("tls-verify").Changed {
|
||||
sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
|
||||
}
|
||||
if c.String("cert-dir") != "" {
|
||||
sc.DockerCertPath = c.String("cert-dir")
|
||||
if c.CertDir != "" {
|
||||
sc.DockerCertPath = c.CertDir
|
||||
}
|
||||
|
||||
if c.IsSet("get-login") {
|
||||
if c.Flag("get-login").Changed {
|
||||
user, err := config.GetUserLoggedIn(sc, server)
|
||||
|
||||
if err != nil {
|
||||
|
@ -98,7 +91,7 @@ func loginCmd(c *cli.Context) error {
|
|||
|
||||
ctx := getContext()
|
||||
// If no username and no password is specified, try to use existing ones.
|
||||
if c.String("username") == "" && c.String("password") == "" {
|
||||
if c.Username == "" && c.Password == "" {
|
||||
fmt.Println("Authenticating with existing credentials...")
|
||||
if err := docker.CheckAuth(ctx, sc, userFromAuthFile, passFromAuthFile, server); err == nil {
|
||||
fmt.Println("Existing credentials are valid. Already logged in to", server)
|
||||
|
@ -107,7 +100,7 @@ func loginCmd(c *cli.Context) error {
|
|||
fmt.Println("Existing credentials are invalid, please enter valid username and password")
|
||||
}
|
||||
|
||||
username, password, err := getUserAndPass(c.String("username"), c.String("password"), userFromAuthFile)
|
||||
username, password, err := getUserAndPass(c.Username, c.Password, userFromAuthFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error getting username and password")
|
||||
}
|
||||
|
|
|
@ -4,53 +4,56 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/containers/image/pkg/docker/config"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/common"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
logoutFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Remove the cached credentials for all registries in the auth file",
|
||||
},
|
||||
}
|
||||
logoutCommand cliconfig.LogoutValues
|
||||
logoutDescription = "Remove the cached username and password for the registry."
|
||||
logoutCommand = cli.Command{
|
||||
Name: "logout",
|
||||
Usage: "Logout of a container registry",
|
||||
Description: logoutDescription,
|
||||
Flags: sortFlags(logoutFlags),
|
||||
Action: logoutCmd,
|
||||
ArgsUsage: "REGISTRY",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_logoutCommand = &cobra.Command{
|
||||
Use: "logout",
|
||||
Short: "Logout of a container registry",
|
||||
Long: logoutDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
logoutCommand.InputArgs = args
|
||||
logoutCommand.GlobalFlags = MainGlobalOpts
|
||||
return logoutCmd(&logoutCommand)
|
||||
},
|
||||
Example: "REGISTRY",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
logoutCommand.Command = _logoutCommand
|
||||
flags := logoutCommand.Flags()
|
||||
flags.BoolVarP(&logoutCommand.All, "all", "a", false, "Remove the cached credentials for all registries in the auth file")
|
||||
flags.StringVar(&logoutCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
|
||||
|
||||
rootCmd.AddCommand(logoutCommand.Command)
|
||||
}
|
||||
|
||||
// logoutCmd uses the authentication package to remove the authenticated of a registry
|
||||
// stored in the auth.json file
|
||||
func logoutCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func logoutCmd(c *cliconfig.LogoutValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 {
|
||||
return errors.Errorf("too many arguments, logout takes at most 1 argument")
|
||||
}
|
||||
if len(args) == 0 && !c.IsSet("all") {
|
||||
if len(args) == 0 && !c.All {
|
||||
return errors.Errorf("registry must be given")
|
||||
}
|
||||
var server string
|
||||
if len(args) == 1 {
|
||||
server = scrubServer(args[0])
|
||||
}
|
||||
authfile := getAuthFile(c.String("authfile"))
|
||||
authfile := getAuthFile(c.Authfile)
|
||||
|
||||
sc := common.GetSystemContext("", authfile, false)
|
||||
|
||||
if c.Bool("all") {
|
||||
if c.All {
|
||||
if err := config.RemoveAllAuthentication(sc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,91 +4,82 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/logs"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
logsFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "details",
|
||||
Usage: "Show extra details provided to the logs",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "follow, f",
|
||||
Usage: "Follow log output. The default is false",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "since",
|
||||
Usage: "Show logs since TIMESTAMP",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "tail",
|
||||
Usage: "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "timestamps, t",
|
||||
Usage: "Output the timestamps in the log",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
logsCommand cliconfig.LogsValues
|
||||
logsDescription = "The podman logs command batch-retrieves whatever logs are present for a container at the time of execution. This does not guarantee execution" +
|
||||
"order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs"
|
||||
logsCommand = cli.Command{
|
||||
Name: "logs",
|
||||
Usage: "Fetch the logs of a container",
|
||||
Description: logsDescription,
|
||||
Flags: sortFlags(logsFlags),
|
||||
Action: logsCmd,
|
||||
ArgsUsage: "CONTAINER",
|
||||
SkipArgReorder: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
UseShortOptionHandling: true,
|
||||
_logsCommand = &cobra.Command{
|
||||
Use: "logs",
|
||||
Short: "Fetch the logs of a container",
|
||||
Long: logsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
logsCommand.InputArgs = args
|
||||
logsCommand.GlobalFlags = MainGlobalOpts
|
||||
return logsCmd(&logsCommand)
|
||||
},
|
||||
Example: "CONTAINER",
|
||||
}
|
||||
)
|
||||
|
||||
func logsCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
logsCommand.Command = _logsCommand
|
||||
flags := logsCommand.Flags()
|
||||
flags.BoolVar(&logsCommand.Details, "details", false, "Show extra details provided to the logs")
|
||||
flags.BoolVarP(&logsCommand.Follow, "follow", "f", false, "Follow log output. The default is false")
|
||||
flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.StringVar(&logsCommand.Since, "since", "", "Show logs since TIMESTAMP")
|
||||
flags.Uint64Var(&logsCommand.Tail, "tail", 0, "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines")
|
||||
flags.BoolVarP(&logsCommand.Timestamps, "timestamps", "t", false, "Output the timestamps in the log")
|
||||
flags.MarkHidden("details")
|
||||
|
||||
flags.SetInterspersed(false)
|
||||
|
||||
rootCmd.AddCommand(logsCommand.Command)
|
||||
}
|
||||
|
||||
func logsCmd(c *cliconfig.LogsValues) error {
|
||||
var ctr *libpod.Container
|
||||
var err error
|
||||
if err := validateFlags(c, logsFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
if len(args) != 1 && !c.Bool("latest") {
|
||||
args := c.InputArgs
|
||||
if len(args) != 1 && !c.Latest {
|
||||
return errors.Errorf("'podman logs' requires exactly one container name/ID")
|
||||
}
|
||||
|
||||
sinceTime := time.Time{}
|
||||
if c.IsSet("since") {
|
||||
if c.Flag("since").Changed {
|
||||
// parse time, error out if something is wrong
|
||||
since, err := parseInputTime(c.String("since"))
|
||||
since, err := parseInputTime(c.Since)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not parse time: %q", c.String("since"))
|
||||
return errors.Wrapf(err, "could not parse time: %q", c.Since)
|
||||
}
|
||||
sinceTime = since
|
||||
}
|
||||
|
||||
opts := &logs.LogOptions{
|
||||
Details: c.Bool("details"),
|
||||
Follow: c.Bool("follow"),
|
||||
Details: c.Details,
|
||||
Follow: c.Follow,
|
||||
Since: sinceTime,
|
||||
Tail: c.Uint64("tail"),
|
||||
Timestamps: c.Bool("timestamps"),
|
||||
Tail: c.Tail,
|
||||
Timestamps: c.Timestamps,
|
||||
}
|
||||
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
ctr, err = runtime.GetLatestContainer()
|
||||
} else {
|
||||
ctr, err = runtime.LookupContainer(args[0])
|
||||
|
|
|
@ -6,9 +6,10 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"runtime/pprof"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod"
|
||||
_ "github.com/containers/libpod/pkg/hooks/0.1.0"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
|
@ -17,7 +18,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
lsyslog "github.com/sirupsen/logrus/hooks/syslog"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// This is populated by the Makefile from the VERSION file
|
||||
|
@ -26,198 +27,159 @@ var (
|
|||
exitCode = 125
|
||||
)
|
||||
|
||||
var cmdsNotRequiringRootless = map[string]bool{
|
||||
"help": true,
|
||||
"version": true,
|
||||
"create": true,
|
||||
"exec": true,
|
||||
"export": true,
|
||||
// `info` must be executed in an user namespace.
|
||||
// If this change, please also update libpod.refreshRootless()
|
||||
"login": true,
|
||||
"logout": true,
|
||||
"mount": true,
|
||||
"kill": true,
|
||||
"pause": true,
|
||||
"restart": true,
|
||||
"run": true,
|
||||
"unpause": true,
|
||||
"search": true,
|
||||
"stats": true,
|
||||
"stop": true,
|
||||
"top": true,
|
||||
var cmdsNotRequiringRootless = map[*cobra.Command]bool{
|
||||
_versionCommand: true,
|
||||
_createCommand: true,
|
||||
_execCommand: true,
|
||||
_exportCommand: true,
|
||||
//// `info` must be executed in an user namespace.
|
||||
//// If this change, please also update libpod.refreshRootless()
|
||||
_loginCommand: true,
|
||||
_logoutCommand: true,
|
||||
_mountCommand: true,
|
||||
_killCommand: true,
|
||||
_pauseCommand: true,
|
||||
_restartCommand: true,
|
||||
_runCommmand: true,
|
||||
_unpauseCommand: true,
|
||||
_searchCommand: true,
|
||||
_statsCommand: true,
|
||||
_stopCommand: true,
|
||||
_topCommand: true,
|
||||
}
|
||||
|
||||
type commandSorted []cli.Command
|
||||
|
||||
func (a commandSorted) Len() int { return len(a) }
|
||||
func (a commandSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type commandSortedAlpha struct{ commandSorted }
|
||||
|
||||
func (a commandSortedAlpha) Less(i, j int) bool {
|
||||
return a.commandSorted[i].Name < a.commandSorted[j].Name
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "podman",
|
||||
Long: "manage pods and images",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return cmd.Help()
|
||||
},
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return before(cmd, args)
|
||||
},
|
||||
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
|
||||
return after(cmd, args)
|
||||
},
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
}
|
||||
|
||||
type flagSorted []cli.Flag
|
||||
var MainGlobalOpts cliconfig.MainFlags
|
||||
|
||||
func (a flagSorted) Len() int { return len(a) }
|
||||
func (a flagSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.TraverseChildren = true
|
||||
rootCmd.Version = version.Version
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CGroupManager, "cgroup-manager", "", "Cgroup manager to use (cgroupfs or systemd, default systemd)")
|
||||
// -c is deprecated due to conflict with -c on subcommands
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Config, "config", "", "Path of a libpod config file detailing container server configuration options")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.ConmonPath, "conmon", "", "Path of the conmon binary")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", "", "Path of the configuration directory for CNI networks")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", "", "Path to default mounts file")
|
||||
rootCmd.PersistentFlags().MarkHidden("defaults-mount-file")
|
||||
rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", []string{}, "Set the OCI hooks directory path (may be set multiple times)")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error (default), fatal or panic")
|
||||
rootCmd.PersistentFlags().IntVar(&MainGlobalOpts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations")
|
||||
rootCmd.PersistentFlags().MarkHidden("max-workers")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", "", "Set the libpod namespace, used to create separate views of the containers and pods on the system")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Root, "root", "", "Path to the root directory in which data, including images, is stored")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored")
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runtime, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc")
|
||||
// -s is depracated due to conflict with -s on subcommands
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
|
||||
rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
|
||||
rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console")
|
||||
|
||||
type flagSortedAlpha struct{ flagSorted }
|
||||
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory")
|
||||
|
||||
func (a flagSortedAlpha) Less(i, j int) bool {
|
||||
return a.flagSorted[i].GetName() < a.flagSorted[j].GetName()
|
||||
}
|
||||
func initConfig() {
|
||||
// we can do more stuff in here.
|
||||
}
|
||||
|
||||
func before(cmd *cobra.Command, args []string) error {
|
||||
if err := libpod.SetXdgRuntimeDir(""); err != nil {
|
||||
logrus.Errorf(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
if rootless.IsRootless() {
|
||||
notRequireRootless := cmdsNotRequiringRootless[cmd]
|
||||
if !notRequireRootless && !strings.HasPrefix(cmd.Use, "help") {
|
||||
became, ret, err := rootless.BecomeRootInUserNS()
|
||||
if err != nil {
|
||||
logrus.Errorf(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
if became {
|
||||
os.Exit(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if MainGlobalOpts.Syslog {
|
||||
hook, err := lsyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
|
||||
if err == nil {
|
||||
logrus.AddHook(hook)
|
||||
}
|
||||
}
|
||||
|
||||
// Set log level
|
||||
level, err := logrus.ParseLevel(MainGlobalOpts.LogLevel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.SetLevel(level)
|
||||
|
||||
rlimits := new(syscall.Rlimit)
|
||||
rlimits.Cur = 1048576
|
||||
rlimits.Max = 1048576
|
||||
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
|
||||
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
|
||||
return errors.Wrapf(err, "error getting rlimits")
|
||||
}
|
||||
rlimits.Cur = rlimits.Max
|
||||
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
|
||||
return errors.Wrapf(err, "error setting new rlimits")
|
||||
}
|
||||
}
|
||||
|
||||
if rootless.IsRootless() {
|
||||
logrus.Info("running as rootless")
|
||||
}
|
||||
|
||||
// Be sure we can create directories with 0755 mode.
|
||||
syscall.Umask(0022)
|
||||
|
||||
if cmd.Flag("cpu-profile").Changed {
|
||||
f, err := os.Create(MainGlobalOpts.CpuProfile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to create cpu profiling file %s",
|
||||
MainGlobalOpts.CpuProfile)
|
||||
}
|
||||
pprof.StartCPUProfile(f)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func after(cmd *cobra.Command, args []string) error {
|
||||
if cmd.Flag("cpu-profile").Changed {
|
||||
pprof.StopCPUProfile()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
debug := false
|
||||
cpuProfile := false
|
||||
//debug := false
|
||||
//cpuProfile := false
|
||||
|
||||
if reexec.Init() {
|
||||
return
|
||||
}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "podman"
|
||||
app.Usage = "manage pods and images"
|
||||
app.OnUsageError = usageErrorHandler
|
||||
app.CommandNotFound = commandNotFoundHandler
|
||||
|
||||
app.Version = version.Version
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
containerCommand,
|
||||
exportCommand,
|
||||
historyCommand,
|
||||
imageCommand,
|
||||
imagesCommand,
|
||||
importCommand,
|
||||
infoCommand,
|
||||
inspectCommand,
|
||||
pullCommand,
|
||||
rmiCommand,
|
||||
systemCommand,
|
||||
tagCommand,
|
||||
versionCommand,
|
||||
}
|
||||
|
||||
app.Commands = append(app.Commands, getAppCommands()...)
|
||||
sort.Sort(commandSortedAlpha{app.Commands})
|
||||
|
||||
if varlinkCommand != nil {
|
||||
app.Commands = append(app.Commands, *varlinkCommand)
|
||||
}
|
||||
|
||||
app.Before = func(c *cli.Context) error {
|
||||
if err := libpod.SetXdgRuntimeDir(""); err != nil {
|
||||
logrus.Errorf(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
args := c.Args()
|
||||
if args.Present() && rootless.IsRootless() {
|
||||
if _, notRequireRootless := cmdsNotRequiringRootless[args.First()]; !notRequireRootless {
|
||||
became, ret, err := rootless.BecomeRootInUserNS()
|
||||
if err != nil {
|
||||
logrus.Errorf(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
if became {
|
||||
os.Exit(ret)
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.GlobalBool("syslog") {
|
||||
hook, err := lsyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
|
||||
if err == nil {
|
||||
logrus.AddHook(hook)
|
||||
}
|
||||
}
|
||||
logLevel := c.GlobalString("log-level")
|
||||
if logLevel != "" {
|
||||
level, err := logrus.ParseLevel(logLevel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.SetLevel(level)
|
||||
}
|
||||
|
||||
rlimits := new(syscall.Rlimit)
|
||||
rlimits.Cur = 1048576
|
||||
rlimits.Max = 1048576
|
||||
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
|
||||
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
|
||||
return errors.Wrapf(err, "error getting rlimits")
|
||||
}
|
||||
rlimits.Cur = rlimits.Max
|
||||
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
|
||||
return errors.Wrapf(err, "error setting new rlimits")
|
||||
}
|
||||
}
|
||||
|
||||
if rootless.IsRootless() {
|
||||
logrus.Info("running as rootless")
|
||||
}
|
||||
|
||||
// Be sure we can create directories with 0755 mode.
|
||||
syscall.Umask(0022)
|
||||
|
||||
if logLevel == "debug" {
|
||||
debug = true
|
||||
|
||||
}
|
||||
if c.GlobalIsSet("cpu-profile") {
|
||||
f, err := os.Create(c.GlobalString("cpu-profile"))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to create cpu profiling file %s",
|
||||
c.GlobalString("cpu-profile"))
|
||||
}
|
||||
cpuProfile = true
|
||||
pprof.StartCPUProfile(f)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
app.After = func(*cli.Context) error {
|
||||
// called by Run() when the command handler succeeds
|
||||
if cpuProfile {
|
||||
pprof.StopCPUProfile()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Usage: "Path of a libpod config file detailing container server configuration options",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpu-profile",
|
||||
Usage: "Path for the cpu profiling results",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "log-level",
|
||||
Usage: "Log messages above specified level: debug, info, warn, error (default), fatal or panic",
|
||||
Value: "error",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tmpdir",
|
||||
Usage: "Path to the tmp directory",
|
||||
},
|
||||
}
|
||||
|
||||
app.Flags = append(app.Flags, getMainAppFlags()...)
|
||||
sort.Sort(flagSortedAlpha{app.Flags})
|
||||
|
||||
// Check if /etc/containers/registries.conf exists when running in
|
||||
// in a local environment.
|
||||
CheckForRegistries()
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
if debug {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
if MainGlobalOpts.LogLevel == "debug" {
|
||||
logrus.Errorf(err.Error())
|
||||
} else {
|
||||
// Retrieve the exit error from the exec call, if it exists
|
||||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := ee.Sys().(syscall.WaitStatus); ok {
|
||||
exitCode = status.ExitStatus()
|
||||
|
@ -233,6 +195,11 @@ func main() {
|
|||
if exitCode == 125 {
|
||||
exitCode = 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check if /etc/containers/registries.conf exists when running in
|
||||
// in a local environment.
|
||||
CheckForRegistries()
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
|
|
@ -5,15 +5,18 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
of "github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
mountCommand cliconfig.MountValues
|
||||
|
||||
mountDescription = `
|
||||
podman mount
|
||||
Lists all mounted containers mount points
|
||||
|
@ -22,32 +25,29 @@ var (
|
|||
Mounts the specified container and outputs the mountpoint
|
||||
`
|
||||
|
||||
mountFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Mount all containers",
|
||||
_mountCommand = &cobra.Command{
|
||||
Use: "mount",
|
||||
Short: "Mount a working container's root filesystem",
|
||||
Long: mountDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
mountCommand.InputArgs = args
|
||||
mountCommand.GlobalFlags = MainGlobalOpts
|
||||
return mountCmd(&mountCommand)
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Change the output format to Go template",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "notruncate",
|
||||
Usage: "Do not truncate output",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
mountCommand = cli.Command{
|
||||
Name: "mount",
|
||||
Usage: "Mount a working container's root filesystem",
|
||||
Description: mountDescription,
|
||||
Action: mountCmd,
|
||||
ArgsUsage: "[CONTAINER-NAME-OR-ID [...]]",
|
||||
Flags: sortFlags(mountFlags),
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
mountCommand.Command = _mountCommand
|
||||
flags := mountCommand.Flags()
|
||||
flags.BoolVarP(&mountCommand.All, "all", "a", false, "Mount all containers")
|
||||
flags.StringVar(&mountCommand.Format, "format", "", "Change the output format to Go template")
|
||||
flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output")
|
||||
|
||||
rootCmd.AddCommand(mountCommand.Command)
|
||||
}
|
||||
|
||||
// jsonMountPoint stores info about each container
|
||||
type jsonMountPoint struct {
|
||||
ID string `json:"id"`
|
||||
|
@ -55,15 +55,12 @@ type jsonMountPoint struct {
|
|||
MountPoint string `json:"mountpoint"`
|
||||
}
|
||||
|
||||
func mountCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, mountFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
func mountCmd(c *cliconfig.MountValues) error {
|
||||
if os.Geteuid() != 0 {
|
||||
rootless.SetSkipStorageSetup(true)
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -85,11 +82,11 @@ func mountCmd(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
if c.Bool("all") && c.Bool("latest") {
|
||||
if c.All && c.Latest {
|
||||
return errors.Errorf("--all and --latest cannot be used together")
|
||||
}
|
||||
|
||||
mountContainers, err := getAllOrLatestContainers(c, runtime, -1, "all")
|
||||
mountContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
|
||||
if err != nil {
|
||||
if len(mountContainers) == 0 {
|
||||
return err
|
||||
|
@ -102,9 +99,9 @@ func mountCmd(c *cli.Context) error {
|
|||
of.JSONString: true,
|
||||
}
|
||||
|
||||
json := c.String("format") == of.JSONString
|
||||
if !formats[c.String("format")] {
|
||||
return errors.Errorf("%q is not a supported format", c.String("format"))
|
||||
json := c.Format == of.JSONString
|
||||
if !formats[c.Format] {
|
||||
return errors.Errorf("%q is not a supported format", c.Format)
|
||||
}
|
||||
|
||||
var lastError error
|
||||
|
@ -149,7 +146,7 @@ func mountCmd(c *cli.Context) error {
|
|||
continue
|
||||
}
|
||||
|
||||
if c.Bool("notruncate") {
|
||||
if c.NoTrunc {
|
||||
fmt.Printf("%-64s %s\n", container.ID(), mountPoint)
|
||||
} else {
|
||||
fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint)
|
||||
|
|
|
@ -3,38 +3,44 @@ package main
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
pauseFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Pause all running containers",
|
||||
},
|
||||
}
|
||||
pauseCommand cliconfig.PauseValues
|
||||
pauseDescription = `
|
||||
podman pause
|
||||
|
||||
Pauses one or more running containers. The container name or ID can be used.
|
||||
`
|
||||
pauseCommand = cli.Command{
|
||||
Name: "pause",
|
||||
Usage: "Pause all the processes in one or more containers",
|
||||
Description: pauseDescription,
|
||||
Flags: pauseFlags,
|
||||
Action: pauseCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_pauseCommand = &cobra.Command{
|
||||
Use: "pause",
|
||||
Short: "Pause all the processes in one or more containers",
|
||||
Long: pauseDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
pauseCommand.InputArgs = args
|
||||
pauseCommand.GlobalFlags = MainGlobalOpts
|
||||
return pauseCmd(&pauseCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func pauseCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
pauseCommand.Command = _pauseCommand
|
||||
flags := pauseCommand.Flags()
|
||||
flags.BoolVarP(&pauseCommand.All, "all", "a", false, "Pause all running containers")
|
||||
|
||||
rootCmd.AddCommand(pauseCommand.Command)
|
||||
}
|
||||
|
||||
func pauseCmd(c *cliconfig.PauseValues) error {
|
||||
var (
|
||||
pauseContainers []*libpod.Container
|
||||
pauseFuncs []shared.ParallelWorkerInput
|
||||
|
@ -43,18 +49,18 @@ func pauseCmd(c *cli.Context) error {
|
|||
return errors.New("pause is not supported for rootless containers")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
if len(args) < 1 && !c.Bool("all") {
|
||||
args := c.InputArgs
|
||||
if len(args) < 1 && !c.All {
|
||||
return errors.Errorf("you must provide at least one container name or id")
|
||||
}
|
||||
if c.Bool("all") {
|
||||
containers, err := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
|
||||
if c.All {
|
||||
containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -84,7 +90,7 @@ func pauseCmd(c *cli.Context) error {
|
|||
|
||||
maxWorkers := shared.Parallelize("pause")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
playSubCommands = []cli.Command{
|
||||
playKubeCommand,
|
||||
var playCommand cliconfig.PodmanCommand
|
||||
|
||||
func init() {
|
||||
var playDescription = "Play a pod and its containers from a structured file."
|
||||
playCommand.Command = &cobra.Command{
|
||||
Use: "play",
|
||||
Short: "Play a pod",
|
||||
Long: playDescription,
|
||||
}
|
||||
|
||||
playDescription = "Play a pod and its containers from a structured file."
|
||||
playCommand = cli.Command{
|
||||
Name: "play",
|
||||
Usage: "Play a container or pod",
|
||||
Description: playDescription,
|
||||
ArgsUsage: "",
|
||||
Subcommands: playSubCommands,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
playCommand.AddCommand(getPlaySubCommands()...)
|
||||
rootCmd.AddCommand(playCommand.Command)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
|
@ -20,51 +21,40 @@ import (
|
|||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
playKubeFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cert-dir",
|
||||
Usage: "`Pathname` of a directory containing TLS certificates and keys",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "creds",
|
||||
Usage: "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress output information when pulling images",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signature-policy",
|
||||
Usage: "`Pathname` of signature policy file (not usually used)",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "tls-verify",
|
||||
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
|
||||
},
|
||||
}
|
||||
playKubeCommand cliconfig.KubePlayValues
|
||||
playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML"
|
||||
playKubeCommand = cli.Command{
|
||||
Name: "kube",
|
||||
Usage: "Play a pod based on Kubernetes YAML",
|
||||
Description: playKubeDescription,
|
||||
Action: playKubeYAMLCmd,
|
||||
Flags: sortFlags(playKubeFlags),
|
||||
ArgsUsage: "Kubernetes YAML file",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_playKubeCommand = &cobra.Command{
|
||||
Use: "kube",
|
||||
Short: "Play a pod based on Kubernetes YAML",
|
||||
Long: playKubeDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
playKubeCommand.InputArgs = args
|
||||
playKubeCommand.GlobalFlags = MainGlobalOpts
|
||||
return playKubeYAMLCmd(&playKubeCommand)
|
||||
},
|
||||
Example: "Kubernetes YAML file",
|
||||
}
|
||||
)
|
||||
|
||||
func playKubeYAMLCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
playKubeCommand.Command = _playKubeCommand
|
||||
flags := playKubeCommand.Flags()
|
||||
flags.StringVar(&playKubeCommand.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(&playKubeCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
|
||||
flags.StringVar(&playKubeCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
|
||||
flags.BoolVarP(&playKubeCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
|
||||
flags.StringVar(&playKubeCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
|
||||
flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
|
||||
|
||||
rootCmd.AddCommand(playKubeCommand.Command)
|
||||
}
|
||||
|
||||
func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
|
||||
var (
|
||||
podOptions []libpod.PodCreateOption
|
||||
podYAML v1.Pod
|
||||
|
@ -77,7 +67,7 @@ func playKubeYAMLCmd(c *cli.Context) error {
|
|||
if rootless.IsRootless() {
|
||||
return errors.Wrapf(libpod.ErrNotImplemented, "rootless users")
|
||||
}
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 {
|
||||
return errors.New("you can only play one kubernetes file at a time")
|
||||
}
|
||||
|
@ -85,7 +75,7 @@ func playKubeYAMLCmd(c *cli.Context) error {
|
|||
return errors.New("you must supply at least one file")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -133,20 +123,20 @@ func playKubeYAMLCmd(c *cli.Context) error {
|
|||
"ipc": fmt.Sprintf("container:%s", podInfraID),
|
||||
"uts": fmt.Sprintf("container:%s", podInfraID),
|
||||
}
|
||||
if !c.Bool("quiet") {
|
||||
if !c.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
|
||||
dockerRegistryOptions := image2.DockerRegistryOptions{
|
||||
DockerRegistryCreds: registryCreds,
|
||||
DockerCertPath: c.String("cert-dir"),
|
||||
DockerCertPath: c.CertDir,
|
||||
}
|
||||
if c.IsSet("tls-verify") {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
|
||||
if c.Flag("tls-verify").Changed {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
|
||||
}
|
||||
|
||||
for _, container := range podYAML.Spec.Containers {
|
||||
newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.String("signature-policy"), c.String("authfile"), writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil)
|
||||
newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,35 +1,24 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podDescription = `Manage container pods.
|
||||
|
||||
Pods are a group of one or more containers sharing the same network, pid and ipc namespaces.
|
||||
`
|
||||
podSubCommands = []cli.Command{
|
||||
podCreateCommand,
|
||||
podExistsCommand,
|
||||
podInspectCommand,
|
||||
podKillCommand,
|
||||
podPauseCommand,
|
||||
podPsCommand,
|
||||
podRestartCommand,
|
||||
podRmCommand,
|
||||
podStartCommand,
|
||||
podStatsCommand,
|
||||
podStopCommand,
|
||||
podTopCommand,
|
||||
podUnpauseCommand,
|
||||
}
|
||||
podCommand = cli.Command{
|
||||
Name: "pod",
|
||||
Usage: "Manage pods",
|
||||
Description: podDescription,
|
||||
UseShortOptionHandling: true,
|
||||
Subcommands: podSubCommands,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
Pods are a group of one or more containers sharing the same network, pid and ipc namespaces.`
|
||||
)
|
||||
var podCommand = cliconfig.PodmanCommand{
|
||||
Command: &cobra.Command{
|
||||
Use: "pod",
|
||||
Short: "Manage pods",
|
||||
Long: podDescription,
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
podCommand.AddCommand(getPodSubCommands()...)
|
||||
rootCmd.AddCommand(podCommand.Command)
|
||||
}
|
||||
|
|
|
@ -5,111 +5,81 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
// Kernel namespaces shared by default within a pod
|
||||
DefaultKernelNamespaces = "cgroup,ipc,net,uts"
|
||||
podCreateCommand cliconfig.PodCreateValues
|
||||
|
||||
podCreateDescription = "Creates a new empty pod. The pod ID is then" +
|
||||
" printed to stdout. You can then start it at any time with the" +
|
||||
" podman pod start <pod_id> command. The pod will be created with the" +
|
||||
" initial state 'created'."
|
||||
|
||||
_podCreateCommand = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a new empty pod",
|
||||
Long: podCreateDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podCreateCommand.InputArgs = args
|
||||
podCreateCommand.GlobalFlags = MainGlobalOpts
|
||||
return podCreateCmd(&podCreateCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var podCreateDescription = "Creates a new empty pod. The pod ID is then" +
|
||||
" printed to stdout. You can then start it at any time with the" +
|
||||
" podman pod start <pod_id> command. The pod will be created with the" +
|
||||
" initial state 'created'."
|
||||
func init() {
|
||||
podCreateCommand.Command = _podCreateCommand
|
||||
flags := podCreateCommand.Flags()
|
||||
flags.SetInterspersed(false)
|
||||
|
||||
flags.StringVar(&podCreateCommand.CgroupParent, "cgroup-parent", "", "Set parent cgroup for the pod")
|
||||
flags.BoolVar(&podCreateCommand.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
|
||||
flags.StringVar(&podCreateCommand.InfraImage, "infra-image", libpod.DefaultInfraImage, "The image of the infra container to associate with the pod")
|
||||
flags.StringVar(&podCreateCommand.InfraCommand, "infra-command", libpod.DefaultInfraCommand, "The command to run on the infra container when the pod is started")
|
||||
flags.StringSliceVar(&podCreateCommand.LabelFile, "label-file", []string{}, "Read in a line delimited file of labels")
|
||||
flags.StringSliceVarP(&podCreateCommand.Labels, "label", "l", []string{}, "Set metadata on pod (default [])")
|
||||
flags.StringVarP(&podCreateCommand.Name, "name", "n", "", "Assign a name to the pod")
|
||||
flags.StringVar(&podCreateCommand.PodIDFile, "pod-id-file", "", "Write the pod ID to the file")
|
||||
flags.StringSliceVarP(&podCreateCommand.Publish, "publish", "p", []string{}, "Publish a container's port, or a range of ports, to the host (default [])")
|
||||
flags.StringVar(&podCreateCommand.Share, "share", DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
|
||||
|
||||
var podCreateFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "cgroup-parent",
|
||||
Usage: "Set parent cgroup for the pod",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "infra",
|
||||
Usage: "Create an infra container associated with the pod to share namespaces with",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "infra-image",
|
||||
Usage: "The image of the infra container to associate with the pod",
|
||||
Value: libpod.DefaultInfraImage,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "infra-command",
|
||||
Usage: "The command to run on the infra container when the pod is started",
|
||||
Value: libpod.DefaultInfraCommand,
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label-file",
|
||||
Usage: "Read in a line delimited file of labels (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label, l",
|
||||
Usage: "Set metadata on pod (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name, n",
|
||||
Usage: "Assign a name to the pod",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pod-id-file",
|
||||
Usage: "Write the pod ID to the file",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "publish, p",
|
||||
Usage: "Publish a container's port, or a range of ports, to the host (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "share",
|
||||
Usage: "A comma delimited list of kernel namespaces the pod will share",
|
||||
Value: DefaultKernelNamespaces,
|
||||
},
|
||||
}
|
||||
|
||||
var podCreateCommand = cli.Command{
|
||||
Name: "create",
|
||||
Usage: "Create a new empty pod",
|
||||
Description: podCreateDescription,
|
||||
Flags: sortFlags(podCreateFlags),
|
||||
Action: podCreateCmd,
|
||||
SkipArgReorder: true,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
|
||||
func podCreateCmd(c *cli.Context) error {
|
||||
func podCreateCmd(c *cliconfig.PodCreateValues) error {
|
||||
var options []libpod.PodCreateOption
|
||||
var err error
|
||||
|
||||
if err = validateFlags(c, createFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
var podIdFile *os.File
|
||||
if c.IsSet("pod-id-file") && os.Geteuid() == 0 {
|
||||
podIdFile, err = libpod.OpenExclusiveFile(c.String("pod-id-file"))
|
||||
if c.Flag("pod-id-file").Changed && os.Geteuid() == 0 {
|
||||
podIdFile, err = libpod.OpenExclusiveFile(c.PodIDFile)
|
||||
if err != nil && os.IsExist(err) {
|
||||
return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", c.String("pod-id-file"))
|
||||
return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", c.PodIDFile)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Errorf("error opening pod-id-file %s", c.String("pod-id-file"))
|
||||
return errors.Errorf("error opening pod-id-file %s", c.PodIDFile)
|
||||
}
|
||||
defer podIdFile.Close()
|
||||
defer podIdFile.Sync()
|
||||
}
|
||||
|
||||
if len(c.StringSlice("publish")) > 0 {
|
||||
if !c.BoolT("infra") {
|
||||
if len(c.Publish) > 0 {
|
||||
if !c.Infra {
|
||||
return errors.Errorf("you must have an infra container to publish port bindings to the host")
|
||||
}
|
||||
if rootless.IsRootless() {
|
||||
|
@ -117,15 +87,15 @@ func podCreateCmd(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
if !c.BoolT("infra") && c.IsSet("share") && c.String("share") != "none" && c.String("share") != "" {
|
||||
if !c.Infra && c.Flag("share").Changed && c.Share != "none" && c.Share != "" {
|
||||
return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container")
|
||||
}
|
||||
|
||||
if c.IsSet("cgroup-parent") {
|
||||
options = append(options, libpod.WithPodCgroupParent(c.String("cgroup-parent")))
|
||||
if c.Flag("cgroup-parent").Changed {
|
||||
options = append(options, libpod.WithPodCgroupParent(c.CgroupParent))
|
||||
}
|
||||
|
||||
labels, err := getAllLabels(c.StringSlice("label-file"), c.StringSlice("label"))
|
||||
labels, err := getAllLabels(c.LabelFile, c.Labels)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to process labels")
|
||||
}
|
||||
|
@ -133,21 +103,21 @@ func podCreateCmd(c *cli.Context) error {
|
|||
options = append(options, libpod.WithPodLabels(labels))
|
||||
}
|
||||
|
||||
if c.IsSet("name") {
|
||||
options = append(options, libpod.WithPodName(c.String("name")))
|
||||
if c.Flag("name").Changed {
|
||||
options = append(options, libpod.WithPodName(c.Name))
|
||||
}
|
||||
|
||||
if c.BoolT("infra") {
|
||||
if c.Infra {
|
||||
options = append(options, libpod.WithInfraContainer())
|
||||
nsOptions, err := shared.GetNamespaceOptions(strings.Split(c.String("share"), ","))
|
||||
nsOptions, err := shared.GetNamespaceOptions(strings.Split(c.Share, ","))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options = append(options, nsOptions...)
|
||||
}
|
||||
|
||||
if len(c.StringSlice("publish")) > 0 {
|
||||
portBindings, err := shared.CreatePortBindings(c.StringSlice("publish"))
|
||||
if len(c.Publish) > 0 {
|
||||
portBindings, err := shared.CreatePortBindings(c.Publish)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,46 +2,53 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podInspectFlags = []cli.Flag{
|
||||
LatestPodFlag,
|
||||
}
|
||||
podInspectCommand cliconfig.PodInspectValues
|
||||
podInspectDescription = "Display the configuration for a pod by name or id"
|
||||
podInspectCommand = cli.Command{
|
||||
Name: "inspect",
|
||||
Usage: "Displays a pod configuration",
|
||||
Description: podInspectDescription,
|
||||
Flags: sortFlags(podInspectFlags),
|
||||
Action: podInspectCmd,
|
||||
UseShortOptionHandling: true,
|
||||
ArgsUsage: "[POD_NAME_OR_ID]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podInspectCommand = &cobra.Command{
|
||||
Use: "inspect",
|
||||
Short: "Displays a pod configuration",
|
||||
Long: podInspectDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podInspectCommand.InputArgs = args
|
||||
podInspectCommand.GlobalFlags = MainGlobalOpts
|
||||
return podInspectCmd(&podInspectCommand)
|
||||
},
|
||||
Example: "[POD_NAME_OR_ID]",
|
||||
}
|
||||
)
|
||||
|
||||
func podInspectCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
podInspectCommand.Command = _podInspectCommand
|
||||
flags := podInspectCommand.Flags()
|
||||
flags.BoolVarP(&podInspectCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
|
||||
}
|
||||
|
||||
func podInspectCmd(c *cliconfig.PodInspectValues) error {
|
||||
var (
|
||||
pod *libpod.Pod
|
||||
)
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
args := c.Args()
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
args := c.InputArgs
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
pod, err = runtime.GetLatestPod()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get latest pod")
|
||||
|
|
|
@ -4,46 +4,45 @@ import (
|
|||
"fmt"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podKillFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Kill all containers in all pods",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signal, s",
|
||||
Usage: "Signal to send to the containers in the pod",
|
||||
Value: "KILL",
|
||||
},
|
||||
LatestPodFlag,
|
||||
}
|
||||
podKillCommand cliconfig.PodKillValues
|
||||
podKillDescription = "The main process of each container inside the specified pod will be sent SIGKILL, or any signal specified with option --signal."
|
||||
podKillCommand = cli.Command{
|
||||
Name: "kill",
|
||||
Usage: "Send the specified signal or SIGKILL to containers in pod",
|
||||
Description: podKillDescription,
|
||||
Flags: sortFlags(podKillFlags),
|
||||
Action: podKillCmd,
|
||||
ArgsUsage: "[POD_NAME_OR_ID]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podKillCommand = &cobra.Command{
|
||||
Use: "kill",
|
||||
Short: "Send the specified signal or SIGKILL to containers in pod",
|
||||
Long: podKillDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podKillCommand.InputArgs = args
|
||||
podKillCommand.GlobalFlags = MainGlobalOpts
|
||||
return podKillCmd(&podKillCommand)
|
||||
},
|
||||
Example: "[POD_NAME_OR_ID]",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
podKillCommand.Command = _podKillCommand
|
||||
flags := podKillCommand.Flags()
|
||||
flags.BoolVarP(&podKillCommand.All, "all", "a", false, "Kill all containers in all pods")
|
||||
flags.BoolVarP(&podKillCommand.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
|
||||
flags.StringVarP(&podKillCommand.Signal, "signal", "s", "KILL", "Signal to send to the containers in the pod")
|
||||
}
|
||||
|
||||
// podKillCmd kills one or more pods with a signal
|
||||
func podKillCmd(c *cli.Context) error {
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
func podKillCmd(c *cliconfig.PodKillValues) error {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -51,10 +50,10 @@ func podKillCmd(c *cli.Context) error {
|
|||
|
||||
var killSignal uint = uint(syscall.SIGTERM)
|
||||
|
||||
if c.String("signal") != "" {
|
||||
if c.Signal != "" {
|
||||
// Check if the signalString provided by the user is valid
|
||||
// Invalid signals will return err
|
||||
sysSignal, err := signal.ParseSignal(c.String("signal"))
|
||||
sysSignal, err := signal.ParseSignal(c.Signal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -64,7 +63,7 @@ func podKillCmd(c *cli.Context) error {
|
|||
// getPodsFromContext returns an error when a requested pod
|
||||
// isn't found. The only fatal error scenerio is when there are no pods
|
||||
// in which case the following loop will be skipped.
|
||||
pods, lastError := getPodsFromContext(c, runtime)
|
||||
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
|
||||
|
||||
for _, pod := range pods {
|
||||
ctr_errs, err := pod.Kill(killSignal)
|
||||
|
|
|
@ -2,43 +2,42 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podPauseFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Pause all running pods",
|
||||
podPauseCommand cliconfig.PodPauseValues
|
||||
podPauseDescription = `Pauses one or more pods. The pod name or ID can be used.`
|
||||
_podPauseCommand = &cobra.Command{
|
||||
Use: "pause",
|
||||
Short: "Pause one or more pods",
|
||||
Long: podPauseDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podPauseCommand.InputArgs = args
|
||||
podPauseCommand.GlobalFlags = MainGlobalOpts
|
||||
return podPauseCmd(&podPauseCommand)
|
||||
},
|
||||
LatestPodFlag,
|
||||
}
|
||||
podPauseDescription = `
|
||||
Pauses one or more pods. The pod name or ID can be used.
|
||||
`
|
||||
|
||||
podPauseCommand = cli.Command{
|
||||
Name: "pause",
|
||||
Usage: "Pause one or more pods",
|
||||
Description: podPauseDescription,
|
||||
Flags: sortFlags(podPauseFlags),
|
||||
Action: podPauseCmd,
|
||||
ArgsUsage: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func podPauseCmd(c *cli.Context) error {
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
func init() {
|
||||
podPauseCommand.Command = _podPauseCommand
|
||||
flags := podPauseCommand.Flags()
|
||||
flags.BoolVarP(&podPauseCommand.All, "all", "a", false, "Pause all running pods")
|
||||
flags.BoolVarP(&podPauseCommand.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
|
||||
}
|
||||
|
||||
func podPauseCmd(c *cliconfig.PodPauseValues) error {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
@ -47,7 +46,7 @@ func podPauseCmd(c *cli.Context) error {
|
|||
// getPodsFromContext returns an error when a requested pod
|
||||
// isn't found. The only fatal error scenerio is when there are no pods
|
||||
// in which case the following loop will be skipped.
|
||||
pods, lastError := getPodsFromContext(c, runtime)
|
||||
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
|
||||
|
||||
for _, pod := range pods {
|
||||
ctr_errs, err := pod.Pause()
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
|
@ -15,7 +16,7 @@ import (
|
|||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -112,95 +113,68 @@ func (a podPsSortedStatus) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
var (
|
||||
podPsFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "ctr-names",
|
||||
Usage: "Display the container names",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "ctr-ids",
|
||||
Usage: "Display the container UUIDs. If no-trunc is not set they will be truncated",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "ctr-status",
|
||||
Usage: "Display the container status",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "filter, f",
|
||||
Usage: "Filter output based on conditions given",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Pretty-print pods to JSON or using a Go template",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "latest, l",
|
||||
Usage: "Show the latest pod created",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "namespace, ns",
|
||||
Usage: "Display namespace information of the pod",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-trunc",
|
||||
Usage: "Do not truncate pod and container IDs",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Print the numeric IDs of the pods only",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "sort",
|
||||
Usage: "Sort output by created, id, name, or number",
|
||||
Value: "created",
|
||||
},
|
||||
}
|
||||
podPsCommand cliconfig.PodPsValues
|
||||
|
||||
podPsDescription = "List all pods on system including their names, ids and current state."
|
||||
podPsCommand = cli.Command{
|
||||
Name: "ps",
|
||||
Aliases: []string{"ls", "list"},
|
||||
Usage: "List pods",
|
||||
Description: podPsDescription,
|
||||
Flags: sortFlags(podPsFlags),
|
||||
Action: podPsCmd,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podPsCommand = &cobra.Command{
|
||||
Use: "ps",
|
||||
Aliases: []string{"ls", "list"},
|
||||
Short: "List pods",
|
||||
Long: podPsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podPsCommand.InputArgs = args
|
||||
podPsCommand.GlobalFlags = MainGlobalOpts
|
||||
return podPsCmd(&podPsCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func podPsCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, podPsFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
func init() {
|
||||
podPsCommand.Command = _podPsCommand
|
||||
flags := podPsCommand.Flags()
|
||||
flags.BoolVar(&podPsCommand.CtrNames, "ctr-names", false, "Display the container names")
|
||||
flags.BoolVar(&podPsCommand.CtrIDs, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated")
|
||||
flags.BoolVar(&podPsCommand.CtrStatus, "ctr-status", false, "Display the container status")
|
||||
flags.StringVarP(&podPsCommand.Filter, "filter", "f", "", "Filter output based on conditions given")
|
||||
flags.StringVar(&podPsCommand.Format, "format", "", "Pretty-print pods to JSON or using a Go template")
|
||||
flags.BoolVarP(&podPsCommand.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
|
||||
flags.BoolVar(&podPsCommand.Namespace, "namespace", false, "Display namespace information of the pod")
|
||||
flags.BoolVar(&podPsCommand.Namespace, "ns", false, "Display namespace information of the pod")
|
||||
flags.BoolVar(&podPsCommand.NoTrunc, "no-trunc", false, "Do not truncate pod and container IDs")
|
||||
flags.BoolVarP(&podPsCommand.Quiet, "quiet", "q", false, "Print the numeric IDs of the pods only")
|
||||
flags.StringVar(&podPsCommand.Sort, "sort", "created", "Sort output by created, id, name, or number")
|
||||
|
||||
}
|
||||
|
||||
func podPsCmd(c *cliconfig.PodPsValues) error {
|
||||
if err := podPsCheckFlagsPassed(c); err != nil {
|
||||
return errors.Wrapf(err, "error with flags passed")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if len(c.Args()) > 0 {
|
||||
if len(c.InputArgs) > 0 {
|
||||
return errors.Errorf("too many arguments, ps takes no arguments")
|
||||
}
|
||||
|
||||
opts := podPsOptions{
|
||||
NoTrunc: c.Bool("no-trunc"),
|
||||
Quiet: c.Bool("quiet"),
|
||||
Sort: c.String("sort"),
|
||||
IdsOfContainers: c.Bool("ctr-ids"),
|
||||
NamesOfContainers: c.Bool("ctr-names"),
|
||||
StatusOfContainers: c.Bool("ctr-status"),
|
||||
NoTrunc: c.NoTrunc,
|
||||
Quiet: c.Quiet,
|
||||
Sort: c.Sort,
|
||||
IdsOfContainers: c.CtrIDs,
|
||||
NamesOfContainers: c.CtrNames,
|
||||
StatusOfContainers: c.CtrStatus,
|
||||
}
|
||||
|
||||
opts.Format = genPodPsFormat(c)
|
||||
|
||||
var filterFuncs []libpod.PodFilter
|
||||
if c.String("filter") != "" {
|
||||
filters := strings.Split(c.String("filter"), ",")
|
||||
if c.Filter != "" {
|
||||
filters := strings.Split(c.Filter, ",")
|
||||
for _, f := range filters {
|
||||
filterSplit := strings.Split(f, "=")
|
||||
if len(filterSplit) < 2 {
|
||||
|
@ -215,7 +189,7 @@ func podPsCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
var pods []*libpod.Pod
|
||||
if c.IsSet("latest") {
|
||||
if c.Latest {
|
||||
pod, err := runtime.GetLatestPod()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -244,13 +218,13 @@ func podPsCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// podPsCheckFlagsPassed checks if mutually exclusive flags are passed together
|
||||
func podPsCheckFlagsPassed(c *cli.Context) error {
|
||||
func podPsCheckFlagsPassed(c *cliconfig.PodPsValues) error {
|
||||
// quiet, and format with Go template are mutually exclusive
|
||||
flags := 0
|
||||
if c.Bool("quiet") {
|
||||
if c.Quiet {
|
||||
flags++
|
||||
}
|
||||
if c.IsSet("format") && c.String("format") != formats.JSONString {
|
||||
if c.Flag("format").Changed && c.Format != formats.JSONString {
|
||||
flags++
|
||||
}
|
||||
if flags > 1 {
|
||||
|
@ -342,20 +316,20 @@ func generatePodFilterFuncs(filter, filterValue string, runtime *libpod.Runtime)
|
|||
}
|
||||
|
||||
// generate the template based on conditions given
|
||||
func genPodPsFormat(c *cli.Context) string {
|
||||
func genPodPsFormat(c *cliconfig.PodPsValues) string {
|
||||
format := ""
|
||||
if c.String("format") != "" {
|
||||
if c.Format != "" {
|
||||
// "\t" from the command line is not being recognized as a tab
|
||||
// replacing the string "\t" to a tab character if the user passes in "\t"
|
||||
format = strings.Replace(c.String("format"), `\t`, "\t", -1)
|
||||
} else if c.Bool("quiet") {
|
||||
format = strings.Replace(c.Format, `\t`, "\t", -1)
|
||||
} else if c.Quiet {
|
||||
format = formats.IDString
|
||||
} else {
|
||||
format = "table {{.ID}}\t{{.Name}}\t{{.Status}}\t{{.Created}}"
|
||||
if c.Bool("namespace") {
|
||||
format += "\t{{.Cgroup}}\t{{.Namespaces}}"
|
||||
}
|
||||
if c.Bool("ctr-names") || c.Bool("ctr-ids") || c.Bool("ctr-status") {
|
||||
if c.CtrNames || c.CtrIDs || c.CtrStatus {
|
||||
format += "\t{{.ContainerInfo}}"
|
||||
} else {
|
||||
format += "\t{{.NumberOfContainers}}"
|
||||
|
|
|
@ -3,40 +3,43 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podRestartFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Restart all pods",
|
||||
},
|
||||
LatestPodFlag,
|
||||
}
|
||||
podRestartCommand cliconfig.PodRestartValues
|
||||
podRestartDescription = `Restarts one or more pods. The pod ID or name can be used.`
|
||||
|
||||
podRestartCommand = cli.Command{
|
||||
Name: "restart",
|
||||
Usage: "Restart one or more pods",
|
||||
Description: podRestartDescription,
|
||||
Flags: sortFlags(podRestartFlags),
|
||||
Action: podRestartCmd,
|
||||
ArgsUsage: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podRestartCommand = &cobra.Command{
|
||||
Use: "restart",
|
||||
Short: "Restart one or more pods",
|
||||
Long: podRestartDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podRestartCommand.InputArgs = args
|
||||
podRestartCommand.GlobalFlags = MainGlobalOpts
|
||||
return podRestartCmd(&podRestartCommand)
|
||||
},
|
||||
Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func podRestartCmd(c *cli.Context) error {
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
func init() {
|
||||
podRestartCommand.Command = _podRestartCommand
|
||||
flags := podRestartCommand.Flags()
|
||||
flags.BoolVarP(&podRestartCommand.All, "all", "a", false, "Restart all running pods")
|
||||
flags.BoolVarP(&podRestartCommand.Latest, "latest", "l", false, "Restart the latest pod podman is aware of")
|
||||
|
||||
}
|
||||
|
||||
func podRestartCmd(c *cliconfig.PodRestartValues) error {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -45,7 +48,7 @@ func podRestartCmd(c *cli.Context) error {
|
|||
// getPodsFromContext returns an error when a requested pod
|
||||
// isn't found. The only fatal error scenerio is when there are no pods
|
||||
// in which case the following loop will be skipped.
|
||||
pods, lastError := getPodsFromContext(c, runtime)
|
||||
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
|
||||
|
||||
ctx := getContext()
|
||||
for _, pod := range pods {
|
||||
|
|
|
@ -3,60 +3,61 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podRmFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Remove all pods",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Force removal of a running pod by first stopping all containers, then removing all containers in the pod. The default is false",
|
||||
},
|
||||
LatestPodFlag,
|
||||
}
|
||||
podRmCommand cliconfig.PodRmValues
|
||||
podRmDescription = fmt.Sprintf(`
|
||||
podman rm will remove one or more pods from the host. The pod name or ID can
|
||||
be used. A pod with containers will not be removed without --force.
|
||||
If --force is specified, all containers will be stopped, then removed.
|
||||
`)
|
||||
podRmCommand = cli.Command{
|
||||
Name: "rm",
|
||||
Usage: "Remove one or more pods",
|
||||
Description: podRmDescription,
|
||||
Flags: sortFlags(podRmFlags),
|
||||
Action: podRmCmd,
|
||||
ArgsUsage: "[POD ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podRmCommand = &cobra.Command{
|
||||
Use: "rm",
|
||||
Short: "Remove one or more pods",
|
||||
Long: podRmDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podRmCommand.InputArgs = args
|
||||
podRmCommand.GlobalFlags = MainGlobalOpts
|
||||
return podRmCmd(&podRmCommand)
|
||||
},
|
||||
Example: "[POD ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
podRmCommand.Command = _podRmCommand
|
||||
flags := podRmCommand.Flags()
|
||||
flags.BoolVarP(&podRmCommand.All, "all", "a", false, "Remove all running pods")
|
||||
flags.BoolVarP(&podRmCommand.Force, "force", "f", false, "Force removal of a running pod by first stopping all containers, then removing all containers in the pod. The default is false")
|
||||
flags.BoolVarP(&podRmCommand.Latest, "latest", "l", false, "Remove the latest pod podman is aware of")
|
||||
|
||||
}
|
||||
|
||||
// saveCmd saves the image to either docker-archive or oci
|
||||
func podRmCmd(c *cli.Context) error {
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
func podRmCmd(c *cliconfig.PodRmValues) error {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
ctx := getContext()
|
||||
force := c.Bool("force")
|
||||
force := c.Force
|
||||
|
||||
// getPodsFromContext returns an error when a requested pod
|
||||
// isn't found. The only fatal error scenerio is when there are no pods
|
||||
// in which case the following loop will be skipped.
|
||||
pods, lastError := getPodsFromContext(c, runtime)
|
||||
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
|
||||
|
||||
for _, pod := range pods {
|
||||
err = runtime.RemovePod(ctx, pod, force, force)
|
||||
|
|
|
@ -3,44 +3,46 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podStartFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Start all running pods",
|
||||
},
|
||||
LatestPodFlag,
|
||||
}
|
||||
podStartCommand cliconfig.PodStartValues
|
||||
podStartDescription = `
|
||||
podman pod start
|
||||
|
||||
Starts one or more pods. The pod name or ID can be used.
|
||||
`
|
||||
|
||||
podStartCommand = cli.Command{
|
||||
Name: "start",
|
||||
Usage: "Start one or more pods",
|
||||
Description: podStartDescription,
|
||||
Flags: sortFlags(podStartFlags),
|
||||
Action: podStartCmd,
|
||||
ArgsUsage: "POD-NAME [POD-NAME ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podStartCommand = &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start one or more pods",
|
||||
Long: podStartDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podStartCommand.InputArgs = args
|
||||
podStartCommand.GlobalFlags = MainGlobalOpts
|
||||
return podStartCmd(&podStartCommand)
|
||||
},
|
||||
Example: "POD-NAME [POD-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func podStartCmd(c *cli.Context) error {
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
func init() {
|
||||
podStartCommand.Command = _podStartCommand
|
||||
flags := podStartCommand.Flags()
|
||||
flags.BoolVarP(&podStartCommand.All, "all", "a", false, "Start all pods")
|
||||
flags.BoolVarP(&podStartCommand.Latest, "latest", "l", false, "Start the latest pod podman is aware of")
|
||||
}
|
||||
|
||||
func podStartCmd(c *cliconfig.PodStartValues) error {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -49,7 +51,7 @@ func podStartCmd(c *cli.Context) error {
|
|||
// getPodsFromContext returns an error when a requested pod
|
||||
// isn't found. The only fatal error scenerio is when there are no pods
|
||||
// in which case the following loop will be skipped.
|
||||
pods, lastError := getPodsFromContext(c, runtime)
|
||||
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
|
||||
|
||||
ctx := getContext()
|
||||
for _, pod := range pods {
|
||||
|
|
|
@ -7,54 +7,49 @@ import (
|
|||
|
||||
"encoding/json"
|
||||
tm "github.com/buger/goterm"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/ulule/deepcopier"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
podStatsFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Show stats for all pods. Only running pods are shown by default.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-stream",
|
||||
Usage: "Disable streaming stats and only pull the first result, default setting is false",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-reset",
|
||||
Usage: "Disable resetting the screen between intervals",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Pretty-print container statistics to JSON or using a Go template",
|
||||
}, LatestPodFlag,
|
||||
}
|
||||
podStatsCommand cliconfig.PodStatsValues
|
||||
podStatsDescription = "Display a live stream of resource usage statistics for the containers in or more pods"
|
||||
podStatsCommand = cli.Command{
|
||||
Name: "stats",
|
||||
Usage: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one or more pods",
|
||||
Description: podStatsDescription,
|
||||
Flags: sortFlags(podStatsFlags),
|
||||
Action: podStatsCmd,
|
||||
ArgsUsage: "[POD_NAME_OR_ID]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podStatsCommand = &cobra.Command{
|
||||
Use: "stats",
|
||||
Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one or more pods",
|
||||
Long: podStatsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podStatsCommand.InputArgs = args
|
||||
podStatsCommand.GlobalFlags = MainGlobalOpts
|
||||
return podStatsCmd(&podStatsCommand)
|
||||
},
|
||||
Example: "[POD_NAME_OR_ID]",
|
||||
}
|
||||
)
|
||||
|
||||
func podStatsCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
podStatsCommand.Command = _podStatsCommand
|
||||
flags := podStatsCommand.Flags()
|
||||
flags.BoolVarP(&podStatsCommand.All, "all", "a", false, "Provide stats for all running pods")
|
||||
flags.StringVar(&podStatsCommand.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template")
|
||||
flags.BoolVarP(&podStatsCommand.Latest, "latest", "l", false, "Provide stats on the latest pod podman is aware of")
|
||||
flags.BoolVar(&podStatsCommand.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false")
|
||||
flags.BoolVar(&podStatsCommand.NoReset, "no-reset", false, "Disable resetting the screen between intervals")
|
||||
}
|
||||
|
||||
func podStatsCmd(c *cliconfig.PodStatsValues) error {
|
||||
var (
|
||||
podFunc func() ([]*libpod.Pod, error)
|
||||
)
|
||||
|
||||
format := c.String("format")
|
||||
all := c.Bool("all")
|
||||
latest := c.Bool("latest")
|
||||
format := c.Format
|
||||
all := c.All
|
||||
latest := c.Latest
|
||||
ctr := 0
|
||||
if all {
|
||||
ctr += 1
|
||||
|
@ -62,7 +57,7 @@ func podStatsCmd(c *cli.Context) error {
|
|||
if latest {
|
||||
ctr += 1
|
||||
}
|
||||
if len(c.Args()) > 0 {
|
||||
if len(c.InputArgs) > 0 {
|
||||
ctr += 1
|
||||
}
|
||||
|
||||
|
@ -73,19 +68,19 @@ func podStatsCmd(c *cli.Context) error {
|
|||
all = true
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
times := -1
|
||||
if c.Bool("no-stream") {
|
||||
if c.NoStream {
|
||||
times = 1
|
||||
}
|
||||
|
||||
if len(c.Args()) > 0 {
|
||||
podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.Args(), runtime) }
|
||||
if len(c.InputArgs) > 0 {
|
||||
podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.InputArgs, runtime) }
|
||||
} else if latest {
|
||||
podFunc = func() ([]*libpod.Pod, error) {
|
||||
latestPod, err := runtime.GetLatestPod()
|
||||
|
@ -159,7 +154,7 @@ func podStatsCmd(c *cli.Context) error {
|
|||
newStats = append(newStats, &newPod)
|
||||
}
|
||||
//Output
|
||||
if strings.ToLower(format) != formats.JSONString && !c.Bool("no-reset") {
|
||||
if strings.ToLower(format) != formats.JSONString && !c.NoReset {
|
||||
tm.Clear()
|
||||
tm.MoveCursor(1, 1)
|
||||
tm.Flush()
|
||||
|
|
|
@ -2,48 +2,50 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podStopFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Stop all running pods",
|
||||
},
|
||||
LatestPodFlag,
|
||||
cli.UintFlag{
|
||||
Name: "timeout, time, t",
|
||||
Usage: "Seconds to wait for pod stop before killing the container",
|
||||
},
|
||||
}
|
||||
podStopCommand cliconfig.PodStopValues
|
||||
podStopDescription = `
|
||||
podman pod stop
|
||||
|
||||
Stops one or more running pods. The pod name or ID can be used.
|
||||
`
|
||||
|
||||
podStopCommand = cli.Command{
|
||||
Name: "stop",
|
||||
Usage: "Stop one or more pods",
|
||||
Description: podStopDescription,
|
||||
Flags: sortFlags(podStopFlags),
|
||||
Action: podStopCmd,
|
||||
ArgsUsage: "POD-NAME [POD-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podStopCommand = &cobra.Command{
|
||||
Use: "stop",
|
||||
Short: "Stop one or more pods",
|
||||
Long: podStopDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podStopCommand.InputArgs = args
|
||||
podStopCommand.GlobalFlags = MainGlobalOpts
|
||||
return podStopCmd(&podStopCommand)
|
||||
},
|
||||
Example: "POD-NAME [POD-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func podStopCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
podStopCommand.Command = _podStopCommand
|
||||
flags := podStopCommand.Flags()
|
||||
flags.BoolVarP(&podStopCommand.All, "all", "a", false, "Stop all running pods")
|
||||
flags.BoolVarP(&podStopCommand.Latest, "latest", "l", false, "Stop the latest pod podman is aware of")
|
||||
flags.UintVarP(&podStopCommand.Timeout, "timeout", "t", 0, "Seconds to wait for pod stop before killing the container")
|
||||
}
|
||||
|
||||
func podStopCmd(c *cliconfig.PodStopValues) error {
|
||||
timeout := -1
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -52,12 +54,12 @@ func podStopCmd(c *cli.Context) error {
|
|||
// getPodsFromContext returns an error when a requested pod
|
||||
// isn't found. The only fatal error scenerio is when there are no pods
|
||||
// in which case the following loop will be skipped.
|
||||
pods, lastError := getPodsFromContext(c, runtime)
|
||||
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
|
||||
|
||||
ctx := getContext()
|
||||
|
||||
if c.IsSet("timeout") {
|
||||
timeout = int(c.Uint("timeout"))
|
||||
if c.Flag("timeout").Changed {
|
||||
timeout = int(c.Timeout)
|
||||
}
|
||||
for _, pod := range pods {
|
||||
// set cleanup to true to clean mounts and namespaces
|
||||
|
|
|
@ -6,21 +6,17 @@ import (
|
|||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podTopFlags = []cli.Flag{
|
||||
LatestFlag,
|
||||
cli.BoolFlag{
|
||||
Name: "list-descriptors",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
podTopCommand cliconfig.PodTopValues
|
||||
|
||||
podTopDescription = fmt.Sprintf(`Display the running processes containers in a pod. Specify format descriptors
|
||||
to alter the output. You may run "podman pod top -l pid pcpu seccomp" to print
|
||||
the process ID, the CPU percentage and the seccomp mode of each process of
|
||||
|
@ -28,24 +24,34 @@ the latest pod.
|
|||
%s
|
||||
`, getDescriptorString())
|
||||
|
||||
podTopCommand = cli.Command{
|
||||
Name: "top",
|
||||
Usage: "Display the running processes of containers in a pod",
|
||||
Description: podTopDescription,
|
||||
Flags: sortFlags(podTopFlags),
|
||||
Action: podTopCmd,
|
||||
ArgsUsage: "POD-NAME [format descriptors]",
|
||||
SkipArgReorder: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_podTopCommand = &cobra.Command{
|
||||
Use: "top",
|
||||
Short: "Display the running processes of containers in a pod",
|
||||
Long: podTopDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podTopCommand.InputArgs = args
|
||||
podTopCommand.GlobalFlags = MainGlobalOpts
|
||||
return podTopCmd(&podTopCommand)
|
||||
},
|
||||
Example: "POD-NAME [format descriptors]",
|
||||
}
|
||||
)
|
||||
|
||||
func podTopCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
podTopCommand.Command = _podTopCommand
|
||||
flags := podTopCommand.Flags()
|
||||
flags.BoolVarP(&podTopCommand.Latest, "latest,", "l", false, "Act on the latest pod podman is aware of")
|
||||
flags.BoolVar(&podTopCommand.ListDescriptors, "list-descriptors", false, "")
|
||||
flags.MarkHidden("list-descriptors")
|
||||
|
||||
}
|
||||
|
||||
func podTopCmd(c *cliconfig.PodTopValues) error {
|
||||
var pod *libpod.Pod
|
||||
var err error
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
|
||||
if c.Bool("list-descriptors") {
|
||||
if c.ListDescriptors {
|
||||
descriptors, err := libpod.GetContainerPidInformationDescriptors()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -54,21 +60,18 @@ func podTopCmd(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if len(args) < 1 && !c.Bool("latest") {
|
||||
if len(args) < 1 && !c.Latest {
|
||||
return errors.Errorf("you must provide the name or id of a running pod")
|
||||
}
|
||||
if err := validateFlags(c, podTopFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
var descriptors []string
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
descriptors = args
|
||||
pod, err = runtime.GetLatestPod()
|
||||
} else {
|
||||
|
|
|
@ -3,42 +3,42 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
podUnpauseFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Unpause all paused pods",
|
||||
podUnpauseCommand cliconfig.PodUnpauseValues
|
||||
podUnpauseDescription = `Unpauses one or more pods. The pod name or ID can be used.`
|
||||
_podUnpauseCommand = &cobra.Command{
|
||||
Use: "unpause",
|
||||
Short: "Unpause one or more pods",
|
||||
Long: podUnpauseDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
podUnpauseCommand.InputArgs = args
|
||||
podUnpauseCommand.GlobalFlags = MainGlobalOpts
|
||||
return podUnpauseCmd(&podUnpauseCommand)
|
||||
},
|
||||
LatestPodFlag,
|
||||
}
|
||||
podUnpauseDescription = `
|
||||
Unpauses one or more pods. The pod name or ID can be used.
|
||||
`
|
||||
|
||||
podUnpauseCommand = cli.Command{
|
||||
Name: "unpause",
|
||||
Usage: "Unpause one or more pods",
|
||||
Description: podUnpauseDescription,
|
||||
Flags: sortFlags(podUnpauseFlags),
|
||||
Action: podUnpauseCmd,
|
||||
ArgsUsage: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func podUnpauseCmd(c *cli.Context) error {
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
func init() {
|
||||
podUnpauseCommand.Command = _podUnpauseCommand
|
||||
flags := podUnpauseCommand.Flags()
|
||||
flags.BoolVarP(&podUnpauseCommand.All, "all", "a", false, "Unpause all running pods")
|
||||
flags.BoolVarP(&podUnpauseCommand.Latest, "latest", "l", false, "Unpause the latest pod podman is aware of")
|
||||
}
|
||||
|
||||
func podUnpauseCmd(c *cliconfig.PodUnpauseValues) error {
|
||||
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func podUnpauseCmd(c *cli.Context) error {
|
|||
// getPodsFromContext returns an error when a requested pod
|
||||
// isn't found. The only fatal error scenerio is when there are no pods
|
||||
// in which case the following loop will be skipped.
|
||||
pods, lastError := getPodsFromContext(c, runtime)
|
||||
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
|
||||
|
||||
for _, pod := range pods {
|
||||
ctr_errs, err := pod.Unpause()
|
||||
|
|
|
@ -5,38 +5,44 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
portFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Display port information for all containers",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
portCommand cliconfig.PortValues
|
||||
portDescription = `
|
||||
podman port
|
||||
|
||||
List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT
|
||||
`
|
||||
|
||||
portCommand = cli.Command{
|
||||
Name: "port",
|
||||
Usage: "List port mappings or a specific mapping for the container",
|
||||
Description: portDescription,
|
||||
Flags: sortFlags(portFlags),
|
||||
Action: portCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [mapping]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_portCommand = &cobra.Command{
|
||||
Use: "port",
|
||||
Short: "List port mappings or a specific mapping for the container",
|
||||
Long: portDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
portCommand.InputArgs = args
|
||||
portCommand.GlobalFlags = MainGlobalOpts
|
||||
return portCmd(&portCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [mapping]",
|
||||
}
|
||||
)
|
||||
|
||||
func portCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
portCommand.Command = _portCommand
|
||||
flags := portCommand.Flags()
|
||||
|
||||
flags.BoolVarP(&portCommand.All, "all", "a", false, "Display port information for all containers")
|
||||
flags.BoolVarP(&portCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
|
||||
rootCmd.AddCommand(portCommand.Command)
|
||||
}
|
||||
|
||||
func portCmd(c *cliconfig.PortValues) error {
|
||||
var (
|
||||
userProto, containerName string
|
||||
userPort int
|
||||
|
@ -44,29 +50,26 @@ func portCmd(c *cli.Context) error {
|
|||
containers []*libpod.Container
|
||||
)
|
||||
|
||||
args := c.Args()
|
||||
if err := validateFlags(c, portFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
args := c.InputArgs
|
||||
|
||||
if c.Bool("latest") && c.Bool("all") {
|
||||
if c.Latest && c.All {
|
||||
return errors.Errorf("the 'all' and 'latest' options cannot be used together")
|
||||
}
|
||||
if c.Bool("all") && len(args) > 0 {
|
||||
if c.All && len(args) > 0 {
|
||||
return errors.Errorf("no additional arguments can be used with 'all'")
|
||||
}
|
||||
if len(args) == 0 && !c.Bool("latest") && !c.Bool("all") {
|
||||
if len(args) == 0 && !c.Latest && !c.All {
|
||||
return errors.Errorf("you must supply a running container name or id")
|
||||
}
|
||||
if !c.Bool("latest") && !c.Bool("all") {
|
||||
if !c.Latest && !c.All {
|
||||
containerName = args[0]
|
||||
}
|
||||
|
||||
port := ""
|
||||
if len(args) > 1 && !c.Bool("latest") {
|
||||
if len(args) > 1 && !c.Latest {
|
||||
port = args[1]
|
||||
}
|
||||
if len(args) == 1 && c.Bool("latest") {
|
||||
if len(args) == 1 && c.Latest {
|
||||
port = args[0]
|
||||
}
|
||||
if port != "" {
|
||||
|
@ -90,19 +93,19 @@ func portCmd(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if !c.Bool("latest") && !c.Bool("all") {
|
||||
if !c.Latest && !c.All {
|
||||
container, err = runtime.LookupContainer(containerName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to find container %s", containerName)
|
||||
}
|
||||
containers = append(containers, container)
|
||||
} else if c.Bool("latest") {
|
||||
} else if c.Latest {
|
||||
container, err = runtime.GetLatestContainer()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get last created container")
|
||||
|
@ -119,7 +122,7 @@ func portCmd(c *cli.Context) error {
|
|||
if state, _ := con.State(); state != libpod.ContainerStateRunning {
|
||||
continue
|
||||
}
|
||||
if c.Bool("all") {
|
||||
if c.All {
|
||||
fmt.Println(con.ID())
|
||||
}
|
||||
// Iterate mappings
|
||||
|
|
145
cmd/podman/ps.go
145
cmd/podman/ps.go
|
@ -12,6 +12,7 @@ import (
|
|||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
|
@ -21,7 +22,7 @@ import (
|
|||
"github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
)
|
||||
|
||||
|
@ -153,112 +154,78 @@ func (a psSortedSize) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
var (
|
||||
psFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Show all the containers, default is only running containers",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "filter, f",
|
||||
Usage: "Filter output based on conditions given",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Pretty-print containers to JSON or using a Go template",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "last, n",
|
||||
Usage: "Print the n last created containers (all states)",
|
||||
Value: -1,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "latest, l",
|
||||
Usage: "Show the latest container created (all states)",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "namespace, ns",
|
||||
Usage: "Display namespace information",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-trunc",
|
||||
Usage: "Display the extended information",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "pod, p",
|
||||
Usage: "Print the ID and name of the pod the containers are associated with",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Print the numeric IDs of the containers only",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "size, s",
|
||||
Usage: "Display the total file sizes",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "sort",
|
||||
Usage: "Sort output by command, created, id, image, names, runningfor, size, or status",
|
||||
Value: "created",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "sync",
|
||||
Usage: "Sync container state with OCI runtime",
|
||||
},
|
||||
}
|
||||
psCommand cliconfig.PsValues
|
||||
psDescription = "Prints out information about the containers"
|
||||
psCommand = cli.Command{
|
||||
Name: "list",
|
||||
Aliases: []string{"ls", "ps"},
|
||||
Usage: "List containers",
|
||||
Description: psDescription,
|
||||
Flags: sortFlags(psFlags),
|
||||
Action: psCmd,
|
||||
ArgsUsage: "",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_psCommand = &cobra.Command{
|
||||
Use: "list",
|
||||
Aliases: []string{"ls", "ps"},
|
||||
Short: "List containers",
|
||||
Long: psDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
psCommand.InputArgs = args
|
||||
psCommand.GlobalFlags = MainGlobalOpts
|
||||
return psCmd(&psCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func psCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
psCommand.Command = _psCommand
|
||||
flags := psCommand.Flags()
|
||||
flags.BoolVarP(&psCommand.All, "all", "a", false, "Show all the containers, default is only running containers")
|
||||
flags.StringSliceVarP(&psCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions given")
|
||||
flags.StringVar(&psCommand.Format, "format", "", "Pretty-print containers to JSON or using a Go template")
|
||||
flags.IntVarP(&psCommand.Last, "last", "n", -1, "Print the n last created containers (all states)")
|
||||
flags.BoolVarP(&psCommand.Latest, "latest", "l", false, "Show the latest container created (all states)")
|
||||
flags.BoolVar(&psCommand.Namespace, "namespace", false, "Display namespace information")
|
||||
flags.BoolVar(&psCommand.Namespace, "ns", false, "Display namespace information")
|
||||
flags.BoolVar(&psCommand.NoTrunct, "no-trunc", false, "Display the extended information")
|
||||
flags.BoolVarP(&psCommand.Pod, "pod", "p", false, "Print the ID and name of the pod the containers are associated with")
|
||||
flags.BoolVarP(&psCommand.Quiet, "quiet", "q", false, "Print the numeric IDs of the containers only")
|
||||
flags.BoolVarP(&psCommand.Size, "size", "s", false, "Display the total file sizes")
|
||||
flags.StringVar(&psCommand.Sort, "sort", "created", "Sort output by command, created, id, image, names, runningfor, size, or status")
|
||||
flags.BoolVar(&psCommand.Sync, "sync", false, "Sync container state with OCI runtime")
|
||||
|
||||
rootCmd.AddCommand(psCommand.Command)
|
||||
|
||||
}
|
||||
func psCmd(c *cliconfig.PsValues) error {
|
||||
var (
|
||||
filterFuncs []libpod.ContainerFilter
|
||||
outputContainers []*libpod.Container
|
||||
)
|
||||
|
||||
if err := validateFlags(c, psFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := checkFlagsPassed(c); err != nil {
|
||||
return errors.Wrapf(err, "error with flags passed")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if len(c.Args()) > 0 {
|
||||
if len(c.InputArgs) > 0 {
|
||||
return errors.Errorf("too many arguments, ps takes no arguments")
|
||||
}
|
||||
|
||||
opts := shared.PsOptions{
|
||||
All: c.Bool("all"),
|
||||
Format: c.String("format"),
|
||||
Last: c.Int("last"),
|
||||
Latest: c.Bool("latest"),
|
||||
NoTrunc: c.Bool("no-trunc"),
|
||||
Pod: c.Bool("pod"),
|
||||
Quiet: c.Bool("quiet"),
|
||||
Size: c.Bool("size"),
|
||||
Namespace: c.Bool("namespace"),
|
||||
Sort: c.String("sort"),
|
||||
Sync: c.Bool("sync"),
|
||||
All: c.All,
|
||||
Format: c.Format,
|
||||
Last: c.Last,
|
||||
Latest: c.Latest,
|
||||
NoTrunc: c.NoTrunct,
|
||||
Pod: c.Pod,
|
||||
Quiet: c.Quiet,
|
||||
Size: c.Size,
|
||||
Namespace: c.Namespace,
|
||||
Sort: c.Sort,
|
||||
Sync: c.Sync,
|
||||
}
|
||||
|
||||
filters := c.StringSlice("filter")
|
||||
filters := c.Filter
|
||||
if len(filters) > 0 {
|
||||
for _, f := range filters {
|
||||
filterSplit := strings.SplitN(f, "=", 2)
|
||||
|
@ -299,7 +266,7 @@ func psCmd(c *cli.Context) error {
|
|||
|
||||
maxWorkers := shared.Parallelize("ps")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
||||
|
@ -384,20 +351,20 @@ func printQuiet(containers []shared.PsContainerOutput) error {
|
|||
}
|
||||
|
||||
// checkFlagsPassed checks if mutually exclusive flags are passed together
|
||||
func checkFlagsPassed(c *cli.Context) error {
|
||||
func checkFlagsPassed(c *cliconfig.PsValues) error {
|
||||
// latest, and last are mutually exclusive.
|
||||
if c.Int("last") >= 0 && c.Bool("latest") {
|
||||
if c.Last >= 0 && c.Latest {
|
||||
return errors.Errorf("last and latest are mutually exclusive")
|
||||
}
|
||||
// Quiet conflicts with size, namespace, and format with a Go template
|
||||
if c.Bool("quiet") {
|
||||
if c.Bool("size") || c.Bool("namespace") || (c.IsSet("format") &&
|
||||
c.String("format") != formats.JSONString) {
|
||||
if c.Quiet {
|
||||
if c.Size || c.Namespace || (c.Flag("format").Changed &&
|
||||
c.Format != formats.JSONString) {
|
||||
return errors.Errorf("quiet conflicts with size, namespace, and format with go template")
|
||||
}
|
||||
}
|
||||
// Size and namespace conflict with each other
|
||||
if c.Bool("size") && c.Bool("namespace") {
|
||||
if c.Size && c.Namespace {
|
||||
return errors.Errorf("size and namespace options conflict")
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -9,68 +9,58 @@ import (
|
|||
dockerarchive "github.com/containers/image/docker/archive"
|
||||
"github.com/containers/image/transports/alltransports"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
image2 "github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
pullFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cert-dir",
|
||||
Usage: "`pathname` of a directory containing TLS certificates and keys",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "creds",
|
||||
Usage: "`credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress output information when pulling images",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signature-policy",
|
||||
Usage: "`pathname` of signature policy file (not usually used)",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "tls-verify",
|
||||
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
|
||||
},
|
||||
}
|
||||
|
||||
pullCommand cliconfig.PullValues
|
||||
pullDescription = `
|
||||
Pulls an image from a registry and stores it locally.
|
||||
An image can be pulled using its tag or digest. If a tag is not
|
||||
specified, the image with the 'latest' tag (if it exists) is pulled
|
||||
`
|
||||
pullCommand = cli.Command{
|
||||
Name: "pull",
|
||||
Usage: "Pull an image from a registry",
|
||||
Description: pullDescription,
|
||||
Flags: sortFlags(pullFlags),
|
||||
Action: pullCmd,
|
||||
ArgsUsage: "",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_pullCommand = &cobra.Command{
|
||||
Use: "pull",
|
||||
Short: "Pull an image from a registry",
|
||||
Long: pullDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
pullCommand.InputArgs = args
|
||||
pullCommand.GlobalFlags = MainGlobalOpts
|
||||
return pullCmd(&pullCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
pullCommand.Command = _pullCommand
|
||||
flags := pullCommand.Flags()
|
||||
flags.StringVar(&pullCommand.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(&pullCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
|
||||
flags.StringVar(&pullCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
|
||||
flags.BoolVarP(&pullCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
|
||||
flags.StringVar(&pullCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
|
||||
flags.BoolVar(&pullCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
|
||||
|
||||
rootCmd.AddCommand(pullCommand.Command)
|
||||
}
|
||||
|
||||
// pullCmd gets the data from the command line and calls pullImage
|
||||
// to copy an image from a registry to a local machine
|
||||
func pullCmd(c *cli.Context) error {
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
func pullCmd(c *cliconfig.PullValues) error {
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) == 0 {
|
||||
logrus.Errorf("an image name must be specified")
|
||||
return nil
|
||||
|
@ -79,15 +69,12 @@ func pullCmd(c *cli.Context) error {
|
|||
logrus.Errorf("too many arguments. Requires exactly 1")
|
||||
return nil
|
||||
}
|
||||
if err := validateFlags(c, pullFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
image := args[0]
|
||||
|
||||
var registryCreds *types.DockerAuthConfig
|
||||
|
||||
if c.IsSet("creds") {
|
||||
creds, err := util.ParseRegistryCreds(c.String("creds"))
|
||||
if c.Flag("creds").Changed {
|
||||
creds, err := util.ParseRegistryCreds(c.Creds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -98,16 +85,16 @@ func pullCmd(c *cli.Context) error {
|
|||
writer io.Writer
|
||||
imgID string
|
||||
)
|
||||
if !c.Bool("quiet") {
|
||||
if !c.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
|
||||
dockerRegistryOptions := image2.DockerRegistryOptions{
|
||||
DockerRegistryCreds: registryCreds,
|
||||
DockerCertPath: c.String("cert-dir"),
|
||||
DockerCertPath: c.CertDir,
|
||||
}
|
||||
if c.IsSet("tls-verify") {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
|
||||
if c.Flag("tls-verify").Changed {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
|
||||
}
|
||||
|
||||
// Possible for docker-archive to have multiple tags, so use LoadFromArchiveReference instead
|
||||
|
@ -116,14 +103,14 @@ func pullCmd(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return errors.Wrapf(err, "error parsing %q", image)
|
||||
}
|
||||
newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.String("signature-policy"), writer)
|
||||
newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.SignaturePolicy, writer)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error pulling image from %q", image)
|
||||
}
|
||||
imgID = newImage[0].ID()
|
||||
} else {
|
||||
authfile := getAuthFile(c.String("authfile"))
|
||||
newImage, err := runtime.New(getContext(), image, c.String("signature-policy"), authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil)
|
||||
authfile := getAuthFile(c.Authfile)
|
||||
newImage, err := runtime.New(getContext(), image, c.SignaturePolicy, authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error pulling image %q", image)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -14,76 +16,52 @@ import (
|
|||
"github.com/containers/libpod/pkg/util"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
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. Use REGISTRY_AUTH_FILE environment variable to override. ",
|
||||
},
|
||||
}
|
||||
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 = cli.Command{
|
||||
Name: "push",
|
||||
Usage: "Push an image to a specified destination",
|
||||
Description: pushDescription,
|
||||
Flags: sortFlags(pushFlags),
|
||||
Action: pushCmd,
|
||||
ArgsUsage: "IMAGE DESTINATION",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_pushCommand = &cobra.Command{
|
||||
Use: "push",
|
||||
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: "IMAGE DESTINATION",
|
||||
}
|
||||
)
|
||||
|
||||
func pushCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
pushCommand.Command = _pushCommand
|
||||
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 (default: true)")
|
||||
rootCmd.AddCommand(pushCommand.Command)
|
||||
}
|
||||
|
||||
func pushCmd(c *cliconfig.PushValues) error {
|
||||
var (
|
||||
registryCreds *types.DockerAuthConfig
|
||||
destName string
|
||||
)
|
||||
|
||||
args := c.Args()
|
||||
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")
|
||||
}
|
||||
|
@ -94,43 +72,40 @@ func pushCmd(c *cli.Context) error {
|
|||
case 2:
|
||||
destName = args[1]
|
||||
}
|
||||
if err := validateFlags(c, pushFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// --compress and --format can only be used for the "dir" transport
|
||||
splitArg := strings.SplitN(destName, ":", 2)
|
||||
if c.IsSet("compress") || c.IsSet("format") {
|
||||
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.String("cert-dir")
|
||||
removeSignatures := c.Bool("remove-signatures")
|
||||
signBy := c.String("sign-by")
|
||||
certPath := c.CertDir
|
||||
removeSignatures := c.RemoveSignatures
|
||||
signBy := c.SignBy
|
||||
|
||||
if c.IsSet("creds") {
|
||||
creds, err := util.ParseRegistryCreds(c.String("creds"))
|
||||
if c.Flag("creds").Changed {
|
||||
creds, err := util.ParseRegistryCreds(c.Creds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
registryCreds = creds
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
var writer io.Writer
|
||||
if !c.Bool("quiet") {
|
||||
if !c.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
|
||||
var manifestType string
|
||||
if c.IsSet("format") {
|
||||
if c.Flag("format").Changed {
|
||||
switch c.String("format") {
|
||||
case "oci":
|
||||
manifestType = imgspecv1.MediaTypeImageManifest
|
||||
|
@ -147,8 +122,8 @@ func pushCmd(c *cli.Context) error {
|
|||
DockerRegistryCreds: registryCreds,
|
||||
DockerCertPath: certPath,
|
||||
}
|
||||
if c.IsSet("tls-verify") {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
|
||||
if c.Flag("tls-verify").Changed {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
|
||||
}
|
||||
|
||||
so := image.SigningOptions{
|
||||
|
@ -161,7 +136,7 @@ func pushCmd(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
authfile := getAuthFile(c.String("authfile"))
|
||||
authfile := getAuthFile(c.Authfile)
|
||||
|
||||
return newImage.PushImageToHeuristicDestination(getContext(), destName, manifestType, authfile, c.String("signature-policy"), writer, c.Bool("compress"), so, &dockerRegistryOptions, nil)
|
||||
return newImage.PushImageToHeuristicDestination(getContext(), destName, manifestType, authfile, c.SignaturePolicy, writer, c.Compress, so, &dockerRegistryOptions, nil)
|
||||
}
|
||||
|
|
|
@ -4,37 +4,38 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
refreshFlags = []cli.Flag{}
|
||||
|
||||
refreshCommand cliconfig.RefreshValues
|
||||
refreshDescription = "The refresh command resets the state of all containers to handle database changes after a Podman upgrade. All running containers will be restarted."
|
||||
|
||||
refreshCommand = cli.Command{
|
||||
Name: "refresh",
|
||||
Usage: "Refresh container state",
|
||||
Description: refreshDescription,
|
||||
Flags: sortFlags(refreshFlags),
|
||||
Action: refreshCmd,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_refreshCommand = &cobra.Command{
|
||||
Use: "refresh",
|
||||
Short: "Refresh container state",
|
||||
Long: refreshDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
refreshCommand.InputArgs = args
|
||||
refreshCommand.GlobalFlags = MainGlobalOpts
|
||||
return refreshCmd(&refreshCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func refreshCmd(c *cli.Context) error {
|
||||
if len(c.Args()) > 0 {
|
||||
func init() {
|
||||
refreshCommand.Command = _refreshCommand
|
||||
rootCmd.AddCommand(refreshCommand.Command)
|
||||
}
|
||||
|
||||
func refreshCmd(c *cliconfig.RefreshValues) error {
|
||||
if len(c.InputArgs) > 0 {
|
||||
return errors.Errorf("refresh does not accept any arguments")
|
||||
}
|
||||
|
||||
if err := validateFlags(c, refreshFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
|
|
@ -4,47 +4,45 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
restartFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Restart all non-running containers",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "running",
|
||||
Usage: "Restart only running containers when --all is used",
|
||||
},
|
||||
cli.UintFlag{
|
||||
Name: "timeout, time, t",
|
||||
Usage: "Seconds to wait for stop before killing the container",
|
||||
Value: libpod.CtrRemoveTimeout,
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
restartCommand cliconfig.RestartValues
|
||||
restartDescription = `Restarts one or more running containers. The container ID or name can be used. A timeout before forcibly stopping can be set, but defaults to 10 seconds`
|
||||
|
||||
restartCommand = cli.Command{
|
||||
Name: "restart",
|
||||
Usage: "Restart one or more containers",
|
||||
Description: restartDescription,
|
||||
Flags: sortFlags(restartFlags),
|
||||
Action: restartCmd,
|
||||
ArgsUsage: "CONTAINER [CONTAINER ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_restartCommand = &cobra.Command{
|
||||
Use: "restart",
|
||||
Short: "Restart one or more containers",
|
||||
Long: restartDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
restartCommand.InputArgs = args
|
||||
restartCommand.GlobalFlags = MainGlobalOpts
|
||||
return restartCmd(&restartCommand)
|
||||
},
|
||||
Example: "CONTAINER [CONTAINER ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func restartCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
restartCommand.Command = _restartCommand
|
||||
flags := restartCommand.Flags()
|
||||
flags.BoolVarP(&restartCommand.All, "all", "a", false, "Restart all non-running containers")
|
||||
flags.BoolVarP(&restartCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.BoolVar(&restartCommand.Running, "running", false, "Restart only running containers when --all is used")
|
||||
flags.UintVarP(&restartCommand.Timeout, "timeout", "t", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
flags.UintVar(&restartCommand.Timeout, "time", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
|
||||
rootCmd.AddCommand(restartCommand.Command)
|
||||
}
|
||||
|
||||
func restartCmd(c *cliconfig.RestartValues) error {
|
||||
var (
|
||||
restartFuncs []shared.ParallelWorkerInput
|
||||
containers []*libpod.Container
|
||||
|
@ -55,34 +53,31 @@ func restartCmd(c *cli.Context) error {
|
|||
rootless.SetSkipStorageSetup(true)
|
||||
}
|
||||
|
||||
args := c.Args()
|
||||
runOnly := c.Bool("running")
|
||||
all := c.Bool("all")
|
||||
if len(args) < 1 && !c.Bool("latest") && !all {
|
||||
args := c.InputArgs
|
||||
runOnly := c.Running
|
||||
all := c.All
|
||||
if len(args) < 1 && !c.Latest && !all {
|
||||
return errors.Wrapf(libpod.ErrInvalidArg, "you must provide at least one container name or ID")
|
||||
}
|
||||
if err := validateFlags(c, restartFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
timeout := c.Uint("timeout")
|
||||
useTimeout := c.IsSet("timeout")
|
||||
timeout := c.Timeout
|
||||
useTimeout := c.Flag("timeout").Changed
|
||||
|
||||
// Handle --latest
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
lastCtr, err := runtime.GetLatestContainer()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get latest container")
|
||||
}
|
||||
restartContainers = append(restartContainers, lastCtr)
|
||||
} else if runOnly {
|
||||
containers, err = getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
|
||||
containers, err = getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -105,7 +100,7 @@ func restartCmd(c *cli.Context) error {
|
|||
|
||||
maxWorkers := shared.Parallelize("restart")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
|
|
@ -5,68 +5,67 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
restoreCommand cliconfig.RestoreValues
|
||||
restoreDescription = `
|
||||
podman container restore
|
||||
|
||||
Restores a container from a checkpoint. The container name or ID can be used.
|
||||
`
|
||||
restoreFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "keep, k",
|
||||
Usage: "Keep all temporary checkpoint files",
|
||||
_restoreCommand = &cobra.Command{
|
||||
Use: "restore",
|
||||
Short: "Restores one or more containers from a checkpoint",
|
||||
Long: restoreDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
restoreCommand.InputArgs = args
|
||||
restoreCommand.GlobalFlags = MainGlobalOpts
|
||||
return restoreCmd(&restoreCommand)
|
||||
},
|
||||
// restore --all would make more sense if there would be
|
||||
// dedicated state for container which are checkpointed.
|
||||
// TODO: add ContainerStateCheckpointed
|
||||
cli.BoolFlag{
|
||||
Name: "tcp-established",
|
||||
Usage: "Checkpoint a container with established TCP connections",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Restore all checkpointed containers",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
restoreCommand = cli.Command{
|
||||
Name: "restore",
|
||||
Usage: "Restores one or more containers from a checkpoint",
|
||||
Description: restoreDescription,
|
||||
Flags: sortFlags(restoreFlags),
|
||||
Action: restoreCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func restoreCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
restoreCommand.Command = _restoreCommand
|
||||
flags := restoreCommand.Flags()
|
||||
flags.BoolVarP(&restoreCommand.All, "all", "a", false, "Restore all checkpointed containers")
|
||||
flags.BoolVarP(&restoreCommand.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
|
||||
flags.BoolVarP(&restoreCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
// TODO: add ContainerStateCheckpointed
|
||||
flags.BoolVar(&restoreCommand.TcpEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
|
||||
|
||||
rootCmd.AddCommand(restoreCommand.Command)
|
||||
}
|
||||
|
||||
func restoreCmd(c *cliconfig.RestoreValues) error {
|
||||
if rootless.IsRootless() {
|
||||
return errors.New("restoring a container requires root")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
options := libpod.ContainerCheckpointOptions{
|
||||
Keep: c.Bool("keep"),
|
||||
TCPEstablished: c.Bool("tcp-established"),
|
||||
Keep: c.Keep,
|
||||
TCPEstablished: c.TcpEstablished,
|
||||
}
|
||||
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateExited, "checkpointed")
|
||||
containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateExited, "checkpointed")
|
||||
|
||||
for _, ctr := range containers {
|
||||
if err = ctr.Restore(context.TODO(), options); err != nil {
|
||||
|
|
|
@ -2,67 +2,64 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
rmFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Remove all containers",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Force removal of a running container. The default is false",
|
||||
},
|
||||
LatestFlag,
|
||||
cli.BoolFlag{
|
||||
Name: "volumes, v",
|
||||
Usage: "Remove the volumes associated with the container (Not implemented yet)",
|
||||
},
|
||||
}
|
||||
rmCommand cliconfig.RmValues
|
||||
rmDescription = fmt.Sprintf(`
|
||||
Podman rm will remove one or more containers from the host.
|
||||
The container name or ID can be used. This does not remove images.
|
||||
Running containers will not be removed without the -f option.
|
||||
`)
|
||||
rmCommand = cli.Command{
|
||||
Name: "rm",
|
||||
Usage: "Remove one or more containers",
|
||||
Description: rmDescription,
|
||||
Flags: sortFlags(rmFlags),
|
||||
Action: rmCmd,
|
||||
ArgsUsage: "",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_rmCommand = &cobra.Command{
|
||||
Use: "rm",
|
||||
Short: "Remove one or more containers",
|
||||
Long: rmDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
rmCommand.InputArgs = args
|
||||
rmCommand.GlobalFlags = MainGlobalOpts
|
||||
return rmCmd(&rmCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
rmCommand.Command = _rmCommand
|
||||
flags := rmCommand.Flags()
|
||||
flags.BoolVarP(&rmCommand.All, "all", "a", false, "Remove all containers")
|
||||
flags.BoolVarP(&rmCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
|
||||
flags.BoolVarP(&rmCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove the volumes associated with the container (Not implemented yet)")
|
||||
|
||||
rootCmd.AddCommand(rmCommand.Command)
|
||||
}
|
||||
|
||||
// saveCmd saves the image to either docker-archive or oci
|
||||
func rmCmd(c *cli.Context) error {
|
||||
func rmCmd(c *cliconfig.RmValues) error {
|
||||
var (
|
||||
deleteFuncs []shared.ParallelWorkerInput
|
||||
)
|
||||
|
||||
ctx := getContext()
|
||||
if err := validateFlags(c, rmFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delContainers, err := getAllOrLatestContainers(c, runtime, -1, "all")
|
||||
delContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
|
||||
if err != nil {
|
||||
if len(delContainers) == 0 {
|
||||
return err
|
||||
|
@ -73,7 +70,7 @@ func rmCmd(c *cli.Context) error {
|
|||
for _, container := range delContainers {
|
||||
con := container
|
||||
f := func() error {
|
||||
return runtime.RemoveContainer(ctx, con, c.Bool("force"))
|
||||
return runtime.RemoveContainer(ctx, con, c.Force)
|
||||
}
|
||||
|
||||
deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{
|
||||
|
@ -83,7 +80,7 @@ func rmCmd(c *cli.Context) error {
|
|||
}
|
||||
maxWorkers := shared.Parallelize("rm")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
||||
|
|
|
@ -4,47 +4,39 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/containers/storage"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
rmiCommand cliconfig.RmiValues
|
||||
rmiDescription = "Removes one or more locally stored images."
|
||||
rmiFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Remove all images",
|
||||
_rmiCommand = &cobra.Command{
|
||||
Use: "rmi",
|
||||
Short: "Removes one or more images from local storage",
|
||||
Long: rmiDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
rmiCommand.InputArgs = args
|
||||
rmiCommand.GlobalFlags = MainGlobalOpts
|
||||
return rmiCmd(&rmiCommand)
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Force removal of the image",
|
||||
},
|
||||
}
|
||||
rmiCommand = cli.Command{
|
||||
Name: "rmi",
|
||||
Usage: "Remove one or more images from local storage",
|
||||
Description: rmiDescription,
|
||||
Action: rmiCmd,
|
||||
ArgsUsage: "IMAGE-NAME-OR-ID [...]",
|
||||
Flags: sortFlags(rmiFlags),
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
rmImageCommand = cli.Command{
|
||||
Name: "rm",
|
||||
Usage: "Removes one or more images from local storage",
|
||||
Description: rmiDescription,
|
||||
Action: rmiCmd,
|
||||
ArgsUsage: "IMAGE-NAME-OR-ID [...]",
|
||||
Flags: rmiFlags,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
Example: "IMAGE-NAME-OR-ID [...]",
|
||||
}
|
||||
)
|
||||
|
||||
func rmiCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
rmiCommand.Command = _rmiCommand
|
||||
flags := rmiCommand.Flags()
|
||||
flags.BoolVarP(&rmiCommand.All, "all", "a", false, "Remove all images")
|
||||
flags.BoolVarP(&rmiCommand.Force, "force", "f", false, "Force Removal of the image")
|
||||
|
||||
rootCmd.AddCommand(rmiCommand.Command)
|
||||
}
|
||||
|
||||
func rmiCmd(c *cliconfig.RmiValues) error {
|
||||
var (
|
||||
lastError error
|
||||
deleted bool
|
||||
|
@ -53,17 +45,14 @@ func rmiCmd(c *cli.Context) error {
|
|||
)
|
||||
|
||||
ctx := getContext()
|
||||
if err := validateFlags(c, rmiFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
removeAll := c.Bool("all")
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
removeAll := c.All
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) == 0 && !removeAll {
|
||||
return errors.Errorf("image name or ID must be specified")
|
||||
}
|
||||
|
@ -75,7 +64,7 @@ func rmiCmd(c *cli.Context) error {
|
|||
|
||||
removeImage := func(img *adapter.ContainerImage) {
|
||||
deleted = true
|
||||
msg, deleteErr = runtime.RemoveImage(ctx, img, c.Bool("force"))
|
||||
msg, deleteErr = runtime.RemoveImage(ctx, img, c.Force)
|
||||
if deleteErr != nil {
|
||||
if errors.Cause(deleteErr) == storage.ErrImageUsedByContainer {
|
||||
fmt.Printf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID())
|
||||
|
|
|
@ -8,49 +8,57 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var runDescription = "Runs a command in a new container from the given image"
|
||||
var (
|
||||
runCommmand cliconfig.RunValues
|
||||
|
||||
var runFlags []cli.Flag = append(createFlags, cli.BoolTFlag{
|
||||
Name: "sig-proxy",
|
||||
Usage: "Proxy received signals to the process (default true)",
|
||||
})
|
||||
runDescription = "Runs a command in a new container from the given image"
|
||||
_runCommmand = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "Run a command in a new container",
|
||||
Long: runDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
runCommmand.InputArgs = args
|
||||
runCommmand.GlobalFlags = MainGlobalOpts
|
||||
return runCmd(&runCommmand)
|
||||
},
|
||||
Example: "IMAGE [COMMAND [ARG...]]",
|
||||
}
|
||||
)
|
||||
|
||||
var runCommand = cli.Command{
|
||||
Name: "run",
|
||||
Usage: "Run a command in a new container",
|
||||
Description: runDescription,
|
||||
Flags: sortFlags(runFlags),
|
||||
Action: runCmd,
|
||||
ArgsUsage: "IMAGE [COMMAND [ARG...]]",
|
||||
HideHelp: true,
|
||||
SkipArgReorder: true,
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
func init() {
|
||||
runCommmand.Command = _runCommmand
|
||||
flags := runCommmand.Flags()
|
||||
flags.SetInterspersed(false)
|
||||
flags.Bool("sig-proxy", true, "Proxy received signals to the process (default true)")
|
||||
getCreateFlags(&runCommmand.PodmanCommand)
|
||||
|
||||
rootCmd.AddCommand(runCommmand.Command)
|
||||
}
|
||||
|
||||
func runCmd(c *cli.Context) error {
|
||||
if err := createInit(c); err != nil {
|
||||
func runCmd(c *cliconfig.RunValues) error {
|
||||
if err := createInit(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
if os.Geteuid() != 0 {
|
||||
rootless.SetSkipStorageSetup(true)
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
ctr, createConfig, err := createContainer(c, runtime)
|
||||
ctr, createConfig, err := createContainer(&c.PodmanCommand, runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -110,7 +118,7 @@ func runCmd(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
if err := startAttachCtr(ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.BoolT("sig-proxy"), true); err != nil {
|
||||
if err := startAttachCtr(ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true); err != nil {
|
||||
// This means the command did not exist
|
||||
exitCode = 127
|
||||
if strings.Index(err.Error(), "permission denied") > -1 {
|
||||
|
|
|
@ -4,24 +4,19 @@ import (
|
|||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/pkg/inspect"
|
||||
cc "github.com/containers/libpod/pkg/spec"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/docker/go-units"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
cmd = []string{"podman", "test", "alpine"}
|
||||
CLI *cli.Context
|
||||
testCommand = cli.Command{
|
||||
Name: "test",
|
||||
Flags: sortFlags(createFlags),
|
||||
Action: testCmd,
|
||||
HideHelp: true,
|
||||
}
|
||||
cmd = []string{"podman", "test", "alpine"}
|
||||
CLI *cliconfig.PodmanCommand
|
||||
)
|
||||
|
||||
// generates a mocked ImageData structure based on alpine
|
||||
|
@ -53,23 +48,29 @@ func generateAlpineImageData() *inspect.ImageData {
|
|||
}
|
||||
|
||||
// sets a global CLI
|
||||
func testCmd(c *cli.Context) error {
|
||||
CLI = c
|
||||
func testCmd(c *cobra.Command) error {
|
||||
CLI = &cliconfig.PodmanCommand{Command: c}
|
||||
return nil
|
||||
}
|
||||
|
||||
// creates the mocked cli pointing to our create flags
|
||||
// global flags like log-level are not implemented
|
||||
func createCLI() cli.App {
|
||||
a := cli.App{
|
||||
Commands: []cli.Command{
|
||||
testCommand,
|
||||
func createCLI(args []string) *cliconfig.PodmanCommand {
|
||||
var testCommand = &cliconfig.PodmanCommand{
|
||||
Command: &cobra.Command{
|
||||
Use: "test",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return testCmd(cmd)
|
||||
},
|
||||
},
|
||||
}
|
||||
return a
|
||||
rootCmd := testCommand
|
||||
getCreateFlags(rootCmd)
|
||||
rootCmd.ParseFlags(args)
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
func getRuntimeSpec(c *cli.Context) (*spec.Spec, error) {
|
||||
func getRuntimeSpec(c *cliconfig.PodmanCommand) (*spec.Spec, error) {
|
||||
/*
|
||||
TODO: This test has never worked. Need to install content
|
||||
runtime, err := getRuntime(c)
|
||||
|
@ -98,10 +99,11 @@ func TestPIDsLimit(t *testing.T) {
|
|||
if runtime.GOOS != "linux" {
|
||||
t.Skip("seccomp, which is enabled by default, is only supported on Linux")
|
||||
}
|
||||
a := createCLI()
|
||||
args := []string{"--pids-limit", "22"}
|
||||
a.Run(append(cmd, args...))
|
||||
runtimeSpec, err := getRuntimeSpec(CLI)
|
||||
a := createCLI(args)
|
||||
a.InputArgs = args
|
||||
//a.Run(append(cmd, args...))
|
||||
runtimeSpec, err := getRuntimeSpec(a)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
@ -116,10 +118,10 @@ func TestBLKIOWeightDevice(t *testing.T) {
|
|||
if runtime.GOOS != "linux" {
|
||||
t.Skip("seccomp, which is enabled by default, is only supported on Linux")
|
||||
}
|
||||
a := createCLI()
|
||||
args := []string{"--blkio-weight-device", "/dev/zero:100"}
|
||||
a.Run(append(cmd, args...))
|
||||
runtimeSpec, err := getRuntimeSpec(CLI)
|
||||
a := createCLI(args)
|
||||
a.InputArgs = args
|
||||
runtimeSpec, err := getRuntimeSpec(a)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
@ -134,10 +136,11 @@ func TestMemorySwap(t *testing.T) {
|
|||
if runtime.GOOS != "linux" {
|
||||
t.Skip("seccomp, which is enabled by default, is only supported on Linux")
|
||||
}
|
||||
a := createCLI()
|
||||
args := []string{"--memory-swap", "45m", "--memory", "40m"}
|
||||
a.Run(append(cmd, args...))
|
||||
runtimeSpec, err := getRuntimeSpec(CLI)
|
||||
a := createCLI(args)
|
||||
a.InputArgs = args
|
||||
//a.Run(append(cmd, args...))
|
||||
runtimeSpec, err := getRuntimeSpec(a)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
|
|
@ -7,88 +7,59 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
runlabelFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "display",
|
||||
Usage: "Preview the command that the label would run",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cert-dir",
|
||||
Usage: "`Pathname` of a directory containing TLS certificates and keys",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "creds",
|
||||
Usage: "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Assign a name to the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "opt1",
|
||||
Usage: "Optional parameter to pass for install",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "opt2",
|
||||
Usage: "Optional parameter to pass for install",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "opt3",
|
||||
Usage: "Optional parameter to pass for install",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress output information when installing images",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "pull, p",
|
||||
Usage: "Pull the image if it does not exist locally prior to executing the label contents",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signature-policy",
|
||||
Usage: "`Pathname` of signature policy file (not usually used)",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "tls-verify",
|
||||
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
|
||||
},
|
||||
}
|
||||
|
||||
runlabelCommand cliconfig.RunlabelValues
|
||||
runlabelDescription = `
|
||||
Executes a command as described by a container image label.
|
||||
`
|
||||
runlabelCommand = cli.Command{
|
||||
Name: "runlabel",
|
||||
Usage: "Execute the command described by an image label",
|
||||
Description: runlabelDescription,
|
||||
Flags: sortFlags(runlabelFlags),
|
||||
Action: runlabelCmd,
|
||||
ArgsUsage: "",
|
||||
SkipArgReorder: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_runlabelCommand = &cobra.Command{
|
||||
Use: "runlabel",
|
||||
Short: "Execute the command described by an image label",
|
||||
Long: runlabelDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
runlabelCommand.InputArgs = args
|
||||
runlabelCommand.GlobalFlags = MainGlobalOpts
|
||||
return runlabelCmd(&runlabelCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
runlabelCommand.Command = _runlabelCommand
|
||||
flags := runlabelCommand.Flags()
|
||||
flags.StringVar(&runlabelCommand.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(&runlabelCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
|
||||
flags.StringVar(&runlabelCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
|
||||
flags.BoolVar(&runlabelCommand.Display, "display", false, "Preview the command that the label would run")
|
||||
flags.StringVar(&runlabelCommand.Name, "name", "", "Assign a name to the container")
|
||||
|
||||
flags.StringVar(&runlabelCommand.Opt1, "opt1", "", "Optional parameter to pass for install")
|
||||
flags.StringVar(&runlabelCommand.Opt2, "opt2", "", "Optional parameter to pass for install")
|
||||
flags.StringVar(&runlabelCommand.Opt3, "opt3", "", "Optional parameter to pass for install")
|
||||
flags.MarkHidden("opt1")
|
||||
flags.MarkHidden("opt3")
|
||||
flags.MarkHidden("opt3")
|
||||
|
||||
flags.BoolVarP(&runlabelCommand.Pull, "pull", "p", false, "Pull the image if it does not exist locally prior to executing the label contents")
|
||||
flags.BoolVarP(&runlabelCommand.Quiet, "quiet", "q", false, "Suppress output information when installing images")
|
||||
flags.StringVar(&runlabelCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
|
||||
flags.BoolVar(&runlabelCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
|
||||
}
|
||||
|
||||
// installCmd gets the data from the command line and calls installImage
|
||||
// to copy an image from a registry to a local machine
|
||||
func runlabelCmd(c *cli.Context) error {
|
||||
func runlabelCmd(c *cliconfig.RunlabelValues) error {
|
||||
var (
|
||||
imageName string
|
||||
stdErr, stdOut io.Writer
|
||||
|
@ -105,40 +76,38 @@ func runlabelCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
opts := make(map[string]string)
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
if len(args) < 2 {
|
||||
logrus.Errorf("the runlabel command requires at least 2 arguments: LABEL IMAGE")
|
||||
return nil
|
||||
}
|
||||
if err := validateFlags(c, runlabelFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Bool("display") && c.Bool("quiet") {
|
||||
if c.Display && c.Quiet {
|
||||
return errors.Errorf("the display and quiet flags cannot be used together.")
|
||||
}
|
||||
|
||||
if len(args) > 2 {
|
||||
extraArgs = args[2:]
|
||||
}
|
||||
pull := c.Bool("pull")
|
||||
pull := c.Pull
|
||||
label := args[0]
|
||||
|
||||
runlabelImage := args[1]
|
||||
|
||||
if c.IsSet("opt1") {
|
||||
opts["opt1"] = c.String("opt1")
|
||||
if c.Flag("opt1").Changed {
|
||||
opts["opt1"] = c.Opt1
|
||||
}
|
||||
if c.IsSet("opt2") {
|
||||
opts["opt2"] = c.String("opt2")
|
||||
|
||||
if c.Flag("opt2").Changed {
|
||||
opts["opt2"] = c.Opt2
|
||||
}
|
||||
if c.IsSet("opt3") {
|
||||
opts["opt3"] = c.String("opt3")
|
||||
if c.Flag("opt3").Changed {
|
||||
opts["opt3"] = c.Opt3
|
||||
}
|
||||
|
||||
ctx := getContext()
|
||||
|
@ -147,21 +116,21 @@ func runlabelCmd(c *cli.Context) error {
|
|||
stdOut = os.Stdout
|
||||
stdIn = os.Stdin
|
||||
|
||||
if c.Bool("quiet") {
|
||||
if c.Quiet {
|
||||
stdErr = nil
|
||||
stdOut = nil
|
||||
stdIn = nil
|
||||
}
|
||||
|
||||
dockerRegistryOptions := image.DockerRegistryOptions{
|
||||
DockerCertPath: c.String("cert-dir"),
|
||||
DockerCertPath: c.CertDir,
|
||||
}
|
||||
if c.IsSet("tls-verify") {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
|
||||
if c.Flag("tls-verify").Changed {
|
||||
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
|
||||
}
|
||||
|
||||
authfile := getAuthFile(c.String("authfile"))
|
||||
runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, pull, c.String("creds"), dockerRegistryOptions, authfile, c.String("signature-policy"), stdOut)
|
||||
authfile := getAuthFile(c.Authfile)
|
||||
runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, pull, c.Creds, dockerRegistryOptions, authfile, c.SignaturePolicy, stdOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -169,13 +138,13 @@ func runlabelCmd(c *cli.Context) error {
|
|||
return errors.Errorf("%s does not have a label of %s", runlabelImage, label)
|
||||
}
|
||||
|
||||
cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, c.String("name"), opts, extraArgs)
|
||||
cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, c.Name, opts, extraArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !c.Bool("quiet") {
|
||||
if !c.Quiet {
|
||||
fmt.Printf("Command: %s\n", strings.Join(cmd, " "))
|
||||
if c.Bool("display") {
|
||||
if c.Display {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,12 +12,13 @@ import (
|
|||
"github.com/containers/image/manifest"
|
||||
ociarchive "github.com/containers/image/oci/archive"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
libpodImage "github.com/containers/libpod/libpod/image"
|
||||
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -26,67 +27,58 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
saveFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "compress",
|
||||
Usage: "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "output, o",
|
||||
Usage: "Write to a file, default is STDOUT",
|
||||
Value: "/dev/stdout",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress the output",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-dir (directory with v2s2 manifest type)",
|
||||
},
|
||||
}
|
||||
saveCommand cliconfig.SaveValues
|
||||
saveDescription = `
|
||||
Save an image to docker-archive or oci-archive on the local machine.
|
||||
Default is docker-archive`
|
||||
|
||||
saveCommand = cli.Command{
|
||||
Name: "save",
|
||||
Usage: "Save image to an archive",
|
||||
Description: saveDescription,
|
||||
Flags: sortFlags(saveFlags),
|
||||
Action: saveCmd,
|
||||
ArgsUsage: "",
|
||||
SkipArgReorder: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_saveCommand = &cobra.Command{
|
||||
Use: "save",
|
||||
Short: "Save image to an archive",
|
||||
Long: saveDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
saveCommand.InputArgs = args
|
||||
saveCommand.GlobalFlags = MainGlobalOpts
|
||||
return saveCmd(&saveCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
saveCommand.Command = _saveCommand
|
||||
flags := saveCommand.Flags()
|
||||
flags.BoolVar(&saveCommand.Compress, "compress", false, "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)")
|
||||
flags.StringVar(&saveCommand.Format, "format", "", "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-dir (directory with v2s2 manifest type)")
|
||||
flags.StringVarP(&saveCommand.Output, "output", "o", "/dev/stdout", "Write to a file, default is STDOUT")
|
||||
flags.BoolVarP(&saveCommand.Quiet, "quiet", "q", false, "Suppress the output")
|
||||
|
||||
rootCmd.AddCommand(saveCommand.Command)
|
||||
}
|
||||
|
||||
// saveCmd saves the image to either docker-archive or oci
|
||||
func saveCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func saveCmd(c *cliconfig.SaveValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) == 0 {
|
||||
return errors.Errorf("need at least 1 argument")
|
||||
}
|
||||
if err := validateFlags(c, saveFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if c.IsSet("compress") && (c.String("format") != ociManifestDir && c.String("format") != v2s2ManifestDir && c.String("format") == "") {
|
||||
if c.Flag("compress").Changed && (c.Format != ociManifestDir && c.Format != v2s2ManifestDir && c.Format == "") {
|
||||
return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'")
|
||||
}
|
||||
|
||||
var writer io.Writer
|
||||
if !c.Bool("quiet") {
|
||||
if !c.Quiet {
|
||||
writer = os.Stderr
|
||||
}
|
||||
|
||||
output := c.String("output")
|
||||
output := c.Output
|
||||
if output == "/dev/stdout" {
|
||||
fi := os.Stdout
|
||||
if logrus.IsTerminal(fi) {
|
||||
|
@ -105,7 +97,7 @@ func saveCmd(c *cli.Context) error {
|
|||
|
||||
var destRef types.ImageReference
|
||||
var manifestType string
|
||||
switch c.String("format") {
|
||||
switch c.Format {
|
||||
case "oci-archive":
|
||||
destImageName := imageNameForSaveDestination(newImage, source)
|
||||
destRef, err = ociarchive.NewReference(output, destImageName) // destImageName may be ""
|
||||
|
|
|
@ -8,13 +8,14 @@ import (
|
|||
|
||||
"github.com/containers/image/docker"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/libpod/common"
|
||||
sysreg "github.com/containers/libpod/pkg/registries"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -23,46 +24,36 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
searchFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "filter, f",
|
||||
Usage: "Filter output based on conditions provided (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Change the output format to a Go template",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "limit",
|
||||
Usage: "Limit the number of results",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-trunc",
|
||||
Usage: "Do not truncate the output",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "tls-verify",
|
||||
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
|
||||
},
|
||||
}
|
||||
searchCommand cliconfig.SearchValues
|
||||
searchDescription = `
|
||||
Search registries for a given image. Can search all the default registries or a specific registry.
|
||||
Can limit the number of results, and filter the output based on certain conditions.`
|
||||
searchCommand = cli.Command{
|
||||
Name: "search",
|
||||
Usage: "Search registry for image",
|
||||
Description: searchDescription,
|
||||
Flags: sortFlags(searchFlags),
|
||||
Action: searchCmd,
|
||||
ArgsUsage: "TERM",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_searchCommand = &cobra.Command{
|
||||
Use: "search",
|
||||
Short: "Search registry for image",
|
||||
Long: searchDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
searchCommand.InputArgs = args
|
||||
searchCommand.GlobalFlags = MainGlobalOpts
|
||||
return searchCmd(&searchCommand)
|
||||
},
|
||||
Example: "TERM",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
searchCommand.Command = _searchCommand
|
||||
flags := searchCommand.Flags()
|
||||
flags.StringVar(&searchCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
|
||||
flags.StringSliceVarP(&searchCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
|
||||
flags.StringVar(&searchCommand.Format, "format", "", "Change the output format to a Go template")
|
||||
flags.IntVar(&searchCommand.Limit, "limit", 0, "Limit the number of results")
|
||||
flags.BoolVar(&searchCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
|
||||
flags.BoolVar(&searchCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
|
||||
|
||||
rootCmd.AddCommand(searchCommand.Command)
|
||||
}
|
||||
|
||||
type searchParams struct {
|
||||
Index string
|
||||
Name string
|
||||
|
@ -87,8 +78,8 @@ type searchFilterParams struct {
|
|||
isOfficial *bool
|
||||
}
|
||||
|
||||
func searchCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func searchCmd(c *cliconfig.SearchValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) > 1 {
|
||||
return errors.Errorf("too many arguments. Requires exactly 1")
|
||||
}
|
||||
|
@ -106,20 +97,16 @@ func searchCmd(c *cli.Context) error {
|
|||
term = term[len(registry)+1:]
|
||||
}
|
||||
|
||||
if err := validateFlags(c, searchFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
format := genSearchFormat(c.String("format"))
|
||||
format := genSearchFormat(c.Format)
|
||||
opts := searchOpts{
|
||||
format: format,
|
||||
noTrunc: c.Bool("no-trunc"),
|
||||
limit: c.Int("limit"),
|
||||
filter: c.StringSlice("filter"),
|
||||
authfile: getAuthFile(c.String("authfile")),
|
||||
noTrunc: c.NoTrunc,
|
||||
limit: c.Limit,
|
||||
filter: c.Filter,
|
||||
authfile: getAuthFile(c.Authfile),
|
||||
}
|
||||
if c.IsSet("tls-verify") {
|
||||
opts.insecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
|
||||
if c.Flag("tls-verify").Changed {
|
||||
opts.insecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
|
||||
}
|
||||
registries, err := getRegistries(registry)
|
||||
if err != nil {
|
||||
|
|
|
@ -11,60 +11,63 @@ import (
|
|||
"github.com/containers/image/signature"
|
||||
"github.com/containers/image/transports"
|
||||
"github.com/containers/image/transports/alltransports"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/trust"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
signFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "sign-by",
|
||||
Usage: "Name of the signing key",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "directory, d",
|
||||
Usage: "Define an alternate directory to store signatures",
|
||||
},
|
||||
}
|
||||
|
||||
signCommand cliconfig.SignValues
|
||||
signDescription = "Create a signature file that can be used later to verify the image"
|
||||
signCommand = cli.Command{
|
||||
Name: "sign",
|
||||
Usage: "Sign an image",
|
||||
Description: signDescription,
|
||||
Flags: sortFlags(signFlags),
|
||||
Action: signCmd,
|
||||
ArgsUsage: "IMAGE-NAME [IMAGE-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_signCommand = &cobra.Command{
|
||||
Use: "sign",
|
||||
Short: "Sign an image",
|
||||
Long: signDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
signCommand.InputArgs = args
|
||||
signCommand.GlobalFlags = MainGlobalOpts
|
||||
return signCmd(&signCommand)
|
||||
},
|
||||
Example: "IMAGE-NAME [IMAGE-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
signCommand.Command = _signCommand
|
||||
flags := signCommand.Flags()
|
||||
flags.StringVarP(&signCommand.Directory, "directory", "d", "", "Define an alternate directory to store signatures")
|
||||
flags.StringVar(&signCommand.SignBy, "sign-by", "", "Name of the signing key")
|
||||
|
||||
rootCmd.AddCommand(signCommand.Command)
|
||||
|
||||
}
|
||||
|
||||
// SignatureStoreDir defines default directory to store signatures
|
||||
const SignatureStoreDir = "/var/lib/containers/sigstore"
|
||||
|
||||
func signCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func signCmd(c *cliconfig.SignValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) < 1 {
|
||||
return errors.Errorf("at least one image name must be specified")
|
||||
}
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
signby := c.String("sign-by")
|
||||
signby := c.SignBy
|
||||
if signby == "" {
|
||||
return errors.Errorf("please provide an identity")
|
||||
}
|
||||
|
||||
var sigStoreDir string
|
||||
if c.IsSet("directory") {
|
||||
sigStoreDir = c.String("directory")
|
||||
if c.Flag("directory").Changed {
|
||||
sigStoreDir = c.Directory
|
||||
if _, err := os.Stat(sigStoreDir); err != nil {
|
||||
return errors.Wrapf(err, "invalid directory %s", sigStoreDir)
|
||||
}
|
||||
|
|
|
@ -5,84 +5,75 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
cc "github.com/containers/libpod/pkg/spec"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
startFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "attach, a",
|
||||
Usage: "Attach container's STDOUT and STDERR",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "detach-keys",
|
||||
Usage: "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "interactive, i",
|
||||
Usage: "Keep STDIN open even if not attached",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "sig-proxy",
|
||||
Usage: "Proxy received signals to the process (default true if attaching, false otherwise)",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
startCommand cliconfig.StartValues
|
||||
startDescription = `
|
||||
podman start
|
||||
|
||||
Starts one or more containers. The container name or ID can be used.
|
||||
`
|
||||
|
||||
startCommand = cli.Command{
|
||||
Name: "start",
|
||||
Usage: "Start one or more containers",
|
||||
Description: startDescription,
|
||||
Flags: sortFlags(startFlags),
|
||||
Action: startCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_startCommand = &cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start one or more containers",
|
||||
Long: startDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
startCommand.InputArgs = args
|
||||
startCommand.GlobalFlags = MainGlobalOpts
|
||||
return startCmd(&startCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func startCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if len(args) < 1 && !c.Bool("latest") {
|
||||
func init() {
|
||||
startCommand.Command = _startCommand
|
||||
flags := startCommand.Flags()
|
||||
flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
|
||||
flags.StringVar(&startCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
|
||||
flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
|
||||
flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.BoolVar(&startCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true if attaching, false otherwise)")
|
||||
|
||||
rootCmd.AddCommand(startCommand.Command)
|
||||
}
|
||||
|
||||
func startCmd(c *cliconfig.StartValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) < 1 && !c.Latest {
|
||||
return errors.Errorf("you must provide at least one container name or id")
|
||||
}
|
||||
|
||||
attach := c.Bool("attach")
|
||||
attach := c.Attach
|
||||
|
||||
if len(args) > 1 && attach {
|
||||
return errors.Errorf("you cannot start and attach multiple containers at once")
|
||||
}
|
||||
|
||||
if err := validateFlags(c, startFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sigProxy := c.BoolT("sig-proxy")
|
||||
sigProxy := c.SigProxy
|
||||
|
||||
if sigProxy && !attach {
|
||||
if c.IsSet("sig-proxy") {
|
||||
if c.Flag("sig-proxy").Changed {
|
||||
return errors.Wrapf(libpod.ErrInvalidArg, "you cannot use sig-proxy without --attach")
|
||||
} else {
|
||||
sigProxy = false
|
||||
}
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
lastCtr, err := runtime.GetLatestContainer()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get latest container")
|
||||
|
@ -112,12 +103,12 @@ func startCmd(c *cli.Context) error {
|
|||
|
||||
if attach {
|
||||
inputStream := os.Stdin
|
||||
if !c.Bool("interactive") {
|
||||
if !c.Interactive {
|
||||
inputStream = nil
|
||||
}
|
||||
|
||||
// attach to the container and also start it not already running
|
||||
err = startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.String("detach-keys"), sigProxy, !ctrRunning)
|
||||
err = startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, sigProxy, !ctrRunning)
|
||||
if ctrRunning {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@ import (
|
|||
"time"
|
||||
|
||||
tm "github.com/buger/goterm"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type statsOutputParams struct {
|
||||
|
@ -28,48 +29,41 @@ type statsOutputParams struct {
|
|||
}
|
||||
|
||||
var (
|
||||
statsFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Show all containers. Only running containers are shown by default. The default is false",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-stream",
|
||||
Usage: "Disable streaming stats and only pull the first result, default setting is false",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Pretty-print container statistics to JSON or using a Go template",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-reset",
|
||||
Usage: "Disable resetting the screen between intervals",
|
||||
}, LatestFlag,
|
||||
}
|
||||
statsCommand cliconfig.StatsValues
|
||||
|
||||
statsDescription = "Display a live stream of one or more containers' resource usage statistics"
|
||||
statsCommand = cli.Command{
|
||||
Name: "stats",
|
||||
Usage: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers",
|
||||
Description: statsDescription,
|
||||
Flags: sortFlags(statsFlags),
|
||||
Action: statsCmd,
|
||||
ArgsUsage: "",
|
||||
OnUsageError: usageErrorHandler,
|
||||
statsDescription = "display a live stream of one or more containers' resource usage statistics"
|
||||
_statsCommand = &cobra.Command{
|
||||
Use: "stats",
|
||||
Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers",
|
||||
Long: statsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
statsCommand.InputArgs = args
|
||||
statsCommand.GlobalFlags = MainGlobalOpts
|
||||
return statsCmd(&statsCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func statsCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, statsFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
func init() {
|
||||
statsCommand.Command = _statsCommand
|
||||
flags := statsCommand.Flags()
|
||||
flags.BoolVarP(&statsCommand.All, "all", "a", false, "Show all containers. Only running containers are shown by default. The default is false")
|
||||
flags.StringVar(&statsCommand.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template")
|
||||
flags.BoolVarP(&statsCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.BoolVar(&statsCommand.NoReset, "no-reset", false, "Disable resetting the screen between intervals")
|
||||
flags.BoolVar(&statsCommand.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false")
|
||||
|
||||
rootCmd.AddCommand(statsCommand.Command)
|
||||
}
|
||||
|
||||
func statsCmd(c *cliconfig.StatsValues) error {
|
||||
if os.Geteuid() != 0 {
|
||||
return errors.New("stats is not supported for rootless containers")
|
||||
}
|
||||
|
||||
all := c.Bool("all")
|
||||
latest := c.Bool("latest")
|
||||
all := c.All
|
||||
latest := c.Latest
|
||||
ctr := 0
|
||||
if all {
|
||||
ctr += 1
|
||||
|
@ -77,7 +71,7 @@ func statsCmd(c *cli.Context) error {
|
|||
if latest {
|
||||
ctr += 1
|
||||
}
|
||||
if len(c.Args()) > 0 {
|
||||
if len(c.InputArgs) > 0 {
|
||||
ctr += 1
|
||||
}
|
||||
|
||||
|
@ -87,14 +81,14 @@ func statsCmd(c *cli.Context) error {
|
|||
return errors.Errorf("you must specify --all, --latest, or at least one container")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
times := -1
|
||||
if c.Bool("no-stream") {
|
||||
if c.NoStream {
|
||||
times = 1
|
||||
}
|
||||
|
||||
|
@ -102,8 +96,8 @@ func statsCmd(c *cli.Context) error {
|
|||
var containerFunc func() ([]*libpod.Container, error)
|
||||
|
||||
containerFunc = runtime.GetRunningContainers
|
||||
if len(c.Args()) > 0 {
|
||||
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.Args()) }
|
||||
if len(c.InputArgs) > 0 {
|
||||
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.InputArgs) }
|
||||
} else if latest {
|
||||
containerFunc = func() ([]*libpod.Container, error) {
|
||||
lastCtr, err := runtime.GetLatestContainer()
|
||||
|
@ -126,7 +120,7 @@ func statsCmd(c *cli.Context) error {
|
|||
initialStats, err := ctr.GetContainerStats(&libpod.ContainerStats{})
|
||||
if err != nil {
|
||||
// when doing "all", dont worry about containers that are not running
|
||||
if c.Bool("all") && errors.Cause(err) == libpod.ErrCtrRemoved || errors.Cause(err) == libpod.ErrNoSuchCtr || errors.Cause(err) == libpod.ErrCtrStateInvalid {
|
||||
if c.All && errors.Cause(err) == libpod.ErrCtrRemoved || errors.Cause(err) == libpod.ErrNoSuchCtr || errors.Cause(err) == libpod.ErrCtrStateInvalid {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
|
@ -134,7 +128,7 @@ func statsCmd(c *cli.Context) error {
|
|||
containerStats[ctr.ID()] = initialStats
|
||||
}
|
||||
|
||||
format := genStatsFormat(c.String("format"))
|
||||
format := genStatsFormat(c.Format)
|
||||
|
||||
step := 1
|
||||
if times == -1 {
|
||||
|
@ -168,7 +162,7 @@ func statsCmd(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.ToLower(format) != formats.JSONString && !c.Bool("no-reset") {
|
||||
if strings.ToLower(format) != formats.JSONString && !c.NoReset {
|
||||
tm.Clear()
|
||||
tm.MoveCursor(1, 1)
|
||||
tm.Flush()
|
||||
|
|
|
@ -3,27 +3,18 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
stopFlags = []cli.Flag{
|
||||
cli.UintFlag{
|
||||
Name: "timeout, time, t",
|
||||
Usage: "Seconds to wait for stop before killing the container",
|
||||
Value: libpod.CtrRemoveTimeout,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Stop all running containers",
|
||||
}, LatestFlag,
|
||||
}
|
||||
stopCommand cliconfig.StopValues
|
||||
stopDescription = `
|
||||
podman stop
|
||||
|
||||
|
@ -31,36 +22,44 @@ var (
|
|||
A timeout to forcibly stop the container can also be set but defaults to 10
|
||||
seconds otherwise.
|
||||
`
|
||||
|
||||
stopCommand = cli.Command{
|
||||
Name: "stop",
|
||||
Usage: "Stop one or more containers",
|
||||
Description: stopDescription,
|
||||
Flags: sortFlags(stopFlags),
|
||||
Action: stopCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_stopCommand = &cobra.Command{
|
||||
Use: "stop",
|
||||
Short: "Stop one or more containers",
|
||||
Long: stopDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
stopCommand.InputArgs = args
|
||||
stopCommand.GlobalFlags = MainGlobalOpts
|
||||
return stopCmd(&stopCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func stopCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
stopCommand.Command = _stopCommand
|
||||
flags := stopCommand.Flags()
|
||||
flags.BoolVarP(&stopCommand.All, "all", "a", false, "Stop all running containers")
|
||||
flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.UintVar(&stopCommand.Timeout, "time", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
flags.UintVarP(&stopCommand.Timeout, "timeout", "t", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
return err
|
||||
}
|
||||
rootCmd.AddCommand(stopCommand.Command)
|
||||
}
|
||||
|
||||
if err := validateFlags(c, stopFlags); err != nil {
|
||||
func stopCmd(c *cliconfig.StopValues) error {
|
||||
|
||||
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rootless.SetSkipStorageSetup(true)
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
containers, err := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
|
||||
containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
|
||||
if err != nil {
|
||||
if len(containers) == 0 {
|
||||
return err
|
||||
|
@ -72,8 +71,8 @@ func stopCmd(c *cli.Context) error {
|
|||
for _, ctr := range containers {
|
||||
con := ctr
|
||||
var stopTimeout uint
|
||||
if c.IsSet("timeout") {
|
||||
stopTimeout = c.Uint("timeout")
|
||||
if c.Flag("timeout").Changed {
|
||||
stopTimeout = c.Timeout
|
||||
} else {
|
||||
stopTimeout = ctr.StopTimeout()
|
||||
}
|
||||
|
@ -92,7 +91,7 @@ func stopCmd(c *cli.Context) error {
|
|||
|
||||
maxWorkers := shared.Parallelize("stop")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
||||
|
|
|
@ -1,29 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
systemSubCommands = []cli.Command{
|
||||
pruneSystemCommand,
|
||||
}
|
||||
systemDescription = "Manage podman"
|
||||
systemCommand = cli.Command{
|
||||
Name: "system",
|
||||
Usage: "Manage podman",
|
||||
Description: systemDescription,
|
||||
ArgsUsage: "",
|
||||
Subcommands: getSystemSubCommandsSorted(),
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
|
||||
systemCommand = cliconfig.PodmanCommand{
|
||||
Command: &cobra.Command{
|
||||
Use: "system",
|
||||
Short: "Manage podman",
|
||||
Long: systemDescription,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func getSystemSubCommandsSorted() []cli.Command {
|
||||
systemSubCommands = append(systemSubCommands, getSystemSubCommands()...)
|
||||
sort.Sort(commandSortedAlpha{systemSubCommands})
|
||||
return systemSubCommands
|
||||
func init() {
|
||||
systemCommand.AddCommand(getSystemSubCommands()...)
|
||||
rootCmd.AddCommand(systemCommand.Command)
|
||||
}
|
||||
|
|
|
@ -6,50 +6,50 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
pruneSystemCommand cliconfig.SystemPruneValues
|
||||
pruneSystemDescription = `
|
||||
podman system prune
|
||||
|
||||
Remove unused data
|
||||
`
|
||||
pruneSystemFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Remove all unused data",
|
||||
_pruneSystemCommand = &cobra.Command{
|
||||
Use: "prune",
|
||||
Short: "Remove unused data",
|
||||
Long: pruneSystemDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
pruneSystemCommand.InputArgs = args
|
||||
pruneSystemCommand.GlobalFlags = MainGlobalOpts
|
||||
return pruneSystemCmd(&pruneSystemCommand)
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Do not prompt for confirmation",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "volumes",
|
||||
Usage: "Prune volumes",
|
||||
},
|
||||
}
|
||||
pruneSystemCommand = cli.Command{
|
||||
Name: "prune",
|
||||
Usage: "Remove unused data",
|
||||
Description: pruneSystemDescription,
|
||||
Action: pruneSystemCmd,
|
||||
OnUsageError: usageErrorHandler,
|
||||
Flags: pruneSystemFlags,
|
||||
}
|
||||
)
|
||||
|
||||
func pruneSystemCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
|
||||
pruneSystemCommand.Command = _pruneSystemCommand
|
||||
flags := pruneSystemCommand.Flags()
|
||||
flags.BoolVarP(&pruneSystemCommand.All, "all", "a", false, "Remove all unused data")
|
||||
flags.BoolVarP(&pruneSystemCommand.Force, "force", "f", false, "Do not prompt for confirmation")
|
||||
flags.BoolVar(&pruneSystemCommand.Volume, "volumes", false, "Prune volumes")
|
||||
|
||||
}
|
||||
|
||||
func pruneSystemCmd(c *cliconfig.SystemPruneValues) error {
|
||||
|
||||
// Prompt for confirmation if --force is not set
|
||||
if !c.Bool("force") {
|
||||
if !c.Force {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
volumeString := ""
|
||||
if c.Bool("volumes") {
|
||||
if c.Volume {
|
||||
volumeString = `
|
||||
- all volumes not used by at least one container`
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
|
|||
}
|
||||
}
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
|
|||
|
||||
// Call prune; if any cids are returned, print them and then
|
||||
// return err in case an error also came up
|
||||
pruneCids, err := runtime.PruneImages(c.Bool("all"))
|
||||
pruneCids, err := runtime.PruneImages(c.All)
|
||||
if len(pruneCids) > 0 {
|
||||
fmt.Println("Deleted Images")
|
||||
for _, cid := range pruneCids {
|
||||
|
|
|
@ -1,29 +1,41 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
tagCommand cliconfig.TagValues
|
||||
|
||||
tagDescription = "Adds one or more additional names to locally-stored image"
|
||||
tagCommand = cli.Command{
|
||||
Name: "tag",
|
||||
Usage: "Add an additional name to a local image",
|
||||
Description: tagDescription,
|
||||
Action: tagCmd,
|
||||
ArgsUsage: "IMAGE-NAME [IMAGE-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_tagCommand = &cobra.Command{
|
||||
Use: "tag",
|
||||
Short: "Add an additional name to a local image",
|
||||
Long: tagDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
tagCommand.InputArgs = args
|
||||
tagCommand.GlobalFlags = MainGlobalOpts
|
||||
return tagCmd(&tagCommand)
|
||||
},
|
||||
Example: "IMAGE-NAME [IMAGE-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func tagCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func init() {
|
||||
tagCommand.Command = _tagCommand
|
||||
rootCmd.AddCommand(tagCommand.Command)
|
||||
|
||||
}
|
||||
|
||||
func tagCmd(c *cliconfig.TagValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) < 2 {
|
||||
return errors.Errorf("image name and at least one new name must be specified")
|
||||
}
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@ import (
|
|||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func getDescriptorString() string {
|
||||
|
@ -24,13 +25,7 @@ Format Descriptors:
|
|||
}
|
||||
|
||||
var (
|
||||
topFlags = []cli.Flag{
|
||||
LatestFlag,
|
||||
cli.BoolFlag{
|
||||
Name: "list-descriptors",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
topCommand cliconfig.TopValues
|
||||
topDescription = fmt.Sprintf(`Display the running processes of the container. Specify format descriptors
|
||||
to alter the output. You may run "podman top -l pid pcpu seccomp" to print
|
||||
the process ID, the CPU percentage and the seccomp mode of each process of
|
||||
|
@ -38,24 +33,35 @@ the latest container.
|
|||
%s
|
||||
`, getDescriptorString())
|
||||
|
||||
topCommand = cli.Command{
|
||||
Name: "top",
|
||||
Usage: "Display the running processes of a container",
|
||||
Description: topDescription,
|
||||
Flags: sortFlags(topFlags),
|
||||
Action: topCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [format descriptors]",
|
||||
SkipArgReorder: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
_topCommand = &cobra.Command{
|
||||
Use: "top",
|
||||
Short: "Display the running processes of a container",
|
||||
Long: topDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
topCommand.InputArgs = args
|
||||
topCommand.GlobalFlags = MainGlobalOpts
|
||||
return topCmd(&topCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [format descriptors]",
|
||||
}
|
||||
)
|
||||
|
||||
func topCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
topCommand.Command = _topCommand
|
||||
flags := topCommand.Flags()
|
||||
flags.BoolVar(&topCommand.ListDescriptors, "list-descriptors", false, "")
|
||||
flags.MarkHidden("list-descriptors")
|
||||
flags.BoolVarP(&topCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
|
||||
rootCmd.AddCommand(topCommand.Command)
|
||||
}
|
||||
|
||||
func topCmd(c *cliconfig.TopValues) error {
|
||||
var container *libpod.Container
|
||||
var err error
|
||||
args := c.Args()
|
||||
args := c.InputArgs
|
||||
|
||||
if c.Bool("list-descriptors") {
|
||||
if c.ListDescriptors {
|
||||
descriptors, err := libpod.GetContainerPidInformationDescriptors()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -64,22 +70,19 @@ func topCmd(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if len(args) < 1 && !c.Bool("latest") {
|
||||
if len(args) < 1 && !c.Latest {
|
||||
return errors.Errorf("you must provide the name or id of a running container")
|
||||
}
|
||||
if err := validateFlags(c, topFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rootless.SetSkipStorageSetup(true)
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
var descriptors []string
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
descriptors = args
|
||||
container, err = runtime.GetLatestContainer()
|
||||
} else {
|
||||
|
|
|
@ -1,369 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/trust"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
setTrustFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "type, t",
|
||||
Usage: "Trust type, accept values: signedBy(default), accept, reject.",
|
||||
Value: "signedBy",
|
||||
trustCommand = cliconfig.PodmanCommand{
|
||||
Command: &cobra.Command{
|
||||
Use: "trust",
|
||||
Short: "Manage container image trust policy",
|
||||
Long: "podman image trust command",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "pubkeysfile, f",
|
||||
Usage: `Path of installed public key(s) to trust for TARGET.
|
||||
Absolute path to keys is added to policy.json. May
|
||||
used multiple times to define multiple public keys.
|
||||
File(s) must exist before using this command.`,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "policypath",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
showTrustFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "raw",
|
||||
Usage: "Output raw policy file",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "json, j",
|
||||
Usage: "Output as json",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "policypath",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "registrypath",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
|
||||
setTrustDescription = "Set default trust policy or add a new trust policy for a registry"
|
||||
setTrustCommand = cli.Command{
|
||||
Name: "set",
|
||||
Usage: "Set default trust policy or a new trust policy for a registry",
|
||||
Description: setTrustDescription,
|
||||
Flags: sortFlags(setTrustFlags),
|
||||
ArgsUsage: "default | REGISTRY[/REPOSITORY]",
|
||||
Action: setTrustCmd,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
|
||||
showTrustDescription = "Display trust policy for the system"
|
||||
showTrustCommand = cli.Command{
|
||||
Name: "show",
|
||||
Usage: "Display trust policy for the system",
|
||||
Description: showTrustDescription,
|
||||
Flags: sortFlags(showTrustFlags),
|
||||
Action: showTrustCmd,
|
||||
ArgsUsage: "",
|
||||
UseShortOptionHandling: true,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
|
||||
trustSubCommands = []cli.Command{
|
||||
setTrustCommand,
|
||||
showTrustCommand,
|
||||
}
|
||||
|
||||
trustDescription = fmt.Sprintf(`Manages the trust policy of the host system. (%s)
|
||||
Trust policy describes a registry scope that must be signed by public keys.`, getDefaultPolicyPath())
|
||||
trustCommand = cli.Command{
|
||||
Name: "trust",
|
||||
Usage: "Manage container image trust policy",
|
||||
Description: trustDescription,
|
||||
ArgsUsage: "{set,show} ...",
|
||||
Subcommands: trustSubCommands,
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
)
|
||||
|
||||
func showTrustCmd(c *cli.Context) error {
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
|
||||
var (
|
||||
policyPath string
|
||||
systemRegistriesDirPath string
|
||||
outjson interface{}
|
||||
)
|
||||
if c.IsSet("policypath") {
|
||||
policyPath = c.String("policypath")
|
||||
} else {
|
||||
policyPath = trust.DefaultPolicyPath(runtime.SystemContext())
|
||||
}
|
||||
policyContent, err := ioutil.ReadFile(policyPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to read %s", policyPath)
|
||||
}
|
||||
if c.IsSet("registrypath") {
|
||||
systemRegistriesDirPath = c.String("registrypath")
|
||||
} else {
|
||||
systemRegistriesDirPath = trust.RegistriesDirPath(runtime.SystemContext())
|
||||
}
|
||||
|
||||
if c.Bool("raw") {
|
||||
_, err := os.Stdout.Write(policyContent)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not read trust policies")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
policyContentStruct, err := trust.GetPolicy(policyPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not read trust policies")
|
||||
}
|
||||
|
||||
if c.Bool("json") {
|
||||
policyJSON, err := getPolicyJSON(policyContentStruct, systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not show trust policies in JSON format")
|
||||
}
|
||||
outjson = policyJSON
|
||||
out := formats.JSONStruct{Output: outjson}
|
||||
return formats.Writer(out).Out()
|
||||
}
|
||||
|
||||
showOutputMap, err := getPolicyShowOutput(policyContentStruct, systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not show trust policies")
|
||||
}
|
||||
out := formats.StdoutTemplateArray{Output: showOutputMap, Template: "{{.Repo}}\t{{.Trusttype}}\t{{.GPGid}}\t{{.Sigstore}}"}
|
||||
return formats.Writer(out).Out()
|
||||
}
|
||||
|
||||
func setTrustCmd(c *cli.Context) error {
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
var (
|
||||
policyPath string
|
||||
policyContentStruct trust.PolicyContent
|
||||
newReposContent []trust.RepoContent
|
||||
)
|
||||
args := c.Args()
|
||||
if len(args) != 1 {
|
||||
return errors.Errorf("default or a registry name must be specified")
|
||||
}
|
||||
valid, err := image.IsValidImageURI(args[0])
|
||||
if err != nil || !valid {
|
||||
return errors.Wrapf(err, "invalid image uri %s", args[0])
|
||||
}
|
||||
|
||||
trusttype := c.String("type")
|
||||
if !isValidTrustType(trusttype) {
|
||||
return errors.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy')", trusttype)
|
||||
}
|
||||
if trusttype == "accept" {
|
||||
trusttype = "insecureAcceptAnything"
|
||||
}
|
||||
|
||||
pubkeysfile := c.StringSlice("pubkeysfile")
|
||||
if len(pubkeysfile) == 0 && trusttype == "signedBy" {
|
||||
return errors.Errorf("At least one public key must be defined for type 'signedBy'")
|
||||
}
|
||||
|
||||
if c.IsSet("policypath") {
|
||||
policyPath = c.String("policypath")
|
||||
} else {
|
||||
policyPath = trust.DefaultPolicyPath(runtime.SystemContext())
|
||||
}
|
||||
_, err = os.Stat(policyPath)
|
||||
if !os.IsNotExist(err) {
|
||||
policyContent, err := ioutil.ReadFile(policyPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to read %s", policyPath)
|
||||
}
|
||||
if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil {
|
||||
return errors.Errorf("could not read trust policies")
|
||||
}
|
||||
}
|
||||
if len(pubkeysfile) != 0 {
|
||||
for _, filepath := range pubkeysfile {
|
||||
newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype, KeyType: "GPGKeys", KeyPath: filepath})
|
||||
}
|
||||
} else {
|
||||
newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype})
|
||||
}
|
||||
if args[0] == "default" {
|
||||
policyContentStruct.Default = newReposContent
|
||||
} else {
|
||||
if len(policyContentStruct.Default) == 0 {
|
||||
return errors.Errorf("Default trust policy must be set.")
|
||||
}
|
||||
registryExists := false
|
||||
for transport, transportval := range policyContentStruct.Transports {
|
||||
_, registryExists = transportval[args[0]]
|
||||
if registryExists {
|
||||
policyContentStruct.Transports[transport][args[0]] = newReposContent
|
||||
break
|
||||
}
|
||||
}
|
||||
if !registryExists {
|
||||
if policyContentStruct.Transports == nil {
|
||||
policyContentStruct.Transports = make(map[string]trust.RepoMap)
|
||||
}
|
||||
if policyContentStruct.Transports["docker"] == nil {
|
||||
policyContentStruct.Transports["docker"] = make(map[string][]trust.RepoContent)
|
||||
}
|
||||
policyContentStruct.Transports["docker"][args[0]] = append(policyContentStruct.Transports["docker"][args[0]], newReposContent...)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(policyContentStruct, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error setting trust policy")
|
||||
}
|
||||
err = ioutil.WriteFile(policyPath, data, 0644)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error setting trust policy")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortShowOutputMapKey(m map[string]trust.ShowOutput) []string {
|
||||
keys := make([]string, len(m))
|
||||
i := 0
|
||||
for k := range m {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func isValidTrustType(t string) bool {
|
||||
if t == "accept" || t == "insecureAcceptAnything" || t == "reject" || t == "signedBy" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getDefaultPolicyPath() string {
|
||||
return trust.DefaultPolicyPath(&types.SystemContext{})
|
||||
}
|
||||
|
||||
func getPolicyJSON(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) (map[string]map[string]interface{}, error) {
|
||||
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policyJSON := make(map[string]map[string]interface{})
|
||||
if len(policyContentStruct.Default) > 0 {
|
||||
policyJSON["* (default)"] = make(map[string]interface{})
|
||||
policyJSON["* (default)"]["type"] = policyContentStruct.Default[0].Type
|
||||
}
|
||||
for transname, transval := range policyContentStruct.Transports {
|
||||
for repo, repoval := range transval {
|
||||
policyJSON[repo] = make(map[string]interface{})
|
||||
policyJSON[repo]["type"] = repoval[0].Type
|
||||
policyJSON[repo]["transport"] = transname
|
||||
keyarr := []string{}
|
||||
uids := []string{}
|
||||
for _, repoele := range repoval {
|
||||
if len(repoele.KeyPath) > 0 {
|
||||
keyarr = append(keyarr, repoele.KeyPath)
|
||||
uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...)
|
||||
}
|
||||
if len(repoele.KeyData) > 0 {
|
||||
keyarr = append(keyarr, string(repoele.KeyData))
|
||||
uids = append(uids, trust.GetGPGIdFromKeyData(string(repoele.KeyData))...)
|
||||
}
|
||||
}
|
||||
policyJSON[repo]["keys"] = keyarr
|
||||
policyJSON[repo]["sigstore"] = ""
|
||||
registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs)
|
||||
if registryNamespace != nil {
|
||||
policyJSON[repo]["sigstore"] = registryNamespace.SigStore
|
||||
}
|
||||
}
|
||||
}
|
||||
return policyJSON, nil
|
||||
}
|
||||
|
||||
var typeDescription = map[string]string{"insecureAcceptAnything": "accept", "signedBy": "signed", "reject": "reject"}
|
||||
|
||||
func trustTypeDescription(trustType string) string {
|
||||
trustDescription, exist := typeDescription[trustType]
|
||||
if !exist {
|
||||
logrus.Warnf("invalid trust type %s", trustType)
|
||||
}
|
||||
return trustDescription
|
||||
}
|
||||
|
||||
func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]interface{}, error) {
|
||||
var output []interface{}
|
||||
|
||||
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
trustShowOutputMap := make(map[string]trust.ShowOutput)
|
||||
if len(policyContentStruct.Default) > 0 {
|
||||
defaultPolicyStruct := trust.ShowOutput{
|
||||
Repo: "default",
|
||||
Trusttype: trustTypeDescription(policyContentStruct.Default[0].Type),
|
||||
}
|
||||
trustShowOutputMap["* (default)"] = defaultPolicyStruct
|
||||
}
|
||||
for _, transval := range policyContentStruct.Transports {
|
||||
for repo, repoval := range transval {
|
||||
tempTrustShowOutput := trust.ShowOutput{
|
||||
Repo: repo,
|
||||
Trusttype: repoval[0].Type,
|
||||
}
|
||||
keyarr := []string{}
|
||||
uids := []string{}
|
||||
for _, repoele := range repoval {
|
||||
if len(repoele.KeyPath) > 0 {
|
||||
keyarr = append(keyarr, repoele.KeyPath)
|
||||
uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...)
|
||||
}
|
||||
if len(repoele.KeyData) > 0 {
|
||||
keyarr = append(keyarr, string(repoele.KeyData))
|
||||
uids = append(uids, trust.GetGPGIdFromKeyData(string(repoele.KeyData))...)
|
||||
}
|
||||
}
|
||||
tempTrustShowOutput.GPGid = strings.Join(uids, ", ")
|
||||
|
||||
registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs)
|
||||
if registryNamespace != nil {
|
||||
tempTrustShowOutput.Sigstore = registryNamespace.SigStore
|
||||
}
|
||||
trustShowOutputMap[repo] = tempTrustShowOutput
|
||||
}
|
||||
}
|
||||
|
||||
sortedRepos := sortShowOutputMapKey(trustShowOutputMap)
|
||||
for _, reponame := range sortedRepos {
|
||||
showOutput, exists := trustShowOutputMap[reponame]
|
||||
if exists {
|
||||
output = append(output, interface{}(showOutput))
|
||||
}
|
||||
}
|
||||
return output, nil
|
||||
func init() {
|
||||
trustCommand.AddCommand(getTrustSubCommands()...)
|
||||
imageCommand.AddCommand(trustCommand.Command)
|
||||
}
|
||||
|
|
343
cmd/podman/trust_set_show.go
Normal file
343
cmd/podman/trust_set_show.go
Normal file
|
@ -0,0 +1,343 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/trust"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
setTrustCommand cliconfig.SetTrustValues
|
||||
showTrustCommand cliconfig.ShowTrustValues
|
||||
setTrustDescription = "Set default trust policy or add a new trust policy for a registry"
|
||||
_setTrustCommand = &cobra.Command{
|
||||
Use: "set",
|
||||
Short: "Set default trust policy or a new trust policy for a registry",
|
||||
Long: setTrustDescription,
|
||||
Example: "default | REGISTRY[/REPOSITORY]",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
setTrustCommand.InputArgs = args
|
||||
setTrustCommand.GlobalFlags = MainGlobalOpts
|
||||
return setTrustCmd(&setTrustCommand)
|
||||
},
|
||||
}
|
||||
|
||||
showTrustDescription = "Display trust policy for the system"
|
||||
_showTrustCommand = &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "Display trust policy for the system",
|
||||
Long: showTrustDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
showTrustCommand.InputArgs = args
|
||||
showTrustCommand.GlobalFlags = MainGlobalOpts
|
||||
return showTrustCmd(&showTrustCommand)
|
||||
},
|
||||
Example: "",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
setTrustCommand.Command = _setTrustCommand
|
||||
showTrustCommand.Command = _showTrustCommand
|
||||
setFlags := setTrustCommand.Flags()
|
||||
setFlags.StringVar(&setTrustCommand.PolicyPath, "policypath", "", "")
|
||||
setFlags.MarkHidden("policypath")
|
||||
setFlags.StringSliceVarP(&setTrustCommand.PubKeysFile, "pubkeysfile", "f", []string{}, `Path of installed public key(s) to trust for TARGET.
|
||||
Absolute path to keys is added to policy.json. May
|
||||
used multiple times to define multiple public keys.
|
||||
File(s) must exist before using this command`)
|
||||
setFlags.StringVarP(&setTrustCommand.TrustType, "type", "t", "signedBy", "Trust type, accept values: signedBy(default), accept, reject")
|
||||
|
||||
showFlags := showTrustCommand.Flags()
|
||||
showFlags.BoolVarP(&showTrustCommand.Json, "json", "j", false, "Output as json")
|
||||
showFlags.StringVar(&showTrustCommand.PolicyPath, "policypath", "", "")
|
||||
showFlags.BoolVar(&showTrustCommand.Raw, "raw", false, "Output raw policy file")
|
||||
showFlags.MarkHidden("policypath")
|
||||
showFlags.StringVar(&showTrustCommand.RegistryPath, "registrypath", "", "")
|
||||
showFlags.MarkHidden("registrypath")
|
||||
}
|
||||
|
||||
func showTrustCmd(c *cliconfig.ShowTrustValues) error {
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
|
||||
var (
|
||||
policyPath string
|
||||
systemRegistriesDirPath string
|
||||
outjson interface{}
|
||||
)
|
||||
if c.Flag("policypath").Changed {
|
||||
policyPath = c.PolicyPath
|
||||
} else {
|
||||
policyPath = trust.DefaultPolicyPath(runtime.SystemContext())
|
||||
}
|
||||
policyContent, err := ioutil.ReadFile(policyPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to read %s", policyPath)
|
||||
}
|
||||
if c.Flag("registrypath").Changed {
|
||||
systemRegistriesDirPath = c.RegistryPath
|
||||
} else {
|
||||
systemRegistriesDirPath = trust.RegistriesDirPath(runtime.SystemContext())
|
||||
}
|
||||
|
||||
if c.Raw {
|
||||
_, err := os.Stdout.Write(policyContent)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not read raw trust policies")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
policyContentStruct, err := trust.GetPolicy(policyPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not read trust policies")
|
||||
}
|
||||
|
||||
if c.Json {
|
||||
policyJSON, err := getPolicyJSON(policyContentStruct, systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not show trust policies in JSON format")
|
||||
}
|
||||
outjson = policyJSON
|
||||
out := formats.JSONStruct{Output: outjson}
|
||||
return formats.Writer(out).Out()
|
||||
}
|
||||
|
||||
showOutputMap, err := getPolicyShowOutput(policyContentStruct, systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not show trust policies")
|
||||
}
|
||||
out := formats.StdoutTemplateArray{Output: showOutputMap, Template: "{{.Repo}}\t{{.Trusttype}}\t{{.GPGid}}\t{{.Sigstore}}"}
|
||||
return formats.Writer(out).Out()
|
||||
}
|
||||
|
||||
func setTrustCmd(c *cliconfig.SetTrustValues) error {
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not create runtime")
|
||||
}
|
||||
var (
|
||||
policyPath string
|
||||
policyContentStruct trust.PolicyContent
|
||||
newReposContent []trust.RepoContent
|
||||
)
|
||||
args := c.InputArgs
|
||||
if len(args) != 1 {
|
||||
return errors.Errorf("default or a registry name must be specified")
|
||||
}
|
||||
valid, err := image.IsValidImageURI(args[0])
|
||||
if err != nil || !valid {
|
||||
return errors.Wrapf(err, "invalid image uri %s", args[0])
|
||||
}
|
||||
|
||||
trusttype := c.TrustType
|
||||
if !isValidTrustType(trusttype) {
|
||||
return errors.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy')", trusttype)
|
||||
}
|
||||
if trusttype == "accept" {
|
||||
trusttype = "insecureAcceptAnything"
|
||||
}
|
||||
|
||||
pubkeysfile := c.PubKeysFile
|
||||
if len(pubkeysfile) == 0 && trusttype == "signedBy" {
|
||||
return errors.Errorf("At least one public key must be defined for type 'signedBy'")
|
||||
}
|
||||
|
||||
if c.Flag("policypath").Changed {
|
||||
policyPath = c.PolicyPath
|
||||
} else {
|
||||
policyPath = trust.DefaultPolicyPath(runtime.SystemContext())
|
||||
}
|
||||
_, err = os.Stat(policyPath)
|
||||
if !os.IsNotExist(err) {
|
||||
policyContent, err := ioutil.ReadFile(policyPath)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to read %s", policyPath)
|
||||
}
|
||||
if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil {
|
||||
return errors.Errorf("could not read trust policies")
|
||||
}
|
||||
}
|
||||
if len(pubkeysfile) != 0 {
|
||||
for _, filepath := range pubkeysfile {
|
||||
newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype, KeyType: "GPGKeys", KeyPath: filepath})
|
||||
}
|
||||
} else {
|
||||
newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype})
|
||||
}
|
||||
if args[0] == "default" {
|
||||
policyContentStruct.Default = newReposContent
|
||||
} else {
|
||||
if len(policyContentStruct.Default) == 0 {
|
||||
return errors.Errorf("Default trust policy must be set.")
|
||||
}
|
||||
registryExists := false
|
||||
for transport, transportval := range policyContentStruct.Transports {
|
||||
_, registryExists = transportval[args[0]]
|
||||
if registryExists {
|
||||
policyContentStruct.Transports[transport][args[0]] = newReposContent
|
||||
break
|
||||
}
|
||||
}
|
||||
if !registryExists {
|
||||
if policyContentStruct.Transports == nil {
|
||||
policyContentStruct.Transports = make(map[string]trust.RepoMap)
|
||||
}
|
||||
if policyContentStruct.Transports["docker"] == nil {
|
||||
policyContentStruct.Transports["docker"] = make(map[string][]trust.RepoContent)
|
||||
}
|
||||
policyContentStruct.Transports["docker"][args[0]] = append(policyContentStruct.Transports["docker"][args[0]], newReposContent...)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(policyContentStruct, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error setting trust policy")
|
||||
}
|
||||
err = ioutil.WriteFile(policyPath, data, 0644)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error setting trust policy")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortShowOutputMapKey(m map[string]trust.ShowOutput) []string {
|
||||
keys := make([]string, len(m))
|
||||
i := 0
|
||||
for k := range m {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func isValidTrustType(t string) bool {
|
||||
if t == "accept" || t == "insecureAcceptAnything" || t == "reject" || t == "signedBy" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getDefaultPolicyPath() string {
|
||||
return trust.DefaultPolicyPath(&types.SystemContext{})
|
||||
}
|
||||
|
||||
func getPolicyJSON(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) (map[string]map[string]interface{}, error) {
|
||||
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policyJSON := make(map[string]map[string]interface{})
|
||||
if len(policyContentStruct.Default) > 0 {
|
||||
policyJSON["* (default)"] = make(map[string]interface{})
|
||||
policyJSON["* (default)"]["type"] = policyContentStruct.Default[0].Type
|
||||
}
|
||||
for transname, transval := range policyContentStruct.Transports {
|
||||
for repo, repoval := range transval {
|
||||
policyJSON[repo] = make(map[string]interface{})
|
||||
policyJSON[repo]["type"] = repoval[0].Type
|
||||
policyJSON[repo]["transport"] = transname
|
||||
keyarr := []string{}
|
||||
uids := []string{}
|
||||
for _, repoele := range repoval {
|
||||
if len(repoele.KeyPath) > 0 {
|
||||
keyarr = append(keyarr, repoele.KeyPath)
|
||||
uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...)
|
||||
}
|
||||
if len(repoele.KeyData) > 0 {
|
||||
keyarr = append(keyarr, string(repoele.KeyData))
|
||||
uids = append(uids, trust.GetGPGIdFromKeyData(string(repoele.KeyData))...)
|
||||
}
|
||||
}
|
||||
policyJSON[repo]["keys"] = keyarr
|
||||
policyJSON[repo]["sigstore"] = ""
|
||||
registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs)
|
||||
if registryNamespace != nil {
|
||||
policyJSON[repo]["sigstore"] = registryNamespace.SigStore
|
||||
}
|
||||
}
|
||||
}
|
||||
return policyJSON, nil
|
||||
}
|
||||
|
||||
var typeDescription = map[string]string{"insecureAcceptAnything": "accept", "signedBy": "signed", "reject": "reject"}
|
||||
|
||||
func trustTypeDescription(trustType string) string {
|
||||
trustDescription, exist := typeDescription[trustType]
|
||||
if !exist {
|
||||
logrus.Warnf("invalid trust type %s", trustType)
|
||||
}
|
||||
return trustDescription
|
||||
}
|
||||
|
||||
func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]interface{}, error) {
|
||||
var output []interface{}
|
||||
|
||||
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
trustShowOutputMap := make(map[string]trust.ShowOutput)
|
||||
if len(policyContentStruct.Default) > 0 {
|
||||
defaultPolicyStruct := trust.ShowOutput{
|
||||
Repo: "default",
|
||||
Trusttype: trustTypeDescription(policyContentStruct.Default[0].Type),
|
||||
}
|
||||
trustShowOutputMap["* (default)"] = defaultPolicyStruct
|
||||
}
|
||||
for _, transval := range policyContentStruct.Transports {
|
||||
for repo, repoval := range transval {
|
||||
tempTrustShowOutput := trust.ShowOutput{
|
||||
Repo: repo,
|
||||
Trusttype: repoval[0].Type,
|
||||
}
|
||||
keyarr := []string{}
|
||||
uids := []string{}
|
||||
for _, repoele := range repoval {
|
||||
if len(repoele.KeyPath) > 0 {
|
||||
keyarr = append(keyarr, repoele.KeyPath)
|
||||
uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...)
|
||||
}
|
||||
if len(repoele.KeyData) > 0 {
|
||||
keyarr = append(keyarr, string(repoele.KeyData))
|
||||
uids = append(uids, trust.GetGPGIdFromKeyData(string(repoele.KeyData))...)
|
||||
}
|
||||
}
|
||||
tempTrustShowOutput.GPGid = strings.Join(uids, ", ")
|
||||
|
||||
registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs)
|
||||
if registryNamespace != nil {
|
||||
tempTrustShowOutput.Sigstore = registryNamespace.SigStore
|
||||
}
|
||||
trustShowOutputMap[repo] = tempTrustShowOutput
|
||||
}
|
||||
}
|
||||
|
||||
sortedRepos := sortShowOutputMapKey(trustShowOutputMap)
|
||||
for _, reponame := range sortedRepos {
|
||||
showOutput, exists := trustShowOutputMap[reponame]
|
||||
if exists {
|
||||
output = append(output, interface{}(showOutput))
|
||||
}
|
||||
}
|
||||
return output, nil
|
||||
}
|
|
@ -3,60 +3,62 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/storage"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
umountFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Umount all of the currently mounted containers",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Force the complete umount all of the currently mounted containers",
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
|
||||
description = `
|
||||
umountCommand cliconfig.UmountValues
|
||||
description = `
|
||||
Container storage increments a mount counter each time a container is mounted.
|
||||
When a container is unmounted, the mount counter is decremented and the
|
||||
container's root filesystem is physically unmounted only when the mount
|
||||
counter reaches zero indicating no other processes are using the mount.
|
||||
An unmount can be forced with the --force flag.
|
||||
`
|
||||
umountCommand = cli.Command{
|
||||
Name: "umount",
|
||||
Aliases: []string{"unmount"},
|
||||
Usage: "Unmount working container's root filesystem",
|
||||
Description: description,
|
||||
Flags: sortFlags(umountFlags),
|
||||
Action: umountCmd,
|
||||
ArgsUsage: "CONTAINER-NAME-OR-ID",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_umountCommand = &cobra.Command{
|
||||
Use: "umount",
|
||||
Aliases: []string{"unmount"},
|
||||
Short: "Unmounts working container's root filesystem",
|
||||
Long: description,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
umountCommand.InputArgs = args
|
||||
umountCommand.GlobalFlags = MainGlobalOpts
|
||||
return umountCmd(&umountCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME-OR-ID",
|
||||
}
|
||||
)
|
||||
|
||||
func umountCmd(c *cli.Context) error {
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
func init() {
|
||||
umountCommand.Command = _umountCommand
|
||||
flags := umountCommand.Flags()
|
||||
flags.BoolVarP(&umountCommand.All, "all", "a", false, "Umount all of the currently mounted containers")
|
||||
flags.BoolVarP(&umountCommand.Force, "force", "f", false, "Force the complete umount all of the currently mounted containers")
|
||||
flags.BoolVarP(&umountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
|
||||
rootCmd.AddCommand(umountCommand.Command)
|
||||
}
|
||||
|
||||
func umountCmd(c *cliconfig.UmountValues) error {
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
force := c.Bool("force")
|
||||
umountAll := c.Bool("all")
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
force := c.Force
|
||||
umountAll := c.All
|
||||
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
containers, err := getAllOrLatestContainers(c, runtime, -1, "all")
|
||||
containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
|
||||
if err != nil {
|
||||
if len(containers) == 0 {
|
||||
return err
|
||||
|
|
|
@ -3,38 +3,45 @@ package main
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
unpauseFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Unpause all paused containers",
|
||||
},
|
||||
}
|
||||
unpauseCommand cliconfig.UnpauseValues
|
||||
|
||||
unpauseDescription = `
|
||||
podman unpause
|
||||
|
||||
Unpauses one or more running containers. The container name or ID can be used.
|
||||
`
|
||||
unpauseCommand = cli.Command{
|
||||
Name: "unpause",
|
||||
Usage: "Unpause the processes in one or more containers",
|
||||
Description: unpauseDescription,
|
||||
Flags: unpauseFlags,
|
||||
Action: unpauseCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
_unpauseCommand = &cobra.Command{
|
||||
Use: "unpause",
|
||||
Short: "Unpause the processes in one or more containers",
|
||||
Long: unpauseDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
unpauseCommand.InputArgs = args
|
||||
unpauseCommand.GlobalFlags = MainGlobalOpts
|
||||
return unpauseCmd(&unpauseCommand)
|
||||
},
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func unpauseCmd(c *cli.Context) error {
|
||||
func init() {
|
||||
unpauseCommand.Command = _unpauseCommand
|
||||
flags := unpauseCommand.Flags()
|
||||
flags.BoolVarP(&unpauseCommand.All, "all", "a", false, "Unpause all paused containers")
|
||||
|
||||
rootCmd.AddCommand(unpauseCommand.Command)
|
||||
}
|
||||
|
||||
func unpauseCmd(c *cliconfig.UnpauseValues) error {
|
||||
var (
|
||||
unpauseContainers []*libpod.Container
|
||||
unpauseFuncs []shared.ParallelWorkerInput
|
||||
|
@ -43,18 +50,18 @@ func unpauseCmd(c *cli.Context) error {
|
|||
return errors.New("unpause is not supported for rootless containers")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
if len(args) < 1 && !c.Bool("all") {
|
||||
args := c.InputArgs
|
||||
if len(args) < 1 && !c.All {
|
||||
return errors.Errorf("you must provide at least one container name or id")
|
||||
}
|
||||
if c.Bool("all") {
|
||||
cs, err := getAllOrLatestContainers(c, runtime, libpod.ContainerStatePaused, "paused")
|
||||
if c.All {
|
||||
cs, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStatePaused, "paused")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -84,7 +91,7 @@ func unpauseCmd(c *cli.Context) error {
|
|||
|
||||
maxWorkers := shared.Parallelize("unpause")
|
||||
if c.GlobalIsSet("max-workers") {
|
||||
maxWorkers = c.GlobalInt("max-workers")
|
||||
maxWorkers = c.GlobalFlags.MaxWorks
|
||||
}
|
||||
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@ import (
|
|||
"os"
|
||||
gosignal "os/signal"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
|
@ -158,13 +158,10 @@ func (f *RawTtyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
|||
return bytes, err
|
||||
}
|
||||
|
||||
func checkMutuallyExclusiveFlags(c *cli.Context) error {
|
||||
func checkMutuallyExclusiveFlags(c *cliconfig.PodmanCommand) error {
|
||||
if err := checkAllAndLatest(c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateFlags(c, startFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -174,8 +171,8 @@ func checkMutuallyExclusiveFlags(c *cli.Context) error {
|
|||
// will hold all of the successful pods, and error will hold the last error.
|
||||
// The remaining errors will be logged. On success, pods will hold all pods and
|
||||
// error will be nil.
|
||||
func getPodsFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Pod, error) {
|
||||
args := c.Args()
|
||||
func getPodsFromContext(c *cliconfig.PodmanCommand, r *libpod.Runtime) ([]*libpod.Pod, error) {
|
||||
args := c.InputArgs
|
||||
var pods []*libpod.Pod
|
||||
var lastError error
|
||||
var err error
|
||||
|
@ -209,8 +206,8 @@ func getPodsFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Pod, error
|
|||
return pods, lastError
|
||||
}
|
||||
|
||||
func getVolumesFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Volume, error) {
|
||||
args := c.Args()
|
||||
func getVolumesFromContext(c *cliconfig.PodmanCommand, r *libpod.Runtime) ([]*libpod.Volume, error) {
|
||||
args := c.InputArgs
|
||||
var (
|
||||
vols []*libpod.Volume
|
||||
lastError error
|
||||
|
|
|
@ -5,55 +5,60 @@ package main
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
iopodman "github.com/containers/libpod/cmd/podman/varlink"
|
||||
"github.com/containers/libpod/pkg/varlinkapi"
|
||||
"github.com/containers/libpod/version"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/varlink/go/varlink"
|
||||
)
|
||||
|
||||
var (
|
||||
varlinkCommand cliconfig.VarlinkValues
|
||||
varlinkDescription = `
|
||||
podman varlink
|
||||
|
||||
run varlink interface
|
||||
`
|
||||
varlinkFlags = []cli.Flag{
|
||||
cli.IntFlag{
|
||||
Name: "timeout, t",
|
||||
Usage: "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout.",
|
||||
Value: 1000,
|
||||
_varlinkCommand = &cobra.Command{
|
||||
Use: "varlink",
|
||||
Short: "Run varlink interface",
|
||||
Long: varlinkDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
varlinkCommand.InputArgs = args
|
||||
varlinkCommand.GlobalFlags = MainGlobalOpts
|
||||
return varlinkCmd(&varlinkCommand)
|
||||
},
|
||||
}
|
||||
varlinkCommand = &cli.Command{
|
||||
Name: "varlink",
|
||||
Usage: "Run varlink interface",
|
||||
Description: varlinkDescription,
|
||||
Flags: sortFlags(varlinkFlags),
|
||||
Action: varlinkCmd,
|
||||
ArgsUsage: "VARLINK_URI",
|
||||
OnUsageError: usageErrorHandler,
|
||||
Example: "VARLINK_URI",
|
||||
}
|
||||
)
|
||||
|
||||
func varlinkCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
func init() {
|
||||
varlinkCommand.Command = _varlinkCommand
|
||||
flags := varlinkCommand.Flags()
|
||||
flags.Int64VarP(&varlinkCommand.Timeout, "timeout", "t", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout")
|
||||
|
||||
rootCmd.AddCommand(varlinkCommand.Command)
|
||||
}
|
||||
|
||||
func varlinkCmd(c *cliconfig.VarlinkValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) < 1 {
|
||||
return errors.Errorf("you must provide a varlink URI")
|
||||
}
|
||||
timeout := time.Duration(c.Int64("timeout")) * time.Millisecond
|
||||
timeout := time.Duration(c.Timeout) * time.Millisecond
|
||||
|
||||
// Create a single runtime for varlink
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(c, runtime)}
|
||||
var varlinkInterfaces = []*iopodman.VarlinkInterface{varlinkapi.New(&c.PodmanCommand, runtime)}
|
||||
// Register varlink service. The metadata can be retrieved with:
|
||||
// $ varlink info [varlink address URI]
|
||||
service, err := varlink.NewService(
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
)
|
||||
|
||||
var varlinkCommand *cli.Command
|
||||
var varlinkCommand *cliconfig.PodmanCommand
|
||||
|
|
|
@ -6,20 +6,41 @@ import (
|
|||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
versionCommand cliconfig.VersionValues
|
||||
_versionCommand = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Display the Podman Version Information",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
versionCommand.InputArgs = args
|
||||
versionCommand.GlobalFlags = MainGlobalOpts
|
||||
return versionCmd(&versionCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
versionCommand.Command = _versionCommand
|
||||
flags := versionCommand.Flags()
|
||||
flags.StringVarP(&versionCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
|
||||
rootCmd.AddCommand(versionCommand.Command)
|
||||
}
|
||||
|
||||
// versionCmd gets and prints version info for version command
|
||||
func versionCmd(c *cli.Context) error {
|
||||
func versionCmd(c *cliconfig.VersionValues) error {
|
||||
output, err := libpod.GetVersion()
|
||||
if err != nil {
|
||||
errors.Wrapf(err, "unable to determine version")
|
||||
}
|
||||
|
||||
versionOutputFormat := c.String("format")
|
||||
versionOutputFormat := c.Format
|
||||
if versionOutputFormat != "" {
|
||||
var out formats.Writer
|
||||
switch versionOutputFormat {
|
||||
|
@ -46,19 +67,3 @@ func versionCmd(c *cli.Context) error {
|
|||
fmt.Fprintf(w, "OS/Arch:\t%s\n", output.OsArch)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Cli command to print out the full version of podman
|
||||
var (
|
||||
versionCommand = cli.Command{
|
||||
Name: "version",
|
||||
Usage: "Display the Podman Version Information",
|
||||
Action: versionCmd,
|
||||
Flags: versionFlags,
|
||||
}
|
||||
versionFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "format, f",
|
||||
Usage: "Change the output format to JSON or a Go template",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,26 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
volumeDescription = `Manage volumes.
|
||||
var volumeDescription = `Manage volumes.
|
||||
|
||||
Volumes are created in and can be shared between containers.`
|
||||
|
||||
volumeSubCommands = []cli.Command{
|
||||
volumeCreateCommand,
|
||||
volumeLsCommand,
|
||||
volumeRmCommand,
|
||||
volumeInspectCommand,
|
||||
volumePruneCommand,
|
||||
}
|
||||
volumeCommand = cli.Command{
|
||||
Name: "volume",
|
||||
Usage: "Manage volumes",
|
||||
Description: volumeDescription,
|
||||
UseShortOptionHandling: true,
|
||||
Subcommands: volumeSubCommands,
|
||||
}
|
||||
)
|
||||
var volumeCommand = cliconfig.PodmanCommand{
|
||||
Command: &cobra.Command{
|
||||
Use: "volume",
|
||||
Short: "Manage volumes",
|
||||
Long: volumeDescription,
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
volumeCommand.AddCommand(getVolumeSubCommands()...)
|
||||
rootCmd.AddCommand(volumeCommand.Command)
|
||||
}
|
||||
|
|
|
@ -3,75 +3,70 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var volumeCreateDescription = `
|
||||
var (
|
||||
volumeCreateCommand cliconfig.VolumeCreateValues
|
||||
volumeCreateDescription = `
|
||||
podman volume create
|
||||
|
||||
Creates a new volume. If using the default driver, "local", the volume will
|
||||
be created at.`
|
||||
|
||||
var volumeCreateFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "driver",
|
||||
Usage: "Specify volume driver name (default local)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label, l",
|
||||
Usage: "Set metadata for a volume (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "opt, o",
|
||||
Usage: "Set driver specific options (default [])",
|
||||
},
|
||||
_volumeCreateCommand = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a new volume",
|
||||
Long: volumeCreateDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
volumeCreateCommand.InputArgs = args
|
||||
volumeCreateCommand.GlobalFlags = MainGlobalOpts
|
||||
return volumeCreateCmd(&volumeCreateCommand)
|
||||
},
|
||||
Example: "[VOLUME-NAME]",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
volumeCreateCommand.Command = _volumeCreateCommand
|
||||
flags := volumeCreateCommand.Flags()
|
||||
flags.StringVar(&volumeCreateCommand.Driver, "driver", "", "Specify volume driver name (default local)")
|
||||
flags.StringSliceVarP(&volumeCreateCommand.Label, "label", "l", []string{}, "Set metadata for a volume (default [])")
|
||||
flags.StringSliceVarP(&volumeCreateCommand.Opt, "opt", "o", []string{}, "Set driver specific options (default [])")
|
||||
|
||||
}
|
||||
|
||||
var volumeCreateCommand = cli.Command{
|
||||
Name: "create",
|
||||
Usage: "Create a new volume",
|
||||
Description: volumeCreateDescription,
|
||||
Flags: volumeCreateFlags,
|
||||
Action: volumeCreateCmd,
|
||||
SkipArgReorder: true,
|
||||
ArgsUsage: "[VOLUME-NAME]",
|
||||
UseShortOptionHandling: true,
|
||||
}
|
||||
|
||||
func volumeCreateCmd(c *cli.Context) error {
|
||||
func volumeCreateCmd(c *cliconfig.VolumeCreateValues) error {
|
||||
var (
|
||||
options []libpod.VolumeCreateOption
|
||||
err error
|
||||
volName string
|
||||
)
|
||||
|
||||
if err = validateFlags(c, volumeCreateFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if len(c.Args()) > 1 {
|
||||
if len(c.InputArgs) > 1 {
|
||||
return errors.Errorf("too many arguments, create takes at most 1 argument")
|
||||
}
|
||||
|
||||
if len(c.Args()) > 0 {
|
||||
volName = c.Args()[0]
|
||||
if len(c.InputArgs) > 0 {
|
||||
volName = c.InputArgs[0]
|
||||
options = append(options, libpod.WithVolumeName(volName))
|
||||
}
|
||||
|
||||
if c.IsSet("driver") {
|
||||
if c.Flag("driver").Changed {
|
||||
options = append(options, libpod.WithVolumeDriver(c.String("driver")))
|
||||
}
|
||||
|
||||
labels, err := getAllLabels([]string{}, c.StringSlice("label"))
|
||||
labels, err := getAllLabels([]string{}, c.Label)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to process labels")
|
||||
}
|
||||
|
@ -79,7 +74,7 @@ func volumeCreateCmd(c *cli.Context) error {
|
|||
options = append(options, libpod.WithVolumeLabels(labels))
|
||||
}
|
||||
|
||||
opts, err := getAllLabels([]string{}, c.StringSlice("opt"))
|
||||
opts, err := getAllLabels([]string{}, c.Opt)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to process options")
|
||||
}
|
||||
|
|
|
@ -1,60 +1,56 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var volumeInspectDescription = `
|
||||
var (
|
||||
volumeInspectCommand cliconfig.VolumeInspectValues
|
||||
volumeInspectDescription = `
|
||||
podman volume inspect
|
||||
|
||||
Display detailed information on one or more volumes. Can change the format
|
||||
from JSON to a Go template.
|
||||
`
|
||||
_volumeInspectCommand = &cobra.Command{
|
||||
Use: "inspect",
|
||||
Short: "Display detailed information on one or more volumes",
|
||||
Long: volumeInspectDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
volumeInspectCommand.InputArgs = args
|
||||
volumeInspectCommand.GlobalFlags = MainGlobalOpts
|
||||
return volumeInspectCmd(&volumeInspectCommand)
|
||||
},
|
||||
Example: "[VOLUME-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
volumeInspectCommand.Command = _volumeInspectCommand
|
||||
flags := volumeInspectCommand.Flags()
|
||||
flags.BoolVarP(&volumeInspectCommand.All, "all", "a", false, "Inspect all volumes")
|
||||
flags.StringVarP(&volumeInspectCommand.Format, "format", "f", "json", "Format volume output using Go template")
|
||||
|
||||
var volumeInspectFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Inspect all volumes",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format, f",
|
||||
Usage: "Format volume output using Go template",
|
||||
Value: "json",
|
||||
},
|
||||
}
|
||||
|
||||
var volumeInspectCommand = cli.Command{
|
||||
Name: "inspect",
|
||||
Usage: "Display detailed information on one or more volumes",
|
||||
Description: volumeInspectDescription,
|
||||
Flags: volumeInspectFlags,
|
||||
Action: volumeInspectCmd,
|
||||
SkipArgReorder: true,
|
||||
ArgsUsage: "[VOLUME-NAME ...]",
|
||||
UseShortOptionHandling: true,
|
||||
}
|
||||
|
||||
func volumeInspectCmd(c *cli.Context) error {
|
||||
func volumeInspectCmd(c *cliconfig.VolumeInspectValues) error {
|
||||
var err error
|
||||
|
||||
if err = validateFlags(c, volumeInspectFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
opts := volumeLsOptions{
|
||||
Format: c.String("format"),
|
||||
Format: c.Format,
|
||||
}
|
||||
|
||||
vols, lastError := getVolumesFromContext(c, runtime)
|
||||
vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
|
||||
if lastError != nil {
|
||||
logrus.Errorf("%q", lastError)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,12 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// volumeOptions is the "ls" command options
|
||||
|
@ -37,64 +38,57 @@ type volumeLsJSONParams struct {
|
|||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
var volumeLsDescription = `
|
||||
var (
|
||||
volumeLsCommand cliconfig.VolumeLsValues
|
||||
|
||||
volumeLsDescription = `
|
||||
podman volume ls
|
||||
|
||||
List all available volumes. The output of the volumes can be filtered
|
||||
and the output format can be changed to JSON or a user specified Go template.
|
||||
`
|
||||
|
||||
var volumeLsFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "filter, f",
|
||||
Usage: "Filter volume output",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "format",
|
||||
Usage: "Format volume output using Go template",
|
||||
Value: "table {{.Driver}}\t{{.Name}}",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Print volume output in quiet mode",
|
||||
},
|
||||
}
|
||||
|
||||
var volumeLsCommand = cli.Command{
|
||||
Name: "ls",
|
||||
Aliases: []string{"list"},
|
||||
Usage: "List volumes",
|
||||
Description: volumeLsDescription,
|
||||
Flags: volumeLsFlags,
|
||||
Action: volumeLsCmd,
|
||||
SkipArgReorder: true,
|
||||
UseShortOptionHandling: true,
|
||||
}
|
||||
|
||||
func volumeLsCmd(c *cli.Context) error {
|
||||
if err := validateFlags(c, volumeLsFlags); err != nil {
|
||||
return err
|
||||
_volumeLsCommand = &cobra.Command{
|
||||
Use: "ls",
|
||||
Aliases: []string{"list"},
|
||||
Short: "List volumes",
|
||||
Long: volumeLsDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
volumeLsCommand.InputArgs = args
|
||||
volumeLsCommand.GlobalFlags = MainGlobalOpts
|
||||
return volumeLsCmd(&volumeLsCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
func init() {
|
||||
volumeLsCommand.Command = _volumeLsCommand
|
||||
flags := volumeLsCommand.Flags()
|
||||
|
||||
flags.StringVarP(&volumeLsCommand.Filter, "filter", "f", "", "Filter volume output")
|
||||
flags.StringVar(&volumeLsCommand.Format, "format", "table {{.Driver}}\t{{.Name}}", "Format volume output using Go template")
|
||||
flags.BoolVarP(&volumeLsCommand.Quiet, "quiet", "q", false, "Print volume output in quiet mode")
|
||||
}
|
||||
|
||||
func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if len(c.Args()) > 0 {
|
||||
if len(c.InputArgs) > 0 {
|
||||
return errors.Errorf("too many arguments, ls takes no arguments")
|
||||
}
|
||||
|
||||
opts := volumeLsOptions{
|
||||
Quiet: c.Bool("quiet"),
|
||||
Quiet: c.Quiet,
|
||||
}
|
||||
opts.Format = genVolLsFormat(c)
|
||||
|
||||
// Get the filter functions based on any filters set
|
||||
var filterFuncs []libpod.VolumeFilter
|
||||
if c.String("filter") != "" {
|
||||
filters := strings.Split(c.String("filter"), ",")
|
||||
if c.Filter != "" {
|
||||
filters := strings.Split(c.Filter, ",")
|
||||
for _, f := range filters {
|
||||
filterSplit := strings.Split(f, "=")
|
||||
if len(filterSplit) < 2 {
|
||||
|
@ -129,14 +123,14 @@ func volumeLsCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// generate the template based on conditions given
|
||||
func genVolLsFormat(c *cli.Context) string {
|
||||
func genVolLsFormat(c *cliconfig.VolumeLsValues) string {
|
||||
var format string
|
||||
if c.String("format") != "" {
|
||||
if c.Format != "" {
|
||||
// "\t" from the command line is not being recognized as a tab
|
||||
// replacing the string "\t" to a tab character if the user passes in "\t"
|
||||
format = strings.Replace(c.String("format"), `\t`, "\t", -1)
|
||||
format = strings.Replace(c.Format, `\t`, "\t", -1)
|
||||
}
|
||||
if c.Bool("quiet") {
|
||||
if c.Quiet {
|
||||
format = "{{.Name}}"
|
||||
}
|
||||
return format
|
||||
|
|
|
@ -7,35 +7,39 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var volumePruneDescription = `
|
||||
var (
|
||||
volumePruneCommand cliconfig.VolumePruneValues
|
||||
volumePruneDescription = `
|
||||
podman volume prune
|
||||
|
||||
Remove all unused volumes. Will prompt for confirmation if not
|
||||
using force.
|
||||
`
|
||||
_volumePruneCommand = &cobra.Command{
|
||||
Use: "prune",
|
||||
Short: "Remove all unused volumes",
|
||||
Long: volumePruneDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
volumePruneCommand.InputArgs = args
|
||||
volumePruneCommand.GlobalFlags = MainGlobalOpts
|
||||
return volumePruneCmd(&volumePruneCommand)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var volumePruneFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Do not prompt for confirmation",
|
||||
},
|
||||
}
|
||||
func init() {
|
||||
volumePruneCommand.Command = _volumePruneCommand
|
||||
flags := volumePruneCommand.Flags()
|
||||
|
||||
var volumePruneCommand = cli.Command{
|
||||
Name: "prune",
|
||||
Usage: "Remove all unused volumes",
|
||||
Description: volumePruneDescription,
|
||||
Flags: volumePruneFlags,
|
||||
Action: volumePruneCmd,
|
||||
SkipArgReorder: true,
|
||||
UseShortOptionHandling: true,
|
||||
flags.BoolVarP(&volumePruneCommand.Force, "force", "f", false, "Do not prompt for confirmation")
|
||||
}
|
||||
|
||||
func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error {
|
||||
|
@ -60,20 +64,15 @@ func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error {
|
|||
return lastError
|
||||
}
|
||||
|
||||
func volumePruneCmd(c *cli.Context) error {
|
||||
|
||||
if err := validateFlags(c, volumePruneFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := adapter.GetRuntime(c)
|
||||
func volumePruneCmd(c *cliconfig.VolumePruneValues) error {
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
// Prompt for confirmation if --force is not set
|
||||
if !c.Bool("force") {
|
||||
if !c.Force {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Println("WARNING! This will remove all volumes not used by at least one container.")
|
||||
fmt.Print("Are you sure you want to continue? [y/N] ")
|
||||
|
|
|
@ -3,51 +3,47 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var volumeRmDescription = `
|
||||
var (
|
||||
volumeRmCommand cliconfig.VolumeRmValues
|
||||
volumeRmDescription = `
|
||||
podman volume rm
|
||||
|
||||
Remove one or more existing volumes. Will only remove volumes that are
|
||||
not being used by any containers. To remove the volumes anyways, use the
|
||||
--force flag.
|
||||
`
|
||||
_volumeRmCommand = &cobra.Command{
|
||||
Use: "rm",
|
||||
Aliases: []string{"remove"},
|
||||
Short: "Remove one or more volumes",
|
||||
Long: volumeRmDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
volumeRmCommand.InputArgs = args
|
||||
volumeRmCommand.GlobalFlags = MainGlobalOpts
|
||||
return volumeRmCmd(&volumeRmCommand)
|
||||
},
|
||||
Example: "[VOLUME-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
var volumeRmFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all, a",
|
||||
Usage: "Remove all volumes",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "force, f",
|
||||
Usage: "Remove a volume by force, even if it is being used by a container",
|
||||
},
|
||||
func init() {
|
||||
volumeRmCommand.Command = _volumeRmCommand
|
||||
flags := volumeRmCommand.Flags()
|
||||
flags.BoolVarP(&volumeRmCommand.All, "all", "a", false, "Remove all volumes")
|
||||
flags.BoolVarP(&volumeRmCommand.Force, "force", "f", false, "Remove a volume by force, even if it is being used by a container")
|
||||
}
|
||||
|
||||
var volumeRmCommand = cli.Command{
|
||||
Name: "rm",
|
||||
Aliases: []string{"remove"},
|
||||
Usage: "Remove one or more volumes",
|
||||
Description: volumeRmDescription,
|
||||
Flags: volumeRmFlags,
|
||||
Action: volumeRmCmd,
|
||||
ArgsUsage: "[VOLUME-NAME ...]",
|
||||
SkipArgReorder: true,
|
||||
UseShortOptionHandling: true,
|
||||
}
|
||||
|
||||
func volumeRmCmd(c *cli.Context) error {
|
||||
func volumeRmCmd(c *cliconfig.VolumeRmValues) error {
|
||||
var err error
|
||||
|
||||
if err = validateFlags(c, volumeRmFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
@ -55,9 +51,9 @@ func volumeRmCmd(c *cli.Context) error {
|
|||
|
||||
ctx := getContext()
|
||||
|
||||
vols, lastError := getVolumesFromContext(c, runtime)
|
||||
vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
|
||||
for _, vol := range vols {
|
||||
err = runtime.RemoveVolume(ctx, vol, c.Bool("force"), false)
|
||||
err = runtime.RemoveVolume(ctx, vol, c.Force, false)
|
||||
if err != nil {
|
||||
if lastError != nil {
|
||||
logrus.Errorf("%q", lastError)
|
||||
|
|
|
@ -5,43 +5,49 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
waitCommand cliconfig.WaitValues
|
||||
|
||||
waitDescription = `
|
||||
podman wait
|
||||
|
||||
Block until one or more containers stop and then print their exit codes
|
||||
`
|
||||
waitFlags = []cli.Flag{
|
||||
cli.UintFlag{
|
||||
Name: "interval, i",
|
||||
Usage: "Milliseconds to wait before polling for completion",
|
||||
Value: 250,
|
||||
_waitCommand = &cobra.Command{
|
||||
Use: "wait",
|
||||
Short: "Block on one or more containers",
|
||||
Long: waitDescription,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
waitCommand.InputArgs = args
|
||||
waitCommand.GlobalFlags = MainGlobalOpts
|
||||
return waitCmd(&waitCommand)
|
||||
},
|
||||
LatestFlag,
|
||||
}
|
||||
waitCommand = cli.Command{
|
||||
Name: "wait",
|
||||
Usage: "Block on one or more containers",
|
||||
Description: waitDescription,
|
||||
Flags: sortFlags(waitFlags),
|
||||
Action: waitCmd,
|
||||
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
OnUsageError: usageErrorHandler,
|
||||
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
|
||||
}
|
||||
)
|
||||
|
||||
func waitCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if len(args) < 1 && !c.Bool("latest") {
|
||||
func init() {
|
||||
waitCommand.Command = _waitCommand
|
||||
flags := waitCommand.Flags()
|
||||
flags.UintVarP(&waitCommand.Interval, "interval", "i", 250, "Milliseconds to wait before polling for completion")
|
||||
flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
|
||||
rootCmd.AddCommand(waitCommand.Command)
|
||||
}
|
||||
|
||||
func waitCmd(c *cliconfig.WaitValues) error {
|
||||
args := c.InputArgs
|
||||
if len(args) < 1 && !c.Latest {
|
||||
return errors.Errorf("you must provide at least one container name or id")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
@ -52,7 +58,7 @@ func waitCmd(c *cli.Context) error {
|
|||
}
|
||||
|
||||
var lastError error
|
||||
if c.Bool("latest") {
|
||||
if c.Latest {
|
||||
latestCtr, err := runtime.GetLatestContainer()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to wait on latest container")
|
||||
|
@ -65,10 +71,10 @@ func waitCmd(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to find container %s", container)
|
||||
}
|
||||
if c.Uint("interval") == 0 {
|
||||
if c.Interval == 0 {
|
||||
return errors.Errorf("interval must be greater then 0")
|
||||
}
|
||||
returnCode, err := ctr.WaitWithInterval(time.Duration(c.Uint("interval")) * time.Millisecond)
|
||||
returnCode, err := ctr.WaitWithInterval(time.Duration(c.Interval) * time.Millisecond)
|
||||
if err != nil {
|
||||
if lastError != nil {
|
||||
fmt.Fprintln(os.Stderr, lastError)
|
||||
|
|
|
@ -11,11 +11,11 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// LocalRuntime describes a typical libpod runtime
|
||||
|
@ -35,7 +35,7 @@ type Container struct {
|
|||
}
|
||||
|
||||
// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it
|
||||
func GetRuntime(c *cli.Context) (*LocalRuntime, error) {
|
||||
func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) {
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -14,12 +14,12 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/varlink"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/varlink/go/varlink"
|
||||
)
|
||||
|
||||
|
@ -38,7 +38,7 @@ type LocalRuntime struct {
|
|||
}
|
||||
|
||||
// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it
|
||||
func GetRuntime(c *cli.Context) (*LocalRuntime, error) {
|
||||
func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) {
|
||||
runtime := RemoteRuntime{}
|
||||
conn, err := runtime.Connect()
|
||||
if err != nil {
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
package varlinkapi
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
iopodman "github.com/containers/libpod/cmd/podman/varlink"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// LibpodAPI is the basic varlink struct for libpod
|
||||
type LibpodAPI struct {
|
||||
Cli *cli.Context
|
||||
Cli *cobra.Command
|
||||
iopodman.VarlinkInterface
|
||||
Runtime *libpod.Runtime
|
||||
}
|
||||
|
||||
// New creates a new varlink client
|
||||
func New(cli *cli.Context, runtime *libpod.Runtime) *iopodman.VarlinkInterface {
|
||||
lp := LibpodAPI{Cli: cli, Runtime: runtime}
|
||||
func New(cli *cliconfig.PodmanCommand, runtime *libpod.Runtime) *iopodman.VarlinkInterface {
|
||||
lp := LibpodAPI{Cli: cli.Command, Runtime: runtime}
|
||||
return iopodman.VarlinkNew(&lp)
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ var _ = Describe("Podman restart", func() {
|
|||
startTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1", "test2"})
|
||||
startTime.WaitWithDefaultTimeout()
|
||||
|
||||
session := podmanTest.Podman([]string{"restart", "-all"})
|
||||
session := podmanTest.Podman([]string{"restart", "--all"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
restartTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1", "test2"})
|
||||
|
|
10
vendor.conf
10
vendor.conf
|
@ -15,8 +15,8 @@ github.com/containerd/cgroups 39b18af02c4120960f517a3a4c2588fabb61d02c
|
|||
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
|
||||
github.com/containernetworking/cni v0.7.0-alpha1
|
||||
github.com/containernetworking/plugins v0.7.4
|
||||
github.com/containers/image 67b1f789f2ce8a3654592a582fff26c396326236
|
||||
github.com/containers/storage v1.8
|
||||
github.com/containers/image v1.3
|
||||
github.com/containers/storage v1.9
|
||||
github.com/containers/psgo v1.1
|
||||
github.com/coreos/go-systemd v14
|
||||
github.com/cri-o/ocicni 2d2983e40c242322a56c22a903785e7f83eb378c
|
||||
|
@ -91,7 +91,7 @@ k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apim
|
|||
k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go
|
||||
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
|
||||
github.com/varlink/go 3ac79db6fd6aec70924193b090962f92985fe199
|
||||
github.com/containers/buildah e7ca330f923701dba8859f5c014d0a9a3f7f0a49
|
||||
github.com/containers/buildah 973bb88ef1861a5b782c722c471dd79b6732852c
|
||||
# TODO: Gotty has not been updated since 2012. Can we find replacement?
|
||||
github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512
|
||||
# do not go beyond the below commit as the next one requires a more recent
|
||||
|
@ -108,5 +108,7 @@ github.com/klauspost/cpuid v1.2.0
|
|||
github.com/onsi/ginkgo v1.7.0
|
||||
github.com/onsi/gomega v1.4.3
|
||||
github.com/hpcloud/tail v1.0.0
|
||||
gopkg.in/fsnotify.v1 v1.4.2
|
||||
gopkg.in/tomb.v1 v1
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/inconshreveable/mousetrap v1.0.0
|
||||
gopkg.in/fsnotify.v1 v1.4.7
|
||||
|
|
26
vendor/github.com/containers/buildah/buildah.go
generated
vendored
26
vendor/github.com/containers/buildah/buildah.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containers/buildah/docker"
|
||||
"github.com/containers/buildah/util"
|
||||
|
@ -25,7 +26,7 @@ const (
|
|||
Package = "buildah"
|
||||
// Version for the Package. Bump version in contrib/rpm/buildah.spec
|
||||
// too.
|
||||
Version = "1.6-dev"
|
||||
Version = "1.7-dev"
|
||||
// The value we use to identify what type of information, currently a
|
||||
// serialized Builder structure, we are using as per-container state.
|
||||
// This should only be changed when we make incompatible changes to
|
||||
|
@ -175,6 +176,15 @@ type Builder struct {
|
|||
// after processing the AddCapabilities set, when running commands in the container.
|
||||
// If a capability appears in both lists, it will be dropped.
|
||||
DropCapabilities []string
|
||||
// PrependedEmptyLayers are history entries that we'll add to a
|
||||
// committed image, after any history items that we inherit from a base
|
||||
// image, but before the history item for the layer that we're
|
||||
// committing.
|
||||
PrependedEmptyLayers []v1.History
|
||||
// AppendedEmptyLayers are history entries that we'll add to a
|
||||
// committed image after the history item for the layer that we're
|
||||
// committing.
|
||||
AppendedEmptyLayers []v1.History
|
||||
|
||||
CommonBuildOpts *CommonBuildOptions
|
||||
// TopLayer is the top layer of the image
|
||||
|
@ -209,11 +219,24 @@ type BuilderInfo struct {
|
|||
DefaultCapabilities []string
|
||||
AddCapabilities []string
|
||||
DropCapabilities []string
|
||||
History []v1.History
|
||||
}
|
||||
|
||||
// GetBuildInfo gets a pointer to a Builder object and returns a BuilderInfo object from it.
|
||||
// This is used in the inspect command to display Manifest and Config as string and not []byte.
|
||||
func GetBuildInfo(b *Builder) BuilderInfo {
|
||||
history := copyHistory(b.OCIv1.History)
|
||||
history = append(history, copyHistory(b.PrependedEmptyLayers)...)
|
||||
now := time.Now().UTC()
|
||||
created := &now
|
||||
history = append(history, v1.History{
|
||||
Created: created,
|
||||
CreatedBy: b.ImageCreatedBy,
|
||||
Author: b.Maintainer(),
|
||||
Comment: b.ImageHistoryComment,
|
||||
EmptyLayer: false,
|
||||
})
|
||||
history = append(history, copyHistory(b.AppendedEmptyLayers)...)
|
||||
return BuilderInfo{
|
||||
Type: b.Type,
|
||||
FromImage: b.FromImage,
|
||||
|
@ -239,6 +262,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
|
|||
DefaultCapabilities: append([]string{}, util.DefaultCapabilities...),
|
||||
AddCapabilities: append([]string{}, b.AddCapabilities...),
|
||||
DropCapabilities: append([]string{}, b.DropCapabilities...),
|
||||
History: history,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
23
vendor/github.com/containers/buildah/chroot/run.go
generated
vendored
23
vendor/github.com/containers/buildah/chroot/run.go
generated
vendored
|
@ -351,21 +351,6 @@ func runUsingChrootMain() {
|
|||
defer stdoutRead.Close()
|
||||
defer stderrRead.Close()
|
||||
}
|
||||
// A helper that returns false if err is an error that would cause us
|
||||
// to give up.
|
||||
logIfNotRetryable := func(err error, what string) (retry bool) {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
if errno, isErrno := err.(syscall.Errno); isErrno {
|
||||
switch errno {
|
||||
case syscall.EINTR, syscall.EAGAIN:
|
||||
return true
|
||||
}
|
||||
}
|
||||
logrus.Error(what)
|
||||
return false
|
||||
}
|
||||
for readFd, writeFd := range relays {
|
||||
if err := unix.SetNonblock(readFd, true); err != nil {
|
||||
logrus.Errorf("error setting descriptor %d (%s) non-blocking: %v", readFd, fdDesc[readFd], err)
|
||||
|
@ -388,7 +373,7 @@ func runUsingChrootMain() {
|
|||
fds = append(fds, unix.PollFd{Fd: int32(fd), Events: unix.POLLIN | unix.POLLHUP})
|
||||
}
|
||||
_, err := unix.Poll(fds, pollTimeout)
|
||||
if !logIfNotRetryable(err, fmt.Sprintf("poll: %v", err)) {
|
||||
if !util.LogIfNotRetryable(err, fmt.Sprintf("poll: %v", err)) {
|
||||
return
|
||||
}
|
||||
removeFds := make(map[int]struct{})
|
||||
|
@ -405,7 +390,7 @@ func runUsingChrootMain() {
|
|||
}
|
||||
b := make([]byte, 8192)
|
||||
nread, err := unix.Read(int(rfd.Fd), b)
|
||||
logIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
|
||||
util.LogIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
|
||||
if nread > 0 {
|
||||
if wfd, ok := relays[int(rfd.Fd)]; ok {
|
||||
nwritten, err := buffers[wfd].Write(b[:nread])
|
||||
|
@ -422,7 +407,7 @@ func runUsingChrootMain() {
|
|||
// from this descriptor, read as much as there is to read.
|
||||
for rfd.Revents&unix.POLLHUP == unix.POLLHUP {
|
||||
nr, err := unix.Read(int(rfd.Fd), b)
|
||||
logIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
|
||||
util.LogIfUnexpectedWhileDraining(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
|
||||
if nr <= 0 {
|
||||
break
|
||||
}
|
||||
|
@ -447,7 +432,7 @@ func runUsingChrootMain() {
|
|||
for wfd, buffer := range buffers {
|
||||
if buffer.Len() > 0 {
|
||||
nwritten, err := unix.Write(wfd, buffer.Bytes())
|
||||
logIfNotRetryable(err, fmt.Sprintf("write %s: %v", fdDesc[wfd], err))
|
||||
util.LogIfNotRetryable(err, fmt.Sprintf("write %s: %v", fdDesc[wfd], err))
|
||||
if nwritten >= 0 {
|
||||
_ = buffer.Next(nwritten)
|
||||
}
|
||||
|
|
13
vendor/github.com/containers/buildah/commit.go
generated
vendored
13
vendor/github.com/containers/buildah/commit.go
generated
vendored
|
@ -67,6 +67,10 @@ type CommitOptions struct {
|
|||
OnBuild []string
|
||||
// Parent is the base image that this image was created by.
|
||||
Parent string
|
||||
|
||||
// OmitTimestamp forces epoch 0 as created timestamp to allow for
|
||||
// deterministic, content-addressable builds.
|
||||
OmitTimestamp bool
|
||||
}
|
||||
|
||||
// PushOptions can be used to alter how an image is copied somewhere.
|
||||
|
@ -97,6 +101,10 @@ type PushOptions struct {
|
|||
// regenerate from on-disk layers, substituting them in the list of
|
||||
// blobs to copy whenever possible.
|
||||
BlobDirectory string
|
||||
// Quiet is a boolean value that determines if minimal output to
|
||||
// the user will be displayed, this is best used for logging.
|
||||
// The default is false.
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
// Commit writes the contents of the container, along with its updated
|
||||
|
@ -140,7 +148,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
|||
}
|
||||
}
|
||||
}
|
||||
src, err := b.makeImageRef(options.PreferredManifestType, options.Parent, exportBaseLayers, options.Squash, options.BlobDirectory, options.Compression, options.HistoryTimestamp)
|
||||
src, err := b.makeImageRef(options.PreferredManifestType, options.Parent, exportBaseLayers, options.Squash, options.BlobDirectory, options.Compression, options.HistoryTimestamp, options.OmitTimestamp)
|
||||
if err != nil {
|
||||
return imgID, nil, "", errors.Wrapf(err, "error computing layer digests and building metadata for container %q", b.ContainerID)
|
||||
}
|
||||
|
@ -224,6 +232,9 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
|||
func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) (reference.Canonical, digest.Digest, error) {
|
||||
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
|
||||
|
||||
if options.Quiet {
|
||||
options.ReportWriter = nil // Turns off logging output
|
||||
}
|
||||
blocked, err := isReferenceBlocked(dest, systemContext)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "error checking if pushing to registry for %q is blocked", transports.ImageName(dest))
|
||||
|
|
47
vendor/github.com/containers/buildah/config.go
generated
vendored
47
vendor/github.com/containers/buildah/config.go
generated
vendored
|
@ -574,3 +574,50 @@ func (b *Builder) SetHealthcheck(config *docker.HealthConfig) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddPrependedEmptyLayer adds an item to the history that we'll create when
|
||||
// commiting the image, after any history we inherit from the base image, but
|
||||
// before the history item that we'll use to describe the new layer that we're
|
||||
// adding.
|
||||
func (b *Builder) AddPrependedEmptyLayer(created *time.Time, createdBy, author, comment string) {
|
||||
if created != nil {
|
||||
copiedTimestamp := *created
|
||||
created = &copiedTimestamp
|
||||
}
|
||||
b.PrependedEmptyLayers = append(b.PrependedEmptyLayers, ociv1.History{
|
||||
Created: created,
|
||||
CreatedBy: createdBy,
|
||||
Author: author,
|
||||
Comment: comment,
|
||||
EmptyLayer: true,
|
||||
})
|
||||
}
|
||||
|
||||
// ClearPrependedEmptyLayers clears the list of history entries that we'll add
|
||||
// to the committed image before the entry for the layer that we're adding.
|
||||
func (b *Builder) ClearPrependedEmptyLayers() {
|
||||
b.PrependedEmptyLayers = nil
|
||||
}
|
||||
|
||||
// AddAppendedEmptyLayer adds an item to the history that we'll create when
|
||||
// commiting the image, after the history item that we'll use to describe the
|
||||
// new layer that we're adding.
|
||||
func (b *Builder) AddAppendedEmptyLayer(created *time.Time, createdBy, author, comment string) {
|
||||
if created != nil {
|
||||
copiedTimestamp := *created
|
||||
created = &copiedTimestamp
|
||||
}
|
||||
b.AppendedEmptyLayers = append(b.AppendedEmptyLayers, ociv1.History{
|
||||
Created: created,
|
||||
CreatedBy: createdBy,
|
||||
Author: author,
|
||||
Comment: comment,
|
||||
EmptyLayer: true,
|
||||
})
|
||||
}
|
||||
|
||||
// ClearAppendedEmptyLayers clears the list of history entries that we'll add
|
||||
// to the committed image after the entry for the layer that we're adding.
|
||||
func (b *Builder) ClearAppendedEmptyLayers() {
|
||||
b.AppendedEmptyLayers = nil
|
||||
}
|
||||
|
|
18
vendor/github.com/containers/buildah/docker/types.go
generated
vendored
18
vendor/github.com/containers/buildah/docker/types.go
generated
vendored
|
@ -18,7 +18,7 @@ const TypeLayers = "layers"
|
|||
const V2S2MediaTypeUncompressedLayer = "application/vnd.docker.image.rootfs.diff.tar"
|
||||
|
||||
// github.com/moby/moby/image/rootfs.go
|
||||
// RootFS describes images root filesystem
|
||||
// V2S2RootFS describes images root filesystem
|
||||
// This is currently a placeholder that only supports layers. In the future
|
||||
// this can be made into an interface that supports different implementations.
|
||||
type V2S2RootFS struct {
|
||||
|
@ -27,7 +27,7 @@ type V2S2RootFS struct {
|
|||
}
|
||||
|
||||
// github.com/moby/moby/image/image.go
|
||||
// History stores build commands that were used to create an image
|
||||
// V2S2History stores build commands that were used to create an image
|
||||
type V2S2History struct {
|
||||
// Created is the timestamp at which the image was created
|
||||
Created time.Time `json:"created"`
|
||||
|
@ -158,7 +158,7 @@ type V1Image struct {
|
|||
}
|
||||
|
||||
// github.com/moby/moby/image/image.go
|
||||
// Image stores the image configuration
|
||||
// V2Image stores the image configuration
|
||||
type V2Image struct {
|
||||
V1Image
|
||||
Parent ID `json:"parent,omitempty"`
|
||||
|
@ -176,7 +176,7 @@ type V2Image struct {
|
|||
}
|
||||
|
||||
// github.com/docker/distribution/manifest/versioned.go
|
||||
// Versioned provides a struct with the manifest schemaVersion and mediaType.
|
||||
// V2Versioned provides a struct with the manifest schemaVersion and mediaType.
|
||||
// Incoming content with unknown schema version can be decoded against this
|
||||
// struct to check the version.
|
||||
type V2Versioned struct {
|
||||
|
@ -188,21 +188,21 @@ type V2Versioned struct {
|
|||
}
|
||||
|
||||
// github.com/docker/distribution/manifest/schema1/manifest.go
|
||||
// FSLayer is a container struct for BlobSums defined in an image manifest
|
||||
// V2S1FSLayer is a container struct for BlobSums defined in an image manifest
|
||||
type V2S1FSLayer struct {
|
||||
// BlobSum is the tarsum of the referenced filesystem image layer
|
||||
BlobSum digest.Digest `json:"blobSum"`
|
||||
}
|
||||
|
||||
// github.com/docker/distribution/manifest/schema1/manifest.go
|
||||
// History stores unstructured v1 compatibility information
|
||||
// V2S1History stores unstructured v1 compatibility information
|
||||
type V2S1History struct {
|
||||
// V1Compatibility is the raw v1 compatibility information
|
||||
V1Compatibility string `json:"v1Compatibility"`
|
||||
}
|
||||
|
||||
// github.com/docker/distribution/manifest/schema1/manifest.go
|
||||
// Manifest provides the base accessible fields for working with V2 image
|
||||
// V2S1Manifest provides the base accessible fields for working with V2 image
|
||||
// format in the registry.
|
||||
type V2S1Manifest struct {
|
||||
V2Versioned
|
||||
|
@ -225,7 +225,7 @@ type V2S1Manifest struct {
|
|||
}
|
||||
|
||||
// github.com/docker/distribution/blobs.go
|
||||
// Descriptor describes targeted content. Used in conjunction with a blob
|
||||
// V2S2Descriptor describes targeted content. Used in conjunction with a blob
|
||||
// store, a descriptor can be used to fetch, store and target any kind of
|
||||
// blob. The struct also describes the wire protocol format. Fields should
|
||||
// only be added but never changed.
|
||||
|
@ -250,7 +250,7 @@ type V2S2Descriptor struct {
|
|||
}
|
||||
|
||||
// github.com/docker/distribution/manifest/schema2/manifest.go
|
||||
// Manifest defines a schema2 manifest.
|
||||
// V2S2Manifest defines a schema2 manifest.
|
||||
type V2S2Manifest struct {
|
||||
V2Versioned
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue