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:
baude 2019-01-31 13:20:04 -06:00
parent 962850c6e0
commit 25a3923b61
149 changed files with 11444 additions and 4448 deletions

View file

@ -352,7 +352,8 @@ vendor: .install.vndr
$(GOPATH)/bin/vndr \ $(GOPATH)/bin/vndr \
-whitelist "github.com/varlink/go" \ -whitelist "github.com/varlink/go" \
-whitelist "github.com/onsi/ginkgo" \ -whitelist "github.com/onsi/ginkgo" \
-whitelist "github.com/onsi/gomega" -whitelist "github.com/onsi/gomega" \
-whitelist "gopkg.in/fsnotify.v1"
.PHONY: \ .PHONY: \
.gopathok \ .gopathok \

View file

@ -3,57 +3,56 @@ package main
import ( import (
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
attachFlags = []cli.Flag{ attachCommand cliconfig.AttachValues
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,
}
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." 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{ _attachCommand = &cobra.Command{
Name: "attach", Use: "attach",
Usage: "Attach to a running container", Short: "Attach to a running container",
Description: attachDescription, Long: attachDescription,
Flags: sortFlags(attachFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: attachCmd, attachCommand.InputArgs = args
ArgsUsage: "", attachCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return attachCmd(&attachCommand)
},
Example: "",
} }
) )
func attachCmd(c *cli.Context) error { func init() {
args := c.Args() 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 var ctr *libpod.Container
if err := validateFlags(c, attachFlags); err != nil {
return err if len(c.InputArgs) > 1 || (len(c.InputArgs) == 0 && !c.Latest) {
}
if len(c.Args()) > 1 || (len(c.Args()) == 0 && !c.Bool("latest")) {
return errors.Errorf("attach requires the name or id of one running container or the latest flag") 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 { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if c.Bool("latest") { if c.Latest {
ctr, err = runtime.GetLatestContainer() ctr, err = runtime.GetLatestContainer()
} else { } else {
ctr, err = runtime.LookupContainer(args[0]) ctr, err = runtime.LookupContainer(args[0])
@ -72,11 +71,11 @@ func attachCmd(c *cli.Context) error {
} }
inputStream := os.Stdin inputStream := os.Stdin
if c.Bool("no-stdin") { if c.NoStdin {
inputStream = nil 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()) return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
} }

View file

@ -10,38 +10,58 @@ import (
"github.com/containers/buildah/imagebuildah" "github.com/containers/buildah/imagebuildah"
buildahcli "github.com/containers/buildah/pkg/cli" buildahcli "github.com/containers/buildah/pkg/cli"
"github.com/containers/buildah/pkg/parse" "github.com/containers/buildah/pkg/parse"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
layerFlags = []cli.Flag{ buildCommand cliconfig.BuildValues
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. ",
},
}
buildDescription = "Builds an OCI or Docker image using instructions from one\n" + buildDescription = "Builds an OCI or Docker image using instructions from one\n" +
"or more Dockerfiles and a specified build context directory." "or more Dockerfiles and a specified build context directory."
buildCommand = cli.Command{ layerValues buildahcli.LayerResults
Name: "build", budFlagsValues buildahcli.BudResults
Usage: "Build an image using instructions from Dockerfiles", fromAndBudValues buildahcli.FromAndBudResults
Description: buildDescription, userNSValues buildahcli.UserNSResults
Flags: sortFlags(append(append(buildahcli.BudFlags, layerFlags...), buildahcli.FromAndBudFlags...)), namespaceValues buildahcli.NameSpaceResults
Action: buildCmd,
ArgsUsage: "CONTEXT-DIRECTORY | URL", _buildCommand = &cobra.Command{
SkipArgReorder: true, Use: "build",
OnUsageError: usageErrorHandler, 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 { func getDockerfiles(files []string) []string {
var dockerfiles []string var dockerfiles []string
for _, f := range files { for _, f := range files {
@ -54,30 +74,30 @@ func getDockerfiles(files []string) []string {
return dockerfiles 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 // 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 // TODO Find a away to vendor more of this in rather than copy from bud
output := "" output := ""
tags := []string{} tags := []string{}
if c.IsSet("tag") || c.IsSet("t") { if c.Flag("tag").Changed {
tags = c.StringSlice("tag") tags = c.Tag
if len(tags) > 0 { if len(tags) > 0 {
output = tags[0] output = tags[0]
tags = tags[1:] tags = tags[1:]
} }
} }
pullPolicy := imagebuildah.PullNever pullPolicy := imagebuildah.PullNever
if c.BoolT("pull") { if c.Pull {
pullPolicy = imagebuildah.PullIfMissing pullPolicy = imagebuildah.PullIfMissing
} }
if c.Bool("pull-always") { if c.PullAlways {
pullPolicy = imagebuildah.PullAlways pullPolicy = imagebuildah.PullAlways
} }
args := make(map[string]string) args := make(map[string]string)
if c.IsSet("build-arg") { if c.Flag("build-arg").Changed {
for _, arg := range c.StringSlice("build-arg") { for _, arg := range c.BuildArg {
av := strings.SplitN(arg, "=", 2) av := strings.SplitN(arg, "=", 2)
if len(av) > 1 { if len(av) > 1 {
args[av[0]] = av[1] args[av[0]] = av[1]
@ -87,15 +107,15 @@ func buildCmd(c *cli.Context) error {
} }
} }
dockerfiles := getDockerfiles(c.StringSlice("file")) dockerfiles := getDockerfiles(c.File)
format, err := getFormat(c) format, err := getFormat(&c.PodmanCommand)
if err != nil { if err != nil {
return nil return nil
} }
contextDir := "" 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 // Check to see if the BUILDAH_LAYERS environment variable is set and override command-line
if _, ok := os.LookupEnv("BUILDAH_LAYERS"); ok { if _, ok := os.LookupEnv("BUILDAH_LAYERS"); ok {
layers = buildahcli.UseLayers() layers = buildahcli.UseLayers()
@ -124,7 +144,7 @@ func buildCmd(c *cli.Context) error {
} }
contextDir = absDir contextDir = absDir
} }
cliArgs = cliArgs.Tail() cliArgs = Tail(cliArgs)
} else { } else {
// No context directory or URL was specified. Try to use the // No context directory or URL was specified. Try to use the
// home of the first locally-available Dockerfile. // home of the first locally-available Dockerfile.
@ -153,17 +173,14 @@ func buildCmd(c *cli.Context) error {
if len(dockerfiles) == 0 { if len(dockerfiles) == 0 {
dockerfiles = append(dockerfiles, filepath.Join(contextDir, "Dockerfile")) dockerfiles = append(dockerfiles, filepath.Join(contextDir, "Dockerfile"))
} }
if err := parse.ValidateFlags(c, buildahcli.BudFlags); err != nil {
return err
}
runtimeFlags := []string{} runtimeFlags := []string{}
for _, arg := range c.StringSlice("runtime-flag") { for _, arg := range c.RuntimeOpts {
runtimeFlags = append(runtimeFlags, "--"+arg) runtimeFlags = append(runtimeFlags, "--"+arg)
} }
// end from buildah // end from buildah
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -173,10 +190,10 @@ func buildCmd(c *cli.Context) error {
stdout = os.Stdout stdout = os.Stdout
stderr = os.Stderr stderr = os.Stderr
reporter = os.Stderr reporter = os.Stderr
if c.IsSet("logfile") { if c.Flag("logfile").Changed {
f, err := os.OpenFile(c.String("logfile"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) f, err := os.OpenFile(c.Logfile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil { 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() defer f.Close()
logrus.SetOutput(f) logrus.SetOutput(f)
@ -185,36 +202,36 @@ func buildCmd(c *cli.Context) error {
reporter = f reporter = f
} }
systemContext, err := parse.SystemContextFromOptions(c) systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command)
if err != nil { if err != nil {
return errors.Wrapf(err, "error building system context") return errors.Wrapf(err, "error building system context")
} }
systemContext.AuthFilePath = getAuthFile(c.String("authfile")) systemContext.AuthFilePath = getAuthFile(c.Authfile)
commonOpts, err := parse.CommonBuildOptions(c) commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command)
if err != nil { if err != nil {
return err return err
} }
namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c) namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command)
if err != nil { if err != nil {
return errors.Wrapf(err, "error parsing namespace-related options") 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 { if err != nil {
return errors.Wrapf(err, "error parsing ID mapping options") return errors.Wrapf(err, "error parsing ID mapping options")
} }
namespaceOptions.AddOrReplace(usernsOption...) namespaceOptions.AddOrReplace(usernsOption...)
ociruntime := runtime.GetOCIRuntimePath() ociruntime := runtime.GetOCIRuntimePath()
if c.IsSet("runtime") { if c.Flag("runtime").Changed {
ociruntime = c.String("runtime") ociruntime = c.Runtime
} }
options := imagebuildah.BuildOptions{ options := imagebuildah.BuildOptions{
ContextDirectory: contextDir, ContextDirectory: contextDir,
PullPolicy: pullPolicy, PullPolicy: pullPolicy,
Compression: imagebuildah.Gzip, Compression: imagebuildah.Gzip,
Quiet: c.Bool("quiet"), Quiet: c.Quiet,
SignaturePolicyPath: c.String("signature-policy"), SignaturePolicyPath: c.SignaturePolicy,
Args: args, Args: args,
Output: output, Output: output,
AdditionalTags: tags, AdditionalTags: tags,
@ -227,22 +244,22 @@ func buildCmd(c *cli.Context) error {
SystemContext: systemContext, SystemContext: systemContext,
NamespaceOptions: namespaceOptions, NamespaceOptions: namespaceOptions,
ConfigureNetwork: networkPolicy, ConfigureNetwork: networkPolicy,
CNIPluginPath: c.String("cni-plugin-path"), CNIPluginPath: c.CNIPlugInPath,
CNIConfigDir: c.String("cni-config-dir"), CNIConfigDir: c.CNIConfigDir,
IDMappingOptions: idmappingOptions, IDMappingOptions: idmappingOptions,
CommonBuildOpts: commonOpts, CommonBuildOpts: commonOpts,
DefaultMountsFilePath: c.GlobalString("default-mounts-file"), DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile,
IIDFile: c.String("iidfile"), IIDFile: c.Iidfile,
Squash: c.Bool("squash"), Squash: c.Squash,
Labels: c.StringSlice("label"), Labels: c.Label,
Annotations: c.StringSlice("annotation"), Annotations: c.Annotation,
Layers: layers, Layers: layers,
NoCache: c.Bool("no-cache"), NoCache: c.NoCache,
RemoveIntermediateCtrs: c.BoolT("rm"), RemoveIntermediateCtrs: c.Rm,
ForceRmIntermediateCtrs: c.BoolT("force-rm"), ForceRmIntermediateCtrs: c.ForceRm,
} }
if c.Bool("quiet") { if c.Quiet {
options.ReportWriter = ioutil.Discard options.ReportWriter = ioutil.Discard
} }
@ -252,3 +269,13 @@ func buildCmd(c *cli.Context) error {
return runtime.Build(getContext(), options, dockerfiles...) 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{}
}

View file

@ -5,70 +5,67 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
checkpointCommand cliconfig.CheckpointValues
checkpointDescription = ` checkpointDescription = `
podman container checkpoint podman container checkpoint
Checkpoints one or more running containers. The container name or ID can be used. Checkpoints one or more running containers. The container name or ID can be used.
` `
checkpointFlags = []cli.Flag{ _checkpointCommand = &cobra.Command{
cli.BoolFlag{ Use: "checkpoint",
Name: "keep, k", Short: "Checkpoints one or more containers",
Usage: "Keep all temporary checkpoint files", Long: checkpointDescription,
RunE: func(cmd *cobra.Command, args []string) error {
checkpointCommand.InputArgs = args
checkpointCommand.GlobalFlags = MainGlobalOpts
return checkpointCmd(&checkpointCommand)
}, },
cli.BoolFlag{ Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
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 ...]",
} }
) )
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() { if rootless.IsRootless() {
return errors.New("checkpointing a container requires root") return errors.New("checkpointing a container requires root")
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
options := libpod.ContainerCheckpointOptions{ options := libpod.ContainerCheckpointOptions{
Keep: c.Bool("keep"), Keep: c.Keep,
KeepRunning: c.Bool("leave-running"), KeepRunning: c.LeaveRunning,
TCPEstablished: c.Bool("tcp-established"), TCPEstablished: c.TcpEstablished,
} }
if err := checkAllAndLatest(c); err != nil { if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err return err
} }
containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running") containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
for _, ctr := range containers { for _, ctr := range containers {
if err = ctr.Checkpoint(context.TODO(), options); err != nil { if err = ctr.Checkpoint(context.TODO(), options); err != nil {

View file

@ -4,50 +4,52 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
cleanupFlags = []cli.Flag{ cleanupCommand cliconfig.CleanupValues
cli.BoolFlag{
Name: "all, a",
Usage: "Cleans up all containers",
},
LatestFlag,
}
cleanupDescription = ` cleanupDescription = `
podman container cleanup 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. 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{ _cleanupCommand = &cobra.Command{
Name: "cleanup", Use: "cleanup",
Usage: "Cleanup network and mountpoints of one or more containers", Short: "Cleanup network and mountpoints of one or more containers",
Description: cleanupDescription, Long: cleanupDescription,
Flags: sortFlags(cleanupFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: cleanupCmd, cleanupCommand.InputArgs = args
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]", cleanupCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return cleanupCmd(&cleanupCommand)
},
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
} }
) )
func cleanupCmd(c *cli.Context) error { func init() {
if err := validateFlags(c, cleanupFlags); err != nil { cleanupCommand.Command = _cleanupCommand
return err flags := cleanupCommand.Flags()
}
runtime, err := libpodruntime.GetRuntime(c) 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if err := checkAllAndLatest(c); err != nil { if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err return err
} }
cleanupContainers, lastError := getAllOrLatestContainers(c, runtime, -1, "all") cleanupContainers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
ctx := getContext() ctx := getContext()

View 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
}

View 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
}

View 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
}

View file

@ -2,151 +2,106 @@
package main package main
import "github.com/urfave/cli" import (
"github.com/spf13/cobra"
)
func getAppCommands() []cli.Command { func getImageSubCommands() []*cobra.Command {
return []cli.Command{ return []*cobra.Command{
attachCommand, _buildCommand,
commitCommand, _importCommand,
buildCommand, _loadCommand,
createCommand, _pullCommand,
diffCommand, _rmiCommand,
execCommand, _saveCommand,
killCommand, _signCommand,
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() []cli.Command { func getContainerSubCommands() []*cobra.Command {
return []cli.Command{ return []*cobra.Command{
buildCommand, _attachCommand,
importCommand, _checkpointCommand,
loadCommand, _cleanupCommand,
pullCommand, _containerExistsCommand,
saveCommand, _commitCommand,
trustCommand, _createCommand,
signCommand, _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 { func getPodSubCommands() []*cobra.Command {
return []cli.Command{infoCommand} return []*cobra.Command{
_podCreateCommand,
_podExistsCommand,
_podInspectCommand,
_podKillCommand,
_podPauseCommand,
_podPsCommand,
_podRestartCommand,
_podRmCommand,
_podStartCommand,
_podStatsCommand,
_podStopCommand,
_podTopCommand,
_podUnpauseCommand,
}
} }
func getContainerSubCommands() []cli.Command { func getVolumeSubCommands() []*cobra.Command {
return []cli.Command{ return []*cobra.Command{
attachCommand, _volumeCreateCommand,
checkpointCommand, _volumeLsCommand,
cleanupCommand, _volumeRmCommand,
containerExistsCommand, _volumeInspectCommand,
commitCommand, _volumePruneCommand,
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 getMainAppFlags() []cli.Flag {
return []cli.Flag{ func getGenerateSubCommands() []*cobra.Command {
cli.StringFlag{ return []*cobra.Command{
Name: "cgroup-manager", _containerKubeCommand,
Usage: "Cgroup manager to use (cgroupfs or systemd, default systemd)", }
}, }
cli.StringFlag{
Name: "cni-config-dir", func getPlaySubCommands() []*cobra.Command {
Usage: "Path of the configuration directory for CNI networks", return []*cobra.Command{
}, _playKubeCommand,
cli.StringFlag{ }
Name: "conmon", }
Usage: "Path of the conmon binary",
}, func getTrustSubCommands() []*cobra.Command {
cli.StringFlag{ return []*cobra.Command{
Name: "default-mounts-file", _setTrustCommand,
Usage: "Path to default mounts file", _showTrustCommand,
Hidden: true, }
}, }
cli.StringSliceFlag{
Name: "hooks-dir", func getSystemSubCommands() []*cobra.Command {
Usage: "Set the OCI hooks directory path (may be set multiple times)", return []*cobra.Command{
}, _infoCommand,
cli.IntFlag{ _pruneSystemCommand,
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",
},
} }
} }

View file

@ -2,24 +2,47 @@
package main package main
import "github.com/urfave/cli" import (
"github.com/spf13/cobra"
)
func getAppCommands() []cli.Command { //import "github.com/urfave/cli"
return []cli.Command{} //
func getAppCommands() []*cobra.Command {
return []*cobra.Command{}
} }
func getImageSubCommands() []cli.Command { func getImageSubCommands() []*cobra.Command {
return []cli.Command{} return []*cobra.Command{}
} }
func getContainerSubCommands() []cli.Command { func getContainerSubCommands() []*cobra.Command {
return []cli.Command{} return []*cobra.Command{}
} }
func getSystemSubCommands() []cli.Command { func getPodSubCommands() []*cobra.Command {
return []cli.Command{} return []*cobra.Command{}
} }
func getMainAppFlags() []cli.Flag { func getVolumeSubCommands() []*cobra.Command {
return []cli.Flag{} 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{}
} }

View file

@ -2,6 +2,8 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"io" "io"
"os" "os"
"strings" "strings"
@ -13,57 +15,43 @@ import (
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli"
) )
var ( var (
commitFlags = []cli.Flag{ commitCommand cliconfig.CommitValues
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",
},
}
commitDescription = `Create an image from a container's changes. commitDescription = `Create an image from a container's changes.
Optionally tag the image created, set the author with the --author flag, Optionally tag the image created, set the author with the --author flag,
set the commit message with the --message flag, set the commit message with the --message flag,
and make changes to the instructions with the --change flag.` and make changes to the instructions with the --change flag.`
commitCommand = cli.Command{
Name: "commit", _commitCommand = &cobra.Command{
Usage: "Create new image based on the changed container", Use: "commit",
Description: commitDescription, Short: "Create new image based on the changed container",
Flags: sortFlags(commitFlags), Long: commitDescription,
Action: commitCmd, RunE: func(cmd *cobra.Command, args []string) error {
ArgsUsage: "CONTAINER [REPOSITORY[:TAG]]", commitCommand.InputArgs = args
OnUsageError: usageErrorHandler, commitCommand.GlobalFlags = MainGlobalOpts
return commitCmd(&commitCommand)
},
Example: "CONTAINER [REPOSITORY[:TAG]]",
} }
) )
func commitCmd(c *cli.Context) error { func init() {
if err := validateFlags(c, commitFlags); err != nil { commitCommand.Command = _commitCommand
return err 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, " | ")))
runtime, err := libpodruntime.GetRuntime(c) 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -73,26 +61,26 @@ func commitCmd(c *cli.Context) error {
writer io.Writer writer io.Writer
mimeType string mimeType string
) )
args := c.Args() args := c.InputArgs
if len(args) != 2 { if len(args) != 2 {
return errors.Errorf("you must provide a container name or ID and a target image name") 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": case "oci":
mimeType = buildah.OCIv1ImageManifest 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)") return errors.Errorf("messages are only compatible with the docker image format (-f docker)")
} }
case "docker": case "docker":
mimeType = manifest.DockerV2Schema2MediaType mimeType = manifest.DockerV2Schema2MediaType
default: default:
return errors.Errorf("unrecognized image format %q", c.String("format")) return errors.Errorf("unrecognized image format %q", c.Format)
} }
container := args[0] container := args[0]
reference := args[1] reference := args[1]
if c.IsSet("change") || c.IsSet("c") { if c.Flag("change").Changed {
for _, change := range c.StringSlice("change") { for _, change := range c.Change {
splitChange := strings.Split(strings.ToUpper(change), "=") splitChange := strings.Split(strings.ToUpper(change), "=")
if !util.StringInSlice(splitChange[0], libpod.ChangeCmds) { if !util.StringInSlice(splitChange[0], libpod.ChangeCmds) {
return errors.Errorf("invalid syntax for --change: %s", change) 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 writer = os.Stderr
} }
ctr, err := runtime.LookupContainer(container) ctr, err := runtime.LookupContainer(container)
@ -117,10 +105,10 @@ func commitCmd(c *cli.Context) error {
} }
options := libpod.ContainerCommitOptions{ options := libpod.ContainerCommitOptions{
CommitOptions: coptions, CommitOptions: coptions,
Pause: c.Bool("pause"), Pause: c.Pause,
Message: c.String("message"), Message: c.Message,
Changes: c.StringSlice("change"), Changes: c.Change,
Author: c.String("author"), Author: c.Author,
} }
newImage, err := ctr.Commit(getContext(), reference, options) newImage, err := ctr.Commit(getContext(), reference, options)
if err != nil { if err != nil {

View file

@ -4,34 +4,19 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"reflect"
"regexp"
"sort"
"strings" "strings"
"github.com/containers/buildah" "github.com/containers/buildah"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/fatih/camelcase" "github.com/fatih/camelcase"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli"
) )
var ( var (
stores = make(map[storage.Store]struct{}) 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",
}
) )
const ( const (
@ -50,53 +35,9 @@ func shortID(id string) string {
return id 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 // checkAllAndLatest checks that --all and --latest are used correctly
func checkAllAndLatest(c *cli.Context) error { func checkAllAndLatest(c *cliconfig.PodmanCommand) error {
argLen := len(c.Args()) argLen := len(c.InputArgs)
if (c.Bool("all") || c.Bool("latest")) && argLen > 0 { if (c.Bool("all") || c.Bool("latest")) && argLen > 0 {
return errors.Errorf("no arguments are needed with --all or --latest") 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 // 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 // error message, if the filter fails, a corresponding verb can be
// specified which will then appear in the error message. // 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 containers []*libpod.Container
var lastError error var lastError error
var err error var err error
@ -142,7 +83,7 @@ func getAllOrLatestContainers(c *cli.Context, runtime *libpod.Runtime, filterSta
} }
containers = append(containers, lastCtr) containers = append(containers, lastCtr)
} else { } else {
args := c.Args() args := c.InputArgs
for _, i := range args { for _, i := range args {
container, err := runtime.LookupContainer(i) container, err := runtime.LookupContainer(i)
if err != nil { if err != nil {
@ -173,363 +114,367 @@ func getDefaultNetwork() string {
return "bridge" return "bridge"
} }
// Common flags shared between commands func getCreateFlags(c *cliconfig.PodmanCommand) {
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",
},
cli.StringSliceFlag{ createFlags := c.Flags()
Name: "sysctl",
Usage: "Sysctl options (default [])", createFlags.StringSlice(
}, "add-host", []string{},
cli.BoolTFlag{ "Add a custom host-to-IP mapping (host:ip) (default [])",
Name: "systemd", )
Usage: "Run container in systemd mode if the command executable is systemd or init", createFlags.StringSlice(
}, "annotation", []string{},
cli.StringSliceFlag{ "Add annotations to container (key:value) (default [])",
Name: "tmpfs", )
Usage: "Mount a temporary filesystem (`tmpfs`) into a container (default [])", createFlags.StringSliceP(
}, "attach", "a", []string{},
cli.BoolFlag{ "Attach to STDIN, STDOUT or STDERR (default [])",
Name: "tty, t", )
Usage: "Allocate a pseudo-TTY for container", createFlags.String(
}, "blkio-weight", "",
cli.StringSliceFlag{ "Block IO weight (relative weight) accepts a weight value between 10 and 1000.",
Name: "uidmap", )
Usage: "UID map to use for the user namespace", createFlags.StringSlice(
}, "blkio-weight-device", []string{},
cli.StringSliceFlag{ "Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)",
Name: "ulimit", )
Usage: "Ulimit options (default [])", createFlags.StringSlice(
}, "cap-add", []string{},
cli.StringFlag{ "Add capabilities to the container",
Name: "user, u", )
Usage: "Username or UID (format: <name|uid>[:<group|gid>])", createFlags.StringSlice(
}, "cap-drop", []string{},
cli.StringFlag{ "Drop capabilities from the container",
Name: "userns", )
Usage: "User namespace to use", createFlags.String(
}, "cgroup-parent", "",
cli.StringFlag{ "Optional parent cgroup for the container",
Name: "uts", )
Usage: "UTS namespace to use", createFlags.String(
}, "cidfile", "",
cli.StringSliceFlag{ "Write the container ID to the file",
Name: "mount", )
Usage: "Attach a filesystem mount to the container (default [])", createFlags.String(
}, "conmon-pidfile", "",
cli.StringSliceFlag{ "Path to the file that will receive the PID of conmon",
Name: "volume, v", )
Usage: "Bind mount a volume into the container (default [])", createFlags.Uint64(
}, "cpu-period", 0,
cli.StringSliceFlag{ "Limit the CPU CFS (Completely Fair Scheduler) period",
Name: "volumes-from", )
Usage: "Mount volumes from the specified container(s) (default [])", createFlags.Int64(
}, "cpu-quota", 0,
WorkDirFlag, "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")) format := strings.ToLower(c.String("format"))
if strings.HasPrefix(format, buildah.OCI) { if strings.HasPrefix(format, buildah.OCI) {
return buildah.OCIv1ImageManifest, nil return buildah.OCIv1ImageManifest, nil
@ -541,13 +486,6 @@ func getFormat(c *cli.Context) (string, error) {
return "", errors.Errorf("unrecognized image type %q", format) 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 { func getAuthFile(authfile string) string {
if authfile != "" { if authfile != "" {
return authfile return authfile

View file

@ -1,30 +1,21 @@
package main package main
import ( import (
"sort" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"github.com/urfave/cli"
) )
var ( var containerDescription = "Manage containers"
containerSubCommands = []cli.Command{ var containerCommand = cliconfig.PodmanCommand{
exportCommand, Command: &cobra.Command{
inspectCommand, Use: "container",
} Short: "Manage Containers",
containerDescription = "Manage containers" Long: containerDescription,
containerCommand = cli.Command{ TraverseChildren: true,
Name: "container", },
Usage: "Manage Containers", }
Description: containerDescription,
ArgsUsage: "", func init() {
Subcommands: getContainerSubCommandsSorted(), containerCommand.AddCommand(getContainerSubCommands()...)
UseShortOptionHandling: true, rootCmd.AddCommand(containerCommand.Command)
OnUsageError: usageErrorHandler,
}
)
func getContainerSubCommandsSorted() []cli.Command {
containerSubCommands = append(containerSubCommands, getContainerSubCommands()...)
sort.Sort(commandSortedAlpha{containerSubCommands})
return containerSubCommands
} }

View file

@ -3,30 +3,39 @@ package main
import ( import (
"context" "context"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
pruneContainersCommand cliconfig.ContainersPrune
pruneContainersDescription = ` pruneContainersDescription = `
podman container prune podman container prune
Removes all exited containers Removes all exited containers
` `
pruneContainersCommand = cli.Command{ _pruneContainersCommand = &cobra.Command{
Name: "prune", Use: "prune",
Usage: "Remove all stopped containers", Short: "Remove all stopped containers",
Description: pruneContainersDescription, Long: pruneContainersDescription,
Action: pruneContainersCmd, RunE: func(cmd *cobra.Command, args []string) error {
OnUsageError: usageErrorHandler, 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 { func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWorkers int, force bool) error {
var deleteFuncs []shared.ParallelWorkerInput var deleteFuncs []shared.ParallelWorkerInput
@ -60,8 +69,8 @@ func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWork
return printParallelOutput(deleteErrors, errCount) return printParallelOutput(deleteErrors, errCount)
} }
func pruneContainersCmd(c *cli.Context) error { func pruneContainersCmd(c *cliconfig.ContainersPrune) error {
runtime, err := adapter.GetRuntime(c) runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -69,7 +78,7 @@ func pruneContainersCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("rm") maxWorkers := shared.Parallelize("rm")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -12,6 +12,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
@ -29,37 +30,46 @@ import (
"github.com/opencontainers/selinux/go-selinux/label" "github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( 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{ defaultEnvVariables = map[string]string{
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM": "xterm", "TERM": "xterm",
} }
) )
var createDescription = "Creates a new container from the given image or" + func init() {
" storage and prepares it for running the specified command. The" + createCommand.PodmanCommand.Command = _createCommand
" 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'."
var createCommand = cli.Command{ getCreateFlags(&createCommand.PodmanCommand)
Name: "create", flags := createCommand.Flags()
Usage: "Create but do not start a container", flags.SetInterspersed(true)
Description: createDescription,
Flags: sortFlags(createFlags), rootCmd.AddCommand(createCommand.Command)
Action: createCmd,
ArgsUsage: "IMAGE [COMMAND [ARG...]]",
HideHelp: true,
SkipArgReorder: true,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
} }
func createCmd(c *cli.Context) error { func createCmd(c *cliconfig.CreateValues) error {
if err := createInit(c); err != nil { if err := createInit(&c.PodmanCommand); err != nil {
return err return err
} }
@ -67,13 +77,13 @@ func createCmd(c *cli.Context) error {
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
ctr, _, err := createContainer(c, runtime) ctr, _, err := createContainer(&c.PodmanCommand, runtime)
if err != nil { if err != nil {
return err return err
} }
@ -82,33 +92,24 @@ func createCmd(c *cli.Context) error {
return nil return nil
} }
func createInit(c *cli.Context) error { func createInit(c *cliconfig.PodmanCommand) error {
// TODO should allow user to create based off a directory on the host not just image
// Need CLI support for this
// Docker-compatibility: the "-h" flag for run/create is reserved for // Docker-compatibility: the "-h" flag for run/create is reserved for
// the hostname (see https://github.com/containers/libpod/issues/1367). // 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 { if len(c.InputArgs) < 1 {
return err
}
if len(c.Args()) < 1 {
return errors.Errorf("image name or ID is required") return errors.Errorf("image name or ID is required")
} }
return nil 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() rtc := runtime.GetConfig()
ctx := getContext() ctx := getContext()
rootfs := "" rootfs := ""
if c.Bool("rootfs") { if c.Bool("rootfs") {
rootfs = c.Args()[0] rootfs = c.InputArgs[0]
} }
var err error var err error
@ -134,7 +135,7 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container
writer = os.Stderr 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 { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -264,7 +265,7 @@ func isPortInImagePorts(exposedPorts map[string]struct{}, port string) bool {
return false return false
} }
func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string { func configureEntrypoint(c *cliconfig.PodmanCommand, data *inspect.ImageData) []string {
entrypoint := []string{} entrypoint := []string{}
if c.IsSet("entrypoint") { if c.IsSet("entrypoint") {
// Force entrypoint to "" // Force entrypoint to ""
@ -284,7 +285,7 @@ func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string {
return entrypoint 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) pod, err := runtime.LookupPod(podName)
if err != nil { if err != nil {
return namespaces, err 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()) { if (namespaces["pid"] == cc.Pod) || (!c.IsSet("pid") && pod.SharesPID()) {
namespaces["pid"] = fmt.Sprintf("container:%s", podInfraID) 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) namespaces["net"] = fmt.Sprintf("container:%s", podInfraID)
} }
if (namespaces["user"] == cc.Pod) || (!c.IsSet("user") && pod.SharesUser()) { 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 // Parses CLI options related to container creation into a config which can be
// parsed into an OCI runtime spec // 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 ( var (
inputCommand, command []string inputCommand, command []string
memoryLimit, memoryReservation, memorySwap, memoryKernel int64 memoryLimit, memoryReservation, memorySwap, memoryKernel int64
@ -335,14 +336,14 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
imageID := "" imageID := ""
inputCommand = c.Args()[1:] inputCommand = c.InputArgs[1:]
if data != nil { if data != nil {
imageID = data.ID imageID = data.ID
} }
rootfs := "" rootfs := ""
if c.Bool("rootfs") { if c.Bool("rootfs") {
rootfs = c.Args()[0] rootfs = c.InputArgs[0]
} }
sysctl, err := validateSysctl(c.StringSlice("sysctl")) sysctl, err := validateSysctl(c.StringSlice("sysctl"))
@ -382,15 +383,15 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
blkioWeight = uint16(u) blkioWeight = uint16(u)
} }
var mountList []spec.Mount 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 return nil, err
} }
if err = parseVolumes(c.StringSlice("volume")); err != nil { if err = parseVolumes(c.StringArray("volume")); err != nil {
return nil, err return nil, err
} }
if err = parseVolumesFrom(c.StringSlice("volumes-from")); err != nil { if err = parseVolumesFrom(c.StringArray("volumes-from")); err != nil {
return nil, err 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") { if c.Bool("detach") && c.Bool("rm") {
return nil, errors.Errorf("--rm and --detach cannot be specified together") 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") 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") 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 // Instead of integrating here, should be done in libpod
// However, that also involves setting up security opts // However, that also involves setting up security opts
// when the pod's namespace is integrated // when the pod's namespace is integrated
namespaceNet := c.String("network")
if c.Flag("net").Changed {
namespaceNet = c.String("net")
}
namespaces = map[string]string{ namespaces = map[string]string{
"pid": c.String("pid"), "pid": c.String("pid"),
"net": c.String("net"), "net": namespaceNet,
"ipc": c.String("ipc"), "ipc": c.String("ipc"),
"user": c.String("userns"), "user": c.String("userns"),
"uts": c.String("uts"), "uts": c.String("uts"),
@ -654,7 +659,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
} }
var systemd bool 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 systemd = true
if signalString == "" { if signalString == "" {
stopSignal, err = signal.ParseSignal("RTMIN+3") 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{ config := &cc.CreateConfig{
Runtime: runtime, Runtime: runtime,
Annotations: annotations, Annotations: annotations,
@ -697,7 +712,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
LogDriverOpt: c.StringSlice("log-opt"), LogDriverOpt: c.StringSlice("log-opt"),
MacAddress: c.String("mac-address"), MacAddress: c.String("mac-address"),
Name: c.String("name"), Name: c.String("name"),
Network: c.String("network"), Network: network,
NetworkAlias: c.StringSlice("network-alias"), NetworkAlias: c.StringSlice("network-alias"),
IpcMode: ipcMode, IpcMode: ipcMode,
NetMode: netMode, NetMode: netMode,
@ -730,12 +745,11 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
Memory: memoryLimit, Memory: memoryLimit,
MemoryReservation: memoryReservation, MemoryReservation: memoryReservation,
MemorySwap: memorySwap, MemorySwap: memorySwap,
MemorySwappiness: c.Int("memory-swappiness"), MemorySwappiness: int(memorySwappiness),
KernelMemory: memoryKernel, KernelMemory: memoryKernel,
OomScoreAdj: c.Int("oom-score-adj"), OomScoreAdj: c.Int("oom-score-adj"),
PidsLimit: c.Int64("pids-limit"),
PidsLimit: c.Int64("pids-limit"), Ulimit: c.StringSlice("ulimit"),
Ulimit: c.StringSlice("ulimit"),
}, },
Rm: c.Bool("rm"), Rm: c.Bool("rm"),
StopSignal: stopSignal, StopSignal: stopSignal,
@ -747,13 +761,12 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
User: user, User: user,
UsernsMode: usernsMode, UsernsMode: usernsMode,
Mounts: mountList, Mounts: mountList,
Volumes: c.StringSlice("volume"), Volumes: c.StringArray("volume"),
WorkDir: workDir, WorkDir: workDir,
Rootfs: rootfs, Rootfs: rootfs,
VolumesFrom: c.StringSlice("volumes-from"), VolumesFrom: c.StringSlice("volumes-from"),
Syslog: c.GlobalBool("syslog"), Syslog: c.GlobalFlags.Syslog,
} }
if c.Bool("init") { if c.Bool("init") {
initPath := c.String("init-path") initPath := c.String("init-path")
if initPath == "" { if initPath == "" {
@ -767,11 +780,11 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
if config.Privileged { if config.Privileged {
config.LabelOpts = label.DisableSecOpt() config.LabelOpts = label.DisableSecOpt()
} else { } else {
if err := parseSecurityOpt(config, c.StringSlice("security-opt")); err != nil { if err := parseSecurityOpt(config, c.StringArray("security-opt")); err != nil {
return nil, err return nil, err
} }
} }
config.SecurityOpts = c.StringSlice("security-opt") config.SecurityOpts = c.StringArray("security-opt")
warnings, err := verifyContainerResources(config, false) warnings, err := verifyContainerResources(config, false)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -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=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
// podman run --mount type=tmpfs,target=/dev/shm .. // podman run --mount type=tmpfs,target=/dev/shm ..
func parseMounts(mounts []string) ([]spec.Mount, error) { 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 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 { for _, mount := range mounts {
var tokenCount int var tokenCount int
var mountInfo spec.Mount var mountInfo spec.Mount
arr := strings.SplitN(mount, ",", 2) arr := strings.SplitN(mount, ",", 2)
if len(arr) < 2 { if len(arr) < 2 {
return nil, errInvalidSyntax return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
} }
kv := strings.Split(arr[0], "=") kv := strings.Split(arr[0], "=")
if kv[0] != "type" { if kv[0] != "type" {
return nil, errInvalidSyntax return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
} }
switch kv[1] { switch kv[1] {
case "bind": case "bind":
@ -168,7 +171,7 @@ func parseVolumes(volumes []string) error {
for _, volume := range volumes { for _, volume := range volumes {
arr := strings.SplitN(volume, ":", 3) arr := strings.SplitN(volume, ":", 3)
if len(arr) < 2 { 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 { if err := validateVolumeHostDir(arr[0]); err != nil {
return err return err

View file

@ -2,12 +2,12 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/archive"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
type diffJSONOutput struct { type diffJSONOutput struct {
@ -33,31 +33,35 @@ func (so stdoutStruct) Out() error {
} }
var ( var (
diffFlags = []cli.Flag{ diffCommand cliconfig.DiffValues
cli.BoolFlag{
Name: "archive",
Usage: "Save the diff as a tar archive",
Hidden: true,
},
cli.StringFlag{
Name: "format",
Usage: "Change the output format.",
},
}
diffDescription = fmt.Sprint(`Displays changes on a container or image's filesystem. The diffDescription = fmt.Sprint(`Displays changes on a container or image's filesystem. The
container or image will be compared to its parent layer`) container or image will be compared to its parent layer`)
diffCommand = cli.Command{ _diffCommand = &cobra.Command{
Name: "diff", Use: "diff",
Usage: "Inspect changes on container's file systems", Short: "Inspect changes on container's file systems",
Description: diffDescription, Long: diffDescription,
Flags: sortFlags(diffFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: diffCmd, diffCommand.InputArgs = args
ArgsUsage: "ID-NAME", diffCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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) { func formatJSON(output []diffOutputParams) (diffJSONOutput, error) {
jsonStruct := diffJSONOutput{} jsonStruct := diffJSONOutput{}
for _, output := range output { for _, output := range output {
@ -75,29 +79,25 @@ func formatJSON(output []diffOutputParams) (diffJSONOutput, error) {
return jsonStruct, nil return jsonStruct, nil
} }
func diffCmd(c *cli.Context) error { func diffCmd(c *cliconfig.DiffValues) error {
if err := validateFlags(c, diffFlags); err != nil { if len(c.InputArgs) != 1 {
return err
}
if len(c.Args()) != 1 {
return errors.Errorf("container, image, or layer name must be specified: podman diff [options [...]] ID-NAME") 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
to := c.Args().Get(0) to := c.InputArgs[0]
changes, err := runtime.GetDiff("", to) changes, err := runtime.GetDiff("", to)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get changes for %q", to) return errors.Wrapf(err, "could not get changes for %q", to)
} }
diffOutput := []diffOutputParams{} diffOutput := []diffOutputParams{}
outputFormat := c.String("format") outputFormat := c.Format
for _, change := range changes { for _, change := range changes {

View file

@ -2,82 +2,76 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"os" "os"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli"
) )
var ( var (
execFlags = []cli.Flag{ execCommand cliconfig.ExecValues
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,
}
execDescription = ` execDescription = `
podman exec podman exec
Run a command in a running container Run a command in a running container
` `
_execCommand = &cobra.Command{
execCommand = cli.Command{ Use: "exec",
Name: "exec", Short: "Run a process in a running container",
Usage: "Run a process in a running container", Long: execDescription,
Description: execDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(execFlags), execCommand.InputArgs = args
Action: execCmd, execCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "CONTAINER-NAME", return execCmd(&execCommand)
SkipArgReorder: true, },
UseShortOptionHandling: true, Example: "CONTAINER-NAME",
OnUsageError: usageErrorHandler,
} }
) )
func execCmd(c *cli.Context) error { func init() {
args := c.Args() 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 ctr *libpod.Container
var err error var err error
argStart := 1 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") 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") return errors.Errorf("you must provide a command to exec")
} }
if c.Bool("latest") { if c.Latest {
argStart = 0 argStart = 0
} }
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
cmd := args[argStart:] cmd := args[argStart:]
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if c.Bool("latest") { if c.Latest {
ctr, err = runtime.GetLatestContainer() ctr, err = runtime.GetLatestContainer()
} else { } else {
ctr, err = runtime.LookupContainer(args[0]) ctr, err = runtime.LookupContainer(args[0])
@ -101,7 +95,7 @@ func execCmd(c *cli.Context) error {
// ENVIRONMENT VARIABLES // ENVIRONMENT VARIABLES
env := map[string]string{} 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") return errors.Wrapf(err, "unable to process environment variables")
} }
envs := []string{} envs := []string{}
@ -109,5 +103,5 @@ func execCmd(c *cli.Context) error {
envs = append(envs, fmt.Sprintf("%s=%s", k, v)) 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)
} }

View file

@ -1,6 +1,8 @@
package main package main
import ( import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"os" "os"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
@ -8,66 +10,78 @@ import (
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli"
) )
var ( var (
imageExistsCommand cliconfig.ImageExistsValues
containerExistsCommand cliconfig.ContainerExistsValues
podExistsCommand cliconfig.PodExistsValues
imageExistsDescription = ` imageExistsDescription = `
podman image exists podman image exists
Check if an image exists in local storage 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 = ` containerExistsDescription = `
podman container exists podman container exists
Check if a container exists in local storage 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 = ` podExistsDescription = `
podman pod exists podman pod exists
Check if a pod exists in local storage 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{ _containerExistsCommand = &cobra.Command{
Name: "exists", Use: "exists",
Usage: "Check if a pod exists in local storage", Short: "Check if a container exists in local storage",
Description: podExistsDescription, Long: containerExistsDescription,
Action: podExistsCmd, RunE: func(cmd *cobra.Command, args []string) error {
ArgsUsage: "POD-NAME", containerExistsCommand.InputArgs = args
OnUsageError: usageErrorHandler, 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 { func init() {
args := c.Args() 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 { if len(args) > 1 || len(args) < 1 {
return errors.New("you may only check for the existence of one image at a time") 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -83,12 +97,12 @@ func imageExistsCmd(c *cli.Context) error {
return nil return nil
} }
func containerExistsCmd(c *cli.Context) error { func containerExistsCmd(c *cliconfig.ContainerExistsValues) error {
args := c.Args() args := c.InputArgs
if len(args) > 1 || len(args) < 1 { if len(args) > 1 || len(args) < 1 {
return errors.New("you may only check for the existence of one container at a time") 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -102,12 +116,12 @@ func containerExistsCmd(c *cli.Context) error {
return nil return nil
} }
func podExistsCmd(c *cli.Context) error { func podExistsCmd(c *cliconfig.PodExistsValues) error {
args := c.Args() args := c.InputArgs
if len(args) > 1 || len(args) < 1 { if len(args) > 1 || len(args) < 1 {
return errors.New("you may only check for the existence of one pod at a time") 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }

View file

@ -3,50 +3,52 @@ package main
import ( import (
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
exportFlags = []cli.Flag{ exportCommand cliconfig.ExportValues
cli.StringFlag{
Name: "output, o",
Usage: "Write to a file, default is STDOUT",
Value: "/dev/stdout",
},
}
exportDescription = "Exports container's filesystem contents as a tar archive" + exportDescription = "Exports container's filesystem contents as a tar archive" +
" and saves it on the local machine." " and saves it on the local machine."
exportCommand = cli.Command{
Name: "export", _exportCommand = &cobra.Command{
Usage: "Export container's filesystem contents as a tar archive", Use: "export",
Description: exportDescription, Short: "Export container's filesystem contents as a tar archive",
Flags: sortFlags(exportFlags), Long: exportDescription,
Action: exportCmd, RunE: func(cmd *cobra.Command, args []string) error {
ArgsUsage: "CONTAINER", exportCommand.InputArgs = args
OnUsageError: usageErrorHandler, 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 // exportCmd saves a container to a tarball on disk
func exportCmd(c *cli.Context) error { func exportCmd(c *cliconfig.ExportValues) error {
if err := validateFlags(c, exportFlags); err != nil {
return err
}
if os.Geteuid() != 0 { if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
} }
runtime, err := adapter.GetRuntime(c) runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
args := c.Args() args := c.InputArgs
if len(args) == 0 { if len(args) == 0 {
return errors.Errorf("container id must be specified") 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.") 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) { if runtime.Remote && (output == "/dev/stdout" || len(output) == 0) {
return errors.New("remote client usage must specify an output file (-o)") return errors.New("remote client usage must specify an output file (-o)")
} }
if output == "/dev/stdout" { if output == "/dev/stdout" {
file := os.Stdout file := os.Stdout
if logrus.IsTerminal(file) { if logrus.IsTerminal(file) {
@ -68,5 +71,5 @@ func exportCmd(c *cli.Context) error {
if err := validateFileName(output); err != nil { if err := validateFileName(output); err != nil {
return err return err
} }
return runtime.Export(args[0], c.String("output")) return runtime.Export(args[0], output)
} }

View file

@ -1,23 +1,21 @@
package main package main
import ( import (
"github.com/urfave/cli" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
) )
var ( var generateDescription = "Generate structured data based for a containers and pods"
generateSubCommands = []cli.Command{ var generateCommand = cliconfig.PodmanCommand{
containerKubeCommand,
}
generateDescription = "Generate structured data based for a containers and pods" Command: &cobra.Command{
kubeCommand = cli.Command{ Use: "generate",
Name: "generate", Short: "Generated structured data",
Usage: "Generate structured data", Long: generateDescription,
Description: generateDescription, },
ArgsUsage: "", }
Subcommands: generateSubCommands,
UseShortOptionHandling: true, func init() {
OnUsageError: usageErrorHandler, generateCommand.AddCommand(getGenerateSubCommands()...)
Hidden: true, rootCmd.AddCommand(generateCommand.Command)
} }
)

View file

@ -2,38 +2,40 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
podmanVersion "github.com/containers/libpod/version" podmanVersion "github.com/containers/libpod/version"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
) )
var ( var (
containerKubeFlags = []cli.Flag{ containerKubeCommand cliconfig.GenerateKubeValues
cli.BoolFlag{
Name: "service, s",
Usage: "Generate YAML for kubernetes service object",
},
}
containerKubeDescription = "Generate Kubernetes Pod YAML" containerKubeDescription = "Generate Kubernetes Pod YAML"
containerKubeCommand = cli.Command{ _containerKubeCommand = &cobra.Command{
Name: "kube", Use: "kube",
Usage: "Generate Kubernetes pod YAML for a container or pod", Short: "Generate Kubernetes pod YAML for a container or pod",
Description: containerKubeDescription, Long: containerKubeDescription,
Flags: sortFlags(containerKubeFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: generateKubeYAMLCmd, containerKubeCommand.InputArgs = args
ArgsUsage: "CONTAINER|POD-NAME", containerKubeCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return generateKubeYAMLCmd(&containerKubeCommand)
OnUsageError: usageErrorHandler, },
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 ( var (
podYAML *v1.Pod podYAML *v1.Pod
container *libpod.Container container *libpod.Container
@ -48,12 +50,12 @@ func generateKubeYAMLCmd(c *cli.Context) error {
if rootless.IsRootless() { if rootless.IsRootless() {
return errors.Wrapf(libpod.ErrNotImplemented, "rootless users") return errors.Wrapf(libpod.ErrNotImplemented, "rootless users")
} }
args := c.Args() args := c.InputArgs
if len(args) > 1 || (len(args) < 1 && !c.Bool("latest")) { if len(args) > 1 || (len(args) < 1 && !c.Bool("latest")) {
return errors.Errorf("you must provide one container|pod ID or name or --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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -77,7 +79,7 @@ func generateKubeYAMLCmd(c *cli.Context) error {
return err return err
} }
if c.Bool("service") { if c.Service {
serviceYAML := libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts) serviceYAML := libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts)
marshalledService, err = yaml.Marshal(serviceYAML) marshalledService, err = yaml.Marshal(serviceYAML)
if err != nil { if err != nil {

View file

@ -6,12 +6,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
const createdByTruncLength = 45 const createdByTruncLength = 45
@ -34,53 +35,44 @@ type historyOptions struct {
} }
var ( var (
historyFlags = []cli.Flag{ historyCommand cliconfig.HistoryValues
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",
},
}
historyDescription = "Displays the history of an image. The information can be printed out in an easy to read, " + 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." "or user specified format, and can be truncated."
historyCommand = cli.Command{ _historyCommand = &cobra.Command{
Name: "history", Use: "history",
Usage: "Show history of a specified image", Short: "Show history of a specified image",
Description: historyDescription, Long: historyDescription,
Flags: sortFlags(historyFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: historyCmd, historyCommand.InputArgs = args
ArgsUsage: "", historyCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return historyCmd(&historyCommand)
OnUsageError: usageErrorHandler, },
} }
) )
func historyCmd(c *cli.Context) error { func init() {
if err := validateFlags(c, historyFlags); err != nil { historyCommand.Command = _historyCommand
return err 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) 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 { if len(args) == 0 {
return errors.Errorf("an image name must be specified") return errors.Errorf("an image name must be specified")
} }
@ -93,9 +85,9 @@ func historyCmd(c *cli.Context) error {
return err return err
} }
opts := historyOptions{ opts := historyOptions{
human: c.BoolT("human"), human: c.Human,
noTrunc: c.Bool("no-trunc"), noTrunc: c.NoTrunc,
quiet: c.Bool("quiet"), quiet: c.Quiet,
format: format, format: format,
} }

View file

@ -1,37 +1,35 @@
package main package main
import ( import (
"sort" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"github.com/urfave/cli"
) )
var ( var (
imageSubCommands = []cli.Command{
importCommand,
historyCommand,
imageExistsCommand,
inspectCommand,
lsImagesCommand,
pruneImagesCommand,
pullCommand,
rmImageCommand,
tagCommand,
}
imageDescription = "Manage images" imageDescription = "Manage images"
imageCommand = cli.Command{ imageCommand = cliconfig.PodmanCommand{
Name: "image", Command: &cobra.Command{
Usage: "Manage images", Use: "image",
Description: imageDescription, Short: "Manage images",
ArgsUsage: "", Long: imageDescription,
Subcommands: getImageSubCommandsSorted(), },
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
} }
) )
func getImageSubCommandsSorted() []cli.Command { //imageSubCommands are implemented both in local and remote clients
imageSubCommands = append(imageSubCommands, getImageSubCommands()...) var imageSubCommands = []*cobra.Command{
sort.Sort(commandSortedAlpha{imageSubCommands}) _historyCommand,
return imageSubCommands _imageExistsCommand,
_inspectCommand,
_imagesCommand,
_pruneImagesCommand,
_pushCommand,
_rmiCommand,
_tagCommand,
}
func init() {
imageCommand.AddCommand(imageSubCommands...)
imageCommand.AddCommand(getImageSubCommands()...)
rootCmd.AddCommand(imageCommand.Command)
} }

View file

@ -8,6 +8,7 @@ import (
"time" "time"
"unicode" "unicode"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/imagefilters" "github.com/containers/libpod/cmd/podman/imagefilters"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
@ -16,7 +17,7 @@ import (
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
type imagesTemplateParams struct { type imagesTemplateParams struct {
@ -83,108 +84,79 @@ func (a imagesSortedSize) Less(i, j int) bool {
} }
var ( var (
imagesFlags = []cli.Flag{ imagesCommand cliconfig.ImagesValues
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",
},
}
imagesDescription = "lists locally stored images." imagesDescription = "lists locally stored images."
imagesCommand = cli.Command{
Name: "images", _imagesCommand = &cobra.Command{
Usage: "List images in local storage", Use: "images",
Description: imagesDescription, Short: "List images in local storage",
Flags: sortFlags(imagesFlags), Long: imagesDescription,
Action: imagesCmd, RunE: func(cmd *cobra.Command, args []string) error {
ArgsUsage: "", imagesCommand.InputArgs = args
UseShortOptionHandling: true, imagesCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return imagesCmd(&imagesCommand)
} },
lsImagesCommand = cli.Command{ Example: "",
Name: "list",
Aliases: []string{"ls"},
Usage: "List images in local storage",
Description: imagesDescription,
Flags: imagesFlags,
Action: imagesCmd,
ArgsUsage: "",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
} }
) )
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 ( var (
filterFuncs []imagefilters.ResultFilter filterFuncs []imagefilters.ResultFilter
newImage *adapter.ContainerImage 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 { if err != nil {
return errors.Wrapf(err, "Could not get runtime") return errors.Wrapf(err, "Could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if len(c.Args()) == 1 { if len(c.InputArgs) == 1 {
newImage, err = runtime.NewImageFromLocal(c.Args().Get(0)) newImage, err = runtime.NewImageFromLocal(c.InputArgs[0])
if err != nil { if err != nil {
return err return err
} }
} }
if len(c.Args()) > 1 { if len(c.InputArgs) > 1 {
return errors.New("'podman images' requires at most 1 argument") return errors.New("'podman images' requires at most 1 argument")
} }
ctx := getContext() ctx := getContext()
if len(c.StringSlice("filter")) > 0 || newImage != nil { if len(c.Filter) > 0 || newImage != nil {
filterFuncs, err = CreateFilterFuncs(ctx, runtime, c, newImage) filterFuncs, err = CreateFilterFuncs(ctx, runtime, c.Filter, newImage)
if err != nil { if err != nil {
return err return err
} }
} }
opts := imagesOptions{ opts := imagesOptions{
quiet: c.Bool("quiet"), quiet: c.Quiet,
noHeading: c.Bool("noheading"), noHeading: c.Noheading,
noTrunc: c.Bool("no-trunc"), noTrunc: c.NoTrunc,
digests: c.Bool("digests"), digests: c.Digests,
format: c.String("format"), format: c.Format,
sort: c.String("sort"), sort: c.Sort,
all: c.Bool("all"), all: c.All,
} }
opts.outputformat = opts.setOutputFormat() opts.outputformat = opts.setOutputFormat()
@ -195,7 +167,7 @@ func imagesCmd(c *cli.Context) error {
var filteredImages []*adapter.ContainerImage var filteredImages []*adapter.ContainerImage
//filter the images //filter the images
if len(c.StringSlice("filter")) > 0 || newImage != nil { if len(c.Filter) > 0 || newImage != nil {
filteredImages = imagefilters.FilterImages(images, filterFuncs) filteredImages = imagefilters.FilterImages(images, filterFuncs)
} else { } else {
filteredImages = images 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 // CreateFilterFuncs returns an array of filter functions based on the user inputs
// and is later used to filter images for output // 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 var filterFuncs []imagefilters.ResultFilter
for _, filter := range c.StringSlice("filter") { for _, filter := range filters {
splitFilter := strings.Split(filter, "=") splitFilter := strings.Split(filter, "=")
switch splitFilter[0] { switch splitFilter[0] {
case "before": case "before":

View file

@ -3,35 +3,39 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
pruneImagesCommand cliconfig.PruneImagesValues
pruneImagesDescription = ` pruneImagesDescription = `
podman image prune podman image prune
Removes all unnamed images from local storage Removes all unnamed images from local storage
` `
pruneImageFlags = []cli.Flag{ _pruneImagesCommand = &cobra.Command{
cli.BoolFlag{ Use: "prune",
Name: "all, a", Short: "Remove unused images",
Usage: "Remove all unused images, not just dangling ones", 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 { func init() {
runtime, err := adapter.GetRuntime(c) 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") 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 // Call prune; if any cids are returned, print them and then
// return err in case an error also came up // 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 { if len(pruneCids) > 0 {
for _, cid := range pruneCids { for _, cid := range pruneCids {
fmt.Println(cid) fmt.Println(cid)

View file

@ -3,47 +3,44 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
importFlags = []cli.Flag{ importCommand cliconfig.ImportValues
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",
},
}
importDescription = `Create a container image from the contents of the specified tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz). 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. Note remote tar balls can be specified, via web address.
Optionally tag the image. You can specify the instructions using the --change option. Optionally tag the image. You can specify the instructions using the --change option.
` `
importCommand = cli.Command{ _importCommand = &cobra.Command{
Name: "import", Use: "import",
Usage: "Import a tarball to create a filesystem image", Short: "Import a tarball to create a filesystem image",
Description: importDescription, Long: importDescription,
Flags: sortFlags(importFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: importCmd, importCommand.InputArgs = args
ArgsUsage: "TARBALL [REFERENCE]", importCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return importCmd(&importCommand)
},
Example: "TARBALL [REFERENCE]",
} }
) )
func importCmd(c *cli.Context) error { func init() {
if err := validateFlags(c, importFlags); err != nil { importCommand.Command = _importCommand
return err 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -54,7 +51,7 @@ func importCmd(c *cli.Context) error {
reference string reference string
) )
args := c.Args() args := c.InputArgs
switch len(args) { switch len(args) {
case 0: case 0:
return errors.Errorf("need to give the path to the tarball, or must specify a tarball of '-' for stdin") 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 return err
} }
quiet := c.Bool("quiet") quiet := c.Quiet
if runtime.Remote { if runtime.Remote {
quiet = false quiet = false
} }

View file

@ -4,45 +4,47 @@ import (
"fmt" "fmt"
rt "runtime" rt "runtime"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/containers/libpod/version" "github.com/containers/libpod/version"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
infoCommand cliconfig.InfoValues
infoDescription = "Display podman system information" infoDescription = "Display podman system information"
infoCommand = cli.Command{ _infoCommand = &cobra.Command{
Name: "info", Use: "info",
Usage: infoDescription, Long: infoDescription,
Description: `Information display here pertain to the host, current storage stats, and build of podman. Useful for the user and when reporting issues.`, Short: `Display information pertaining to the host, current storage stats, and build of podman. Useful for the user and when reporting issues.`,
Flags: sortFlags(infoFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: infoCmd, infoCommand.InputArgs = args
ArgsUsage: "", infoCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return infoCmd(&infoCommand)
}
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",
}, },
Example: "",
} }
) )
func infoCmd(c *cli.Context) error { func init() {
if err := validateFlags(c, infoFlags); err != nil { infoCommand.Command = _infoCommand
return err 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{}{} info := map[string]interface{}{}
remoteClientInfo := map[string]interface{}{} remoteClientInfo := map[string]interface{}{}
runtime, err := adapter.GetRuntime(c) runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") 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}) infoArr = append(infoArr, libpod.InfoData{Type: "client", Data: remoteClientInfo})
} }
if !runtime.Remote && c.Bool("debug") { if !runtime.Remote && c.Debug {
debugInfo := debugInfo(c) debugInfo := debugInfo(c)
infoArr = append(infoArr, libpod.InfoData{Type: "debug", Data: debugInfo}) infoArr = append(infoArr, libpod.InfoData{Type: "debug", Data: debugInfo})
} }
@ -69,7 +71,7 @@ func infoCmd(c *cli.Context) error {
} }
var out formats.Writer var out formats.Writer
infoOutputFormat := c.String("format") infoOutputFormat := c.Format
switch infoOutputFormat { switch infoOutputFormat {
case formats.JSONString: case formats.JSONString:
out = formats.JSONStruct{Output: info} out = formats.JSONStruct{Output: info}
@ -85,11 +87,11 @@ func infoCmd(c *cli.Context) error {
} }
// top-level "debug" info // 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 := map[string]interface{}{}
info["compiler"] = rt.Compiler info["compiler"] = rt.Compiler
info["go version"] = rt.Version() info["go version"] = rt.Version()
info["podman version"] = c.App.Version info["podman version"] = version.Version
version, _ := libpod.GetVersion() version, _ := libpod.GetVersion()
info["git commit"] = version.GitCommit info["git commit"] = version.GitCommit
return info return info

View file

@ -5,13 +5,14 @@ import (
"encoding/json" "encoding/json"
"strings" "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
cc "github.com/containers/libpod/pkg/spec" cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
const ( const (
@ -21,38 +22,37 @@ const (
) )
var ( var (
inspectFlags = []cli.Flag{ inspectCommand cliconfig.InspectValues
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,
}
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." 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{ _inspectCommand = &cobra.Command{
Name: "inspect", Use: "inspect",
Usage: "Display the configuration of a container or image", Short: "Display the configuration of a container or image",
Description: inspectDescription, Long: inspectDescription,
Flags: sortFlags(inspectFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: inspectCmd, inspectCommand.InputArgs = args
ArgsUsage: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...", inspectCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return inspectCmd(&inspectCommand)
},
Example: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...",
} }
) )
func inspectCmd(c *cli.Context) error { func init() {
args := c.Args() inspectCommand.Command = _inspectCommand
inspectType := c.String("type") flags := inspectCommand.Flags()
latestContainer := c.Bool("latest") 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 { if len(args) == 0 && !latestContainer {
return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name") 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 { if len(args) > 0 && latestContainer {
return errors.Errorf("you cannot provide additional arguments with --latest") 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 { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") 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) 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}}") { if strings.Contains(outputFormat, "{{.Id}}") {
outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1) outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1)
} }
@ -87,7 +84,7 @@ func inspectCmd(c *cli.Context) error {
inspectType = inspectTypeContainer inspectType = inspectTypeContainer
} }
inspectedObjects, iterateErr := iterateInput(getContext(), c, args, runtime, inspectType) inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, args, runtime, inspectType)
if iterateErr != nil { if iterateErr != nil {
return iterateErr 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 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 ( var (
data interface{} data interface{}
inspectedItems []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) inspectError = errors.Wrapf(err, "error looking up container %q", input)
break break
} }
libpodInspectData, err := ctr.Inspect(c.Bool("size")) libpodInspectData, err := ctr.Inspect(size)
if err != nil { if err != nil {
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID()) inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
break break
@ -160,7 +157,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *a
break break
} }
} else { } else {
libpodInspectData, err := ctr.Inspect(c.Bool("size")) libpodInspectData, err := ctr.Inspect(size)
if err != nil { if err != nil {
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID()) inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
break break

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"syscall" "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
@ -11,68 +12,66 @@ import (
"github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/signal"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
killFlags = []cli.Flag{ killCommand cliconfig.KillValues
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,
}
killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal." killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal."
killCommand = cli.Command{ _killCommand = &cobra.Command{
Name: "kill", Use: "kill",
Usage: "Kill one or more running containers with a specific signal", Short: "Kill one or more running containers with a specific signal",
Description: killDescription, Long: killDescription,
Flags: sortFlags(killFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: killCmd, killCommand.InputArgs = args
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]", killCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return killCmd(&killCommand)
OnUsageError: usageErrorHandler, },
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 // killCmd kills one or more containers with a signal
func killCmd(c *cli.Context) error { func killCmd(c *cliconfig.KillValues) error {
var ( var (
killFuncs []shared.ParallelWorkerInput killFuncs []shared.ParallelWorkerInput
killSignal uint = uint(syscall.SIGTERM) killSignal uint = uint(syscall.SIGTERM)
) )
if err := checkAllAndLatest(c); err != nil { if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err
}
if err := validateFlags(c, killFlags); err != nil {
return err return err
} }
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if c.String("signal") != "" { if c.Signal != "" {
// Check if the signalString provided by the user is valid // Check if the signalString provided by the user is valid
// Invalid signals will return err // Invalid signals will return err
sysSignal, err := signal.ParseSignal(c.String("signal")) sysSignal, err := signal.ParseSignal(c.Signal)
if err != nil { if err != nil {
return err return err
} }
killSignal = uint(sysSignal) killSignal = uint(sysSignal)
} }
containers, err := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running") containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
if err != nil { if err != nil {
if len(containers) == 0 { if len(containers) == 0 {
return err return err
@ -94,7 +93,7 @@ func killCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("kill") maxWorkers := shared.Parallelize("kill")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -1,15 +1,15 @@
package libpodruntime package libpodruntime
import ( import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli"
) )
// GetRuntime generates a new libpod runtime configured by command line options // 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{} options := []libpod.RuntimeOption{}
storageOpts, volumePath, err := util.GetDefaultStoreOptions() storageOpts, volumePath, err := util.GetDefaultStoreOptions()
@ -17,29 +17,39 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
return nil, err return nil, err
} }
if c.IsSet("uidmap") || c.IsSet("gidmap") || c.IsSet("subuidmap") || c.IsSet("subgidmap") { uidmapFlag := c.Flags().Lookup("uidmap")
mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap")) 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 { if err != nil {
return nil, err return nil, err
} }
storageOpts.UIDMap = mappings.UIDMap storageOpts.UIDMap = mappings.UIDMap
storageOpts.GIDMap = mappings.GIDMap storageOpts.GIDMap = mappings.GIDMap
} }
if c.GlobalIsSet("root") { if c.Flags().Changed("root") {
storageOpts.GraphRoot = c.GlobalString("root") storageOpts.GraphRoot = c.GlobalFlags.Root
} }
if c.GlobalIsSet("runroot") { if c.Flags().Changed("runroot") {
storageOpts.RunRoot = c.GlobalString("runroot") storageOpts.RunRoot = c.GlobalFlags.Runroot
} }
if len(storageOpts.RunRoot) > 50 { if len(storageOpts.RunRoot) > 50 {
return nil, errors.New("the specified runroot is longer than 50 characters") return nil, errors.New("the specified runroot is longer than 50 characters")
} }
if c.GlobalIsSet("storage-driver") { if c.Flags().Changed("storage-driver") {
storageOpts.GraphDriverName = c.GlobalString("storage-driver") storageOpts.GraphDriverName = c.GlobalFlags.StorageDriver
} }
if c.GlobalIsSet("storage-opt") { if c.Flags().Changed("storage-opt") {
storageOpts.GraphDriverOptions = c.GlobalStringSlice("storage-opt") storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts
} }
options = append(options, libpod.WithStorageConfig(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 flags for image config?
// TODO CLI flag for signature policy? // TODO CLI flag for signature policy?
if c.GlobalIsSet("namespace") { if len(c.GlobalFlags.Namespace) > 0 {
options = append(options, libpod.WithNamespace(c.GlobalString("namespace"))) options = append(options, libpod.WithNamespace(c.GlobalFlags.Namespace))
} }
if c.GlobalIsSet("runtime") { if c.Flags().Changed("runtime") {
options = append(options, libpod.WithOCIRuntime(c.GlobalString("runtime"))) options = append(options, libpod.WithOCIRuntime(c.GlobalFlags.Runtime))
} }
if c.GlobalIsSet("conmon") { if c.Flags().Changed("conmon") {
options = append(options, libpod.WithConmonPath(c.GlobalString("conmon"))) options = append(options, libpod.WithConmonPath(c.GlobalFlags.ConmonPath))
} }
if c.GlobalIsSet("tmpdir") { if c.Flags().Changed("tmpdir") {
options = append(options, libpod.WithTmpDir(c.GlobalString("tmpdir"))) options = append(options, libpod.WithTmpDir(c.GlobalFlags.TmpDir))
} }
if c.GlobalIsSet("cgroup-manager") { if c.Flags().Changed("cgroup-manager") {
options = append(options, libpod.WithCgroupManager(c.GlobalString("cgroup-manager"))) options = append(options, libpod.WithCgroupManager(c.GlobalFlags.CGroupManager))
} else { } else {
if rootless.IsRootless() { if rootless.IsRootless() {
options = append(options, libpod.WithCgroupManager("cgroupfs")) 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 static dir?
// TODO flag to set libpod tmp dir? // TODO flag to set libpod tmp dir?
if c.GlobalIsSet("cni-config-dir") { if c.Flags().Changed("cni-config-dir") {
options = append(options, libpod.WithCNIConfigDir(c.GlobalString("cni-config-dir"))) options = append(options, libpod.WithCNIConfigDir(c.GlobalFlags.CniConfigDir))
} }
if c.GlobalIsSet("default-mounts-file") { if c.Flags().Changed("default-mounts-file") {
options = append(options, libpod.WithDefaultMountsFile(c.GlobalString("default-mounts-file"))) options = append(options, libpod.WithDefaultMountsFile(c.GlobalFlags.DefaultMountsFile))
} }
if c.GlobalIsSet("hooks-dir") { if c.Flags().Changed("hooks-dir") {
options = append(options, libpod.WithHooksDir(c.GlobalStringSlice("hooks-dir")...)) options = append(options, libpod.WithHooksDir(c.GlobalFlags.HooksDir...))
} }
// TODO flag to set CNI plugins dir? // 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 // 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") { infraCommandFlag := c.Flags().Lookup("infra-command")
options = append(options, libpod.WithDefaultInfraCommand(c.String("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)) options = append(options, libpod.WithVolumePath(volumePath))
if c.IsSet("config") { if c.Flags().Changed("config") {
return libpod.NewRuntimeFromConfig(c.String("config"), options...) return libpod.NewRuntimeFromConfig(c.GlobalFlags.Config, options...)
} }
return libpod.NewRuntime(options...) return libpod.NewRuntime(options...)
} }

View file

@ -9,45 +9,44 @@ import (
"github.com/containers/image/directory" "github.com/containers/image/directory"
dockerarchive "github.com/containers/image/docker/archive" dockerarchive "github.com/containers/image/docker/archive"
ociarchive "github.com/containers/image/oci/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/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
loadFlags = []cli.Flag{ loadCommand cliconfig.LoadValues
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)",
},
}
loadDescription = "Loads the image from docker-archive stored on the local machine." loadDescription = "Loads the image from docker-archive stored on the local machine."
loadCommand = cli.Command{ _loadCommand = &cobra.Command{
Name: "load", Use: "load",
Usage: "Load an image from docker archive", Short: "Load an image from docker archive",
Description: loadDescription, Long: loadDescription,
Flags: sortFlags(loadFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: loadCmd, loadCommand.InputArgs = args
ArgsUsage: "", loadCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 // loadCmd gets the image/file to be loaded from the command line
// and calls loadImage to load the image to containers-storage // 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 var imageName string
if len(args) == 1 { if len(args) == 1 {
@ -56,17 +55,14 @@ func loadCmd(c *cli.Context) error {
if len(args) > 1 { if len(args) > 1 {
return errors.New("too many arguments. Requires exactly 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
input := c.String("input") input := c.Input
if input == "/dev/stdin" { if input == "/dev/stdin" {
fi, err := os.Stdin.Stat() fi, err := os.Stdin.Stat()
@ -101,7 +97,7 @@ func loadCmd(c *cli.Context) error {
} }
var writer io.Writer var writer io.Writer
if !c.Bool("quiet") { if !c.Quiet {
writer = os.Stderr writer = os.Stderr
} }
@ -110,18 +106,18 @@ func loadCmd(c *cli.Context) error {
var newImages []*image.Image var newImages []*image.Image
src, err := dockerarchive.ParseReference(input) // FIXME? We should add dockerarchive.NewReference() src, err := dockerarchive.ParseReference(input) // FIXME? We should add dockerarchive.NewReference()
if err == nil { 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 { if err != nil {
// generate full src name with specified image:tag // generate full src name with specified image:tag
src, err := ociarchive.NewReference(input, imageName) // imageName may be "" src, err := ociarchive.NewReference(input, imageName) // imageName may be ""
if err == nil { 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 { if err != nil {
src, err := directory.NewReference(input) src, err := directory.NewReference(input)
if err == nil { 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 { if err != nil {
return errors.Wrapf(err, "error pulling %q", input) return errors.Wrapf(err, "error pulling %q", input)

View file

@ -9,55 +9,48 @@ import (
"github.com/containers/image/docker" "github.com/containers/image/docker"
"github.com/containers/image/pkg/docker/config" "github.com/containers/image/pkg/docker/config"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/common" "github.com/containers/libpod/libpod/common"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
) )
var ( var (
loginFlags = []cli.Flag{ loginCommand cliconfig.LoginValues
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)",
},
}
loginDescription = "Login to a container registry on a specified server." loginDescription = "Login to a container registry on a specified server."
loginCommand = cli.Command{ _loginCommand = &cobra.Command{
Name: "login", Use: "login",
Usage: "Login to a container registry", Short: "Login to a container registry",
Description: loginDescription, Long: loginDescription,
Flags: sortFlags(loginFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: loginCmd, loginCommand.InputArgs = args
ArgsUsage: "REGISTRY", loginCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 // loginCmd uses the authentication package to store a user's authenticated credentials
// in an auth.json file for future use // in an auth.json file for future use
func loginCmd(c *cli.Context) error { func loginCmd(c *cliconfig.LoginValues) error {
args := c.Args() args := c.InputArgs
if len(args) > 1 { if len(args) > 1 {
return errors.Errorf("too many arguments, login takes only 1 argument") 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") return errors.Errorf("please specify a registry to login to")
} }
server := registryFromFullName(scrubServer(args[0])) server := registryFromFullName(scrubServer(args[0]))
authfile := getAuthFile(c.String("authfile")) authfile := getAuthFile(c.Authfile)
sc := common.GetSystemContext("", authfile, false) sc := common.GetSystemContext("", authfile, false)
if c.IsSet("tls-verify") { if c.Flag("tls-verify").Changed {
sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify")) sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
} }
if c.String("cert-dir") != "" { if c.CertDir != "" {
sc.DockerCertPath = c.String("cert-dir") sc.DockerCertPath = c.CertDir
} }
if c.IsSet("get-login") { if c.Flag("get-login").Changed {
user, err := config.GetUserLoggedIn(sc, server) user, err := config.GetUserLoggedIn(sc, server)
if err != nil { if err != nil {
@ -98,7 +91,7 @@ func loginCmd(c *cli.Context) error {
ctx := getContext() ctx := getContext()
// If no username and no password is specified, try to use existing ones. // 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...") fmt.Println("Authenticating with existing credentials...")
if err := docker.CheckAuth(ctx, sc, userFromAuthFile, passFromAuthFile, server); err == nil { if err := docker.CheckAuth(ctx, sc, userFromAuthFile, passFromAuthFile, server); err == nil {
fmt.Println("Existing credentials are valid. Already logged in to", server) 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") 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 { if err != nil {
return errors.Wrapf(err, "error getting username and password") return errors.Wrapf(err, "error getting username and password")
} }

View file

@ -4,53 +4,56 @@ import (
"fmt" "fmt"
"github.com/containers/image/pkg/docker/config" "github.com/containers/image/pkg/docker/config"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/common" "github.com/containers/libpod/libpod/common"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
logoutFlags = []cli.Flag{ logoutCommand cliconfig.LogoutValues
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",
},
}
logoutDescription = "Remove the cached username and password for the registry." logoutDescription = "Remove the cached username and password for the registry."
logoutCommand = cli.Command{ _logoutCommand = &cobra.Command{
Name: "logout", Use: "logout",
Usage: "Logout of a container registry", Short: "Logout of a container registry",
Description: logoutDescription, Long: logoutDescription,
Flags: sortFlags(logoutFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: logoutCmd, logoutCommand.InputArgs = args
ArgsUsage: "REGISTRY", logoutCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 // logoutCmd uses the authentication package to remove the authenticated of a registry
// stored in the auth.json file // stored in the auth.json file
func logoutCmd(c *cli.Context) error { func logoutCmd(c *cliconfig.LogoutValues) error {
args := c.Args() args := c.InputArgs
if len(args) > 1 { if len(args) > 1 {
return errors.Errorf("too many arguments, logout takes at most 1 argument") 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") return errors.Errorf("registry must be given")
} }
var server string var server string
if len(args) == 1 { if len(args) == 1 {
server = scrubServer(args[0]) server = scrubServer(args[0])
} }
authfile := getAuthFile(c.String("authfile")) authfile := getAuthFile(c.Authfile)
sc := common.GetSystemContext("", authfile, false) sc := common.GetSystemContext("", authfile, false)
if c.Bool("all") { if c.All {
if err := config.RemoveAllAuthentication(sc); err != nil { if err := config.RemoveAllAuthentication(sc); err != nil {
return err return err
} }

View file

@ -4,91 +4,82 @@ import (
"os" "os"
"time" "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/logs" "github.com/containers/libpod/pkg/logs"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
logsFlags = []cli.Flag{ logsCommand cliconfig.LogsValues
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,
}
logsDescription = "The podman logs command batch-retrieves whatever logs are present for a container at the time of execution. This does not guarantee execution" + 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" "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{ _logsCommand = &cobra.Command{
Name: "logs", Use: "logs",
Usage: "Fetch the logs of a container", Short: "Fetch the logs of a container",
Description: logsDescription, Long: logsDescription,
Flags: sortFlags(logsFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: logsCmd, logsCommand.InputArgs = args
ArgsUsage: "CONTAINER", logsCommand.GlobalFlags = MainGlobalOpts
SkipArgReorder: true, return logsCmd(&logsCommand)
OnUsageError: usageErrorHandler, },
UseShortOptionHandling: true, 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 ctr *libpod.Container
var err error 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
args := c.Args() args := c.InputArgs
if len(args) != 1 && !c.Bool("latest") { if len(args) != 1 && !c.Latest {
return errors.Errorf("'podman logs' requires exactly one container name/ID") return errors.Errorf("'podman logs' requires exactly one container name/ID")
} }
sinceTime := time.Time{} sinceTime := time.Time{}
if c.IsSet("since") { if c.Flag("since").Changed {
// parse time, error out if something is wrong // parse time, error out if something is wrong
since, err := parseInputTime(c.String("since")) since, err := parseInputTime(c.Since)
if err != nil { 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 sinceTime = since
} }
opts := &logs.LogOptions{ opts := &logs.LogOptions{
Details: c.Bool("details"), Details: c.Details,
Follow: c.Bool("follow"), Follow: c.Follow,
Since: sinceTime, Since: sinceTime,
Tail: c.Uint64("tail"), Tail: c.Tail,
Timestamps: c.Bool("timestamps"), Timestamps: c.Timestamps,
} }
if c.Bool("latest") { if c.Latest {
ctr, err = runtime.GetLatestContainer() ctr, err = runtime.GetLatestContainer()
} else { } else {
ctr, err = runtime.LookupContainer(args[0]) ctr, err = runtime.LookupContainer(args[0])

View file

@ -6,9 +6,10 @@ import (
"os" "os"
"os/exec" "os/exec"
"runtime/pprof" "runtime/pprof"
"sort" "strings"
"syscall" "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
_ "github.com/containers/libpod/pkg/hooks/0.1.0" _ "github.com/containers/libpod/pkg/hooks/0.1.0"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
@ -17,7 +18,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
lsyslog "github.com/sirupsen/logrus/hooks/syslog" 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 // This is populated by the Makefile from the VERSION file
@ -26,198 +27,159 @@ var (
exitCode = 125 exitCode = 125
) )
var cmdsNotRequiringRootless = map[string]bool{ var cmdsNotRequiringRootless = map[*cobra.Command]bool{
"help": true, _versionCommand: true,
"version": true, _createCommand: true,
"create": true, _execCommand: true,
"exec": true, _exportCommand: true,
"export": true, //// `info` must be executed in an user namespace.
// `info` must be executed in an user namespace. //// If this change, please also update libpod.refreshRootless()
// If this change, please also update libpod.refreshRootless() _loginCommand: true,
"login": true, _logoutCommand: true,
"logout": true, _mountCommand: true,
"mount": true, _killCommand: true,
"kill": true, _pauseCommand: true,
"pause": true, _restartCommand: true,
"restart": true, _runCommmand: true,
"run": true, _unpauseCommand: true,
"unpause": true, _searchCommand: true,
"search": true, _statsCommand: true,
"stats": true, _stopCommand: true,
"stop": true, _topCommand: true,
"top": true,
} }
type commandSorted []cli.Command var rootCmd = &cobra.Command{
Use: "podman",
func (a commandSorted) Len() int { return len(a) } Long: "manage pods and images",
func (a commandSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] } RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
type commandSortedAlpha struct{ commandSorted } },
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
func (a commandSortedAlpha) Less(i, j int) bool { return before(cmd, args)
return a.commandSorted[i].Name < a.commandSorted[j].Name },
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 init() {
func (a flagSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 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() { func main() {
debug := false //debug := false
cpuProfile := false //cpuProfile := false
if reexec.Init() { if reexec.Init() {
return return
} }
if err := rootCmd.Execute(); err != nil {
app := cli.NewApp() if MainGlobalOpts.LogLevel == "debug" {
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 {
logrus.Errorf(err.Error()) logrus.Errorf(err.Error())
} else { } else {
// Retrieve the exit error from the exec call, if it exists
if ee, ok := err.(*exec.ExitError); ok { if ee, ok := err.(*exec.ExitError); ok {
if status, ok := ee.Sys().(syscall.WaitStatus); ok { if status, ok := ee.Sys().(syscall.WaitStatus); ok {
exitCode = status.ExitStatus() exitCode = status.ExitStatus()
@ -233,6 +195,11 @@ func main() {
if exitCode == 125 { if exitCode == 125 {
exitCode = 0 exitCode = 0
} }
} }
// Check if /etc/containers/registries.conf exists when running in
// in a local environment.
CheckForRegistries()
os.Exit(exitCode) os.Exit(exitCode)
} }

View file

@ -5,15 +5,18 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
of "github.com/containers/libpod/cmd/podman/formats" of "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
mountCommand cliconfig.MountValues
mountDescription = ` mountDescription = `
podman mount podman mount
Lists all mounted containers mount points Lists all mounted containers mount points
@ -22,32 +25,29 @@ var (
Mounts the specified container and outputs the mountpoint Mounts the specified container and outputs the mountpoint
` `
mountFlags = []cli.Flag{ _mountCommand = &cobra.Command{
cli.BoolFlag{ Use: "mount",
Name: "all, a", Short: "Mount a working container's root filesystem",
Usage: "Mount all containers", 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 // jsonMountPoint stores info about each container
type jsonMountPoint struct { type jsonMountPoint struct {
ID string `json:"id"` ID string `json:"id"`
@ -55,15 +55,12 @@ type jsonMountPoint struct {
MountPoint string `json:"mountpoint"` MountPoint string `json:"mountpoint"`
} }
func mountCmd(c *cli.Context) error { func mountCmd(c *cliconfig.MountValues) error {
if err := validateFlags(c, mountFlags); err != nil {
return err
}
if os.Geteuid() != 0 { if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") 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") 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 err != nil {
if len(mountContainers) == 0 { if len(mountContainers) == 0 {
return err return err
@ -102,9 +99,9 @@ func mountCmd(c *cli.Context) error {
of.JSONString: true, of.JSONString: true,
} }
json := c.String("format") == of.JSONString json := c.Format == of.JSONString
if !formats[c.String("format")] { if !formats[c.Format] {
return errors.Errorf("%q is not a supported format", c.String("format")) return errors.Errorf("%q is not a supported format", c.Format)
} }
var lastError error var lastError error
@ -149,7 +146,7 @@ func mountCmd(c *cli.Context) error {
continue continue
} }
if c.Bool("notruncate") { if c.NoTrunc {
fmt.Printf("%-64s %s\n", container.ID(), mountPoint) fmt.Printf("%-64s %s\n", container.ID(), mountPoint)
} else { } else {
fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint) fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint)

View file

@ -3,38 +3,44 @@ package main
import ( import (
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
pauseFlags = []cli.Flag{ pauseCommand cliconfig.PauseValues
cli.BoolFlag{
Name: "all, a",
Usage: "Pause all running containers",
},
}
pauseDescription = ` pauseDescription = `
podman pause podman pause
Pauses one or more running containers. The container name or ID can be used. Pauses one or more running containers. The container name or ID can be used.
` `
pauseCommand = cli.Command{ _pauseCommand = &cobra.Command{
Name: "pause", Use: "pause",
Usage: "Pause all the processes in one or more containers", Short: "Pause all the processes in one or more containers",
Description: pauseDescription, Long: pauseDescription,
Flags: pauseFlags, RunE: func(cmd *cobra.Command, args []string) error {
Action: pauseCmd, pauseCommand.InputArgs = args
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]", pauseCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 ( var (
pauseContainers []*libpod.Container pauseContainers []*libpod.Container
pauseFuncs []shared.ParallelWorkerInput pauseFuncs []shared.ParallelWorkerInput
@ -43,18 +49,18 @@ func pauseCmd(c *cli.Context) error {
return errors.New("pause is not supported for rootless containers") return errors.New("pause is not supported for rootless containers")
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
args := c.Args() args := c.InputArgs
if len(args) < 1 && !c.Bool("all") { if len(args) < 1 && !c.All {
return errors.Errorf("you must provide at least one container name or id") return errors.Errorf("you must provide at least one container name or id")
} }
if c.Bool("all") { if c.All {
containers, err := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running") containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
if err != nil { if err != nil {
return err return err
} }
@ -84,7 +90,7 @@ func pauseCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("pause") maxWorkers := shared.Parallelize("pause")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -1,23 +1,23 @@
package main package main
import ( import (
"github.com/urfave/cli" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
) )
var ( var playCommand cliconfig.PodmanCommand
playSubCommands = []cli.Command{
playKubeCommand, 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", func init() {
Usage: "Play a container or pod", playCommand.AddCommand(getPlaySubCommands()...)
Description: playDescription, rootCmd.AddCommand(playCommand.Command)
ArgsUsage: "", }
Subcommands: playSubCommands,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
Hidden: true,
}
)

View file

@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/containers/image/types" "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/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
@ -20,51 +21,40 @@ import (
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
) )
var ( var (
playKubeFlags = []cli.Flag{ playKubeCommand cliconfig.KubePlayValues
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)",
},
}
playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML" playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML"
playKubeCommand = cli.Command{ _playKubeCommand = &cobra.Command{
Name: "kube", Use: "kube",
Usage: "Play a pod based on Kubernetes YAML", Short: "Play a pod based on Kubernetes YAML",
Description: playKubeDescription, Long: playKubeDescription,
Action: playKubeYAMLCmd, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(playKubeFlags), playKubeCommand.InputArgs = args
ArgsUsage: "Kubernetes YAML file", playKubeCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return playKubeYAMLCmd(&playKubeCommand)
OnUsageError: usageErrorHandler, },
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 ( var (
podOptions []libpod.PodCreateOption podOptions []libpod.PodCreateOption
podYAML v1.Pod podYAML v1.Pod
@ -77,7 +67,7 @@ func playKubeYAMLCmd(c *cli.Context) error {
if rootless.IsRootless() { if rootless.IsRootless() {
return errors.Wrapf(libpod.ErrNotImplemented, "rootless users") return errors.Wrapf(libpod.ErrNotImplemented, "rootless users")
} }
args := c.Args() args := c.InputArgs
if len(args) > 1 { if len(args) > 1 {
return errors.New("you can only play one kubernetes file at a time") 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") return errors.New("you must supply at least one file")
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -133,20 +123,20 @@ func playKubeYAMLCmd(c *cli.Context) error {
"ipc": fmt.Sprintf("container:%s", podInfraID), "ipc": fmt.Sprintf("container:%s", podInfraID),
"uts": fmt.Sprintf("container:%s", podInfraID), "uts": fmt.Sprintf("container:%s", podInfraID),
} }
if !c.Bool("quiet") { if !c.Quiet {
writer = os.Stderr writer = os.Stderr
} }
dockerRegistryOptions := image2.DockerRegistryOptions{ dockerRegistryOptions := image2.DockerRegistryOptions{
DockerRegistryCreds: registryCreds, DockerRegistryCreds: registryCreds,
DockerCertPath: c.String("cert-dir"), DockerCertPath: c.CertDir,
} }
if c.IsSet("tls-verify") { if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify")) dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
} }
for _, container := range podYAML.Spec.Containers { 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 { if err != nil {
return err return err
} }

View file

@ -1,35 +1,24 @@
package main package main
import ( import (
"github.com/urfave/cli" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
) )
var ( var (
podDescription = `Manage container pods. podDescription = `Manage container pods.
Pods are a group of one or more containers sharing the same network, pid and ipc namespaces. 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,
}
) )
var podCommand = cliconfig.PodmanCommand{
Command: &cobra.Command{
Use: "pod",
Short: "Manage pods",
Long: podDescription,
},
}
func init() {
podCommand.AddCommand(getPodSubCommands()...)
rootCmd.AddCommand(podCommand.Command)
}

View file

@ -5,111 +5,81 @@ import (
"os" "os"
"strings" "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
// Kernel namespaces shared by default within a pod // Kernel namespaces shared by default within a pod
DefaultKernelNamespaces = "cgroup,ipc,net,uts" 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" + func init() {
" printed to stdout. You can then start it at any time with the" + podCreateCommand.Command = _podCreateCommand
" podman pod start <pod_id> command. The pod will be created with the" + flags := podCreateCommand.Flags()
" initial state 'created'." 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{ func podCreateCmd(c *cliconfig.PodCreateValues) error {
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 {
var options []libpod.PodCreateOption var options []libpod.PodCreateOption
var err error var err error
if err = validateFlags(c, createFlags); err != nil { runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
return err
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
var podIdFile *os.File var podIdFile *os.File
if c.IsSet("pod-id-file") && os.Geteuid() == 0 { if c.Flag("pod-id-file").Changed && os.Geteuid() == 0 {
podIdFile, err = libpod.OpenExclusiveFile(c.String("pod-id-file")) podIdFile, err = libpod.OpenExclusiveFile(c.PodIDFile)
if err != nil && os.IsExist(err) { 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 { 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.Close()
defer podIdFile.Sync() defer podIdFile.Sync()
} }
if len(c.StringSlice("publish")) > 0 { if len(c.Publish) > 0 {
if !c.BoolT("infra") { if !c.Infra {
return errors.Errorf("you must have an infra container to publish port bindings to the host") return errors.Errorf("you must have an infra container to publish port bindings to the host")
} }
if rootless.IsRootless() { 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") return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container")
} }
if c.IsSet("cgroup-parent") { if c.Flag("cgroup-parent").Changed {
options = append(options, libpod.WithPodCgroupParent(c.String("cgroup-parent"))) 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 { if err != nil {
return errors.Wrapf(err, "unable to process labels") return errors.Wrapf(err, "unable to process labels")
} }
@ -133,21 +103,21 @@ func podCreateCmd(c *cli.Context) error {
options = append(options, libpod.WithPodLabels(labels)) options = append(options, libpod.WithPodLabels(labels))
} }
if c.IsSet("name") { if c.Flag("name").Changed {
options = append(options, libpod.WithPodName(c.String("name"))) options = append(options, libpod.WithPodName(c.Name))
} }
if c.BoolT("infra") { if c.Infra {
options = append(options, libpod.WithInfraContainer()) 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 { if err != nil {
return err return err
} }
options = append(options, nsOptions...) options = append(options, nsOptions...)
} }
if len(c.StringSlice("publish")) > 0 { if len(c.Publish) > 0 {
portBindings, err := shared.CreatePortBindings(c.StringSlice("publish")) portBindings, err := shared.CreatePortBindings(c.Publish)
if err != nil { if err != nil {
return err return err
} }

View file

@ -2,46 +2,53 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podInspectFlags = []cli.Flag{ podInspectCommand cliconfig.PodInspectValues
LatestPodFlag,
}
podInspectDescription = "Display the configuration for a pod by name or id" podInspectDescription = "Display the configuration for a pod by name or id"
podInspectCommand = cli.Command{ _podInspectCommand = &cobra.Command{
Name: "inspect", Use: "inspect",
Usage: "Displays a pod configuration", Short: "Displays a pod configuration",
Description: podInspectDescription, Long: podInspectDescription,
Flags: sortFlags(podInspectFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: podInspectCmd, podInspectCommand.InputArgs = args
UseShortOptionHandling: true, podInspectCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "[POD_NAME_OR_ID]", return podInspectCmd(&podInspectCommand)
OnUsageError: usageErrorHandler, },
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 ( var (
pod *libpod.Pod pod *libpod.Pod
) )
if err := checkMutuallyExclusiveFlags(c); err != nil { if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
return err return err
} }
args := c.Args() args := c.InputArgs
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if c.Bool("latest") { if c.Latest {
pod, err = runtime.GetLatestPod() pod, err = runtime.GetLatestPod()
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to get latest pod") return errors.Wrapf(err, "unable to get latest pod")

View file

@ -4,46 +4,45 @@ import (
"fmt" "fmt"
"syscall" "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/signal"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podKillFlags = []cli.Flag{ podKillCommand cliconfig.PodKillValues
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,
}
podKillDescription = "The main process of each container inside the specified pod will be sent SIGKILL, or any signal specified with option --signal." 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{ _podKillCommand = &cobra.Command{
Name: "kill", Use: "kill",
Usage: "Send the specified signal or SIGKILL to containers in pod", Short: "Send the specified signal or SIGKILL to containers in pod",
Description: podKillDescription, Long: podKillDescription,
Flags: sortFlags(podKillFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: podKillCmd, podKillCommand.InputArgs = args
ArgsUsage: "[POD_NAME_OR_ID]", podKillCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return podKillCmd(&podKillCommand)
OnUsageError: usageErrorHandler, },
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 // podKillCmd kills one or more pods with a signal
func podKillCmd(c *cli.Context) error { func podKillCmd(c *cliconfig.PodKillValues) error {
if err := checkMutuallyExclusiveFlags(c); err != nil { if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
return err return err
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
@ -51,10 +50,10 @@ func podKillCmd(c *cli.Context) error {
var killSignal uint = uint(syscall.SIGTERM) var killSignal uint = uint(syscall.SIGTERM)
if c.String("signal") != "" { if c.Signal != "" {
// Check if the signalString provided by the user is valid // Check if the signalString provided by the user is valid
// Invalid signals will return err // Invalid signals will return err
sysSignal, err := signal.ParseSignal(c.String("signal")) sysSignal, err := signal.ParseSignal(c.Signal)
if err != nil { if err != nil {
return err return err
} }
@ -64,7 +63,7 @@ func podKillCmd(c *cli.Context) error {
// getPodsFromContext returns an error when a requested pod // getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods // isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped. // in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime) pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
for _, pod := range pods { for _, pod := range pods {
ctr_errs, err := pod.Kill(killSignal) ctr_errs, err := pod.Kill(killSignal)

View file

@ -2,43 +2,42 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podPauseFlags = []cli.Flag{ podPauseCommand cliconfig.PodPauseValues
cli.BoolFlag{ podPauseDescription = `Pauses one or more pods. The pod name or ID can be used.`
Name: "all, a", _podPauseCommand = &cobra.Command{
Usage: "Pause all running pods", 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, Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
}
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,
} }
) )
func podPauseCmd(c *cli.Context) error { func init() {
if err := checkMutuallyExclusiveFlags(c); err != nil { 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 return err
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") 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 // getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods // isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped. // in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime) pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
for _, pod := range pods { for _, pod := range pods {
ctr_errs, err := pod.Pause() ctr_errs, err := pod.Pause()

View file

@ -8,6 +8,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
@ -15,7 +16,7 @@ import (
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
const ( const (
@ -112,95 +113,68 @@ func (a podPsSortedStatus) Less(i, j int) bool {
} }
var ( var (
podPsFlags = []cli.Flag{ podPsCommand cliconfig.PodPsValues
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",
},
}
podPsDescription = "List all pods on system including their names, ids and current state." podPsDescription = "List all pods on system including their names, ids and current state."
podPsCommand = cli.Command{ _podPsCommand = &cobra.Command{
Name: "ps", Use: "ps",
Aliases: []string{"ls", "list"}, Aliases: []string{"ls", "list"},
Usage: "List pods", Short: "List pods",
Description: podPsDescription, Long: podPsDescription,
Flags: sortFlags(podPsFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: podPsCmd, podPsCommand.InputArgs = args
UseShortOptionHandling: true, podPsCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return podPsCmd(&podPsCommand)
},
} }
) )
func podPsCmd(c *cli.Context) error { func init() {
if err := validateFlags(c, podPsFlags); err != nil { podPsCommand.Command = _podPsCommand
return err 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 { if err := podPsCheckFlagsPassed(c); err != nil {
return errors.Wrapf(err, "error with flags passed") return errors.Wrapf(err, "error with flags passed")
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
return errors.Errorf("too many arguments, ps takes no arguments") return errors.Errorf("too many arguments, ps takes no arguments")
} }
opts := podPsOptions{ opts := podPsOptions{
NoTrunc: c.Bool("no-trunc"), NoTrunc: c.NoTrunc,
Quiet: c.Bool("quiet"), Quiet: c.Quiet,
Sort: c.String("sort"), Sort: c.Sort,
IdsOfContainers: c.Bool("ctr-ids"), IdsOfContainers: c.CtrIDs,
NamesOfContainers: c.Bool("ctr-names"), NamesOfContainers: c.CtrNames,
StatusOfContainers: c.Bool("ctr-status"), StatusOfContainers: c.CtrStatus,
} }
opts.Format = genPodPsFormat(c) opts.Format = genPodPsFormat(c)
var filterFuncs []libpod.PodFilter var filterFuncs []libpod.PodFilter
if c.String("filter") != "" { if c.Filter != "" {
filters := strings.Split(c.String("filter"), ",") filters := strings.Split(c.Filter, ",")
for _, f := range filters { for _, f := range filters {
filterSplit := strings.Split(f, "=") filterSplit := strings.Split(f, "=")
if len(filterSplit) < 2 { if len(filterSplit) < 2 {
@ -215,7 +189,7 @@ func podPsCmd(c *cli.Context) error {
} }
var pods []*libpod.Pod var pods []*libpod.Pod
if c.IsSet("latest") { if c.Latest {
pod, err := runtime.GetLatestPod() pod, err := runtime.GetLatestPod()
if err != nil { if err != nil {
return err return err
@ -244,13 +218,13 @@ func podPsCmd(c *cli.Context) error {
} }
// podPsCheckFlagsPassed checks if mutually exclusive flags are passed together // 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 // quiet, and format with Go template are mutually exclusive
flags := 0 flags := 0
if c.Bool("quiet") { if c.Quiet {
flags++ flags++
} }
if c.IsSet("format") && c.String("format") != formats.JSONString { if c.Flag("format").Changed && c.Format != formats.JSONString {
flags++ flags++
} }
if flags > 1 { if flags > 1 {
@ -342,20 +316,20 @@ func generatePodFilterFuncs(filter, filterValue string, runtime *libpod.Runtime)
} }
// generate the template based on conditions given // generate the template based on conditions given
func genPodPsFormat(c *cli.Context) string { func genPodPsFormat(c *cliconfig.PodPsValues) string {
format := "" format := ""
if c.String("format") != "" { if c.Format != "" {
// "\t" from the command line is not being recognized as a tab // "\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" // 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)
} else if c.Bool("quiet") { } else if c.Quiet {
format = formats.IDString format = formats.IDString
} else { } else {
format = "table {{.ID}}\t{{.Name}}\t{{.Status}}\t{{.Created}}" format = "table {{.ID}}\t{{.Name}}\t{{.Status}}\t{{.Created}}"
if c.Bool("namespace") { if c.Bool("namespace") {
format += "\t{{.Cgroup}}\t{{.Namespaces}}" 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}}" format += "\t{{.ContainerInfo}}"
} else { } else {
format += "\t{{.NumberOfContainers}}" format += "\t{{.NumberOfContainers}}"

View file

@ -3,40 +3,43 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podRestartFlags = []cli.Flag{ podRestartCommand cliconfig.PodRestartValues
cli.BoolFlag{
Name: "all, a",
Usage: "Restart all pods",
},
LatestPodFlag,
}
podRestartDescription = `Restarts one or more pods. The pod ID or name can be used.` podRestartDescription = `Restarts one or more pods. The pod ID or name can be used.`
_podRestartCommand = &cobra.Command{
podRestartCommand = cli.Command{ Use: "restart",
Name: "restart", Short: "Restart one or more pods",
Usage: "Restart one or more pods", Long: podRestartDescription,
Description: podRestartDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(podRestartFlags), podRestartCommand.InputArgs = args
Action: podRestartCmd, podRestartCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]", return podRestartCmd(&podRestartCommand)
UseShortOptionHandling: true, },
OnUsageError: usageErrorHandler, Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
} }
) )
func podRestartCmd(c *cli.Context) error { func init() {
if err := checkMutuallyExclusiveFlags(c); err != nil { 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 return err
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") 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 // getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods // isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped. // in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime) pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
ctx := getContext() ctx := getContext()
for _, pod := range pods { for _, pod := range pods {

View file

@ -3,60 +3,61 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podRmFlags = []cli.Flag{ podRmCommand cliconfig.PodRmValues
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,
}
podRmDescription = fmt.Sprintf(` podRmDescription = fmt.Sprintf(`
podman rm will remove one or more pods from the host. The pod name or ID can 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. be used. A pod with containers will not be removed without --force.
If --force is specified, all containers will be stopped, then removed. If --force is specified, all containers will be stopped, then removed.
`) `)
podRmCommand = cli.Command{ _podRmCommand = &cobra.Command{
Name: "rm", Use: "rm",
Usage: "Remove one or more pods", Short: "Remove one or more pods",
Description: podRmDescription, Long: podRmDescription,
Flags: sortFlags(podRmFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: podRmCmd, podRmCommand.InputArgs = args
ArgsUsage: "[POD ...]", podRmCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return podRmCmd(&podRmCommand)
OnUsageError: usageErrorHandler, },
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 // saveCmd saves the image to either docker-archive or oci
func podRmCmd(c *cli.Context) error { func podRmCmd(c *cliconfig.PodRmValues) error {
if err := checkMutuallyExclusiveFlags(c); err != nil { if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
return err return err
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
ctx := getContext() ctx := getContext()
force := c.Bool("force") force := c.Force
// getPodsFromContext returns an error when a requested pod // getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods // isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped. // in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime) pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
for _, pod := range pods { for _, pod := range pods {
err = runtime.RemovePod(ctx, pod, force, force) err = runtime.RemovePod(ctx, pod, force, force)

View file

@ -3,44 +3,46 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podStartFlags = []cli.Flag{ podStartCommand cliconfig.PodStartValues
cli.BoolFlag{
Name: "all, a",
Usage: "Start all running pods",
},
LatestPodFlag,
}
podStartDescription = ` podStartDescription = `
podman pod start podman pod start
Starts one or more pods. The pod name or ID can be used. Starts one or more pods. The pod name or ID can be used.
` `
_podStartCommand = &cobra.Command{
podStartCommand = cli.Command{ Use: "start",
Name: "start", Short: "Start one or more pods",
Usage: "Start one or more pods", Long: podStartDescription,
Description: podStartDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(podStartFlags), podStartCommand.InputArgs = args
Action: podStartCmd, podStartCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "POD-NAME [POD-NAME ...]", return podStartCmd(&podStartCommand)
UseShortOptionHandling: true, },
OnUsageError: usageErrorHandler, Example: "POD-NAME [POD-NAME ...]",
} }
) )
func podStartCmd(c *cli.Context) error { func init() {
if err := checkMutuallyExclusiveFlags(c); err != nil { 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 return err
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") 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 // getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods // isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped. // in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime) pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
ctx := getContext() ctx := getContext()
for _, pod := range pods { for _, pod := range pods {

View file

@ -7,54 +7,49 @@ import (
"encoding/json" "encoding/json"
tm "github.com/buger/goterm" 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/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/ulule/deepcopier" "github.com/ulule/deepcopier"
"github.com/urfave/cli"
) )
var ( var (
podStatsFlags = []cli.Flag{ podStatsCommand cliconfig.PodStatsValues
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,
}
podStatsDescription = "Display a live stream of resource usage statistics for the containers in or more pods" podStatsDescription = "Display a live stream of resource usage statistics for the containers in or more pods"
podStatsCommand = cli.Command{ _podStatsCommand = &cobra.Command{
Name: "stats", Use: "stats",
Usage: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one or more pods", Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one or more pods",
Description: podStatsDescription, Long: podStatsDescription,
Flags: sortFlags(podStatsFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: podStatsCmd, podStatsCommand.InputArgs = args
ArgsUsage: "[POD_NAME_OR_ID]", podStatsCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return podStatsCmd(&podStatsCommand)
OnUsageError: usageErrorHandler, },
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 ( var (
podFunc func() ([]*libpod.Pod, error) podFunc func() ([]*libpod.Pod, error)
) )
format := c.String("format") format := c.Format
all := c.Bool("all") all := c.All
latest := c.Bool("latest") latest := c.Latest
ctr := 0 ctr := 0
if all { if all {
ctr += 1 ctr += 1
@ -62,7 +57,7 @@ func podStatsCmd(c *cli.Context) error {
if latest { if latest {
ctr += 1 ctr += 1
} }
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
ctr += 1 ctr += 1
} }
@ -73,19 +68,19 @@ func podStatsCmd(c *cli.Context) error {
all = true all = true
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
times := -1 times := -1
if c.Bool("no-stream") { if c.NoStream {
times = 1 times = 1
} }
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.Args(), runtime) } podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.InputArgs, runtime) }
} else if latest { } else if latest {
podFunc = func() ([]*libpod.Pod, error) { podFunc = func() ([]*libpod.Pod, error) {
latestPod, err := runtime.GetLatestPod() latestPod, err := runtime.GetLatestPod()
@ -159,7 +154,7 @@ func podStatsCmd(c *cli.Context) error {
newStats = append(newStats, &newPod) newStats = append(newStats, &newPod)
} }
//Output //Output
if strings.ToLower(format) != formats.JSONString && !c.Bool("no-reset") { if strings.ToLower(format) != formats.JSONString && !c.NoReset {
tm.Clear() tm.Clear()
tm.MoveCursor(1, 1) tm.MoveCursor(1, 1)
tm.Flush() tm.Flush()

View file

@ -2,48 +2,50 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podStopFlags = []cli.Flag{ podStopCommand cliconfig.PodStopValues
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",
},
}
podStopDescription = ` podStopDescription = `
podman pod stop podman pod stop
Stops one or more running pods. The pod name or ID can be used. Stops one or more running pods. The pod name or ID can be used.
` `
podStopCommand = cli.Command{ _podStopCommand = &cobra.Command{
Name: "stop", Use: "stop",
Usage: "Stop one or more pods", Short: "Stop one or more pods",
Description: podStopDescription, Long: podStopDescription,
Flags: sortFlags(podStopFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: podStopCmd, podStopCommand.InputArgs = args
ArgsUsage: "POD-NAME [POD-NAME ...]", podStopCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 timeout := -1
if err := checkMutuallyExclusiveFlags(c); err != nil { if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
return err return err
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") 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 // getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods // isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped. // in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime) pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
ctx := getContext() ctx := getContext()
if c.IsSet("timeout") { if c.Flag("timeout").Changed {
timeout = int(c.Uint("timeout")) timeout = int(c.Timeout)
} }
for _, pod := range pods { for _, pod := range pods {
// set cleanup to true to clean mounts and namespaces // set cleanup to true to clean mounts and namespaces

View file

@ -6,21 +6,17 @@ import (
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podTopFlags = []cli.Flag{ podTopCommand cliconfig.PodTopValues
LatestFlag,
cli.BoolFlag{
Name: "list-descriptors",
Hidden: true,
},
}
podTopDescription = fmt.Sprintf(`Display the running processes containers in a pod. Specify format descriptors 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 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 the process ID, the CPU percentage and the seccomp mode of each process of
@ -28,24 +24,34 @@ the latest pod.
%s %s
`, getDescriptorString()) `, getDescriptorString())
podTopCommand = cli.Command{ _podTopCommand = &cobra.Command{
Name: "top", Use: "top",
Usage: "Display the running processes of containers in a pod", Short: "Display the running processes of containers in a pod",
Description: podTopDescription, Long: podTopDescription,
Flags: sortFlags(podTopFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: podTopCmd, podTopCommand.InputArgs = args
ArgsUsage: "POD-NAME [format descriptors]", podTopCommand.GlobalFlags = MainGlobalOpts
SkipArgReorder: true, return podTopCmd(&podTopCommand)
OnUsageError: usageErrorHandler, },
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 pod *libpod.Pod
var err error var err error
args := c.Args() args := c.InputArgs
if c.Bool("list-descriptors") { if c.ListDescriptors {
descriptors, err := libpod.GetContainerPidInformationDescriptors() descriptors, err := libpod.GetContainerPidInformationDescriptors()
if err != nil { if err != nil {
return err return err
@ -54,21 +60,18 @@ func podTopCmd(c *cli.Context) error {
return nil 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") 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 { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
var descriptors []string var descriptors []string
if c.Bool("latest") { if c.Latest {
descriptors = args descriptors = args
pod, err = runtime.GetLatestPod() pod, err = runtime.GetLatestPod()
} else { } else {

View file

@ -3,42 +3,42 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
podUnpauseFlags = []cli.Flag{ podUnpauseCommand cliconfig.PodUnpauseValues
cli.BoolFlag{ podUnpauseDescription = `Unpauses one or more pods. The pod name or ID can be used.`
Name: "all, a", _podUnpauseCommand = &cobra.Command{
Usage: "Unpause all paused pods", 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, Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
}
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,
} }
) )
func podUnpauseCmd(c *cli.Context) error { func init() {
if err := checkMutuallyExclusiveFlags(c); err != nil { 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 return err
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") 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 // getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods // isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped. // in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime) pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
for _, pod := range pods { for _, pod := range pods {
ctr_errs, err := pod.Unpause() ctr_errs, err := pod.Unpause()

View file

@ -5,38 +5,44 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
portFlags = []cli.Flag{ portCommand cliconfig.PortValues
cli.BoolFlag{
Name: "all, a",
Usage: "Display port information for all containers",
},
LatestFlag,
}
portDescription = ` portDescription = `
podman port podman port
List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT
` `
_portCommand = &cobra.Command{
portCommand = cli.Command{ Use: "port",
Name: "port", Short: "List port mappings or a specific mapping for the container",
Usage: "List port mappings or a specific mapping for the container", Long: portDescription,
Description: portDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(portFlags), portCommand.InputArgs = args
Action: portCmd, portCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "CONTAINER-NAME [mapping]", return portCmd(&portCommand)
OnUsageError: usageErrorHandler, },
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 ( var (
userProto, containerName string userProto, containerName string
userPort int userPort int
@ -44,29 +50,26 @@ func portCmd(c *cli.Context) error {
containers []*libpod.Container containers []*libpod.Container
) )
args := c.Args() args := c.InputArgs
if err := validateFlags(c, portFlags); err != nil {
return err
}
if c.Bool("latest") && c.Bool("all") { if c.Latest && c.All {
return errors.Errorf("the 'all' and 'latest' options cannot be used together") 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'") 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") 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] containerName = args[0]
} }
port := "" port := ""
if len(args) > 1 && !c.Bool("latest") { if len(args) > 1 && !c.Latest {
port = args[1] port = args[1]
} }
if len(args) == 1 && c.Bool("latest") { if len(args) == 1 && c.Latest {
port = args[0] port = args[0]
} }
if port != "" { 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if !c.Bool("latest") && !c.Bool("all") { if !c.Latest && !c.All {
container, err = runtime.LookupContainer(containerName) container, err = runtime.LookupContainer(containerName)
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to find container %s", containerName) return errors.Wrapf(err, "unable to find container %s", containerName)
} }
containers = append(containers, container) containers = append(containers, container)
} else if c.Bool("latest") { } else if c.Latest {
container, err = runtime.GetLatestContainer() container, err = runtime.GetLatestContainer()
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to get last created container") 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 { if state, _ := con.State(); state != libpod.ContainerStateRunning {
continue continue
} }
if c.Bool("all") { if c.All {
fmt.Println(con.ID()) fmt.Println(con.ID())
} }
// Iterate mappings // Iterate mappings

View file

@ -12,6 +12,7 @@ import (
"text/tabwriter" "text/tabwriter"
"time" "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
@ -21,7 +22,7 @@ import (
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
) )
@ -153,112 +154,78 @@ func (a psSortedSize) Less(i, j int) bool {
} }
var ( var (
psFlags = []cli.Flag{ psCommand cliconfig.PsValues
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",
},
}
psDescription = "Prints out information about the containers" psDescription = "Prints out information about the containers"
psCommand = cli.Command{ _psCommand = &cobra.Command{
Name: "list", Use: "list",
Aliases: []string{"ls", "ps"}, Aliases: []string{"ls", "ps"},
Usage: "List containers", Short: "List containers",
Description: psDescription, Long: psDescription,
Flags: sortFlags(psFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: psCmd, psCommand.InputArgs = args
ArgsUsage: "", psCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return psCmd(&psCommand)
OnUsageError: usageErrorHandler, },
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 ( var (
filterFuncs []libpod.ContainerFilter filterFuncs []libpod.ContainerFilter
outputContainers []*libpod.Container outputContainers []*libpod.Container
) )
if err := validateFlags(c, psFlags); err != nil {
return err
}
if err := checkFlagsPassed(c); err != nil { if err := checkFlagsPassed(c); err != nil {
return errors.Wrapf(err, "error with flags passed") return errors.Wrapf(err, "error with flags passed")
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
return errors.Errorf("too many arguments, ps takes no arguments") return errors.Errorf("too many arguments, ps takes no arguments")
} }
opts := shared.PsOptions{ opts := shared.PsOptions{
All: c.Bool("all"), All: c.All,
Format: c.String("format"), Format: c.Format,
Last: c.Int("last"), Last: c.Last,
Latest: c.Bool("latest"), Latest: c.Latest,
NoTrunc: c.Bool("no-trunc"), NoTrunc: c.NoTrunct,
Pod: c.Bool("pod"), Pod: c.Pod,
Quiet: c.Bool("quiet"), Quiet: c.Quiet,
Size: c.Bool("size"), Size: c.Size,
Namespace: c.Bool("namespace"), Namespace: c.Namespace,
Sort: c.String("sort"), Sort: c.Sort,
Sync: c.Bool("sync"), Sync: c.Sync,
} }
filters := c.StringSlice("filter") filters := c.Filter
if len(filters) > 0 { if len(filters) > 0 {
for _, f := range filters { for _, f := range filters {
filterSplit := strings.SplitN(f, "=", 2) filterSplit := strings.SplitN(f, "=", 2)
@ -299,7 +266,7 @@ func psCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("ps") maxWorkers := shared.Parallelize("ps")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) 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 // 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. // 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") return errors.Errorf("last and latest are mutually exclusive")
} }
// Quiet conflicts with size, namespace, and format with a Go template // Quiet conflicts with size, namespace, and format with a Go template
if c.Bool("quiet") { if c.Quiet {
if c.Bool("size") || c.Bool("namespace") || (c.IsSet("format") && if c.Size || c.Namespace || (c.Flag("format").Changed &&
c.String("format") != formats.JSONString) { c.Format != formats.JSONString) {
return errors.Errorf("quiet conflicts with size, namespace, and format with go template") return errors.Errorf("quiet conflicts with size, namespace, and format with go template")
} }
} }
// Size and namespace conflict with each other // 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 errors.Errorf("size and namespace options conflict")
} }
return nil return nil

View file

@ -9,68 +9,58 @@ import (
dockerarchive "github.com/containers/image/docker/archive" dockerarchive "github.com/containers/image/docker/archive"
"github.com/containers/image/transports/alltransports" "github.com/containers/image/transports/alltransports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
image2 "github.com/containers/libpod/libpod/image" image2 "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
pullFlags = []cli.Flag{ pullCommand cliconfig.PullValues
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)",
},
}
pullDescription = ` pullDescription = `
Pulls an image from a registry and stores it locally. 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 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 specified, the image with the 'latest' tag (if it exists) is pulled
` `
pullCommand = cli.Command{ _pullCommand = &cobra.Command{
Name: "pull", Use: "pull",
Usage: "Pull an image from a registry", Short: "Pull an image from a registry",
Description: pullDescription, Long: pullDescription,
Flags: sortFlags(pullFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: pullCmd, pullCommand.InputArgs = args
ArgsUsage: "", pullCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 // pullCmd gets the data from the command line and calls pullImage
// to copy an image from a registry to a local machine // to copy an image from a registry to a local machine
func pullCmd(c *cli.Context) error { func pullCmd(c *cliconfig.PullValues) error {
runtime, err := adapter.GetRuntime(c) runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
args := c.Args() args := c.InputArgs
if len(args) == 0 { if len(args) == 0 {
logrus.Errorf("an image name must be specified") logrus.Errorf("an image name must be specified")
return nil return nil
@ -79,15 +69,12 @@ func pullCmd(c *cli.Context) error {
logrus.Errorf("too many arguments. Requires exactly 1") logrus.Errorf("too many arguments. Requires exactly 1")
return nil return nil
} }
if err := validateFlags(c, pullFlags); err != nil {
return err
}
image := args[0] image := args[0]
var registryCreds *types.DockerAuthConfig var registryCreds *types.DockerAuthConfig
if c.IsSet("creds") { if c.Flag("creds").Changed {
creds, err := util.ParseRegistryCreds(c.String("creds")) creds, err := util.ParseRegistryCreds(c.Creds)
if err != nil { if err != nil {
return err return err
} }
@ -98,16 +85,16 @@ func pullCmd(c *cli.Context) error {
writer io.Writer writer io.Writer
imgID string imgID string
) )
if !c.Bool("quiet") { if !c.Quiet {
writer = os.Stderr writer = os.Stderr
} }
dockerRegistryOptions := image2.DockerRegistryOptions{ dockerRegistryOptions := image2.DockerRegistryOptions{
DockerRegistryCreds: registryCreds, DockerRegistryCreds: registryCreds,
DockerCertPath: c.String("cert-dir"), DockerCertPath: c.CertDir,
} }
if c.IsSet("tls-verify") { if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify")) dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
} }
// Possible for docker-archive to have multiple tags, so use LoadFromArchiveReference instead // 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 { if err != nil {
return errors.Wrapf(err, "error parsing %q", image) 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 { if err != nil {
return errors.Wrapf(err, "error pulling image from %q", image) return errors.Wrapf(err, "error pulling image from %q", image)
} }
imgID = newImage[0].ID() imgID = newImage[0].ID()
} else { } else {
authfile := getAuthFile(c.String("authfile")) authfile := getAuthFile(c.Authfile)
newImage, err := runtime.New(getContext(), image, c.String("signature-policy"), authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil) newImage, err := runtime.New(getContext(), image, c.SignaturePolicy, authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil)
if err != nil { if err != nil {
return errors.Wrapf(err, "error pulling image %q", image) return errors.Wrapf(err, "error pulling image %q", image)
} }

View file

@ -2,6 +2,8 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"io" "io"
"os" "os"
"strings" "strings"
@ -14,76 +16,52 @@ import (
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli"
) )
var ( var (
pushFlags = []cli.Flag{ pushCommand cliconfig.PushValues
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. ",
},
}
pushDescription = fmt.Sprintf(` pushDescription = fmt.Sprintf(`
Pushes an image to a specified location. Pushes an image to a specified location.
The Image "DESTINATION" uses a "transport":"details" format. The Image "DESTINATION" uses a "transport":"details" format.
See podman-push(1) section "DESTINATION" for the expected format`) See podman-push(1) section "DESTINATION" for the expected format`)
pushCommand = cli.Command{ _pushCommand = &cobra.Command{
Name: "push", Use: "push",
Usage: "Push an image to a specified destination", Short: "Push an image to a specified destination",
Description: pushDescription, Long: pushDescription,
Flags: sortFlags(pushFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: pushCmd, pushCommand.InputArgs = args
ArgsUsage: "IMAGE DESTINATION", pushCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 ( var (
registryCreds *types.DockerAuthConfig registryCreds *types.DockerAuthConfig
destName string destName string
) )
args := c.Args() args := c.InputArgs
if len(args) == 0 || len(args) > 2 { 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") 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: case 2:
destName = args[1] destName = args[1]
} }
if err := validateFlags(c, pushFlags); err != nil {
return err
}
// --compress and --format can only be used for the "dir" transport // --compress and --format can only be used for the "dir" transport
splitArg := strings.SplitN(destName, ":", 2) 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() { 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") return errors.Errorf("--compress and --format can be set only when pushing to a directory using the 'dir' transport")
} }
} }
certPath := c.String("cert-dir") certPath := c.CertDir
removeSignatures := c.Bool("remove-signatures") removeSignatures := c.RemoveSignatures
signBy := c.String("sign-by") signBy := c.SignBy
if c.IsSet("creds") { if c.Flag("creds").Changed {
creds, err := util.ParseRegistryCreds(c.String("creds")) creds, err := util.ParseRegistryCreds(c.Creds)
if err != nil { if err != nil {
return err return err
} }
registryCreds = creds registryCreds = creds
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not create runtime") return errors.Wrapf(err, "could not create runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
var writer io.Writer var writer io.Writer
if !c.Bool("quiet") { if !c.Quiet {
writer = os.Stderr writer = os.Stderr
} }
var manifestType string var manifestType string
if c.IsSet("format") { if c.Flag("format").Changed {
switch c.String("format") { switch c.String("format") {
case "oci": case "oci":
manifestType = imgspecv1.MediaTypeImageManifest manifestType = imgspecv1.MediaTypeImageManifest
@ -147,8 +122,8 @@ func pushCmd(c *cli.Context) error {
DockerRegistryCreds: registryCreds, DockerRegistryCreds: registryCreds,
DockerCertPath: certPath, DockerCertPath: certPath,
} }
if c.IsSet("tls-verify") { if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify")) dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
} }
so := image.SigningOptions{ so := image.SigningOptions{
@ -161,7 +136,7 @@ func pushCmd(c *cli.Context) error {
return err 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)
} }

View file

@ -4,37 +4,38 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( 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." 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 = &cobra.Command{
refreshCommand = cli.Command{ Use: "refresh",
Name: "refresh", Short: "Refresh container state",
Usage: "Refresh container state", Long: refreshDescription,
Description: refreshDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(refreshFlags), refreshCommand.InputArgs = args
Action: refreshCmd, refreshCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return refreshCmd(&refreshCommand)
OnUsageError: usageErrorHandler, },
} }
) )
func refreshCmd(c *cli.Context) error { func init() {
if len(c.Args()) > 0 { 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") return errors.Errorf("refresh does not accept any arguments")
} }
if err := validateFlags(c, refreshFlags); err != nil { runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
return err
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }

View file

@ -4,47 +4,45 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
restartFlags = []cli.Flag{ restartCommand cliconfig.RestartValues
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,
}
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` 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 = &cobra.Command{
restartCommand = cli.Command{ Use: "restart",
Name: "restart", Short: "Restart one or more containers",
Usage: "Restart one or more containers", Long: restartDescription,
Description: restartDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(restartFlags), restartCommand.InputArgs = args
Action: restartCmd, restartCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "CONTAINER [CONTAINER ...]", return restartCmd(&restartCommand)
UseShortOptionHandling: true, },
OnUsageError: usageErrorHandler, 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 ( var (
restartFuncs []shared.ParallelWorkerInput restartFuncs []shared.ParallelWorkerInput
containers []*libpod.Container containers []*libpod.Container
@ -55,34 +53,31 @@ func restartCmd(c *cli.Context) error {
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
} }
args := c.Args() args := c.InputArgs
runOnly := c.Bool("running") runOnly := c.Running
all := c.Bool("all") all := c.All
if len(args) < 1 && !c.Bool("latest") && !all { if len(args) < 1 && !c.Latest && !all {
return errors.Wrapf(libpod.ErrInvalidArg, "you must provide at least one container name or ID") 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 { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
timeout := c.Uint("timeout") timeout := c.Timeout
useTimeout := c.IsSet("timeout") useTimeout := c.Flag("timeout").Changed
// Handle --latest // Handle --latest
if c.Bool("latest") { if c.Latest {
lastCtr, err := runtime.GetLatestContainer() lastCtr, err := runtime.GetLatestContainer()
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to get latest container") return errors.Wrapf(err, "unable to get latest container")
} }
restartContainers = append(restartContainers, lastCtr) restartContainers = append(restartContainers, lastCtr)
} else if runOnly { } else if runOnly {
containers, err = getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running") containers, err = getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
if err != nil { if err != nil {
return err return err
} }
@ -105,7 +100,7 @@ func restartCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("restart") maxWorkers := shared.Parallelize("restart")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -5,68 +5,67 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
restoreCommand cliconfig.RestoreValues
restoreDescription = ` restoreDescription = `
podman container restore podman container restore
Restores a container from a checkpoint. The container name or ID can be used. Restores a container from a checkpoint. The container name or ID can be used.
` `
restoreFlags = []cli.Flag{ _restoreCommand = &cobra.Command{
cli.BoolFlag{ Use: "restore",
Name: "keep, k", Short: "Restores one or more containers from a checkpoint",
Usage: "Keep all temporary checkpoint files", 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 Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
// 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 ...]",
} }
) )
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() { if rootless.IsRootless() {
return errors.New("restoring a container requires root") return errors.New("restoring a container requires root")
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
options := libpod.ContainerCheckpointOptions{ options := libpod.ContainerCheckpointOptions{
Keep: c.Bool("keep"), Keep: c.Keep,
TCPEstablished: c.Bool("tcp-established"), TCPEstablished: c.TcpEstablished,
} }
if err := checkAllAndLatest(c); err != nil { if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err return err
} }
containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateExited, "checkpointed") containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateExited, "checkpointed")
for _, ctr := range containers { for _, ctr := range containers {
if err = ctr.Restore(context.TODO(), options); err != nil { if err = ctr.Restore(context.TODO(), options); err != nil {

View file

@ -2,67 +2,64 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
rmFlags = []cli.Flag{ rmCommand cliconfig.RmValues
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)",
},
}
rmDescription = fmt.Sprintf(` rmDescription = fmt.Sprintf(`
Podman rm will remove one or more containers from the host. Podman rm will remove one or more containers from the host.
The container name or ID can be used. This does not remove images. The container name or ID can be used. This does not remove images.
Running containers will not be removed without the -f option. Running containers will not be removed without the -f option.
`) `)
rmCommand = cli.Command{ _rmCommand = &cobra.Command{
Name: "rm", Use: "rm",
Usage: "Remove one or more containers", Short: "Remove one or more containers",
Description: rmDescription, Long: rmDescription,
Flags: sortFlags(rmFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: rmCmd, rmCommand.InputArgs = args
ArgsUsage: "", rmCommand.GlobalFlags = MainGlobalOpts
UseShortOptionHandling: true, return rmCmd(&rmCommand)
OnUsageError: usageErrorHandler, },
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 // saveCmd saves the image to either docker-archive or oci
func rmCmd(c *cli.Context) error { func rmCmd(c *cliconfig.RmValues) error {
var ( var (
deleteFuncs []shared.ParallelWorkerInput deleteFuncs []shared.ParallelWorkerInput
) )
ctx := getContext() ctx := getContext()
if err := validateFlags(c, rmFlags); err != nil { runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
return err
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if err := checkAllAndLatest(c); err != nil { if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err return err
} }
delContainers, err := getAllOrLatestContainers(c, runtime, -1, "all") delContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
if err != nil { if err != nil {
if len(delContainers) == 0 { if len(delContainers) == 0 {
return err return err
@ -73,7 +70,7 @@ func rmCmd(c *cli.Context) error {
for _, container := range delContainers { for _, container := range delContainers {
con := container con := container
f := func() error { f := func() error {
return runtime.RemoveContainer(ctx, con, c.Bool("force")) return runtime.RemoveContainer(ctx, con, c.Force)
} }
deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{ deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{
@ -83,7 +80,7 @@ func rmCmd(c *cli.Context) error {
} }
maxWorkers := shared.Parallelize("rm") maxWorkers := shared.Parallelize("rm")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -4,47 +4,39 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
rmiCommand cliconfig.RmiValues
rmiDescription = "Removes one or more locally stored images." rmiDescription = "Removes one or more locally stored images."
rmiFlags = []cli.Flag{ _rmiCommand = &cobra.Command{
cli.BoolFlag{ Use: "rmi",
Name: "all, a", Short: "Removes one or more images from local storage",
Usage: "Remove all images", Long: rmiDescription,
RunE: func(cmd *cobra.Command, args []string) error {
rmiCommand.InputArgs = args
rmiCommand.GlobalFlags = MainGlobalOpts
return rmiCmd(&rmiCommand)
}, },
cli.BoolFlag{ Example: "IMAGE-NAME-OR-ID [...]",
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,
} }
) )
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 ( var (
lastError error lastError error
deleted bool deleted bool
@ -53,17 +45,14 @@ func rmiCmd(c *cli.Context) error {
) )
ctx := getContext() ctx := getContext()
if err := validateFlags(c, rmiFlags); err != nil { removeAll := c.All
return err runtime, err := adapter.GetRuntime(&c.PodmanCommand)
}
removeAll := c.Bool("all")
runtime, err := adapter.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
args := c.Args() args := c.InputArgs
if len(args) == 0 && !removeAll { if len(args) == 0 && !removeAll {
return errors.Errorf("image name or ID must be specified") 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) { removeImage := func(img *adapter.ContainerImage) {
deleted = true deleted = true
msg, deleteErr = runtime.RemoveImage(ctx, img, c.Bool("force")) msg, deleteErr = runtime.RemoveImage(ctx, img, c.Force)
if deleteErr != nil { if deleteErr != nil {
if errors.Cause(deleteErr) == storage.ErrImageUsedByContainer { 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()) 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())

View file

@ -8,49 +8,57 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "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{ runDescription = "Runs a command in a new container from the given image"
Name: "sig-proxy", _runCommmand = &cobra.Command{
Usage: "Proxy received signals to the process (default true)", 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{ func init() {
Name: "run", runCommmand.Command = _runCommmand
Usage: "Run a command in a new container", flags := runCommmand.Flags()
Description: runDescription, flags.SetInterspersed(false)
Flags: sortFlags(runFlags), flags.Bool("sig-proxy", true, "Proxy received signals to the process (default true)")
Action: runCmd, getCreateFlags(&runCommmand.PodmanCommand)
ArgsUsage: "IMAGE [COMMAND [ARG...]]",
HideHelp: true, rootCmd.AddCommand(runCommmand.Command)
SkipArgReorder: true,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
} }
func runCmd(c *cli.Context) error { func runCmd(c *cliconfig.RunValues) error {
if err := createInit(c); err != nil { if err := createInit(&c.PodmanCommand); err != nil {
return err return err
} }
if os.Geteuid() != 0 { if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
ctr, createConfig, err := createContainer(c, runtime) ctr, createConfig, err := createContainer(&c.PodmanCommand, runtime)
if err != nil { if err != nil {
return err 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 // This means the command did not exist
exitCode = 127 exitCode = 127
if strings.Index(err.Error(), "permission denied") > -1 { if strings.Index(err.Error(), "permission denied") > -1 {

View file

@ -4,24 +4,19 @@ import (
"runtime" "runtime"
"testing" "testing"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/inspect" "github.com/containers/libpod/pkg/inspect"
cc "github.com/containers/libpod/pkg/spec" 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" ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/urfave/cli"
) )
var ( var (
cmd = []string{"podman", "test", "alpine"} cmd = []string{"podman", "test", "alpine"}
CLI *cli.Context CLI *cliconfig.PodmanCommand
testCommand = cli.Command{
Name: "test",
Flags: sortFlags(createFlags),
Action: testCmd,
HideHelp: true,
}
) )
// generates a mocked ImageData structure based on alpine // generates a mocked ImageData structure based on alpine
@ -53,23 +48,29 @@ func generateAlpineImageData() *inspect.ImageData {
} }
// sets a global CLI // sets a global CLI
func testCmd(c *cli.Context) error { func testCmd(c *cobra.Command) error {
CLI = c CLI = &cliconfig.PodmanCommand{Command: c}
return nil return nil
} }
// creates the mocked cli pointing to our create flags // creates the mocked cli pointing to our create flags
// global flags like log-level are not implemented // global flags like log-level are not implemented
func createCLI() cli.App { func createCLI(args []string) *cliconfig.PodmanCommand {
a := cli.App{ var testCommand = &cliconfig.PodmanCommand{
Commands: []cli.Command{ Command: &cobra.Command{
testCommand, 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 TODO: This test has never worked. Need to install content
runtime, err := getRuntime(c) runtime, err := getRuntime(c)
@ -98,10 +99,11 @@ func TestPIDsLimit(t *testing.T) {
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
t.Skip("seccomp, which is enabled by default, is only supported on Linux") t.Skip("seccomp, which is enabled by default, is only supported on Linux")
} }
a := createCLI()
args := []string{"--pids-limit", "22"} args := []string{"--pids-limit", "22"}
a.Run(append(cmd, args...)) a := createCLI(args)
runtimeSpec, err := getRuntimeSpec(CLI) a.InputArgs = args
//a.Run(append(cmd, args...))
runtimeSpec, err := getRuntimeSpec(a)
if err != nil { if err != nil {
t.Fatalf(err.Error()) t.Fatalf(err.Error())
} }
@ -116,10 +118,10 @@ func TestBLKIOWeightDevice(t *testing.T) {
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
t.Skip("seccomp, which is enabled by default, is only supported on Linux") t.Skip("seccomp, which is enabled by default, is only supported on Linux")
} }
a := createCLI()
args := []string{"--blkio-weight-device", "/dev/zero:100"} args := []string{"--blkio-weight-device", "/dev/zero:100"}
a.Run(append(cmd, args...)) a := createCLI(args)
runtimeSpec, err := getRuntimeSpec(CLI) a.InputArgs = args
runtimeSpec, err := getRuntimeSpec(a)
if err != nil { if err != nil {
t.Fatalf(err.Error()) t.Fatalf(err.Error())
} }
@ -134,10 +136,11 @@ func TestMemorySwap(t *testing.T) {
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
t.Skip("seccomp, which is enabled by default, is only supported on Linux") t.Skip("seccomp, which is enabled by default, is only supported on Linux")
} }
a := createCLI()
args := []string{"--memory-swap", "45m", "--memory", "40m"} args := []string{"--memory-swap", "45m", "--memory", "40m"}
a.Run(append(cmd, args...)) a := createCLI(args)
runtimeSpec, err := getRuntimeSpec(CLI) a.InputArgs = args
//a.Run(append(cmd, args...))
runtimeSpec, err := getRuntimeSpec(a)
if err != nil { if err != nil {
t.Fatalf(err.Error()) t.Fatalf(err.Error())
} }

View file

@ -7,88 +7,59 @@ import (
"strings" "strings"
"github.com/containers/image/types" "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/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/utils" "github.com/containers/libpod/utils"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
runlabelFlags = []cli.Flag{ runlabelCommand cliconfig.RunlabelValues
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)",
},
}
runlabelDescription = ` runlabelDescription = `
Executes a command as described by a container image label. Executes a command as described by a container image label.
` `
runlabelCommand = cli.Command{ _runlabelCommand = &cobra.Command{
Name: "runlabel", Use: "runlabel",
Usage: "Execute the command described by an image label", Short: "Execute the command described by an image label",
Description: runlabelDescription, Long: runlabelDescription,
Flags: sortFlags(runlabelFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: runlabelCmd, runlabelCommand.InputArgs = args
ArgsUsage: "", runlabelCommand.GlobalFlags = MainGlobalOpts
SkipArgReorder: true, return runlabelCmd(&runlabelCommand)
OnUsageError: usageErrorHandler, },
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 // installCmd gets the data from the command line and calls installImage
// to copy an image from a registry to a local machine // to copy an image from a registry to a local machine
func runlabelCmd(c *cli.Context) error { func runlabelCmd(c *cliconfig.RunlabelValues) error {
var ( var (
imageName string imageName string
stdErr, stdOut io.Writer stdErr, stdOut io.Writer
@ -105,40 +76,38 @@ func runlabelCmd(c *cli.Context) error {
} }
opts := make(map[string]string) opts := make(map[string]string)
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
args := c.Args() args := c.InputArgs
if len(args) < 2 { if len(args) < 2 {
logrus.Errorf("the runlabel command requires at least 2 arguments: LABEL IMAGE") logrus.Errorf("the runlabel command requires at least 2 arguments: LABEL IMAGE")
return nil return nil
} }
if err := validateFlags(c, runlabelFlags); err != nil { if c.Display && c.Quiet {
return err
}
if c.Bool("display") && c.Bool("quiet") {
return errors.Errorf("the display and quiet flags cannot be used together.") return errors.Errorf("the display and quiet flags cannot be used together.")
} }
if len(args) > 2 { if len(args) > 2 {
extraArgs = args[2:] extraArgs = args[2:]
} }
pull := c.Bool("pull") pull := c.Pull
label := args[0] label := args[0]
runlabelImage := args[1] runlabelImage := args[1]
if c.IsSet("opt1") { if c.Flag("opt1").Changed {
opts["opt1"] = c.String("opt1") 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") { if c.Flag("opt3").Changed {
opts["opt3"] = c.String("opt3") opts["opt3"] = c.Opt3
} }
ctx := getContext() ctx := getContext()
@ -147,21 +116,21 @@ func runlabelCmd(c *cli.Context) error {
stdOut = os.Stdout stdOut = os.Stdout
stdIn = os.Stdin stdIn = os.Stdin
if c.Bool("quiet") { if c.Quiet {
stdErr = nil stdErr = nil
stdOut = nil stdOut = nil
stdIn = nil stdIn = nil
} }
dockerRegistryOptions := image.DockerRegistryOptions{ dockerRegistryOptions := image.DockerRegistryOptions{
DockerCertPath: c.String("cert-dir"), DockerCertPath: c.CertDir,
} }
if c.IsSet("tls-verify") { if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify")) dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
} }
authfile := getAuthFile(c.String("authfile")) authfile := getAuthFile(c.Authfile)
runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, pull, c.String("creds"), dockerRegistryOptions, authfile, c.String("signature-policy"), stdOut) runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, pull, c.Creds, dockerRegistryOptions, authfile, c.SignaturePolicy, stdOut)
if err != nil { if err != nil {
return err 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) 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 { if err != nil {
return err return err
} }
if !c.Bool("quiet") { if !c.Quiet {
fmt.Printf("Command: %s\n", strings.Join(cmd, " ")) fmt.Printf("Command: %s\n", strings.Join(cmd, " "))
if c.Bool("display") { if c.Display {
return nil return nil
} }
} }

View file

@ -12,12 +12,13 @@ import (
"github.com/containers/image/manifest" "github.com/containers/image/manifest"
ociarchive "github.com/containers/image/oci/archive" ociarchive "github.com/containers/image/oci/archive"
"github.com/containers/image/types" "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/libpodruntime"
libpodImage "github.com/containers/libpod/libpod/image" libpodImage "github.com/containers/libpod/libpod/image"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
const ( const (
@ -26,67 +27,58 @@ const (
) )
var ( var (
saveFlags = []cli.Flag{ saveCommand cliconfig.SaveValues
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)",
},
}
saveDescription = ` saveDescription = `
Save an image to docker-archive or oci-archive on the local machine. Save an image to docker-archive or oci-archive on the local machine.
Default is docker-archive` Default is docker-archive`
saveCommand = cli.Command{ _saveCommand = &cobra.Command{
Name: "save", Use: "save",
Usage: "Save image to an archive", Short: "Save image to an archive",
Description: saveDescription, Long: saveDescription,
Flags: sortFlags(saveFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: saveCmd, saveCommand.InputArgs = args
ArgsUsage: "", saveCommand.GlobalFlags = MainGlobalOpts
SkipArgReorder: true, return saveCmd(&saveCommand)
OnUsageError: usageErrorHandler, },
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 // saveCmd saves the image to either docker-archive or oci
func saveCmd(c *cli.Context) error { func saveCmd(c *cliconfig.SaveValues) error {
args := c.Args() args := c.InputArgs
if len(args) == 0 { if len(args) == 0 {
return errors.Errorf("need at least 1 argument") 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 { if err != nil {
return errors.Wrapf(err, "could not create runtime") return errors.Wrapf(err, "could not create runtime")
} }
defer runtime.Shutdown(false) 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'") return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'")
} }
var writer io.Writer var writer io.Writer
if !c.Bool("quiet") { if !c.Quiet {
writer = os.Stderr writer = os.Stderr
} }
output := c.String("output") output := c.Output
if output == "/dev/stdout" { if output == "/dev/stdout" {
fi := os.Stdout fi := os.Stdout
if logrus.IsTerminal(fi) { if logrus.IsTerminal(fi) {
@ -105,7 +97,7 @@ func saveCmd(c *cli.Context) error {
var destRef types.ImageReference var destRef types.ImageReference
var manifestType string var manifestType string
switch c.String("format") { switch c.Format {
case "oci-archive": case "oci-archive":
destImageName := imageNameForSaveDestination(newImage, source) destImageName := imageNameForSaveDestination(newImage, source)
destRef, err = ociarchive.NewReference(output, destImageName) // destImageName may be "" destRef, err = ociarchive.NewReference(output, destImageName) // destImageName may be ""

View file

@ -8,13 +8,14 @@ import (
"github.com/containers/image/docker" "github.com/containers/image/docker"
"github.com/containers/image/types" "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/formats"
"github.com/containers/libpod/libpod/common" "github.com/containers/libpod/libpod/common"
sysreg "github.com/containers/libpod/pkg/registries" sysreg "github.com/containers/libpod/pkg/registries"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
const ( const (
@ -23,46 +24,36 @@ const (
) )
var ( var (
searchFlags = []cli.Flag{ searchCommand cliconfig.SearchValues
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)",
},
}
searchDescription = ` searchDescription = `
Search registries for a given image. Can search all the default registries or a specific registry. 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.` Can limit the number of results, and filter the output based on certain conditions.`
searchCommand = cli.Command{ _searchCommand = &cobra.Command{
Name: "search", Use: "search",
Usage: "Search registry for image", Short: "Search registry for image",
Description: searchDescription, Long: searchDescription,
Flags: sortFlags(searchFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: searchCmd, searchCommand.InputArgs = args
ArgsUsage: "TERM", searchCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 { type searchParams struct {
Index string Index string
Name string Name string
@ -87,8 +78,8 @@ type searchFilterParams struct {
isOfficial *bool isOfficial *bool
} }
func searchCmd(c *cli.Context) error { func searchCmd(c *cliconfig.SearchValues) error {
args := c.Args() args := c.InputArgs
if len(args) > 1 { if len(args) > 1 {
return errors.Errorf("too many arguments. Requires exactly 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:] term = term[len(registry)+1:]
} }
if err := validateFlags(c, searchFlags); err != nil { format := genSearchFormat(c.Format)
return err
}
format := genSearchFormat(c.String("format"))
opts := searchOpts{ opts := searchOpts{
format: format, format: format,
noTrunc: c.Bool("no-trunc"), noTrunc: c.NoTrunc,
limit: c.Int("limit"), limit: c.Limit,
filter: c.StringSlice("filter"), filter: c.Filter,
authfile: getAuthFile(c.String("authfile")), authfile: getAuthFile(c.Authfile),
} }
if c.IsSet("tls-verify") { if c.Flag("tls-verify").Changed {
opts.insecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify")) opts.insecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
} }
registries, err := getRegistries(registry) registries, err := getRegistries(registry)
if err != nil { if err != nil {

View file

@ -11,60 +11,63 @@ import (
"github.com/containers/image/signature" "github.com/containers/image/signature"
"github.com/containers/image/transports" "github.com/containers/image/transports"
"github.com/containers/image/transports/alltransports" "github.com/containers/image/transports/alltransports"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/trust" "github.com/containers/libpod/pkg/trust"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
signFlags = []cli.Flag{ signCommand cliconfig.SignValues
cli.StringFlag{
Name: "sign-by",
Usage: "Name of the signing key",
},
cli.StringFlag{
Name: "directory, d",
Usage: "Define an alternate directory to store signatures",
},
}
signDescription = "Create a signature file that can be used later to verify the image" signDescription = "Create a signature file that can be used later to verify the image"
signCommand = cli.Command{ _signCommand = &cobra.Command{
Name: "sign", Use: "sign",
Usage: "Sign an image", Short: "Sign an image",
Description: signDescription, Long: signDescription,
Flags: sortFlags(signFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: signCmd, signCommand.InputArgs = args
ArgsUsage: "IMAGE-NAME [IMAGE-NAME ...]", signCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 // SignatureStoreDir defines default directory to store signatures
const SignatureStoreDir = "/var/lib/containers/sigstore" const SignatureStoreDir = "/var/lib/containers/sigstore"
func signCmd(c *cli.Context) error { func signCmd(c *cliconfig.SignValues) error {
args := c.Args() args := c.InputArgs
if len(args) < 1 { if len(args) < 1 {
return errors.Errorf("at least one image name must be specified") 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 { if err != nil {
return errors.Wrapf(err, "could not create runtime") return errors.Wrapf(err, "could not create runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
signby := c.String("sign-by") signby := c.SignBy
if signby == "" { if signby == "" {
return errors.Errorf("please provide an identity") return errors.Errorf("please provide an identity")
} }
var sigStoreDir string var sigStoreDir string
if c.IsSet("directory") { if c.Flag("directory").Changed {
sigStoreDir = c.String("directory") sigStoreDir = c.Directory
if _, err := os.Stat(sigStoreDir); err != nil { if _, err := os.Stat(sigStoreDir); err != nil {
return errors.Wrapf(err, "invalid directory %s", sigStoreDir) return errors.Wrapf(err, "invalid directory %s", sigStoreDir)
} }

View file

@ -5,84 +5,75 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
cc "github.com/containers/libpod/pkg/spec" cc "github.com/containers/libpod/pkg/spec"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
startFlags = []cli.Flag{ startCommand cliconfig.StartValues
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,
}
startDescription = ` startDescription = `
podman start podman start
Starts one or more containers. The container name or ID can be used. Starts one or more containers. The container name or ID can be used.
` `
_startCommand = &cobra.Command{
startCommand = cli.Command{ Use: "start",
Name: "start", Short: "Start one or more containers",
Usage: "Start one or more containers", Long: startDescription,
Description: startDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(startFlags), startCommand.InputArgs = args
Action: startCmd, startCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]", return startCmd(&startCommand)
UseShortOptionHandling: true, },
OnUsageError: usageErrorHandler, Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
} }
) )
func startCmd(c *cli.Context) error { func init() {
args := c.Args() startCommand.Command = _startCommand
if len(args) < 1 && !c.Bool("latest") { 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") 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 { if len(args) > 1 && attach {
return errors.Errorf("you cannot start and attach multiple containers at once") return errors.Errorf("you cannot start and attach multiple containers at once")
} }
if err := validateFlags(c, startFlags); err != nil { sigProxy := c.SigProxy
return err
}
sigProxy := c.BoolT("sig-proxy")
if sigProxy && !attach { 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") return errors.Wrapf(libpod.ErrInvalidArg, "you cannot use sig-proxy without --attach")
} else { } else {
sigProxy = false sigProxy = false
} }
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if c.Bool("latest") { if c.Latest {
lastCtr, err := runtime.GetLatestContainer() lastCtr, err := runtime.GetLatestContainer()
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to get latest container") return errors.Wrapf(err, "unable to get latest container")
@ -112,12 +103,12 @@ func startCmd(c *cli.Context) error {
if attach { if attach {
inputStream := os.Stdin inputStream := os.Stdin
if !c.Bool("interactive") { if !c.Interactive {
inputStream = nil inputStream = nil
} }
// attach to the container and also start it not already running // 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 { if ctrRunning {
return err return err
} }

View file

@ -8,12 +8,13 @@ import (
"time" "time"
tm "github.com/buger/goterm" 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/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
type statsOutputParams struct { type statsOutputParams struct {
@ -28,48 +29,41 @@ type statsOutputParams struct {
} }
var ( var (
statsFlags = []cli.Flag{ statsCommand cliconfig.StatsValues
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,
}
statsDescription = "Display a live stream of one or more containers' resource usage statistics" statsDescription = "display a live stream of one or more containers' resource usage statistics"
statsCommand = cli.Command{ _statsCommand = &cobra.Command{
Name: "stats", Use: "stats",
Usage: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers", Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers",
Description: statsDescription, Long: statsDescription,
Flags: sortFlags(statsFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: statsCmd, statsCommand.InputArgs = args
ArgsUsage: "", statsCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return statsCmd(&statsCommand)
},
Example: "",
} }
) )
func statsCmd(c *cli.Context) error { func init() {
if err := validateFlags(c, statsFlags); err != nil { statsCommand.Command = _statsCommand
return err 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 { if os.Geteuid() != 0 {
return errors.New("stats is not supported for rootless containers") return errors.New("stats is not supported for rootless containers")
} }
all := c.Bool("all") all := c.All
latest := c.Bool("latest") latest := c.Latest
ctr := 0 ctr := 0
if all { if all {
ctr += 1 ctr += 1
@ -77,7 +71,7 @@ func statsCmd(c *cli.Context) error {
if latest { if latest {
ctr += 1 ctr += 1
} }
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
ctr += 1 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") 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
times := -1 times := -1
if c.Bool("no-stream") { if c.NoStream {
times = 1 times = 1
} }
@ -102,8 +96,8 @@ func statsCmd(c *cli.Context) error {
var containerFunc func() ([]*libpod.Container, error) var containerFunc func() ([]*libpod.Container, error)
containerFunc = runtime.GetRunningContainers containerFunc = runtime.GetRunningContainers
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.Args()) } containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.InputArgs) }
} else if latest { } else if latest {
containerFunc = func() ([]*libpod.Container, error) { containerFunc = func() ([]*libpod.Container, error) {
lastCtr, err := runtime.GetLatestContainer() lastCtr, err := runtime.GetLatestContainer()
@ -126,7 +120,7 @@ func statsCmd(c *cli.Context) error {
initialStats, err := ctr.GetContainerStats(&libpod.ContainerStats{}) initialStats, err := ctr.GetContainerStats(&libpod.ContainerStats{})
if err != nil { if err != nil {
// when doing "all", dont worry about containers that are not running // 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 continue
} }
return err return err
@ -134,7 +128,7 @@ func statsCmd(c *cli.Context) error {
containerStats[ctr.ID()] = initialStats containerStats[ctr.ID()] = initialStats
} }
format := genStatsFormat(c.String("format")) format := genStatsFormat(c.Format)
step := 1 step := 1
if times == -1 { if times == -1 {
@ -168,7 +162,7 @@ func statsCmd(c *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
if strings.ToLower(format) != formats.JSONString && !c.Bool("no-reset") { if strings.ToLower(format) != formats.JSONString && !c.NoReset {
tm.Clear() tm.Clear()
tm.MoveCursor(1, 1) tm.MoveCursor(1, 1)
tm.Flush() tm.Flush()

View file

@ -3,27 +3,18 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
stopFlags = []cli.Flag{ stopCommand cliconfig.StopValues
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,
}
stopDescription = ` stopDescription = `
podman stop podman stop
@ -31,36 +22,44 @@ var (
A timeout to forcibly stop the container can also be set but defaults to 10 A timeout to forcibly stop the container can also be set but defaults to 10
seconds otherwise. seconds otherwise.
` `
_stopCommand = &cobra.Command{
stopCommand = cli.Command{ Use: "stop",
Name: "stop", Short: "Stop one or more containers",
Usage: "Stop one or more containers", Long: stopDescription,
Description: stopDescription, RunE: func(cmd *cobra.Command, args []string) error {
Flags: sortFlags(stopFlags), stopCommand.InputArgs = args
Action: stopCmd, stopCommand.GlobalFlags = MainGlobalOpts
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]", return stopCmd(&stopCommand)
OnUsageError: usageErrorHandler, },
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 { rootCmd.AddCommand(stopCommand.Command)
return err }
}
if err := validateFlags(c, stopFlags); err != nil { func stopCmd(c *cliconfig.StopValues) error {
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err return err
} }
rootless.SetSkipStorageSetup(true) rootless.SetSkipStorageSetup(true)
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) 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 err != nil {
if len(containers) == 0 { if len(containers) == 0 {
return err return err
@ -72,8 +71,8 @@ func stopCmd(c *cli.Context) error {
for _, ctr := range containers { for _, ctr := range containers {
con := ctr con := ctr
var stopTimeout uint var stopTimeout uint
if c.IsSet("timeout") { if c.Flag("timeout").Changed {
stopTimeout = c.Uint("timeout") stopTimeout = c.Timeout
} else { } else {
stopTimeout = ctr.StopTimeout() stopTimeout = ctr.StopTimeout()
} }
@ -92,7 +91,7 @@ func stopCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("stop") maxWorkers := shared.Parallelize("stop")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -1,29 +1,23 @@
package main package main
import ( import (
"sort" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"github.com/urfave/cli"
) )
var ( var (
systemSubCommands = []cli.Command{
pruneSystemCommand,
}
systemDescription = "Manage podman" systemDescription = "Manage podman"
systemCommand = cli.Command{
Name: "system", systemCommand = cliconfig.PodmanCommand{
Usage: "Manage podman", Command: &cobra.Command{
Description: systemDescription, Use: "system",
ArgsUsage: "", Short: "Manage podman",
Subcommands: getSystemSubCommandsSorted(), Long: systemDescription,
UseShortOptionHandling: true, },
OnUsageError: usageErrorHandler,
} }
) )
func getSystemSubCommandsSorted() []cli.Command { func init() {
systemSubCommands = append(systemSubCommands, getSystemSubCommands()...) systemCommand.AddCommand(getSystemSubCommands()...)
sort.Sort(commandSortedAlpha{systemSubCommands}) rootCmd.AddCommand(systemCommand.Command)
return systemSubCommands
} }

View file

@ -6,50 +6,50 @@ import (
"os" "os"
"strings" "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
pruneSystemCommand cliconfig.SystemPruneValues
pruneSystemDescription = ` pruneSystemDescription = `
podman system prune podman system prune
Remove unused data Remove unused data
` `
pruneSystemFlags = []cli.Flag{ _pruneSystemCommand = &cobra.Command{
cli.BoolFlag{ Use: "prune",
Name: "all, a", Short: "Remove unused data",
Usage: "Remove all 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 // Prompt for confirmation if --force is not set
if !c.Bool("force") { if !c.Force {
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
volumeString := "" volumeString := ""
if c.Bool("volumes") { if c.Volume {
volumeString = ` volumeString = `
- all volumes not used by at least one container` - 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") 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 // Call prune; if any cids are returned, print them and then
// return err in case an error also came up // 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 { if len(pruneCids) > 0 {
fmt.Println("Deleted Images") fmt.Println("Deleted Images")
for _, cid := range pruneCids { for _, cid := range pruneCids {

View file

@ -1,29 +1,41 @@
package main package main
import ( import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
tagCommand cliconfig.TagValues
tagDescription = "Adds one or more additional names to locally-stored image" tagDescription = "Adds one or more additional names to locally-stored image"
tagCommand = cli.Command{ _tagCommand = &cobra.Command{
Name: "tag", Use: "tag",
Usage: "Add an additional name to a local image", Short: "Add an additional name to a local image",
Description: tagDescription, Long: tagDescription,
Action: tagCmd, RunE: func(cmd *cobra.Command, args []string) error {
ArgsUsage: "IMAGE-NAME [IMAGE-NAME ...]", tagCommand.InputArgs = args
OnUsageError: usageErrorHandler, tagCommand.GlobalFlags = MainGlobalOpts
return tagCmd(&tagCommand)
},
Example: "IMAGE-NAME [IMAGE-NAME ...]",
} }
) )
func tagCmd(c *cli.Context) error { func init() {
args := c.Args() tagCommand.Command = _tagCommand
rootCmd.AddCommand(tagCommand.Command)
}
func tagCmd(c *cliconfig.TagValues) error {
args := c.InputArgs
if len(args) < 2 { if len(args) < 2 {
return errors.Errorf("image name and at least one new name must be specified") 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 { if err != nil {
return errors.Wrapf(err, "could not create runtime") return errors.Wrapf(err, "could not create runtime")
} }

View file

@ -6,11 +6,12 @@ import (
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
func getDescriptorString() string { func getDescriptorString() string {
@ -24,13 +25,7 @@ Format Descriptors:
} }
var ( var (
topFlags = []cli.Flag{ topCommand cliconfig.TopValues
LatestFlag,
cli.BoolFlag{
Name: "list-descriptors",
Hidden: true,
},
}
topDescription = fmt.Sprintf(`Display the running processes of the container. Specify format descriptors 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 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 the process ID, the CPU percentage and the seccomp mode of each process of
@ -38,24 +33,35 @@ the latest container.
%s %s
`, getDescriptorString()) `, getDescriptorString())
topCommand = cli.Command{ _topCommand = &cobra.Command{
Name: "top", Use: "top",
Usage: "Display the running processes of a container", Short: "Display the running processes of a container",
Description: topDescription, Long: topDescription,
Flags: sortFlags(topFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: topCmd, topCommand.InputArgs = args
ArgsUsage: "CONTAINER-NAME [format descriptors]", topCommand.GlobalFlags = MainGlobalOpts
SkipArgReorder: true, return topCmd(&topCommand)
OnUsageError: usageErrorHandler, },
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 container *libpod.Container
var err error var err error
args := c.Args() args := c.InputArgs
if c.Bool("list-descriptors") { if c.ListDescriptors {
descriptors, err := libpod.GetContainerPidInformationDescriptors() descriptors, err := libpod.GetContainerPidInformationDescriptors()
if err != nil { if err != nil {
return err return err
@ -64,22 +70,19 @@ func topCmd(c *cli.Context) error {
return nil 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") 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) rootless.SetSkipStorageSetup(true)
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
var descriptors []string var descriptors []string
if c.Bool("latest") { if c.Latest {
descriptors = args descriptors = args
container, err = runtime.GetLatestContainer() container, err = runtime.GetLatestContainer()
} else { } else {

View file

@ -1,369 +1,21 @@
package main package main
import ( import (
"encoding/json" "github.com/containers/libpod/cmd/podman/cliconfig"
"fmt" "github.com/spf13/cobra"
"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"
) )
var ( var (
setTrustFlags = []cli.Flag{ trustCommand = cliconfig.PodmanCommand{
cli.StringFlag{ Command: &cobra.Command{
Name: "type, t", Use: "trust",
Usage: "Trust type, accept values: signedBy(default), accept, reject.", Short: "Manage container image trust policy",
Value: "signedBy", 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 { func init() {
runtime, err := libpodruntime.GetRuntime(c) trustCommand.AddCommand(getTrustSubCommands()...)
if err != nil { imageCommand.AddCommand(trustCommand.Command)
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
} }

View 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
}

View file

@ -3,60 +3,62 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
umountFlags = []cli.Flag{ umountCommand cliconfig.UmountValues
cli.BoolFlag{ description = `
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 = `
Container storage increments a mount counter each time a container is mounted. Container storage increments a mount counter each time a container is mounted.
When a container is unmounted, the mount counter is decremented and the When a container is unmounted, the mount counter is decremented and the
container's root filesystem is physically unmounted only when the mount container's root filesystem is physically unmounted only when the mount
counter reaches zero indicating no other processes are using the mount. counter reaches zero indicating no other processes are using the mount.
An unmount can be forced with the --force flag. An unmount can be forced with the --force flag.
` `
umountCommand = cli.Command{ _umountCommand = &cobra.Command{
Name: "umount", Use: "umount",
Aliases: []string{"unmount"}, Aliases: []string{"unmount"},
Usage: "Unmount working container's root filesystem", Short: "Unmounts working container's root filesystem",
Description: description, Long: description,
Flags: sortFlags(umountFlags), RunE: func(cmd *cobra.Command, args []string) error {
Action: umountCmd, umountCommand.InputArgs = args
ArgsUsage: "CONTAINER-NAME-OR-ID", umountCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, return umountCmd(&umountCommand)
},
Example: "CONTAINER-NAME-OR-ID",
} }
) )
func umountCmd(c *cli.Context) error { func init() {
runtime, err := libpodruntime.GetRuntime(c) 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 { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
force := c.Bool("force") force := c.Force
umountAll := c.Bool("all") umountAll := c.All
if err := checkAllAndLatest(c); err != nil { if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err return err
} }
containers, err := getAllOrLatestContainers(c, runtime, -1, "all") containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
if err != nil { if err != nil {
if len(containers) == 0 { if len(containers) == 0 {
return err return err

View file

@ -3,38 +3,45 @@ package main
import ( import (
"os" "os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
unpauseFlags = []cli.Flag{ unpauseCommand cliconfig.UnpauseValues
cli.BoolFlag{
Name: "all, a",
Usage: "Unpause all paused containers",
},
}
unpauseDescription = ` unpauseDescription = `
podman unpause podman unpause
Unpauses one or more running containers. The container name or ID can be used. Unpauses one or more running containers. The container name or ID can be used.
` `
unpauseCommand = cli.Command{ _unpauseCommand = &cobra.Command{
Name: "unpause", Use: "unpause",
Usage: "Unpause the processes in one or more containers", Short: "Unpause the processes in one or more containers",
Description: unpauseDescription, Long: unpauseDescription,
Flags: unpauseFlags, RunE: func(cmd *cobra.Command, args []string) error {
Action: unpauseCmd, unpauseCommand.InputArgs = args
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]", unpauseCommand.GlobalFlags = MainGlobalOpts
OnUsageError: usageErrorHandler, 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 ( var (
unpauseContainers []*libpod.Container unpauseContainers []*libpod.Container
unpauseFuncs []shared.ParallelWorkerInput unpauseFuncs []shared.ParallelWorkerInput
@ -43,18 +50,18 @@ func unpauseCmd(c *cli.Context) error {
return errors.New("unpause is not supported for rootless containers") return errors.New("unpause is not supported for rootless containers")
} }
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "could not get runtime") return errors.Wrapf(err, "could not get runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
args := c.Args() args := c.InputArgs
if len(args) < 1 && !c.Bool("all") { if len(args) < 1 && !c.All {
return errors.Errorf("you must provide at least one container name or id") return errors.Errorf("you must provide at least one container name or id")
} }
if c.Bool("all") { if c.All {
cs, err := getAllOrLatestContainers(c, runtime, libpod.ContainerStatePaused, "paused") cs, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStatePaused, "paused")
if err != nil { if err != nil {
return err return err
} }
@ -84,7 +91,7 @@ func unpauseCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("unpause") maxWorkers := shared.Parallelize("unpause")
if c.GlobalIsSet("max-workers") { if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers") maxWorkers = c.GlobalFlags.MaxWorks
} }
logrus.Debugf("Setting maximum workers to %d", maxWorkers) logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -6,12 +6,12 @@ import (
"os" "os"
gosignal "os/signal" gosignal "os/signal"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/term" "github.com/docker/docker/pkg/term"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/tools/remotecommand"
) )
@ -158,13 +158,10 @@ func (f *RawTtyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
return bytes, err return bytes, err
} }
func checkMutuallyExclusiveFlags(c *cli.Context) error { func checkMutuallyExclusiveFlags(c *cliconfig.PodmanCommand) error {
if err := checkAllAndLatest(c); err != nil { if err := checkAllAndLatest(c); err != nil {
return err return err
} }
if err := validateFlags(c, startFlags); err != nil {
return err
}
return nil 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. // 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 // The remaining errors will be logged. On success, pods will hold all pods and
// error will be nil. // error will be nil.
func getPodsFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Pod, error) { func getPodsFromContext(c *cliconfig.PodmanCommand, r *libpod.Runtime) ([]*libpod.Pod, error) {
args := c.Args() args := c.InputArgs
var pods []*libpod.Pod var pods []*libpod.Pod
var lastError error var lastError error
var err error var err error
@ -209,8 +206,8 @@ func getPodsFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Pod, error
return pods, lastError return pods, lastError
} }
func getVolumesFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Volume, error) { func getVolumesFromContext(c *cliconfig.PodmanCommand, r *libpod.Runtime) ([]*libpod.Volume, error) {
args := c.Args() args := c.InputArgs
var ( var (
vols []*libpod.Volume vols []*libpod.Volume
lastError error lastError error

View file

@ -5,55 +5,60 @@ package main
import ( import (
"time" "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
iopodman "github.com/containers/libpod/cmd/podman/varlink" iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/pkg/varlinkapi" "github.com/containers/libpod/pkg/varlinkapi"
"github.com/containers/libpod/version" "github.com/containers/libpod/version"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
"github.com/varlink/go/varlink" "github.com/varlink/go/varlink"
) )
var ( var (
varlinkCommand cliconfig.VarlinkValues
varlinkDescription = ` varlinkDescription = `
podman varlink podman varlink
run varlink interface run varlink interface
` `
varlinkFlags = []cli.Flag{ _varlinkCommand = &cobra.Command{
cli.IntFlag{ Use: "varlink",
Name: "timeout, t", Short: "Run varlink interface",
Usage: "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout.", Long: varlinkDescription,
Value: 1000, RunE: func(cmd *cobra.Command, args []string) error {
varlinkCommand.InputArgs = args
varlinkCommand.GlobalFlags = MainGlobalOpts
return varlinkCmd(&varlinkCommand)
}, },
} Example: "VARLINK_URI",
varlinkCommand = &cli.Command{
Name: "varlink",
Usage: "Run varlink interface",
Description: varlinkDescription,
Flags: sortFlags(varlinkFlags),
Action: varlinkCmd,
ArgsUsage: "VARLINK_URI",
OnUsageError: usageErrorHandler,
} }
) )
func varlinkCmd(c *cli.Context) error { func init() {
args := c.Args() 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 { if len(args) < 1 {
return errors.Errorf("you must provide a varlink URI") 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 // Create a single runtime for varlink
runtime, err := libpodruntime.GetRuntime(c) runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) 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: // Register varlink service. The metadata can be retrieved with:
// $ varlink info [varlink address URI] // $ varlink info [varlink address URI]
service, err := varlink.NewService( service, err := varlink.NewService(

View file

@ -3,7 +3,7 @@
package main package main
import ( import (
"github.com/urfave/cli" "github.com/containers/libpod/cmd/podman/cliconfig"
) )
var varlinkCommand *cli.Command var varlinkCommand *cliconfig.PodmanCommand

View file

@ -6,20 +6,41 @@ import (
"text/tabwriter" "text/tabwriter"
"time" "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "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 // 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() output, err := libpod.GetVersion()
if err != nil { if err != nil {
errors.Wrapf(err, "unable to determine version") errors.Wrapf(err, "unable to determine version")
} }
versionOutputFormat := c.String("format") versionOutputFormat := c.Format
if versionOutputFormat != "" { if versionOutputFormat != "" {
var out formats.Writer var out formats.Writer
switch versionOutputFormat { switch versionOutputFormat {
@ -46,19 +67,3 @@ func versionCmd(c *cli.Context) error {
fmt.Fprintf(w, "OS/Arch:\t%s\n", output.OsArch) fmt.Fprintf(w, "OS/Arch:\t%s\n", output.OsArch)
return nil 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",
},
}
)

View file

@ -1,26 +1,23 @@
package main package main
import ( import (
"github.com/urfave/cli" "github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
) )
var ( var volumeDescription = `Manage volumes.
volumeDescription = `Manage volumes.
Volumes are created in and can be shared between containers.` Volumes are created in and can be shared between containers.`
volumeSubCommands = []cli.Command{ var volumeCommand = cliconfig.PodmanCommand{
volumeCreateCommand, Command: &cobra.Command{
volumeLsCommand, Use: "volume",
volumeRmCommand, Short: "Manage volumes",
volumeInspectCommand, Long: volumeDescription,
volumePruneCommand, },
} }
volumeCommand = cli.Command{
Name: "volume", func init() {
Usage: "Manage volumes", volumeCommand.AddCommand(getVolumeSubCommands()...)
Description: volumeDescription, rootCmd.AddCommand(volumeCommand.Command)
UseShortOptionHandling: true, }
Subcommands: volumeSubCommands,
}
)

View file

@ -3,75 +3,70 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var volumeCreateDescription = ` var (
volumeCreateCommand cliconfig.VolumeCreateValues
volumeCreateDescription = `
podman volume create podman volume create
Creates a new volume. If using the default driver, "local", the volume will Creates a new volume. If using the default driver, "local", the volume will
be created at.` be created at.`
var volumeCreateFlags = []cli.Flag{ _volumeCreateCommand = &cobra.Command{
cli.StringFlag{ Use: "create",
Name: "driver", Short: "Create a new volume",
Usage: "Specify volume driver name (default local)", Long: volumeCreateDescription,
}, RunE: func(cmd *cobra.Command, args []string) error {
cli.StringSliceFlag{ volumeCreateCommand.InputArgs = args
Name: "label, l", volumeCreateCommand.GlobalFlags = MainGlobalOpts
Usage: "Set metadata for a volume (default [])", return volumeCreateCmd(&volumeCreateCommand)
}, },
cli.StringSliceFlag{ Example: "[VOLUME-NAME]",
Name: "opt, o", }
Usage: "Set driver specific options (default [])", )
},
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{ func volumeCreateCmd(c *cliconfig.VolumeCreateValues) error {
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 {
var ( var (
options []libpod.VolumeCreateOption options []libpod.VolumeCreateOption
err error err error
volName string volName string
) )
if err = validateFlags(c, volumeCreateFlags); err != nil { runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
return err
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) 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") return errors.Errorf("too many arguments, create takes at most 1 argument")
} }
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
volName = c.Args()[0] volName = c.InputArgs[0]
options = append(options, libpod.WithVolumeName(volName)) options = append(options, libpod.WithVolumeName(volName))
} }
if c.IsSet("driver") { if c.Flag("driver").Changed {
options = append(options, libpod.WithVolumeDriver(c.String("driver"))) options = append(options, libpod.WithVolumeDriver(c.String("driver")))
} }
labels, err := getAllLabels([]string{}, c.StringSlice("label")) labels, err := getAllLabels([]string{}, c.Label)
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to process labels") return errors.Wrapf(err, "unable to process labels")
} }
@ -79,7 +74,7 @@ func volumeCreateCmd(c *cli.Context) error {
options = append(options, libpod.WithVolumeLabels(labels)) options = append(options, libpod.WithVolumeLabels(labels))
} }
opts, err := getAllLabels([]string{}, c.StringSlice("opt")) opts, err := getAllLabels([]string{}, c.Opt)
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to process options") return errors.Wrapf(err, "unable to process options")
} }

View file

@ -1,60 +1,56 @@
package main package main
import ( import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var volumeInspectDescription = ` var (
volumeInspectCommand cliconfig.VolumeInspectValues
volumeInspectDescription = `
podman volume inspect podman volume inspect
Display detailed information on one or more volumes. Can change the format Display detailed information on one or more volumes. Can change the format
from JSON to a Go template. 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{ func volumeInspectCmd(c *cliconfig.VolumeInspectValues) error {
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 {
var err error var err error
if err = validateFlags(c, volumeInspectFlags); err != nil { runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
return err
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
opts := volumeLsOptions{ opts := volumeLsOptions{
Format: c.String("format"), Format: c.Format,
} }
vols, lastError := getVolumesFromContext(c, runtime) vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
if lastError != nil { if lastError != nil {
logrus.Errorf("%q", lastError) logrus.Errorf("%q", lastError)
} }

View file

@ -4,11 +4,12 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
// volumeOptions is the "ls" command options // volumeOptions is the "ls" command options
@ -37,64 +38,57 @@ type volumeLsJSONParams struct {
Scope string `json:"scope"` Scope string `json:"scope"`
} }
var volumeLsDescription = ` var (
volumeLsCommand cliconfig.VolumeLsValues
volumeLsDescription = `
podman volume ls podman volume ls
List all available volumes. The output of the volumes can be filtered 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. and the output format can be changed to JSON or a user specified Go template.
` `
_volumeLsCommand = &cobra.Command{
var volumeLsFlags = []cli.Flag{ Use: "ls",
cli.StringFlag{ Aliases: []string{"list"},
Name: "filter, f", Short: "List volumes",
Usage: "Filter volume output", Long: volumeLsDescription,
}, RunE: func(cmd *cobra.Command, args []string) error {
cli.StringFlag{ volumeLsCommand.InputArgs = args
Name: "format", volumeLsCommand.GlobalFlags = MainGlobalOpts
Usage: "Format volume output using Go template", return volumeLsCmd(&volumeLsCommand)
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
} }
)
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 { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
if len(c.Args()) > 0 { if len(c.InputArgs) > 0 {
return errors.Errorf("too many arguments, ls takes no arguments") return errors.Errorf("too many arguments, ls takes no arguments")
} }
opts := volumeLsOptions{ opts := volumeLsOptions{
Quiet: c.Bool("quiet"), Quiet: c.Quiet,
} }
opts.Format = genVolLsFormat(c) opts.Format = genVolLsFormat(c)
// Get the filter functions based on any filters set // Get the filter functions based on any filters set
var filterFuncs []libpod.VolumeFilter var filterFuncs []libpod.VolumeFilter
if c.String("filter") != "" { if c.Filter != "" {
filters := strings.Split(c.String("filter"), ",") filters := strings.Split(c.Filter, ",")
for _, f := range filters { for _, f := range filters {
filterSplit := strings.Split(f, "=") filterSplit := strings.Split(f, "=")
if len(filterSplit) < 2 { if len(filterSplit) < 2 {
@ -129,14 +123,14 @@ func volumeLsCmd(c *cli.Context) error {
} }
// generate the template based on conditions given // generate the template based on conditions given
func genVolLsFormat(c *cli.Context) string { func genVolLsFormat(c *cliconfig.VolumeLsValues) string {
var format string var format string
if c.String("format") != "" { if c.Format != "" {
// "\t" from the command line is not being recognized as a tab // "\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" // 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}}" format = "{{.Name}}"
} }
return format return format

View file

@ -7,35 +7,39 @@ import (
"os" "os"
"strings" "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/adapter" "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var volumePruneDescription = ` var (
volumePruneCommand cliconfig.VolumePruneValues
volumePruneDescription = `
podman volume prune podman volume prune
Remove all unused volumes. Will prompt for confirmation if not Remove all unused volumes. Will prompt for confirmation if not
using force. 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{ func init() {
cli.BoolFlag{ volumePruneCommand.Command = _volumePruneCommand
Name: "force, f", flags := volumePruneCommand.Flags()
Usage: "Do not prompt for confirmation",
},
}
var volumePruneCommand = cli.Command{ flags.BoolVarP(&volumePruneCommand.Force, "force", "f", false, "Do not prompt for confirmation")
Name: "prune",
Usage: "Remove all unused volumes",
Description: volumePruneDescription,
Flags: volumePruneFlags,
Action: volumePruneCmd,
SkipArgReorder: true,
UseShortOptionHandling: true,
} }
func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error { func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error {
@ -60,20 +64,15 @@ func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error {
return lastError return lastError
} }
func volumePruneCmd(c *cli.Context) error { func volumePruneCmd(c *cliconfig.VolumePruneValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err := validateFlags(c, volumePruneFlags); err != nil {
return err
}
runtime, err := adapter.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
defer runtime.Shutdown(false) defer runtime.Shutdown(false)
// Prompt for confirmation if --force is not set // Prompt for confirmation if --force is not set
if !c.Bool("force") { if !c.Force {
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
fmt.Println("WARNING! This will remove all volumes not used by at least one container.") 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] ") fmt.Print("Are you sure you want to continue? [y/N] ")

View file

@ -3,51 +3,47 @@ package main
import ( import (
"fmt" "fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var volumeRmDescription = ` var (
volumeRmCommand cliconfig.VolumeRmValues
volumeRmDescription = `
podman volume rm podman volume rm
Remove one or more existing volumes. Will only remove volumes that are 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 not being used by any containers. To remove the volumes anyways, use the
--force flag. --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{ func init() {
cli.BoolFlag{ volumeRmCommand.Command = _volumeRmCommand
Name: "all, a", flags := volumeRmCommand.Flags()
Usage: "Remove all volumes", 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")
cli.BoolFlag{
Name: "force, f",
Usage: "Remove a volume by force, even if it is being used by a container",
},
} }
var volumeRmCommand = cli.Command{ func volumeRmCmd(c *cliconfig.VolumeRmValues) error {
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 {
var err error var err error
if err = validateFlags(c, volumeRmFlags); err != nil { runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
return err
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
@ -55,9 +51,9 @@ func volumeRmCmd(c *cli.Context) error {
ctx := getContext() ctx := getContext()
vols, lastError := getVolumesFromContext(c, runtime) vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
for _, vol := range vols { 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 err != nil {
if lastError != nil { if lastError != nil {
logrus.Errorf("%q", lastError) logrus.Errorf("%q", lastError)

View file

@ -5,43 +5,49 @@ import (
"os" "os"
"time" "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
var ( var (
waitCommand cliconfig.WaitValues
waitDescription = ` waitDescription = `
podman wait podman wait
Block until one or more containers stop and then print their exit codes Block until one or more containers stop and then print their exit codes
` `
waitFlags = []cli.Flag{ _waitCommand = &cobra.Command{
cli.UintFlag{ Use: "wait",
Name: "interval, i", Short: "Block on one or more containers",
Usage: "Milliseconds to wait before polling for completion", Long: waitDescription,
Value: 250, RunE: func(cmd *cobra.Command, args []string) error {
waitCommand.InputArgs = args
waitCommand.GlobalFlags = MainGlobalOpts
return waitCmd(&waitCommand)
}, },
LatestFlag, Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
}
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,
} }
) )
func waitCmd(c *cli.Context) error { func init() {
args := c.Args() waitCommand.Command = _waitCommand
if len(args) < 1 && !c.Bool("latest") { 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") 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 { if err != nil {
return errors.Wrapf(err, "error creating libpod runtime") return errors.Wrapf(err, "error creating libpod runtime")
} }
@ -52,7 +58,7 @@ func waitCmd(c *cli.Context) error {
} }
var lastError error var lastError error
if c.Bool("latest") { if c.Latest {
latestCtr, err := runtime.GetLatestContainer() latestCtr, err := runtime.GetLatestContainer()
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to wait on latest container") return errors.Wrapf(err, "unable to wait on latest container")
@ -65,10 +71,10 @@ func waitCmd(c *cli.Context) error {
if err != nil { if err != nil {
return errors.Wrapf(err, "unable to find container %s", container) 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") 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 err != nil {
if lastError != nil { if lastError != nil {
fmt.Fprintln(os.Stderr, lastError) fmt.Fprintln(os.Stderr, lastError)

View file

@ -11,11 +11,11 @@ import (
"strconv" "strconv"
"github.com/containers/image/types" "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/libpodruntime"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/urfave/cli"
) )
// LocalRuntime describes a typical libpod runtime // 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 // 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) runtime, err := libpodruntime.GetRuntime(c)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -14,12 +14,12 @@ import (
"time" "time"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/varlink" "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/image"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/varlink/go/varlink" "github.com/varlink/go/varlink"
) )
@ -38,7 +38,7 @@ type LocalRuntime struct {
} }
// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it // 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{} runtime := RemoteRuntime{}
conn, err := runtime.Connect() conn, err := runtime.Connect()
if err != nil { if err != nil {

View file

@ -1,20 +1,21 @@
package varlinkapi package varlinkapi
import ( import (
"github.com/containers/libpod/cmd/podman/cliconfig"
iopodman "github.com/containers/libpod/cmd/podman/varlink" iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/urfave/cli" "github.com/spf13/cobra"
) )
// LibpodAPI is the basic varlink struct for libpod // LibpodAPI is the basic varlink struct for libpod
type LibpodAPI struct { type LibpodAPI struct {
Cli *cli.Context Cli *cobra.Command
iopodman.VarlinkInterface iopodman.VarlinkInterface
Runtime *libpod.Runtime Runtime *libpod.Runtime
} }
// New creates a new varlink client // New creates a new varlink client
func New(cli *cli.Context, runtime *libpod.Runtime) *iopodman.VarlinkInterface { func New(cli *cliconfig.PodmanCommand, runtime *libpod.Runtime) *iopodman.VarlinkInterface {
lp := LibpodAPI{Cli: cli, Runtime: runtime} lp := LibpodAPI{Cli: cli.Command, Runtime: runtime}
return iopodman.VarlinkNew(&lp) return iopodman.VarlinkNew(&lp)
} }

View file

@ -151,7 +151,7 @@ var _ = Describe("Podman restart", func() {
startTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1", "test2"}) startTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1", "test2"})
startTime.WaitWithDefaultTimeout() startTime.WaitWithDefaultTimeout()
session := podmanTest.Podman([]string{"restart", "-all"}) session := podmanTest.Podman([]string{"restart", "--all"})
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0)) Expect(session.ExitCode()).To(Equal(0))
restartTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1", "test2"}) restartTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1", "test2"})

View file

@ -15,8 +15,8 @@ github.com/containerd/cgroups 39b18af02c4120960f517a3a4c2588fabb61d02c
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-alpha1 github.com/containernetworking/cni v0.7.0-alpha1
github.com/containernetworking/plugins v0.7.4 github.com/containernetworking/plugins v0.7.4
github.com/containers/image 67b1f789f2ce8a3654592a582fff26c396326236 github.com/containers/image v1.3
github.com/containers/storage v1.8 github.com/containers/storage v1.9
github.com/containers/psgo v1.1 github.com/containers/psgo v1.1
github.com/coreos/go-systemd v14 github.com/coreos/go-systemd v14
github.com/cri-o/ocicni 2d2983e40c242322a56c22a903785e7f83eb378c 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 k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7 github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
github.com/varlink/go 3ac79db6fd6aec70924193b090962f92985fe199 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? # TODO: Gotty has not been updated since 2012. Can we find replacement?
github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512 github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512
# do not go beyond the below commit as the next one requires a more recent # 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/ginkgo v1.7.0
github.com/onsi/gomega v1.4.3 github.com/onsi/gomega v1.4.3
github.com/hpcloud/tail v1.0.0 github.com/hpcloud/tail v1.0.0
gopkg.in/fsnotify.v1 v1.4.2
gopkg.in/tomb.v1 v1 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

View file

@ -8,6 +8,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"time"
"github.com/containers/buildah/docker" "github.com/containers/buildah/docker"
"github.com/containers/buildah/util" "github.com/containers/buildah/util"
@ -25,7 +26,7 @@ const (
Package = "buildah" Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec // Version for the Package. Bump version in contrib/rpm/buildah.spec
// too. // too.
Version = "1.6-dev" Version = "1.7-dev"
// The value we use to identify what type of information, currently a // The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state. // serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to // 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. // after processing the AddCapabilities set, when running commands in the container.
// If a capability appears in both lists, it will be dropped. // If a capability appears in both lists, it will be dropped.
DropCapabilities []string 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 CommonBuildOpts *CommonBuildOptions
// TopLayer is the top layer of the image // TopLayer is the top layer of the image
@ -209,11 +219,24 @@ type BuilderInfo struct {
DefaultCapabilities []string DefaultCapabilities []string
AddCapabilities []string AddCapabilities []string
DropCapabilities []string DropCapabilities []string
History []v1.History
} }
// GetBuildInfo gets a pointer to a Builder object and returns a BuilderInfo object from it. // 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. // This is used in the inspect command to display Manifest and Config as string and not []byte.
func GetBuildInfo(b *Builder) BuilderInfo { 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{ return BuilderInfo{
Type: b.Type, Type: b.Type,
FromImage: b.FromImage, FromImage: b.FromImage,
@ -239,6 +262,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
DefaultCapabilities: append([]string{}, util.DefaultCapabilities...), DefaultCapabilities: append([]string{}, util.DefaultCapabilities...),
AddCapabilities: append([]string{}, b.AddCapabilities...), AddCapabilities: append([]string{}, b.AddCapabilities...),
DropCapabilities: append([]string{}, b.DropCapabilities...), DropCapabilities: append([]string{}, b.DropCapabilities...),
History: history,
} }
} }

View file

@ -351,21 +351,6 @@ func runUsingChrootMain() {
defer stdoutRead.Close() defer stdoutRead.Close()
defer stderrRead.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 { for readFd, writeFd := range relays {
if err := unix.SetNonblock(readFd, true); err != nil { if err := unix.SetNonblock(readFd, true); err != nil {
logrus.Errorf("error setting descriptor %d (%s) non-blocking: %v", readFd, fdDesc[readFd], err) 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}) fds = append(fds, unix.PollFd{Fd: int32(fd), Events: unix.POLLIN | unix.POLLHUP})
} }
_, err := unix.Poll(fds, pollTimeout) _, err := unix.Poll(fds, pollTimeout)
if !logIfNotRetryable(err, fmt.Sprintf("poll: %v", err)) { if !util.LogIfNotRetryable(err, fmt.Sprintf("poll: %v", err)) {
return return
} }
removeFds := make(map[int]struct{}) removeFds := make(map[int]struct{})
@ -405,7 +390,7 @@ func runUsingChrootMain() {
} }
b := make([]byte, 8192) b := make([]byte, 8192)
nread, err := unix.Read(int(rfd.Fd), b) 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 nread > 0 {
if wfd, ok := relays[int(rfd.Fd)]; ok { if wfd, ok := relays[int(rfd.Fd)]; ok {
nwritten, err := buffers[wfd].Write(b[:nread]) nwritten, err := buffers[wfd].Write(b[:nread])
@ -422,7 +407,7 @@ func runUsingChrootMain() {
// from this descriptor, read as much as there is to read. // from this descriptor, read as much as there is to read.
for rfd.Revents&unix.POLLHUP == unix.POLLHUP { for rfd.Revents&unix.POLLHUP == unix.POLLHUP {
nr, err := unix.Read(int(rfd.Fd), b) 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 { if nr <= 0 {
break break
} }
@ -447,7 +432,7 @@ func runUsingChrootMain() {
for wfd, buffer := range buffers { for wfd, buffer := range buffers {
if buffer.Len() > 0 { if buffer.Len() > 0 {
nwritten, err := unix.Write(wfd, buffer.Bytes()) 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 { if nwritten >= 0 {
_ = buffer.Next(nwritten) _ = buffer.Next(nwritten)
} }

View file

@ -67,6 +67,10 @@ type CommitOptions struct {
OnBuild []string OnBuild []string
// Parent is the base image that this image was created by. // Parent is the base image that this image was created by.
Parent string 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. // 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 // regenerate from on-disk layers, substituting them in the list of
// blobs to copy whenever possible. // blobs to copy whenever possible.
BlobDirectory string 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 // 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 { if err != nil {
return imgID, nil, "", errors.Wrapf(err, "error computing layer digests and building metadata for container %q", b.ContainerID) 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) { func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) (reference.Canonical, digest.Digest, error) {
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath) systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
if options.Quiet {
options.ReportWriter = nil // Turns off logging output
}
blocked, err := isReferenceBlocked(dest, systemContext) blocked, err := isReferenceBlocked(dest, systemContext)
if err != nil { if err != nil {
return nil, "", errors.Wrapf(err, "error checking if pushing to registry for %q is blocked", transports.ImageName(dest)) return nil, "", errors.Wrapf(err, "error checking if pushing to registry for %q is blocked", transports.ImageName(dest))

View file

@ -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
}

View file

@ -18,7 +18,7 @@ const TypeLayers = "layers"
const V2S2MediaTypeUncompressedLayer = "application/vnd.docker.image.rootfs.diff.tar" const V2S2MediaTypeUncompressedLayer = "application/vnd.docker.image.rootfs.diff.tar"
// github.com/moby/moby/image/rootfs.go // 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 is currently a placeholder that only supports layers. In the future
// this can be made into an interface that supports different implementations. // this can be made into an interface that supports different implementations.
type V2S2RootFS struct { type V2S2RootFS struct {
@ -27,7 +27,7 @@ type V2S2RootFS struct {
} }
// github.com/moby/moby/image/image.go // 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 { type V2S2History struct {
// Created is the timestamp at which the image was created // Created is the timestamp at which the image was created
Created time.Time `json:"created"` Created time.Time `json:"created"`
@ -158,7 +158,7 @@ type V1Image struct {
} }
// github.com/moby/moby/image/image.go // github.com/moby/moby/image/image.go
// Image stores the image configuration // V2Image stores the image configuration
type V2Image struct { type V2Image struct {
V1Image V1Image
Parent ID `json:"parent,omitempty"` Parent ID `json:"parent,omitempty"`
@ -176,7 +176,7 @@ type V2Image struct {
} }
// github.com/docker/distribution/manifest/versioned.go // 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 // Incoming content with unknown schema version can be decoded against this
// struct to check the version. // struct to check the version.
type V2Versioned struct { type V2Versioned struct {
@ -188,21 +188,21 @@ type V2Versioned struct {
} }
// github.com/docker/distribution/manifest/schema1/manifest.go // 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 { type V2S1FSLayer struct {
// BlobSum is the tarsum of the referenced filesystem image layer // BlobSum is the tarsum of the referenced filesystem image layer
BlobSum digest.Digest `json:"blobSum"` BlobSum digest.Digest `json:"blobSum"`
} }
// github.com/docker/distribution/manifest/schema1/manifest.go // github.com/docker/distribution/manifest/schema1/manifest.go
// History stores unstructured v1 compatibility information // V2S1History stores unstructured v1 compatibility information
type V2S1History struct { type V2S1History struct {
// V1Compatibility is the raw v1 compatibility information // V1Compatibility is the raw v1 compatibility information
V1Compatibility string `json:"v1Compatibility"` V1Compatibility string `json:"v1Compatibility"`
} }
// github.com/docker/distribution/manifest/schema1/manifest.go // 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. // format in the registry.
type V2S1Manifest struct { type V2S1Manifest struct {
V2Versioned V2Versioned
@ -225,7 +225,7 @@ type V2S1Manifest struct {
} }
// github.com/docker/distribution/blobs.go // 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 // 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 // blob. The struct also describes the wire protocol format. Fields should
// only be added but never changed. // only be added but never changed.
@ -250,7 +250,7 @@ type V2S2Descriptor struct {
} }
// github.com/docker/distribution/manifest/schema2/manifest.go // github.com/docker/distribution/manifest/schema2/manifest.go
// Manifest defines a schema2 manifest. // V2S2Manifest defines a schema2 manifest.
type V2S2Manifest struct { type V2S2Manifest struct {
V2Versioned V2Versioned

Some files were not shown because too many files have changed in this diff Show more