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 \
-whitelist "github.com/varlink/go" \
-whitelist "github.com/onsi/ginkgo" \
-whitelist "github.com/onsi/gomega"
-whitelist "github.com/onsi/gomega" \
-whitelist "gopkg.in/fsnotify.v1"
.PHONY: \
.gopathok \

View file

@ -3,57 +3,56 @@ package main
import (
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
attachFlags = []cli.Flag{
cli.StringFlag{
Name: "detach-keys",
Usage: "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _.",
},
cli.BoolFlag{
Name: "no-stdin",
Usage: "Do not attach STDIN. The default is false.",
},
cli.BoolTFlag{
Name: "sig-proxy",
Usage: "Proxy received signals to the process (default true)",
},
LatestFlag,
}
attachCommand cliconfig.AttachValues
attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively."
attachCommand = cli.Command{
Name: "attach",
Usage: "Attach to a running container",
Description: attachDescription,
Flags: sortFlags(attachFlags),
Action: attachCmd,
ArgsUsage: "",
OnUsageError: usageErrorHandler,
_attachCommand = &cobra.Command{
Use: "attach",
Short: "Attach to a running container",
Long: attachDescription,
RunE: func(cmd *cobra.Command, args []string) error {
attachCommand.InputArgs = args
attachCommand.GlobalFlags = MainGlobalOpts
return attachCmd(&attachCommand)
},
Example: "",
}
)
func attachCmd(c *cli.Context) error {
args := c.Args()
func init() {
attachCommand.Command = _attachCommand
flags := attachCommand.Flags()
flags.StringVar(&attachCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false")
flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true)")
flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
rootCmd.AddCommand(attachCommand.Command)
}
func attachCmd(c *cliconfig.AttachValues) error {
args := c.InputArgs
var ctr *libpod.Container
if err := validateFlags(c, attachFlags); err != nil {
return err
}
if len(c.Args()) > 1 || (len(c.Args()) == 0 && !c.Bool("latest")) {
if len(c.InputArgs) > 1 || (len(c.InputArgs) == 0 && !c.Latest) {
return errors.Errorf("attach requires the name or id of one running container or the latest flag")
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
if c.Bool("latest") {
if c.Latest {
ctr, err = runtime.GetLatestContainer()
} else {
ctr, err = runtime.LookupContainer(args[0])
@ -72,11 +71,11 @@ func attachCmd(c *cli.Context) error {
}
inputStream := os.Stdin
if c.Bool("no-stdin") {
if c.NoStdin {
inputStream = nil
}
if err := startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.String("detach-keys"), c.BoolT("sig-proxy"), false); err != nil {
if err := startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, c.SigProxy, false); err != nil {
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
}

View file

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

View file

@ -5,70 +5,67 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
checkpointCommand cliconfig.CheckpointValues
checkpointDescription = `
podman container checkpoint
Checkpoints one or more running containers. The container name or ID can be used.
`
checkpointFlags = []cli.Flag{
cli.BoolFlag{
Name: "keep, k",
Usage: "Keep all temporary checkpoint files",
_checkpointCommand = &cobra.Command{
Use: "checkpoint",
Short: "Checkpoints one or more containers",
Long: checkpointDescription,
RunE: func(cmd *cobra.Command, args []string) error {
checkpointCommand.InputArgs = args
checkpointCommand.GlobalFlags = MainGlobalOpts
return checkpointCmd(&checkpointCommand)
},
cli.BoolFlag{
Name: "leave-running, R",
Usage: "Leave the container running after writing checkpoint to disk",
},
cli.BoolFlag{
Name: "tcp-established",
Usage: "Checkpoint a container with established TCP connections",
},
cli.BoolFlag{
Name: "all, a",
Usage: "Checkpoint all running containers",
},
LatestFlag,
}
checkpointCommand = cli.Command{
Name: "checkpoint",
Usage: "Checkpoints one or more containers",
Description: checkpointDescription,
Flags: sortFlags(checkpointFlags),
Action: checkpointCmd,
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
}
)
func checkpointCmd(c *cli.Context) error {
func init() {
checkpointCommand.Command = _checkpointCommand
flags := checkpointCommand.Flags()
flags.BoolVarP(&checkpointCommand.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
flags.BoolVarP(&checkpointCommand.LeaveRunning, "leave-running", "R", false, "Leave the container running after writing checkpoint to disk")
flags.BoolVar(&checkpointCommand.TcpEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
flags.BoolVarP(&checkpointCommand.All, "all", "a", false, "Checkpoint all running containers")
flags.BoolVarP(&checkpointCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
}
func checkpointCmd(c *cliconfig.CheckpointValues) error {
if rootless.IsRootless() {
return errors.New("checkpointing a container requires root")
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
options := libpod.ContainerCheckpointOptions{
Keep: c.Bool("keep"),
KeepRunning: c.Bool("leave-running"),
TCPEstablished: c.Bool("tcp-established"),
Keep: c.Keep,
KeepRunning: c.LeaveRunning,
TCPEstablished: c.TcpEstablished,
}
if err := checkAllAndLatest(c); err != nil {
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err
}
containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
for _, ctr := range containers {
if err = ctr.Checkpoint(context.TODO(), options); err != nil {

View file

@ -4,50 +4,52 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
cleanupFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Cleans up all containers",
},
LatestFlag,
}
cleanupCommand cliconfig.CleanupValues
cleanupDescription = `
podman container cleanup
Cleans up mount points and network stacks on one or more containers from the host. The container name or ID can be used. This command is used internally when running containers, but can also be used if container cleanup has failed when a container exits.
`
cleanupCommand = cli.Command{
Name: "cleanup",
Usage: "Cleanup network and mountpoints of one or more containers",
Description: cleanupDescription,
Flags: sortFlags(cleanupFlags),
Action: cleanupCmd,
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
OnUsageError: usageErrorHandler,
_cleanupCommand = &cobra.Command{
Use: "cleanup",
Short: "Cleanup network and mountpoints of one or more containers",
Long: cleanupDescription,
RunE: func(cmd *cobra.Command, args []string) error {
cleanupCommand.InputArgs = args
cleanupCommand.GlobalFlags = MainGlobalOpts
return cleanupCmd(&cleanupCommand)
},
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
}
)
func cleanupCmd(c *cli.Context) error {
if err := validateFlags(c, cleanupFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
func init() {
cleanupCommand.Command = _cleanupCommand
flags := cleanupCommand.Flags()
flags.BoolVarP(&cleanupCommand.All, "all", "a", false, "Cleans up all containers")
flags.BoolVarP(&cleanupCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
}
func cleanupCmd(c *cliconfig.CleanupValues) error {
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
if err := checkAllAndLatest(c); err != nil {
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err
}
cleanupContainers, lastError := getAllOrLatestContainers(c, runtime, -1, "all")
cleanupContainers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
ctx := getContext()

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
import "github.com/urfave/cli"
import (
"github.com/spf13/cobra"
)
func getAppCommands() []cli.Command {
return []cli.Command{
attachCommand,
commitCommand,
buildCommand,
createCommand,
diffCommand,
execCommand,
killCommand,
kubeCommand,
loadCommand,
loginCommand,
logoutCommand,
logsCommand,
mountCommand,
pauseCommand,
psCommand,
podCommand,
portCommand,
pushCommand,
playCommand,
restartCommand,
rmCommand,
runCommand,
saveCommand,
searchCommand,
startCommand,
statsCommand,
stopCommand,
topCommand,
umountCommand,
unpauseCommand,
volumeCommand,
waitCommand,
func getImageSubCommands() []*cobra.Command {
return []*cobra.Command{
_buildCommand,
_importCommand,
_loadCommand,
_pullCommand,
_rmiCommand,
_saveCommand,
_signCommand,
}
}
func getImageSubCommands() []cli.Command {
return []cli.Command{
buildCommand,
importCommand,
loadCommand,
pullCommand,
saveCommand,
trustCommand,
signCommand,
func getContainerSubCommands() []*cobra.Command {
return []*cobra.Command{
_attachCommand,
_checkpointCommand,
_cleanupCommand,
_containerExistsCommand,
_commitCommand,
_createCommand,
_diffCommand,
_execCommand,
_exportCommand,
_killCommand,
_logsCommand,
_psCommand,
_mountCommand,
_pauseCommand,
_portCommand,
_pruneContainersCommand,
_refreshCommand,
_restartCommand,
_restoreCommand,
_rmCommand,
_runCommmand,
_runlabelCommand,
_startCommand,
_statsCommand,
_stopCommand,
_topCommand,
_umountCommand,
_unpauseCommand,
_waitCommand,
}
}
func getSystemSubCommands() []cli.Command {
return []cli.Command{infoCommand}
func getPodSubCommands() []*cobra.Command {
return []*cobra.Command{
_podCreateCommand,
_podExistsCommand,
_podInspectCommand,
_podKillCommand,
_podPauseCommand,
_podPsCommand,
_podRestartCommand,
_podRmCommand,
_podStartCommand,
_podStatsCommand,
_podStopCommand,
_podTopCommand,
_podUnpauseCommand,
}
}
func getContainerSubCommands() []cli.Command {
return []cli.Command{
attachCommand,
checkpointCommand,
cleanupCommand,
containerExistsCommand,
commitCommand,
createCommand,
diffCommand,
execCommand,
exportCommand,
killCommand,
logsCommand,
psCommand,
mountCommand,
pauseCommand,
portCommand,
pruneContainersCommand,
refreshCommand,
restartCommand,
restoreCommand,
rmCommand,
runCommand,
runlabelCommand,
startCommand,
statsCommand,
stopCommand,
topCommand,
umountCommand,
unpauseCommand,
// updateCommand,
waitCommand,
func getVolumeSubCommands() []*cobra.Command {
return []*cobra.Command{
_volumeCreateCommand,
_volumeLsCommand,
_volumeRmCommand,
_volumeInspectCommand,
_volumePruneCommand,
}
}
func getMainAppFlags() []cli.Flag {
return []cli.Flag{
cli.StringFlag{
Name: "cgroup-manager",
Usage: "Cgroup manager to use (cgroupfs or systemd, default systemd)",
},
cli.StringFlag{
Name: "cni-config-dir",
Usage: "Path of the configuration directory for CNI networks",
},
cli.StringFlag{
Name: "conmon",
Usage: "Path of the conmon binary",
},
cli.StringFlag{
Name: "default-mounts-file",
Usage: "Path to default mounts file",
Hidden: true,
},
cli.StringSliceFlag{
Name: "hooks-dir",
Usage: "Set the OCI hooks directory path (may be set multiple times)",
},
cli.IntFlag{
Name: "max-workers",
Usage: "The maximum number of workers for parallel operations",
Hidden: true,
},
cli.StringFlag{
Name: "namespace",
Usage: "Set the libpod namespace, used to create separate views of the containers and pods on the system",
Value: "",
},
cli.StringFlag{
Name: "root",
Usage: "Path to the root directory in which data, including images, is stored",
},
cli.StringFlag{
Name: "runroot",
Usage: "Path to the 'run directory' where all state information is stored",
},
cli.StringFlag{
Name: "runtime",
Usage: "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc",
},
cli.StringFlag{
Name: "storage-driver, s",
Usage: "Select which storage driver is used to manage storage of images and containers (default is overlay)",
},
cli.StringSliceFlag{
Name: "storage-opt",
Usage: "Used to pass an option to the storage driver",
},
cli.BoolFlag{
Name: "syslog",
Usage: "Output logging information to syslog as well as the console",
},
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{
_containerKubeCommand,
}
}
func getPlaySubCommands() []*cobra.Command {
return []*cobra.Command{
_playKubeCommand,
}
}
func getTrustSubCommands() []*cobra.Command {
return []*cobra.Command{
_setTrustCommand,
_showTrustCommand,
}
}
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{
_infoCommand,
_pruneSystemCommand,
}
}

View file

@ -2,24 +2,47 @@
package main
import "github.com/urfave/cli"
import (
"github.com/spf13/cobra"
)
func getAppCommands() []cli.Command {
return []cli.Command{}
//import "github.com/urfave/cli"
//
func getAppCommands() []*cobra.Command {
return []*cobra.Command{}
}
func getImageSubCommands() []cli.Command {
return []cli.Command{}
func getImageSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
func getContainerSubCommands() []cli.Command {
return []cli.Command{}
func getContainerSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
func getSystemSubCommands() []cli.Command {
return []cli.Command{}
func getPodSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
func getMainAppFlags() []cli.Flag {
return []cli.Flag{}
func getVolumeSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
func getPlaySubCommands() []*cobra.Command {
return []*cobra.Command{}
}
func getTrustSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
//func getMainAppFlags() []cli.Flag {
// return []cli.Flag{}
//}
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{}
}

View file

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

View file

@ -4,34 +4,19 @@ import (
"context"
"fmt"
"os"
"reflect"
"regexp"
"sort"
"strings"
"github.com/containers/buildah"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage"
"github.com/fatih/camelcase"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
stores = make(map[storage.Store]struct{})
LatestFlag = cli.BoolFlag{
Name: "latest, l",
Usage: "Act on the latest container podman is aware of",
}
LatestPodFlag = cli.BoolFlag{
Name: "latest, l",
Usage: "Act on the latest pod podman is aware of",
}
WorkDirFlag = cli.StringFlag{
Name: "workdir, w",
Usage: "Working directory inside the container",
}
stores = make(map[storage.Store]struct{})
)
const (
@ -50,53 +35,9 @@ func shortID(id string) string {
return id
}
func usageErrorHandler(context *cli.Context, err error, _ bool) error {
cmd := context.App.Name
if len(context.Command.Name) > 0 {
cmd = cmd + " " + context.Command.Name
}
return fmt.Errorf("%s\nSee '%s --help'.", err, cmd)
}
func commandNotFoundHandler(context *cli.Context, command string) {
fmt.Fprintf(os.Stderr, "Command %q not found.\nSee `%s --help`.\n", command, context.App.Name)
os.Exit(exitCode)
}
// validateFlags searches for StringFlags or StringSlice flags that never had
// a value set. This commonly occurs when the CLI mistakenly takes the next
// option and uses it as a value.
func validateFlags(c *cli.Context, flags []cli.Flag) error {
for _, flag := range flags {
switch reflect.TypeOf(flag).String() {
case "cli.StringSliceFlag":
{
f := flag.(cli.StringSliceFlag)
name := strings.Split(f.Name, ",")
val := c.StringSlice(name[0])
for _, v := range val {
if ok, _ := regexp.MatchString("^-.+", v); ok {
return errors.Errorf("option --%s requires a value", name[0])
}
}
}
case "cli.StringFlag":
{
f := flag.(cli.StringFlag)
name := strings.Split(f.Name, ",")
val := c.String(name[0])
if ok, _ := regexp.MatchString("^-.+", val); ok {
return errors.Errorf("option --%s requires a value", name[0])
}
}
}
}
return nil
}
// checkAllAndLatest checks that --all and --latest are used correctly
func checkAllAndLatest(c *cli.Context) error {
argLen := len(c.Args())
func checkAllAndLatest(c *cliconfig.PodmanCommand) error {
argLen := len(c.InputArgs)
if (c.Bool("all") || c.Bool("latest")) && argLen > 0 {
return errors.Errorf("no arguments are needed with --all or --latest")
}
@ -117,7 +58,7 @@ func checkAllAndLatest(c *cli.Context) error {
// is desired a -1 can be used to get all containers. For a better
// error message, if the filter fails, a corresponding verb can be
// specified which will then appear in the error message.
func getAllOrLatestContainers(c *cli.Context, runtime *libpod.Runtime, filterState libpod.ContainerStatus, verb string) ([]*libpod.Container, error) {
func getAllOrLatestContainers(c *cliconfig.PodmanCommand, runtime *libpod.Runtime, filterState libpod.ContainerStatus, verb string) ([]*libpod.Container, error) {
var containers []*libpod.Container
var lastError error
var err error
@ -142,7 +83,7 @@ func getAllOrLatestContainers(c *cli.Context, runtime *libpod.Runtime, filterSta
}
containers = append(containers, lastCtr)
} else {
args := c.Args()
args := c.InputArgs
for _, i := range args {
container, err := runtime.LookupContainer(i)
if err != nil {
@ -173,363 +114,367 @@ func getDefaultNetwork() string {
return "bridge"
}
// Common flags shared between commands
var createFlags = []cli.Flag{
cli.StringSliceFlag{
Name: "add-host",
Usage: "Add a custom host-to-IP mapping (host:ip) (default [])",
},
cli.StringSliceFlag{
Name: "annotation",
Usage: "Add annotations to container (key:value) (default [])",
},
cli.StringSliceFlag{
Name: "attach, a",
Usage: "Attach to STDIN, STDOUT or STDERR (default [])",
},
cli.StringFlag{
Name: "blkio-weight",
Usage: "Block IO weight (relative weight) accepts a weight value between 10 and 1000.",
},
cli.StringSliceFlag{
Name: "blkio-weight-device",
Usage: "Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)",
},
cli.StringSliceFlag{
Name: "cap-add",
Usage: "Add capabilities to the container",
},
cli.StringSliceFlag{
Name: "cap-drop",
Usage: "Drop capabilities from the container",
},
cli.StringFlag{
Name: "cgroup-parent",
Usage: "Optional parent cgroup for the container",
},
cli.StringFlag{
Name: "cidfile",
Usage: "Write the container ID to the file",
},
cli.StringFlag{
Name: "conmon-pidfile",
Usage: "Path to the file that will receive the PID of conmon",
},
cli.Uint64Flag{
Name: "cpu-period",
Usage: "Limit the CPU CFS (Completely Fair Scheduler) period",
},
cli.Int64Flag{
Name: "cpu-quota",
Usage: "Limit the CPU CFS (Completely Fair Scheduler) quota",
},
cli.Uint64Flag{
Name: "cpu-rt-period",
Usage: "Limit the CPU real-time period in microseconds",
},
cli.Int64Flag{
Name: "cpu-rt-runtime",
Usage: "Limit the CPU real-time runtime in microseconds",
},
cli.Uint64Flag{
Name: "cpu-shares",
Usage: "CPU shares (relative weight)",
},
cli.Float64Flag{
Name: "cpus",
Usage: "Number of CPUs. The default is 0.000 which means no limit",
},
cli.StringFlag{
Name: "cpuset-cpus",
Usage: "CPUs in which to allow execution (0-3, 0,1)",
},
cli.StringFlag{
Name: "cpuset-mems",
Usage: "Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
},
cli.BoolFlag{
Name: "detach, d",
Usage: "Run container in background and print container ID",
},
cli.StringFlag{
Name: "detach-keys",
Usage: "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`",
},
cli.StringSliceFlag{
Name: "device",
Usage: "Add a host device to the container (default [])",
},
cli.StringSliceFlag{
Name: "device-read-bps",
Usage: "Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
},
cli.StringSliceFlag{
Name: "device-read-iops",
Usage: "Limit read rate (IO per second) from a device (e.g. --device-read-iops=/dev/sda:1000)",
},
cli.StringSliceFlag{
Name: "device-write-bps",
Usage: "Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sda:1mb)",
},
cli.StringSliceFlag{
Name: "device-write-iops",
Usage: "Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)",
},
cli.StringSliceFlag{
Name: "dns",
Usage: "Set custom DNS servers",
},
cli.StringSliceFlag{
Name: "dns-opt",
Usage: "Set custom DNS options",
},
cli.StringSliceFlag{
Name: "dns-search",
Usage: "Set custom DNS search domains",
},
cli.StringFlag{
Name: "entrypoint",
Usage: "Overwrite the default ENTRYPOINT of the image",
},
cli.StringSliceFlag{
Name: "env, e",
Usage: "Set environment variables in container",
},
cli.StringSliceFlag{
Name: "env-file",
Usage: "Read in a file of environment variables",
},
cli.StringSliceFlag{
Name: "expose",
Usage: "Expose a port or a range of ports (default [])",
},
cli.StringSliceFlag{
Name: "gidmap",
Usage: "GID map to use for the user namespace",
},
cli.StringSliceFlag{
Name: "group-add",
Usage: "Add additional groups to join (default [])",
},
cli.BoolFlag{
Name: "help",
Hidden: true,
},
cli.StringFlag{
Name: "hostname, h",
Usage: "Set container hostname",
},
cli.StringFlag{
Name: "image-volume, builtin-volume",
Usage: "Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore' (default 'bind')",
Value: "bind",
},
cli.BoolFlag{
Name: "init",
Usage: "Run an init binary inside the container that forwards signals and reaps processes",
},
cli.StringFlag{
Name: "init-path",
// Do not use the Value field for setting the default value to determine user input (i.e., non-empty string)
Usage: fmt.Sprintf("Path to the container-init binary (default: %q)", libpod.DefaultInitPath),
},
cli.BoolFlag{
Name: "interactive, i",
Usage: "Keep STDIN open even if not attached",
},
cli.StringFlag{
Name: "ip",
Usage: "Specify a static IPv4 address for the container",
},
cli.StringFlag{
Name: "ipc",
Usage: "IPC namespace to use",
},
cli.StringFlag{
Name: "kernel-memory",
Usage: "Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)",
},
cli.StringSliceFlag{
Name: "label",
Usage: "Set metadata on container (default [])",
},
cli.StringSliceFlag{
Name: "label-file",
Usage: "Read in a line delimited file of labels (default [])",
},
cli.StringFlag{
Name: "log-driver",
Usage: "Logging driver for the container",
},
cli.StringSliceFlag{
Name: "log-opt",
Usage: "Logging driver options (default [])",
},
cli.StringFlag{
Name: "mac-address",
Usage: "Container MAC address (e.g. 92:d0:c6:0a:29:33), not currently supported",
},
cli.StringFlag{
Name: "memory, m",
Usage: "Memory limit (format: <number>[<unit>], where unit = b, k, m or g)",
},
cli.StringFlag{
Name: "memory-reservation",
Usage: "Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)",
},
cli.StringFlag{
Name: "memory-swap",
Usage: "Swap limit equal to memory plus swap: '-1' to enable unlimited swap",
},
cli.Int64Flag{
Name: "memory-swappiness",
Usage: "Tune container memory swappiness (0 to 100) (default -1)",
Value: -1,
},
cli.StringFlag{
Name: "name",
Usage: "Assign a name to the container",
},
cli.StringFlag{
Name: "net, network",
Usage: "Connect a container to a network",
Value: getDefaultNetwork(),
},
cli.BoolFlag{
Name: "oom-kill-disable",
Usage: "Disable OOM Killer",
},
cli.StringFlag{
Name: "oom-score-adj",
Usage: "Tune the host's OOM preferences (-1000 to 1000)",
},
cli.StringFlag{
Name: "pid",
Usage: "PID namespace to use",
},
cli.Int64Flag{
Name: "pids-limit",
Usage: "Tune container pids limit (set -1 for unlimited)",
},
cli.StringFlag{
Name: "pod",
Usage: "Run container in an existing pod",
},
cli.BoolFlag{
Name: "privileged",
Usage: "Give extended privileges to container",
},
cli.StringSliceFlag{
Name: "publish, p",
Usage: "Publish a container's port, or a range of ports, to the host (default [])",
},
cli.BoolFlag{
Name: "publish-all, P",
Usage: "Publish all exposed ports to random ports on the host interface",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Suppress output information when pulling images",
},
cli.BoolFlag{
Name: "read-only",
Usage: "Make containers root filesystem read-only",
},
cli.StringFlag{
Name: "restart",
Usage: "Restart is not supported. Please use a systemd unit file for restart",
},
cli.BoolFlag{
Name: "rm",
Usage: "Remove container (and pod if created) after exit",
},
cli.BoolFlag{
Name: "rootfs",
Usage: "The first argument is not an image but the rootfs to the exploded container",
},
cli.StringSliceFlag{
Name: "security-opt",
Usage: "Security Options (default [])",
},
cli.StringFlag{
Name: "shm-size",
Usage: "Size of `/dev/shm`. The format is `<number><unit>`.",
Value: "65536k",
},
cli.StringFlag{
Name: "stop-signal",
Usage: "Signal to stop a container. Default is SIGTERM",
},
cli.IntFlag{
Name: "stop-timeout",
Usage: "Timeout (in seconds) to stop a container. Default is 10",
Value: libpod.CtrRemoveTimeout,
},
cli.StringSliceFlag{
Name: "storage-opt",
Usage: "Storage driver options per container (default [])",
},
cli.StringFlag{
Name: "subgidname",
Usage: "Name of range listed in /etc/subgid for use in user namespace",
},
cli.StringFlag{
Name: "subuidname",
Usage: "Name of range listed in /etc/subuid for use in user namespace",
},
func getCreateFlags(c *cliconfig.PodmanCommand) {
cli.StringSliceFlag{
Name: "sysctl",
Usage: "Sysctl options (default [])",
},
cli.BoolTFlag{
Name: "systemd",
Usage: "Run container in systemd mode if the command executable is systemd or init",
},
cli.StringSliceFlag{
Name: "tmpfs",
Usage: "Mount a temporary filesystem (`tmpfs`) into a container (default [])",
},
cli.BoolFlag{
Name: "tty, t",
Usage: "Allocate a pseudo-TTY for container",
},
cli.StringSliceFlag{
Name: "uidmap",
Usage: "UID map to use for the user namespace",
},
cli.StringSliceFlag{
Name: "ulimit",
Usage: "Ulimit options (default [])",
},
cli.StringFlag{
Name: "user, u",
Usage: "Username or UID (format: <name|uid>[:<group|gid>])",
},
cli.StringFlag{
Name: "userns",
Usage: "User namespace to use",
},
cli.StringFlag{
Name: "uts",
Usage: "UTS namespace to use",
},
cli.StringSliceFlag{
Name: "mount",
Usage: "Attach a filesystem mount to the container (default [])",
},
cli.StringSliceFlag{
Name: "volume, v",
Usage: "Bind mount a volume into the container (default [])",
},
cli.StringSliceFlag{
Name: "volumes-from",
Usage: "Mount volumes from the specified container(s) (default [])",
},
WorkDirFlag,
createFlags := c.Flags()
createFlags.StringSlice(
"add-host", []string{},
"Add a custom host-to-IP mapping (host:ip) (default [])",
)
createFlags.StringSlice(
"annotation", []string{},
"Add annotations to container (key:value) (default [])",
)
createFlags.StringSliceP(
"attach", "a", []string{},
"Attach to STDIN, STDOUT or STDERR (default [])",
)
createFlags.String(
"blkio-weight", "",
"Block IO weight (relative weight) accepts a weight value between 10 and 1000.",
)
createFlags.StringSlice(
"blkio-weight-device", []string{},
"Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)",
)
createFlags.StringSlice(
"cap-add", []string{},
"Add capabilities to the container",
)
createFlags.StringSlice(
"cap-drop", []string{},
"Drop capabilities from the container",
)
createFlags.String(
"cgroup-parent", "",
"Optional parent cgroup for the container",
)
createFlags.String(
"cidfile", "",
"Write the container ID to the file",
)
createFlags.String(
"conmon-pidfile", "",
"Path to the file that will receive the PID of conmon",
)
createFlags.Uint64(
"cpu-period", 0,
"Limit the CPU CFS (Completely Fair Scheduler) period",
)
createFlags.Int64(
"cpu-quota", 0,
"Limit the CPU CFS (Completely Fair Scheduler) quota",
)
createFlags.Uint64(
"cpu-rt-period", 0,
"Limit the CPU real-time period in microseconds",
)
createFlags.Int64(
"cpu-rt-runtime", 0,
"Limit the CPU real-time runtime in microseconds",
)
createFlags.Uint64(
"cpu-shares", 0,
"CPU shares (relative weight)",
)
createFlags.Float64(
"cpus", 0,
"Number of CPUs. The default is 0.000 which means no limit",
)
createFlags.String(
"cpuset-cpus", "",
"CPUs in which to allow execution (0-3, 0,1)",
)
createFlags.String(
"cpuset-mems", "",
"Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
)
createFlags.BoolP(
"detach", "d", false,
"Run container in background and print container ID",
)
createFlags.String(
"detach-keys", "",
"Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`",
)
createFlags.StringSlice(
"device", []string{},
"Add a host device to the container (default [])",
)
createFlags.StringSlice(
"device-read-bps", []string{},
"Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
)
createFlags.StringSlice(
"device-read-iops", []string{},
"Limit read rate (IO per second) from a device (e.g. --device-read-iops=/dev/sda:1000)",
)
createFlags.StringSlice(
"device-write-bps", []string{},
"Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sda:1mb)",
)
createFlags.StringSlice(
"device-write-iops", []string{},
"Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)",
)
createFlags.StringSlice(
"dns", []string{},
"Set custom DNS servers",
)
createFlags.StringSlice(
"dns-opt", []string{},
"Set custom DNS options",
)
createFlags.StringSlice(
"dns-search", []string{},
"Set custom DNS search domains",
)
createFlags.String(
"entrypoint", "",
"Overwrite the default ENTRYPOINT of the image",
)
createFlags.StringSliceP(
"env", "e", []string{},
"Set environment variables in container",
)
createFlags.StringSlice(
"env-file", []string{},
"Read in a file of environment variables",
)
createFlags.StringSlice(
"expose", []string{},
"Expose a port or a range of ports (default [])",
)
createFlags.StringSlice(
"gidmap", []string{},
"GID map to use for the user namespace",
)
createFlags.StringSlice(
"group-add", []string{},
"Add additional groups to join (default [])",
)
createFlags.Bool(
"help", false, "",
)
createFlags.StringP(
"hostname", "h", "",
"Set container hostname",
)
createFlags.String(
"image-volume", "bind",
"Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore' (default 'bind')",
)
createFlags.Bool(
"init", false,
"Run an init binary inside the container that forwards signals and reaps processes",
)
createFlags.String(
"init-path", "",
// Do not use the Value field for setting the default value to determine user input (i.e., non-empty string)
fmt.Sprintf("Path to the container-init binary (default: %q)", libpod.DefaultInitPath),
)
createFlags.BoolP(
"interactive", "i", false,
"Keep STDIN open even if not attached",
)
createFlags.String(
"ip", "",
"Specify a static IPv4 address for the container",
)
createFlags.String(
"ipc", "",
"IPC namespace to use",
)
createFlags.String(
"kernel-memory", "",
"Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)",
)
createFlags.StringSlice(
"label", []string{},
"Set metadata on container (default [])",
)
createFlags.StringSlice(
"label-file", []string{},
"Read in a line delimited file of labels (default [])",
)
createFlags.String(
"log-driver", "",
"Logging driver for the container",
)
createFlags.StringSlice(
"log-opt", []string{},
"Logging driver options (default [])",
)
createFlags.String(
"mac-address", "",
"Container MAC address (e.g. 92:d0:c6:0a:29:33), not currently supported",
)
createFlags.StringP(
"memory", "m", "",
"Memory limit (format: <number>[<unit>], where unit = b, k, m or g)",
)
createFlags.String(
"memory-reservation", "",
"Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)",
)
createFlags.String(
"memory-swap", "",
"Swap limit equal to memory plus swap: '-1' to enable unlimited swap",
)
createFlags.Int64(
"memory-swappiness", -1,
"Tune container memory swappiness (0 to 100) (default -1)",
)
createFlags.String(
"name", "",
"Assign a name to the container",
)
createFlags.String(
"net", getDefaultNetwork(),
"Connect a container to a network",
)
createFlags.String(
"network", getDefaultNetwork(),
"Connect a container to a network",
)
createFlags.Bool(
"oom-kill-disable", false,
"Disable OOM Killer",
)
createFlags.Int(
"oom-score-adj", 0,
"Tune the host's OOM preferences (-1000 to 1000)",
)
createFlags.String(
"pid", "",
"PID namespace to use",
)
createFlags.Int64(
"pids-limit", 0,
"Tune container pids limit (set -1 for unlimited)",
)
createFlags.String(
"pod", "",
"Run container in an existing pod",
)
createFlags.Bool(
"privileged", false,
"Give extended privileges to container",
)
createFlags.StringSliceP(
"publish", "p", []string{},
"Publish a container's port, or a range of ports, to the host (default [])",
)
createFlags.BoolP(
"publish-all", "P", false,
"Publish all exposed ports to random ports on the host interface",
)
createFlags.BoolP(
"quiet", "q", false,
"Suppress output information when pulling images",
)
createFlags.Bool(
"read-only", false,
"Make containers root filesystem read-only",
)
createFlags.String(
"restart", "",
"Restart is not supported. Please use a systemd unit file for restart",
)
createFlags.Bool(
"rm", false,
"Remove container (and pod if created) after exit",
)
createFlags.Bool(
"rootfs", false,
"The first argument is not an image but the rootfs to the exploded container",
)
createFlags.StringArray(
"security-opt", []string{},
"Security Options (default [])",
)
createFlags.String(
"shm-size", "65536k",
"Size of `/dev/shm`. The format is `<number><unit>`",
)
createFlags.String(
"stop-signal", "",
"Signal to stop a container. Default is SIGTERM",
)
createFlags.Int(
"stop-timeout", libpod.CtrRemoveTimeout,
"Timeout (in seconds) to stop a container. Default is 10",
)
createFlags.StringSlice(
"storage-opt", []string{},
"Storage driver options per container (default [])",
)
createFlags.String(
"subgidname", "",
"Name of range listed in /etc/subgid for use in user namespace",
)
createFlags.String(
"subuidname", "",
"Name of range listed in /etc/subuid for use in user namespace",
)
createFlags.StringSlice(
"sysctl", []string{},
"Sysctl options (default [])",
)
createFlags.Bool(
"systemd", true,
"Run container in systemd mode if the command executable is systemd or init",
)
createFlags.StringSlice(
"tmpfs", []string{},
"Mount a temporary filesystem (`tmpfs`) into a container (default [])",
)
createFlags.BoolP(
"tty", "t", false,
"Allocate a pseudo-TTY for container",
)
createFlags.StringSlice(
"uidmap", []string{},
"UID map to use for the user namespace",
)
createFlags.StringSlice(
"ulimit", []string{},
"Ulimit options (default [])",
)
createFlags.StringP(
"user", "u", "",
"Username or UID (format: <name|uid>[:<group|gid>])",
)
createFlags.String(
"userns", "",
"User namespace to use",
)
createFlags.String(
"uts", "",
"UTS namespace to use",
)
createFlags.StringArray(
"mount", []string{},
"Attach a filesystem mount to the container (default [])",
)
createFlags.StringArrayP(
"volume", "v", []string{},
"Bind mount a volume into the container (default [])",
)
createFlags.StringSlice(
"volumes-from", []string{},
"Mount volumes from the specified container(s) (default [])",
)
createFlags.StringP(
"workdir", "w", "",
"Working directory inside the container",
)
}
func getFormat(c *cli.Context) (string, error) {
func getFormat(c *cliconfig.PodmanCommand) (string, error) {
format := strings.ToLower(c.String("format"))
if strings.HasPrefix(format, buildah.OCI) {
return buildah.OCIv1ImageManifest, nil
@ -541,13 +486,6 @@ func getFormat(c *cli.Context) (string, error) {
return "", errors.Errorf("unrecognized image type %q", format)
}
func sortFlags(flags []cli.Flag) []cli.Flag {
sort.Slice(flags, func(i, j int) bool {
return strings.Compare(flags[i].GetName(), flags[j].GetName()) < 0
})
return flags
}
func getAuthFile(authfile string) string {
if authfile != "" {
return authfile

View file

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

View file

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

View file

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

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=tmpfs,target=/dev/shm ..
func parseMounts(mounts []string) ([]spec.Mount, error) {
// TODO(vrothberg): the manual parsing can be replaced with a regular expression
// to allow a more robust parsing of the mount format and to give
// precise errors regarding supported format versus suppored options.
var mountList []spec.Mount
errInvalidSyntax := errors.Errorf("incorrect mount format : should be --mount type=<bind|tmpfs>,[src=<host-dir>,]target=<ctr-dir>,[options]")
errInvalidSyntax := errors.Errorf("incorrect mount format: should be --mount type=<bind|tmpfs>,[src=<host-dir>,]target=<ctr-dir>[,options]")
for _, mount := range mounts {
var tokenCount int
var mountInfo spec.Mount
arr := strings.SplitN(mount, ",", 2)
if len(arr) < 2 {
return nil, errInvalidSyntax
return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
}
kv := strings.Split(arr[0], "=")
if kv[0] != "type" {
return nil, errInvalidSyntax
return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
}
switch kv[1] {
case "bind":
@ -168,7 +171,7 @@ func parseVolumes(volumes []string) error {
for _, volume := range volumes {
arr := strings.SplitN(volume, ":", 3)
if len(arr) < 2 {
return errors.Errorf("incorrect volume format %q, should be host-dir:ctr-dir:[option]", volume)
return errors.Errorf("incorrect volume format %q, should be host-dir:ctr-dir[:option]", volume)
}
if err := validateVolumeHostDir(arr[0]); err != nil {
return err

View file

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

View file

@ -2,82 +2,76 @@ package main
import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"os"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
execFlags = []cli.Flag{
cli.StringSliceFlag{
Name: "env, e",
Usage: "Set environment variables",
},
cli.BoolFlag{
Name: "privileged",
Usage: "Give the process extended Linux capabilities inside the container. The default is false",
},
cli.BoolFlag{
Name: "interactive, i",
Usage: "Not supported. All exec commands are interactive by default.",
},
cli.BoolFlag{
Name: "tty, t",
Usage: "Allocate a pseudo-TTY. The default is false",
},
cli.StringFlag{
Name: "user, u",
Usage: "Sets the username or UID used and optionally the groupname or GID for the specified command",
},
LatestFlag,
WorkDirFlag,
}
execCommand cliconfig.ExecValues
execDescription = `
podman exec
Run a command in a running container
`
execCommand = cli.Command{
Name: "exec",
Usage: "Run a process in a running container",
Description: execDescription,
Flags: sortFlags(execFlags),
Action: execCmd,
ArgsUsage: "CONTAINER-NAME",
SkipArgReorder: true,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_execCommand = &cobra.Command{
Use: "exec",
Short: "Run a process in a running container",
Long: execDescription,
RunE: func(cmd *cobra.Command, args []string) error {
execCommand.InputArgs = args
execCommand.GlobalFlags = MainGlobalOpts
return execCmd(&execCommand)
},
Example: "CONTAINER-NAME",
}
)
func execCmd(c *cli.Context) error {
args := c.Args()
func init() {
execCommand.Command = _execCommand
flags := execCommand.Flags()
flags.SetInterspersed(false)
flags.StringSliceVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables")
flags.BoolVarP(&execCommand.Interfactive, "interactive", "i", false, "Not supported. All exec commands are interactive by default")
flags.BoolVarP(&execCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&execCommand.Privileged, "privileged", false, "Give the process extended Linux capabilities inside the container. The default is false")
flags.BoolVarP(&execCommand.Tty, "tty", "t", false, "Allocate a pseudo-TTY. The default is false")
flags.StringVarP(&execCommand.User, "user", "u", "", "Sets the username or UID used and optionally the groupname or GID for the specified command")
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
rootCmd.AddCommand(execCommand.Command)
}
func execCmd(c *cliconfig.ExecValues) error {
args := c.InputArgs
var ctr *libpod.Container
var err error
argStart := 1
if len(args) < 1 && !c.Bool("latest") {
if len(args) < 1 && !c.Latest {
return errors.Errorf("you must provide one container name or id")
}
if len(args) < 2 && !c.Bool("latest") {
if len(args) < 2 && !c.Latest {
return errors.Errorf("you must provide a command to exec")
}
if c.Bool("latest") {
if c.Latest {
argStart = 0
}
rootless.SetSkipStorageSetup(true)
cmd := args[argStart:]
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
if c.Bool("latest") {
if c.Latest {
ctr, err = runtime.GetLatestContainer()
} else {
ctr, err = runtime.LookupContainer(args[0])
@ -101,7 +95,7 @@ func execCmd(c *cli.Context) error {
// ENVIRONMENT VARIABLES
env := map[string]string{}
if err := readKVStrings(env, []string{}, c.StringSlice("env")); err != nil {
if err := readKVStrings(env, []string{}, c.Env); err != nil {
return errors.Wrapf(err, "unable to process environment variables")
}
envs := []string{}
@ -109,5 +103,5 @@ func execCmd(c *cli.Context) error {
envs = append(envs, fmt.Sprintf("%s=%s", k, v))
}
return ctr.Exec(c.Bool("tty"), c.Bool("privileged"), envs, cmd, c.String("user"), c.String("workdir"))
return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir)
}

View file

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

View file

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

View file

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

View file

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

View file

@ -6,12 +6,13 @@ import (
"strings"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/libpod/adapter"
"github.com/containers/libpod/libpod/image"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
const createdByTruncLength = 45
@ -34,53 +35,44 @@ type historyOptions struct {
}
var (
historyFlags = []cli.Flag{
cli.BoolTFlag{
Name: "human, H",
Usage: "Display sizes and dates in human readable format",
},
cli.BoolFlag{
Name: "no-trunc, notruncate",
Usage: "Do not truncate the output",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Display the numeric IDs only",
},
cli.StringFlag{
Name: "format",
Usage: "Change the output to JSON or a Go template",
},
}
historyCommand cliconfig.HistoryValues
historyDescription = "Displays the history of an image. The information can be printed out in an easy to read, " +
"or user specified format, and can be truncated."
historyCommand = cli.Command{
Name: "history",
Usage: "Show history of a specified image",
Description: historyDescription,
Flags: sortFlags(historyFlags),
Action: historyCmd,
ArgsUsage: "",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_historyCommand = &cobra.Command{
Use: "history",
Short: "Show history of a specified image",
Long: historyDescription,
RunE: func(cmd *cobra.Command, args []string) error {
historyCommand.InputArgs = args
historyCommand.GlobalFlags = MainGlobalOpts
return historyCmd(&historyCommand)
},
}
)
func historyCmd(c *cli.Context) error {
if err := validateFlags(c, historyFlags); err != nil {
return err
}
func init() {
historyCommand.Command = _historyCommand
flags := historyCommand.Flags()
flags.StringVar(&historyCommand.Format, "format", "", "Change the output to JSON or a Go template")
flags.BoolVarP(&historyCommand.Human, "human", "H", true, "Display sizes and dates in human readable format")
// notrucate needs to be added
flags.BoolVar(&historyCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
flags.BoolVarP(&historyCommand.Quiet, "quiet", "q", false, "Display the numeric IDs only")
runtime, err := adapter.GetRuntime(c)
rootCmd.AddCommand(historyCommand.Command)
}
func historyCmd(c *cliconfig.HistoryValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
format := genHistoryFormat(c.String("format"), c.Bool("quiet"))
format := genHistoryFormat(c.Format, c.Quiet)
args := c.Args()
args := c.InputArgs
if len(args) == 0 {
return errors.Errorf("an image name must be specified")
}
@ -93,9 +85,9 @@ func historyCmd(c *cli.Context) error {
return err
}
opts := historyOptions{
human: c.BoolT("human"),
noTrunc: c.Bool("no-trunc"),
quiet: c.Bool("quiet"),
human: c.Human,
noTrunc: c.NoTrunc,
quiet: c.Quiet,
format: format,
}

View file

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

View file

@ -8,6 +8,7 @@ import (
"time"
"unicode"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/imagefilters"
"github.com/containers/libpod/libpod/adapter"
@ -16,7 +17,7 @@ import (
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
type imagesTemplateParams struct {
@ -83,108 +84,79 @@ func (a imagesSortedSize) Less(i, j int) bool {
}
var (
imagesFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Show all images (default hides intermediate images)",
},
cli.BoolFlag{
Name: "digests",
Usage: "Show digests",
},
cli.StringSliceFlag{
Name: "filter, f",
Usage: "Filter output based on conditions provided (default [])",
},
cli.StringFlag{
Name: "format",
Usage: "Change the output format to JSON or a Go template",
},
cli.BoolFlag{
Name: "noheading, n",
Usage: "Do not print column headings",
},
cli.BoolFlag{
Name: "no-trunc, notruncate",
Usage: "Do not truncate output",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Display only image IDs",
},
cli.StringFlag{
Name: "sort",
Usage: "Sort by created, id, repository, size, or tag",
Value: "Created",
},
}
imagesCommand cliconfig.ImagesValues
imagesDescription = "lists locally stored images."
imagesCommand = cli.Command{
Name: "images",
Usage: "List images in local storage",
Description: imagesDescription,
Flags: sortFlags(imagesFlags),
Action: imagesCmd,
ArgsUsage: "",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
}
lsImagesCommand = cli.Command{
Name: "list",
Aliases: []string{"ls"},
Usage: "List images in local storage",
Description: imagesDescription,
Flags: imagesFlags,
Action: imagesCmd,
ArgsUsage: "",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_imagesCommand = &cobra.Command{
Use: "images",
Short: "List images in local storage",
Long: imagesDescription,
RunE: func(cmd *cobra.Command, args []string) error {
imagesCommand.InputArgs = args
imagesCommand.GlobalFlags = MainGlobalOpts
return imagesCmd(&imagesCommand)
},
Example: "",
}
)
func imagesCmd(c *cli.Context) error {
func init() {
imagesCommand.Command = _imagesCommand
flags := imagesCommand.Flags()
flags.BoolVarP(&imagesCommand.All, "all", "a", false, "Show all images (default hides intermediate images)")
flags.BoolVar(&imagesCommand.Digests, "digests", false, "Show digests")
flags.StringSliceVarP(&imagesCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
flags.StringVar(&imagesCommand.Format, "format", "", "Change the output format to JSON or a Go template")
flags.BoolVarP(&imagesCommand.Noheading, "noheading", "n", false, "Do not print column headings")
// TODO Need to learn how to deal with second name being a string instead of a char.
// This needs to be "no-trunc, notruncate"
flags.BoolVar(&imagesCommand.NoTrunc, "no-trunc", false, "Do not truncate output")
flags.BoolVarP(&imagesCommand.Quiet, "quiet", "q", false, "Display only image IDs")
flags.StringVar(&imagesCommand.Sort, "sort", "created", "Sort by created, id, repository, size, or tag")
rootCmd.AddCommand(imagesCommand.Command)
}
func imagesCmd(c *cliconfig.ImagesValues) error {
var (
filterFuncs []imagefilters.ResultFilter
newImage *adapter.ContainerImage
)
if err := validateFlags(c, imagesFlags); err != nil {
return err
}
runtime, err := adapter.GetRuntime(c)
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "Could not get runtime")
}
defer runtime.Shutdown(false)
if len(c.Args()) == 1 {
newImage, err = runtime.NewImageFromLocal(c.Args().Get(0))
if len(c.InputArgs) == 1 {
newImage, err = runtime.NewImageFromLocal(c.InputArgs[0])
if err != nil {
return err
}
}
if len(c.Args()) > 1 {
if len(c.InputArgs) > 1 {
return errors.New("'podman images' requires at most 1 argument")
}
ctx := getContext()
if len(c.StringSlice("filter")) > 0 || newImage != nil {
filterFuncs, err = CreateFilterFuncs(ctx, runtime, c, newImage)
if len(c.Filter) > 0 || newImage != nil {
filterFuncs, err = CreateFilterFuncs(ctx, runtime, c.Filter, newImage)
if err != nil {
return err
}
}
opts := imagesOptions{
quiet: c.Bool("quiet"),
noHeading: c.Bool("noheading"),
noTrunc: c.Bool("no-trunc"),
digests: c.Bool("digests"),
format: c.String("format"),
sort: c.String("sort"),
all: c.Bool("all"),
quiet: c.Quiet,
noHeading: c.Noheading,
noTrunc: c.NoTrunc,
digests: c.Digests,
format: c.Format,
sort: c.Sort,
all: c.All,
}
opts.outputformat = opts.setOutputFormat()
@ -195,7 +167,7 @@ func imagesCmd(c *cli.Context) error {
var filteredImages []*adapter.ContainerImage
//filter the images
if len(c.StringSlice("filter")) > 0 || newImage != nil {
if len(c.Filter) > 0 || newImage != nil {
filteredImages = imagefilters.FilterImages(images, filterFuncs)
} else {
filteredImages = images
@ -368,9 +340,9 @@ func (i *imagesTemplateParams) HeaderMap() map[string]string {
// CreateFilterFuncs returns an array of filter functions based on the user inputs
// and is later used to filter images for output
func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, c *cli.Context, img *adapter.ContainerImage) ([]imagefilters.ResultFilter, error) {
func CreateFilterFuncs(ctx context.Context, r *adapter.LocalRuntime, filters []string, img *adapter.ContainerImage) ([]imagefilters.ResultFilter, error) {
var filterFuncs []imagefilters.ResultFilter
for _, filter := range c.StringSlice("filter") {
for _, filter := range filters {
splitFilter := strings.Split(filter, "=")
switch splitFilter[0] {
case "before":

View file

@ -3,35 +3,39 @@ package main
import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
pruneImagesCommand cliconfig.PruneImagesValues
pruneImagesDescription = `
podman image prune
Removes all unnamed images from local storage
`
pruneImageFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Remove all unused images, not just dangling ones",
_pruneImagesCommand = &cobra.Command{
Use: "prune",
Short: "Remove unused images",
Long: pruneImagesDescription,
RunE: func(cmd *cobra.Command, args []string) error {
pruneImagesCommand.InputArgs = args
pruneImagesCommand.GlobalFlags = MainGlobalOpts
return pruneImagesCmd(&pruneImagesCommand)
},
}
pruneImagesCommand = cli.Command{
Name: "prune",
Usage: "Remove unused images",
Description: pruneImagesDescription,
Action: pruneImagesCmd,
OnUsageError: usageErrorHandler,
Flags: pruneImageFlags,
}
)
func pruneImagesCmd(c *cli.Context) error {
runtime, err := adapter.GetRuntime(c)
func init() {
pruneImagesCommand.Command = _pruneImagesCommand
flags := pruneImagesCommand.Flags()
flags.BoolVarP(&pruneImagesCommand.All, "all", "a", false, "Remove all unused images, not just dangling ones")
}
func pruneImagesCmd(c *cliconfig.PruneImagesValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@ -39,7 +43,7 @@ func pruneImagesCmd(c *cli.Context) error {
// Call prune; if any cids are returned, print them and then
// return err in case an error also came up
pruneCids, err := runtime.PruneImages(c.Bool("all"))
pruneCids, err := runtime.PruneImages(c.All)
if len(pruneCids) > 0 {
for _, cid := range pruneCids {
fmt.Println(cid)

View file

@ -3,47 +3,44 @@ package main
import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
importFlags = []cli.Flag{
cli.StringSliceFlag{
Name: "change, c",
Usage: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR",
},
cli.StringFlag{
Name: "message, m",
Usage: "Set commit message for imported image",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Suppress output",
},
}
importCommand cliconfig.ImportValues
importDescription = `Create a container image from the contents of the specified tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz).
Note remote tar balls can be specified, via web address.
Optionally tag the image. You can specify the instructions using the --change option.
`
importCommand = cli.Command{
Name: "import",
Usage: "Import a tarball to create a filesystem image",
Description: importDescription,
Flags: sortFlags(importFlags),
Action: importCmd,
ArgsUsage: "TARBALL [REFERENCE]",
OnUsageError: usageErrorHandler,
_importCommand = &cobra.Command{
Use: "import",
Short: "Import a tarball to create a filesystem image",
Long: importDescription,
RunE: func(cmd *cobra.Command, args []string) error {
importCommand.InputArgs = args
importCommand.GlobalFlags = MainGlobalOpts
return importCmd(&importCommand)
},
Example: "TARBALL [REFERENCE]",
}
)
func importCmd(c *cli.Context) error {
if err := validateFlags(c, importFlags); err != nil {
return err
}
func init() {
importCommand.Command = _importCommand
flags := importCommand.Flags()
flags.StringSliceVarP(&importCommand.Change, "change", "c", []string{}, "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR")
flags.StringVarP(&importCommand.Message, "message", "m", "", "Set commit message for imported image")
flags.BoolVarP(&importCommand.Quiet, "quiet", "q", false, "Suppress output")
runtime, err := adapter.GetRuntime(c)
rootCmd.AddCommand(importCommand.Command)
}
func importCmd(c *cliconfig.ImportValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@ -54,7 +51,7 @@ func importCmd(c *cli.Context) error {
reference string
)
args := c.Args()
args := c.InputArgs
switch len(args) {
case 0:
return errors.Errorf("need to give the path to the tarball, or must specify a tarball of '-' for stdin")
@ -71,7 +68,7 @@ func importCmd(c *cli.Context) error {
return err
}
quiet := c.Bool("quiet")
quiet := c.Quiet
if runtime.Remote {
quiet = false
}

View file

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

View file

@ -5,13 +5,14 @@ import (
"encoding/json"
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/adapter"
cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
const (
@ -21,38 +22,37 @@ const (
)
var (
inspectFlags = []cli.Flag{
cli.StringFlag{
Name: "type, t",
Value: inspectAll,
Usage: "Return JSON for specified type, (e.g image, container or task)",
},
cli.StringFlag{
Name: "format, f",
Usage: "Change the output format to a Go template",
},
cli.BoolFlag{
Name: "size, s",
Usage: "Display total file size if the type is container",
},
LatestFlag,
}
inspectCommand cliconfig.InspectValues
inspectDescription = "This displays the low-level information on containers and images identified by name or ID. By default, this will render all results in a JSON array. If the container and image have the same name, this will return container JSON for unspecified type."
inspectCommand = cli.Command{
Name: "inspect",
Usage: "Display the configuration of a container or image",
Description: inspectDescription,
Flags: sortFlags(inspectFlags),
Action: inspectCmd,
ArgsUsage: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...",
OnUsageError: usageErrorHandler,
_inspectCommand = &cobra.Command{
Use: "inspect",
Short: "Display the configuration of a container or image",
Long: inspectDescription,
RunE: func(cmd *cobra.Command, args []string) error {
inspectCommand.InputArgs = args
inspectCommand.GlobalFlags = MainGlobalOpts
return inspectCmd(&inspectCommand)
},
Example: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...",
}
)
func inspectCmd(c *cli.Context) error {
args := c.Args()
inspectType := c.String("type")
latestContainer := c.Bool("latest")
func init() {
inspectCommand.Command = _inspectCommand
flags := inspectCommand.Flags()
flags.StringVarP(&inspectCommand.TypeObject, "type", "t", inspectAll, "Return JSON for specified type, (e.g image, container or task)")
flags.StringVarP(&inspectCommand.Format, "format", "f", "", "Change the output format to a Go template")
flags.BoolVarP(&inspectCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of if the type is a container")
flags.BoolVarP(&inspectCommand.Size, "size", "s", false, "Display total file size if the type is container")
rootCmd.AddCommand(inspectCommand.Command)
}
func inspectCmd(c *cliconfig.InspectValues) error {
args := c.InputArgs
inspectType := c.TypeObject
latestContainer := c.Latest
if len(args) == 0 && !latestContainer {
return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name")
}
@ -60,11 +60,8 @@ func inspectCmd(c *cli.Context) error {
if len(args) > 0 && latestContainer {
return errors.Errorf("you cannot provide additional arguments with --latest")
}
if err := validateFlags(c, inspectFlags); err != nil {
return err
}
runtime, err := adapter.GetRuntime(c)
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
@ -74,7 +71,7 @@ func inspectCmd(c *cli.Context) error {
return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
}
outputFormat := c.String("format")
outputFormat := c.Format
if strings.Contains(outputFormat, "{{.Id}}") {
outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1)
}
@ -87,7 +84,7 @@ func inspectCmd(c *cli.Context) error {
inspectType = inspectTypeContainer
}
inspectedObjects, iterateErr := iterateInput(getContext(), c, args, runtime, inspectType)
inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, args, runtime, inspectType)
if iterateErr != nil {
return iterateErr
}
@ -105,7 +102,7 @@ func inspectCmd(c *cli.Context) error {
}
// func iterateInput iterates the images|containers the user has requested and returns the inspect data and error
func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *adapter.LocalRuntime, inspectType string) ([]interface{}, error) {
func iterateInput(ctx context.Context, size bool, args []string, runtime *adapter.LocalRuntime, inspectType string) ([]interface{}, error) {
var (
data interface{}
inspectedItems []interface{}
@ -120,7 +117,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *a
inspectError = errors.Wrapf(err, "error looking up container %q", input)
break
}
libpodInspectData, err := ctr.Inspect(c.Bool("size"))
libpodInspectData, err := ctr.Inspect(size)
if err != nil {
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
break
@ -160,7 +157,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *a
break
}
} else {
libpodInspectData, err := ctr.Inspect(c.Bool("size"))
libpodInspectData, err := ctr.Inspect(size)
if err != nil {
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
break

View file

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

View file

@ -1,15 +1,15 @@
package libpodruntime
import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
// GetRuntime generates a new libpod runtime configured by command line options
func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
func GetRuntime(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
storageOpts, volumePath, err := util.GetDefaultStoreOptions()
@ -17,29 +17,39 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
return nil, err
}
if c.IsSet("uidmap") || c.IsSet("gidmap") || c.IsSet("subuidmap") || c.IsSet("subgidmap") {
mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap"))
uidmapFlag := c.Flags().Lookup("uidmap")
gidmapFlag := c.Flags().Lookup("gidmap")
subuidname := c.Flags().Lookup("subuidname")
subgidname := c.Flags().Lookup("subgidname")
if (uidmapFlag != nil && gidmapFlag != nil && subuidname != nil && subgidname != nil) &&
(uidmapFlag.Changed || gidmapFlag.Changed || subuidname.Changed || subgidname.Changed) {
uidmapVal, _ := c.Flags().GetStringSlice("uidmap")
gidmapVal, _ := c.Flags().GetStringSlice("gidmap")
subuidVal, _ := c.Flags().GetString("subuidname")
subgidVal, _ := c.Flags().GetString("subgidname")
mappings, err := util.ParseIDMapping(uidmapVal, gidmapVal, subuidVal, subgidVal)
if err != nil {
return nil, err
}
storageOpts.UIDMap = mappings.UIDMap
storageOpts.GIDMap = mappings.GIDMap
}
if c.GlobalIsSet("root") {
storageOpts.GraphRoot = c.GlobalString("root")
if c.Flags().Changed("root") {
storageOpts.GraphRoot = c.GlobalFlags.Root
}
if c.GlobalIsSet("runroot") {
storageOpts.RunRoot = c.GlobalString("runroot")
if c.Flags().Changed("runroot") {
storageOpts.RunRoot = c.GlobalFlags.Runroot
}
if len(storageOpts.RunRoot) > 50 {
return nil, errors.New("the specified runroot is longer than 50 characters")
}
if c.GlobalIsSet("storage-driver") {
storageOpts.GraphDriverName = c.GlobalString("storage-driver")
if c.Flags().Changed("storage-driver") {
storageOpts.GraphDriverName = c.GlobalFlags.StorageDriver
}
if c.GlobalIsSet("storage-opt") {
storageOpts.GraphDriverOptions = c.GlobalStringSlice("storage-opt")
if c.Flags().Changed("storage-opt") {
storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts
}
options = append(options, libpod.WithStorageConfig(storageOpts))
@ -47,23 +57,23 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
// TODO CLI flags for image config?
// TODO CLI flag for signature policy?
if c.GlobalIsSet("namespace") {
options = append(options, libpod.WithNamespace(c.GlobalString("namespace")))
if len(c.GlobalFlags.Namespace) > 0 {
options = append(options, libpod.WithNamespace(c.GlobalFlags.Namespace))
}
if c.GlobalIsSet("runtime") {
options = append(options, libpod.WithOCIRuntime(c.GlobalString("runtime")))
if c.Flags().Changed("runtime") {
options = append(options, libpod.WithOCIRuntime(c.GlobalFlags.Runtime))
}
if c.GlobalIsSet("conmon") {
options = append(options, libpod.WithConmonPath(c.GlobalString("conmon")))
if c.Flags().Changed("conmon") {
options = append(options, libpod.WithConmonPath(c.GlobalFlags.ConmonPath))
}
if c.GlobalIsSet("tmpdir") {
options = append(options, libpod.WithTmpDir(c.GlobalString("tmpdir")))
if c.Flags().Changed("tmpdir") {
options = append(options, libpod.WithTmpDir(c.GlobalFlags.TmpDir))
}
if c.GlobalIsSet("cgroup-manager") {
options = append(options, libpod.WithCgroupManager(c.GlobalString("cgroup-manager")))
if c.Flags().Changed("cgroup-manager") {
options = append(options, libpod.WithCgroupManager(c.GlobalFlags.CGroupManager))
} else {
if rootless.IsRootless() {
options = append(options, libpod.WithCgroupManager("cgroupfs"))
@ -73,29 +83,37 @@ func GetRuntime(c *cli.Context) (*libpod.Runtime, error) {
// TODO flag to set libpod static dir?
// TODO flag to set libpod tmp dir?
if c.GlobalIsSet("cni-config-dir") {
options = append(options, libpod.WithCNIConfigDir(c.GlobalString("cni-config-dir")))
if c.Flags().Changed("cni-config-dir") {
options = append(options, libpod.WithCNIConfigDir(c.GlobalFlags.CniConfigDir))
}
if c.GlobalIsSet("default-mounts-file") {
options = append(options, libpod.WithDefaultMountsFile(c.GlobalString("default-mounts-file")))
if c.Flags().Changed("default-mounts-file") {
options = append(options, libpod.WithDefaultMountsFile(c.GlobalFlags.DefaultMountsFile))
}
if c.GlobalIsSet("hooks-dir") {
options = append(options, libpod.WithHooksDir(c.GlobalStringSlice("hooks-dir")...))
if c.Flags().Changed("hooks-dir") {
options = append(options, libpod.WithHooksDir(c.GlobalFlags.HooksDir...))
}
// TODO flag to set CNI plugins dir?
// TODO I dont think these belong here?
// Will follow up with a different PR to address
//
// Pod create options
if c.IsSet("infra-image") {
options = append(options, libpod.WithDefaultInfraImage(c.String("infra-image")))
infraImageFlag := c.Flags().Lookup("infra-image")
if infraImageFlag != nil && infraImageFlag.Changed {
infraImage, _ := c.Flags().GetString("infra-image")
options = append(options, libpod.WithDefaultInfraImage(infraImage))
}
if c.IsSet("infra-command") {
options = append(options, libpod.WithDefaultInfraCommand(c.String("infra-command")))
infraCommandFlag := c.Flags().Lookup("infra-command")
if infraCommandFlag != nil && infraImageFlag.Changed {
infraCommand, _ := c.Flags().GetString("infra-command")
options = append(options, libpod.WithDefaultInfraCommand(infraCommand))
}
options = append(options, libpod.WithVolumePath(volumePath))
if c.IsSet("config") {
return libpod.NewRuntimeFromConfig(c.String("config"), options...)
if c.Flags().Changed("config") {
return libpod.NewRuntimeFromConfig(c.GlobalFlags.Config, options...)
}
return libpod.NewRuntime(options...)
}

View file

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

View file

@ -9,55 +9,48 @@ import (
"github.com/containers/image/docker"
"github.com/containers/image/pkg/docker/config"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/common"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
)
var (
loginFlags = []cli.Flag{
cli.StringFlag{
Name: "password, p",
Usage: "Password for registry",
},
cli.StringFlag{
Name: "username, u",
Usage: "Username for registry",
},
cli.StringFlag{
Name: "authfile",
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
},
cli.StringFlag{
Name: "cert-dir",
Usage: "Pathname of a directory containing TLS certificates and keys used to connect to the registry",
},
cli.BoolTFlag{
Name: "get-login",
Usage: "Return the current login user for the registry",
},
cli.BoolTFlag{
Name: "tls-verify",
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
},
}
loginCommand cliconfig.LoginValues
loginDescription = "Login to a container registry on a specified server."
loginCommand = cli.Command{
Name: "login",
Usage: "Login to a container registry",
Description: loginDescription,
Flags: sortFlags(loginFlags),
Action: loginCmd,
ArgsUsage: "REGISTRY",
OnUsageError: usageErrorHandler,
_loginCommand = &cobra.Command{
Use: "login",
Short: "Login to a container registry",
Long: loginDescription,
RunE: func(cmd *cobra.Command, args []string) error {
loginCommand.InputArgs = args
loginCommand.GlobalFlags = MainGlobalOpts
return loginCmd(&loginCommand)
},
Example: "REGISTRY",
}
)
func init() {
loginCommand.Command = _loginCommand
flags := loginCommand.Flags()
flags.StringVar(&loginCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&loginCommand.CertDir, "cert-dir", "", "Pathname of a directory containing TLS certificates and keys used to connect to the registry")
flags.BoolVar(&loginCommand.GetLogin, "get-login", true, "Return the current login user for the registry")
flags.StringVarP(&loginCommand.Password, "password", "p", "", "Password for registry")
flags.BoolVar(&loginCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
flags.StringVarP(&loginCommand.Username, "username", "u", "", "Username for registry")
rootCmd.AddCommand(loginCommand.Command)
}
// loginCmd uses the authentication package to store a user's authenticated credentials
// in an auth.json file for future use
func loginCmd(c *cli.Context) error {
args := c.Args()
func loginCmd(c *cliconfig.LoginValues) error {
args := c.InputArgs
if len(args) > 1 {
return errors.Errorf("too many arguments, login takes only 1 argument")
}
@ -65,17 +58,17 @@ func loginCmd(c *cli.Context) error {
return errors.Errorf("please specify a registry to login to")
}
server := registryFromFullName(scrubServer(args[0]))
authfile := getAuthFile(c.String("authfile"))
authfile := getAuthFile(c.Authfile)
sc := common.GetSystemContext("", authfile, false)
if c.IsSet("tls-verify") {
sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
if c.Flag("tls-verify").Changed {
sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
if c.String("cert-dir") != "" {
sc.DockerCertPath = c.String("cert-dir")
if c.CertDir != "" {
sc.DockerCertPath = c.CertDir
}
if c.IsSet("get-login") {
if c.Flag("get-login").Changed {
user, err := config.GetUserLoggedIn(sc, server)
if err != nil {
@ -98,7 +91,7 @@ func loginCmd(c *cli.Context) error {
ctx := getContext()
// If no username and no password is specified, try to use existing ones.
if c.String("username") == "" && c.String("password") == "" {
if c.Username == "" && c.Password == "" {
fmt.Println("Authenticating with existing credentials...")
if err := docker.CheckAuth(ctx, sc, userFromAuthFile, passFromAuthFile, server); err == nil {
fmt.Println("Existing credentials are valid. Already logged in to", server)
@ -107,7 +100,7 @@ func loginCmd(c *cli.Context) error {
fmt.Println("Existing credentials are invalid, please enter valid username and password")
}
username, password, err := getUserAndPass(c.String("username"), c.String("password"), userFromAuthFile)
username, password, err := getUserAndPass(c.Username, c.Password, userFromAuthFile)
if err != nil {
return errors.Wrapf(err, "error getting username and password")
}

View file

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

View file

@ -4,91 +4,82 @@ import (
"os"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/logs"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
logsFlags = []cli.Flag{
cli.BoolFlag{
Name: "details",
Usage: "Show extra details provided to the logs",
Hidden: true,
},
cli.BoolFlag{
Name: "follow, f",
Usage: "Follow log output. The default is false",
},
cli.StringFlag{
Name: "since",
Usage: "Show logs since TIMESTAMP",
},
cli.Uint64Flag{
Name: "tail",
Usage: "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines",
},
cli.BoolFlag{
Name: "timestamps, t",
Usage: "Output the timestamps in the log",
},
LatestFlag,
}
logsCommand cliconfig.LogsValues
logsDescription = "The podman logs command batch-retrieves whatever logs are present for a container at the time of execution. This does not guarantee execution" +
"order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs"
logsCommand = cli.Command{
Name: "logs",
Usage: "Fetch the logs of a container",
Description: logsDescription,
Flags: sortFlags(logsFlags),
Action: logsCmd,
ArgsUsage: "CONTAINER",
SkipArgReorder: true,
OnUsageError: usageErrorHandler,
UseShortOptionHandling: true,
_logsCommand = &cobra.Command{
Use: "logs",
Short: "Fetch the logs of a container",
Long: logsDescription,
RunE: func(cmd *cobra.Command, args []string) error {
logsCommand.InputArgs = args
logsCommand.GlobalFlags = MainGlobalOpts
return logsCmd(&logsCommand)
},
Example: "CONTAINER",
}
)
func logsCmd(c *cli.Context) error {
func init() {
logsCommand.Command = _logsCommand
flags := logsCommand.Flags()
flags.BoolVar(&logsCommand.Details, "details", false, "Show extra details provided to the logs")
flags.BoolVarP(&logsCommand.Follow, "follow", "f", false, "Follow log output. The default is false")
flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.StringVar(&logsCommand.Since, "since", "", "Show logs since TIMESTAMP")
flags.Uint64Var(&logsCommand.Tail, "tail", 0, "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines")
flags.BoolVarP(&logsCommand.Timestamps, "timestamps", "t", false, "Output the timestamps in the log")
flags.MarkHidden("details")
flags.SetInterspersed(false)
rootCmd.AddCommand(logsCommand.Command)
}
func logsCmd(c *cliconfig.LogsValues) error {
var ctr *libpod.Container
var err error
if err := validateFlags(c, logsFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
args := c.Args()
if len(args) != 1 && !c.Bool("latest") {
args := c.InputArgs
if len(args) != 1 && !c.Latest {
return errors.Errorf("'podman logs' requires exactly one container name/ID")
}
sinceTime := time.Time{}
if c.IsSet("since") {
if c.Flag("since").Changed {
// parse time, error out if something is wrong
since, err := parseInputTime(c.String("since"))
since, err := parseInputTime(c.Since)
if err != nil {
return errors.Wrapf(err, "could not parse time: %q", c.String("since"))
return errors.Wrapf(err, "could not parse time: %q", c.Since)
}
sinceTime = since
}
opts := &logs.LogOptions{
Details: c.Bool("details"),
Follow: c.Bool("follow"),
Details: c.Details,
Follow: c.Follow,
Since: sinceTime,
Tail: c.Uint64("tail"),
Timestamps: c.Bool("timestamps"),
Tail: c.Tail,
Timestamps: c.Timestamps,
}
if c.Bool("latest") {
if c.Latest {
ctr, err = runtime.GetLatestContainer()
} else {
ctr, err = runtime.LookupContainer(args[0])

View file

@ -6,9 +6,10 @@ import (
"os"
"os/exec"
"runtime/pprof"
"sort"
"strings"
"syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
_ "github.com/containers/libpod/pkg/hooks/0.1.0"
"github.com/containers/libpod/pkg/rootless"
@ -17,7 +18,7 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
lsyslog "github.com/sirupsen/logrus/hooks/syslog"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
// This is populated by the Makefile from the VERSION file
@ -26,198 +27,159 @@ var (
exitCode = 125
)
var cmdsNotRequiringRootless = map[string]bool{
"help": true,
"version": true,
"create": true,
"exec": true,
"export": true,
// `info` must be executed in an user namespace.
// If this change, please also update libpod.refreshRootless()
"login": true,
"logout": true,
"mount": true,
"kill": true,
"pause": true,
"restart": true,
"run": true,
"unpause": true,
"search": true,
"stats": true,
"stop": true,
"top": true,
var cmdsNotRequiringRootless = map[*cobra.Command]bool{
_versionCommand: true,
_createCommand: true,
_execCommand: true,
_exportCommand: true,
//// `info` must be executed in an user namespace.
//// If this change, please also update libpod.refreshRootless()
_loginCommand: true,
_logoutCommand: true,
_mountCommand: true,
_killCommand: true,
_pauseCommand: true,
_restartCommand: true,
_runCommmand: true,
_unpauseCommand: true,
_searchCommand: true,
_statsCommand: true,
_stopCommand: true,
_topCommand: true,
}
type commandSorted []cli.Command
func (a commandSorted) Len() int { return len(a) }
func (a commandSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type commandSortedAlpha struct{ commandSorted }
func (a commandSortedAlpha) Less(i, j int) bool {
return a.commandSorted[i].Name < a.commandSorted[j].Name
var rootCmd = &cobra.Command{
Use: "podman",
Long: "manage pods and images",
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return before(cmd, args)
},
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return after(cmd, args)
},
SilenceUsage: true,
SilenceErrors: true,
}
type flagSorted []cli.Flag
var MainGlobalOpts cliconfig.MainFlags
func (a flagSorted) Len() int { return len(a) }
func (a flagSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func init() {
cobra.OnInitialize(initConfig)
rootCmd.TraverseChildren = true
rootCmd.Version = version.Version
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CGroupManager, "cgroup-manager", "", "Cgroup manager to use (cgroupfs or systemd, default systemd)")
// -c is deprecated due to conflict with -c on subcommands
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Config, "config", "", "Path of a libpod config file detailing container server configuration options")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.ConmonPath, "conmon", "", "Path of the conmon binary")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", "", "Path of the configuration directory for CNI networks")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", "", "Path to default mounts file")
rootCmd.PersistentFlags().MarkHidden("defaults-mount-file")
rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", []string{}, "Set the OCI hooks directory path (may be set multiple times)")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error (default), fatal or panic")
rootCmd.PersistentFlags().IntVar(&MainGlobalOpts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations")
rootCmd.PersistentFlags().MarkHidden("max-workers")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", "", "Set the libpod namespace, used to create separate views of the containers and pods on the system")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Root, "root", "", "Path to the root directory in which data, including images, is stored")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runtime, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc")
// -s is depracated due to conflict with -s on subcommands
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console")
type flagSortedAlpha struct{ flagSorted }
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory")
func (a flagSortedAlpha) Less(i, j int) bool {
return a.flagSorted[i].GetName() < a.flagSorted[j].GetName()
}
func initConfig() {
// we can do more stuff in here.
}
func before(cmd *cobra.Command, args []string) error {
if err := libpod.SetXdgRuntimeDir(""); err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
if rootless.IsRootless() {
notRequireRootless := cmdsNotRequiringRootless[cmd]
if !notRequireRootless && !strings.HasPrefix(cmd.Use, "help") {
became, ret, err := rootless.BecomeRootInUserNS()
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
if became {
os.Exit(ret)
}
}
}
if MainGlobalOpts.Syslog {
hook, err := lsyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
if err == nil {
logrus.AddHook(hook)
}
}
// Set log level
level, err := logrus.ParseLevel(MainGlobalOpts.LogLevel)
if err != nil {
return err
}
logrus.SetLevel(level)
rlimits := new(syscall.Rlimit)
rlimits.Cur = 1048576
rlimits.Max = 1048576
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
return errors.Wrapf(err, "error getting rlimits")
}
rlimits.Cur = rlimits.Max
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
return errors.Wrapf(err, "error setting new rlimits")
}
}
if rootless.IsRootless() {
logrus.Info("running as rootless")
}
// Be sure we can create directories with 0755 mode.
syscall.Umask(0022)
if cmd.Flag("cpu-profile").Changed {
f, err := os.Create(MainGlobalOpts.CpuProfile)
if err != nil {
return errors.Wrapf(err, "unable to create cpu profiling file %s",
MainGlobalOpts.CpuProfile)
}
pprof.StartCPUProfile(f)
}
return nil
}
func after(cmd *cobra.Command, args []string) error {
if cmd.Flag("cpu-profile").Changed {
pprof.StopCPUProfile()
}
return nil
}
func main() {
debug := false
cpuProfile := false
//debug := false
//cpuProfile := false
if reexec.Init() {
return
}
app := cli.NewApp()
app.Name = "podman"
app.Usage = "manage pods and images"
app.OnUsageError = usageErrorHandler
app.CommandNotFound = commandNotFoundHandler
app.Version = version.Version
app.Commands = []cli.Command{
containerCommand,
exportCommand,
historyCommand,
imageCommand,
imagesCommand,
importCommand,
infoCommand,
inspectCommand,
pullCommand,
rmiCommand,
systemCommand,
tagCommand,
versionCommand,
}
app.Commands = append(app.Commands, getAppCommands()...)
sort.Sort(commandSortedAlpha{app.Commands})
if varlinkCommand != nil {
app.Commands = append(app.Commands, *varlinkCommand)
}
app.Before = func(c *cli.Context) error {
if err := libpod.SetXdgRuntimeDir(""); err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
args := c.Args()
if args.Present() && rootless.IsRootless() {
if _, notRequireRootless := cmdsNotRequiringRootless[args.First()]; !notRequireRootless {
became, ret, err := rootless.BecomeRootInUserNS()
if err != nil {
logrus.Errorf(err.Error())
os.Exit(1)
}
if became {
os.Exit(ret)
}
}
}
if c.GlobalBool("syslog") {
hook, err := lsyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
if err == nil {
logrus.AddHook(hook)
}
}
logLevel := c.GlobalString("log-level")
if logLevel != "" {
level, err := logrus.ParseLevel(logLevel)
if err != nil {
return err
}
logrus.SetLevel(level)
}
rlimits := new(syscall.Rlimit)
rlimits.Cur = 1048576
rlimits.Max = 1048576
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
return errors.Wrapf(err, "error getting rlimits")
}
rlimits.Cur = rlimits.Max
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
return errors.Wrapf(err, "error setting new rlimits")
}
}
if rootless.IsRootless() {
logrus.Info("running as rootless")
}
// Be sure we can create directories with 0755 mode.
syscall.Umask(0022)
if logLevel == "debug" {
debug = true
}
if c.GlobalIsSet("cpu-profile") {
f, err := os.Create(c.GlobalString("cpu-profile"))
if err != nil {
return errors.Wrapf(err, "unable to create cpu profiling file %s",
c.GlobalString("cpu-profile"))
}
cpuProfile = true
pprof.StartCPUProfile(f)
}
return nil
}
app.After = func(*cli.Context) error {
// called by Run() when the command handler succeeds
if cpuProfile {
pprof.StopCPUProfile()
}
return nil
}
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "config, c",
Usage: "Path of a libpod config file detailing container server configuration options",
Hidden: true,
},
cli.StringFlag{
Name: "cpu-profile",
Usage: "Path for the cpu profiling results",
},
cli.StringFlag{
Name: "log-level",
Usage: "Log messages above specified level: debug, info, warn, error (default), fatal or panic",
Value: "error",
},
cli.StringFlag{
Name: "tmpdir",
Usage: "Path to the tmp directory",
},
}
app.Flags = append(app.Flags, getMainAppFlags()...)
sort.Sort(flagSortedAlpha{app.Flags})
// Check if /etc/containers/registries.conf exists when running in
// in a local environment.
CheckForRegistries()
if err := app.Run(os.Args); err != nil {
if debug {
if err := rootCmd.Execute(); err != nil {
if MainGlobalOpts.LogLevel == "debug" {
logrus.Errorf(err.Error())
} else {
// Retrieve the exit error from the exec call, if it exists
if ee, ok := err.(*exec.ExitError); ok {
if status, ok := ee.Sys().(syscall.WaitStatus); ok {
exitCode = status.ExitStatus()
@ -233,6 +195,11 @@ func main() {
if exitCode == 125 {
exitCode = 0
}
}
// Check if /etc/containers/registries.conf exists when running in
// in a local environment.
CheckForRegistries()
os.Exit(exitCode)
}

View file

@ -5,15 +5,18 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
of "github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
mountCommand cliconfig.MountValues
mountDescription = `
podman mount
Lists all mounted containers mount points
@ -22,32 +25,29 @@ var (
Mounts the specified container and outputs the mountpoint
`
mountFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Mount all containers",
_mountCommand = &cobra.Command{
Use: "mount",
Short: "Mount a working container's root filesystem",
Long: mountDescription,
RunE: func(cmd *cobra.Command, args []string) error {
mountCommand.InputArgs = args
mountCommand.GlobalFlags = MainGlobalOpts
return mountCmd(&mountCommand)
},
cli.StringFlag{
Name: "format",
Usage: "Change the output format to Go template",
},
cli.BoolFlag{
Name: "notruncate",
Usage: "Do not truncate output",
},
LatestFlag,
}
mountCommand = cli.Command{
Name: "mount",
Usage: "Mount a working container's root filesystem",
Description: mountDescription,
Action: mountCmd,
ArgsUsage: "[CONTAINER-NAME-OR-ID [...]]",
Flags: sortFlags(mountFlags),
OnUsageError: usageErrorHandler,
}
)
func init() {
mountCommand.Command = _mountCommand
flags := mountCommand.Flags()
flags.BoolVarP(&mountCommand.All, "all", "a", false, "Mount all containers")
flags.StringVar(&mountCommand.Format, "format", "", "Change the output format to Go template")
flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output")
rootCmd.AddCommand(mountCommand.Command)
}
// jsonMountPoint stores info about each container
type jsonMountPoint struct {
ID string `json:"id"`
@ -55,15 +55,12 @@ type jsonMountPoint struct {
MountPoint string `json:"mountpoint"`
}
func mountCmd(c *cli.Context) error {
if err := validateFlags(c, mountFlags); err != nil {
return err
}
func mountCmd(c *cliconfig.MountValues) error {
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@ -85,11 +82,11 @@ func mountCmd(c *cli.Context) error {
}
}
if c.Bool("all") && c.Bool("latest") {
if c.All && c.Latest {
return errors.Errorf("--all and --latest cannot be used together")
}
mountContainers, err := getAllOrLatestContainers(c, runtime, -1, "all")
mountContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
if err != nil {
if len(mountContainers) == 0 {
return err
@ -102,9 +99,9 @@ func mountCmd(c *cli.Context) error {
of.JSONString: true,
}
json := c.String("format") == of.JSONString
if !formats[c.String("format")] {
return errors.Errorf("%q is not a supported format", c.String("format"))
json := c.Format == of.JSONString
if !formats[c.Format] {
return errors.Errorf("%q is not a supported format", c.Format)
}
var lastError error
@ -149,7 +146,7 @@ func mountCmd(c *cli.Context) error {
continue
}
if c.Bool("notruncate") {
if c.NoTrunc {
fmt.Printf("%-64s %s\n", container.ID(), mountPoint)
} else {
fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint)

View file

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

View file

@ -1,23 +1,23 @@
package main
import (
"github.com/urfave/cli"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
)
var (
playSubCommands = []cli.Command{
playKubeCommand,
var playCommand cliconfig.PodmanCommand
func init() {
var playDescription = "Play a pod and its containers from a structured file."
playCommand.Command = &cobra.Command{
Use: "play",
Short: "Play a pod",
Long: playDescription,
}
playDescription = "Play a pod and its containers from a structured file."
playCommand = cli.Command{
Name: "play",
Usage: "Play a container or pod",
Description: playDescription,
ArgsUsage: "",
Subcommands: playSubCommands,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
Hidden: true,
}
)
}
func init() {
playCommand.AddCommand(getPlaySubCommands()...)
rootCmd.AddCommand(playCommand.Command)
}

View file

@ -8,6 +8,7 @@ import (
"strings"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
@ -20,51 +21,40 @@ import (
"github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
"k8s.io/api/core/v1"
)
var (
playKubeFlags = []cli.Flag{
cli.StringFlag{
Name: "authfile",
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
},
cli.StringFlag{
Name: "cert-dir",
Usage: "`Pathname` of a directory containing TLS certificates and keys",
},
cli.StringFlag{
Name: "creds",
Usage: "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Suppress output information when pulling images",
},
cli.StringFlag{
Name: "signature-policy",
Usage: "`Pathname` of signature policy file (not usually used)",
},
cli.BoolTFlag{
Name: "tls-verify",
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
},
}
playKubeCommand cliconfig.KubePlayValues
playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML"
playKubeCommand = cli.Command{
Name: "kube",
Usage: "Play a pod based on Kubernetes YAML",
Description: playKubeDescription,
Action: playKubeYAMLCmd,
Flags: sortFlags(playKubeFlags),
ArgsUsage: "Kubernetes YAML file",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_playKubeCommand = &cobra.Command{
Use: "kube",
Short: "Play a pod based on Kubernetes YAML",
Long: playKubeDescription,
RunE: func(cmd *cobra.Command, args []string) error {
playKubeCommand.InputArgs = args
playKubeCommand.GlobalFlags = MainGlobalOpts
return playKubeYAMLCmd(&playKubeCommand)
},
Example: "Kubernetes YAML file",
}
)
func playKubeYAMLCmd(c *cli.Context) error {
func init() {
playKubeCommand.Command = _playKubeCommand
flags := playKubeCommand.Flags()
flags.StringVar(&playKubeCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&playKubeCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.StringVar(&playKubeCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.BoolVarP(&playKubeCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.StringVar(&playKubeCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
rootCmd.AddCommand(playKubeCommand.Command)
}
func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error {
var (
podOptions []libpod.PodCreateOption
podYAML v1.Pod
@ -77,7 +67,7 @@ func playKubeYAMLCmd(c *cli.Context) error {
if rootless.IsRootless() {
return errors.Wrapf(libpod.ErrNotImplemented, "rootless users")
}
args := c.Args()
args := c.InputArgs
if len(args) > 1 {
return errors.New("you can only play one kubernetes file at a time")
}
@ -85,7 +75,7 @@ func playKubeYAMLCmd(c *cli.Context) error {
return errors.New("you must supply at least one file")
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@ -133,20 +123,20 @@ func playKubeYAMLCmd(c *cli.Context) error {
"ipc": fmt.Sprintf("container:%s", podInfraID),
"uts": fmt.Sprintf("container:%s", podInfraID),
}
if !c.Bool("quiet") {
if !c.Quiet {
writer = os.Stderr
}
dockerRegistryOptions := image2.DockerRegistryOptions{
DockerRegistryCreds: registryCreds,
DockerCertPath: c.String("cert-dir"),
DockerCertPath: c.CertDir,
}
if c.IsSet("tls-verify") {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
for _, container := range podYAML.Spec.Containers {
newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.String("signature-policy"), c.String("authfile"), writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil)
newImage, err := runtime.ImageRuntime().New(ctx, container.Image, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, false, nil)
if err != nil {
return err
}

View file

@ -1,35 +1,24 @@
package main
import (
"github.com/urfave/cli"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
)
var (
podDescription = `Manage container pods.
Pods are a group of one or more containers sharing the same network, pid and ipc namespaces.
`
podSubCommands = []cli.Command{
podCreateCommand,
podExistsCommand,
podInspectCommand,
podKillCommand,
podPauseCommand,
podPsCommand,
podRestartCommand,
podRmCommand,
podStartCommand,
podStatsCommand,
podStopCommand,
podTopCommand,
podUnpauseCommand,
}
podCommand = cli.Command{
Name: "pod",
Usage: "Manage pods",
Description: podDescription,
UseShortOptionHandling: true,
Subcommands: podSubCommands,
OnUsageError: usageErrorHandler,
}
Pods are a group of one or more containers sharing the same network, pid and ipc namespaces.`
)
var podCommand = cliconfig.PodmanCommand{
Command: &cobra.Command{
Use: "pod",
Short: "Manage pods",
Long: podDescription,
},
}
func init() {
podCommand.AddCommand(getPodSubCommands()...)
rootCmd.AddCommand(podCommand.Command)
}

View file

@ -5,111 +5,81 @@ import (
"os"
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
// Kernel namespaces shared by default within a pod
DefaultKernelNamespaces = "cgroup,ipc,net,uts"
podCreateCommand cliconfig.PodCreateValues
podCreateDescription = "Creates a new empty pod. The pod ID is then" +
" printed to stdout. You can then start it at any time with the" +
" podman pod start <pod_id> command. The pod will be created with the" +
" initial state 'created'."
_podCreateCommand = &cobra.Command{
Use: "create",
Short: "Create a new empty pod",
Long: podCreateDescription,
RunE: func(cmd *cobra.Command, args []string) error {
podCreateCommand.InputArgs = args
podCreateCommand.GlobalFlags = MainGlobalOpts
return podCreateCmd(&podCreateCommand)
},
}
)
var podCreateDescription = "Creates a new empty pod. The pod ID is then" +
" printed to stdout. You can then start it at any time with the" +
" podman pod start <pod_id> command. The pod will be created with the" +
" initial state 'created'."
func init() {
podCreateCommand.Command = _podCreateCommand
flags := podCreateCommand.Flags()
flags.SetInterspersed(false)
flags.StringVar(&podCreateCommand.CgroupParent, "cgroup-parent", "", "Set parent cgroup for the pod")
flags.BoolVar(&podCreateCommand.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
flags.StringVar(&podCreateCommand.InfraImage, "infra-image", libpod.DefaultInfraImage, "The image of the infra container to associate with the pod")
flags.StringVar(&podCreateCommand.InfraCommand, "infra-command", libpod.DefaultInfraCommand, "The command to run on the infra container when the pod is started")
flags.StringSliceVar(&podCreateCommand.LabelFile, "label-file", []string{}, "Read in a line delimited file of labels")
flags.StringSliceVarP(&podCreateCommand.Labels, "label", "l", []string{}, "Set metadata on pod (default [])")
flags.StringVarP(&podCreateCommand.Name, "name", "n", "", "Assign a name to the pod")
flags.StringVar(&podCreateCommand.PodIDFile, "pod-id-file", "", "Write the pod ID to the file")
flags.StringSliceVarP(&podCreateCommand.Publish, "publish", "p", []string{}, "Publish a container's port, or a range of ports, to the host (default [])")
flags.StringVar(&podCreateCommand.Share, "share", DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
var podCreateFlags = []cli.Flag{
cli.StringFlag{
Name: "cgroup-parent",
Usage: "Set parent cgroup for the pod",
},
cli.BoolTFlag{
Name: "infra",
Usage: "Create an infra container associated with the pod to share namespaces with",
},
cli.StringFlag{
Name: "infra-image",
Usage: "The image of the infra container to associate with the pod",
Value: libpod.DefaultInfraImage,
},
cli.StringFlag{
Name: "infra-command",
Usage: "The command to run on the infra container when the pod is started",
Value: libpod.DefaultInfraCommand,
},
cli.StringSliceFlag{
Name: "label-file",
Usage: "Read in a line delimited file of labels (default [])",
},
cli.StringSliceFlag{
Name: "label, l",
Usage: "Set metadata on pod (default [])",
},
cli.StringFlag{
Name: "name, n",
Usage: "Assign a name to the pod",
},
cli.StringFlag{
Name: "pod-id-file",
Usage: "Write the pod ID to the file",
},
cli.StringSliceFlag{
Name: "publish, p",
Usage: "Publish a container's port, or a range of ports, to the host (default [])",
},
cli.StringFlag{
Name: "share",
Usage: "A comma delimited list of kernel namespaces the pod will share",
Value: DefaultKernelNamespaces,
},
}
var podCreateCommand = cli.Command{
Name: "create",
Usage: "Create a new empty pod",
Description: podCreateDescription,
Flags: sortFlags(podCreateFlags),
Action: podCreateCmd,
SkipArgReorder: true,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
}
func podCreateCmd(c *cli.Context) error {
func podCreateCmd(c *cliconfig.PodCreateValues) error {
var options []libpod.PodCreateOption
var err error
if err = validateFlags(c, createFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
var podIdFile *os.File
if c.IsSet("pod-id-file") && os.Geteuid() == 0 {
podIdFile, err = libpod.OpenExclusiveFile(c.String("pod-id-file"))
if c.Flag("pod-id-file").Changed && os.Geteuid() == 0 {
podIdFile, err = libpod.OpenExclusiveFile(c.PodIDFile)
if err != nil && os.IsExist(err) {
return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", c.String("pod-id-file"))
return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", c.PodIDFile)
}
if err != nil {
return errors.Errorf("error opening pod-id-file %s", c.String("pod-id-file"))
return errors.Errorf("error opening pod-id-file %s", c.PodIDFile)
}
defer podIdFile.Close()
defer podIdFile.Sync()
}
if len(c.StringSlice("publish")) > 0 {
if !c.BoolT("infra") {
if len(c.Publish) > 0 {
if !c.Infra {
return errors.Errorf("you must have an infra container to publish port bindings to the host")
}
if rootless.IsRootless() {
@ -117,15 +87,15 @@ func podCreateCmd(c *cli.Context) error {
}
}
if !c.BoolT("infra") && c.IsSet("share") && c.String("share") != "none" && c.String("share") != "" {
if !c.Infra && c.Flag("share").Changed && c.Share != "none" && c.Share != "" {
return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container")
}
if c.IsSet("cgroup-parent") {
options = append(options, libpod.WithPodCgroupParent(c.String("cgroup-parent")))
if c.Flag("cgroup-parent").Changed {
options = append(options, libpod.WithPodCgroupParent(c.CgroupParent))
}
labels, err := getAllLabels(c.StringSlice("label-file"), c.StringSlice("label"))
labels, err := getAllLabels(c.LabelFile, c.Labels)
if err != nil {
return errors.Wrapf(err, "unable to process labels")
}
@ -133,21 +103,21 @@ func podCreateCmd(c *cli.Context) error {
options = append(options, libpod.WithPodLabels(labels))
}
if c.IsSet("name") {
options = append(options, libpod.WithPodName(c.String("name")))
if c.Flag("name").Changed {
options = append(options, libpod.WithPodName(c.Name))
}
if c.BoolT("infra") {
if c.Infra {
options = append(options, libpod.WithInfraContainer())
nsOptions, err := shared.GetNamespaceOptions(strings.Split(c.String("share"), ","))
nsOptions, err := shared.GetNamespaceOptions(strings.Split(c.Share, ","))
if err != nil {
return err
}
options = append(options, nsOptions...)
}
if len(c.StringSlice("publish")) > 0 {
portBindings, err := shared.CreatePortBindings(c.StringSlice("publish"))
if len(c.Publish) > 0 {
portBindings, err := shared.CreatePortBindings(c.Publish)
if err != nil {
return err
}

View file

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

View file

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

View file

@ -2,43 +2,42 @@ package main
import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
podPauseFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Pause all running pods",
podPauseCommand cliconfig.PodPauseValues
podPauseDescription = `Pauses one or more pods. The pod name or ID can be used.`
_podPauseCommand = &cobra.Command{
Use: "pause",
Short: "Pause one or more pods",
Long: podPauseDescription,
RunE: func(cmd *cobra.Command, args []string) error {
podPauseCommand.InputArgs = args
podPauseCommand.GlobalFlags = MainGlobalOpts
return podPauseCmd(&podPauseCommand)
},
LatestPodFlag,
}
podPauseDescription = `
Pauses one or more pods. The pod name or ID can be used.
`
podPauseCommand = cli.Command{
Name: "pause",
Usage: "Pause one or more pods",
Description: podPauseDescription,
Flags: sortFlags(podPauseFlags),
Action: podPauseCmd,
ArgsUsage: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
}
)
func podPauseCmd(c *cli.Context) error {
if err := checkMutuallyExclusiveFlags(c); err != nil {
func init() {
podPauseCommand.Command = _podPauseCommand
flags := podPauseCommand.Flags()
flags.BoolVarP(&podPauseCommand.All, "all", "a", false, "Pause all running pods")
flags.BoolVarP(&podPauseCommand.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
}
func podPauseCmd(c *cliconfig.PodPauseValues) error {
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
@ -47,7 +46,7 @@ func podPauseCmd(c *cli.Context) error {
// getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime)
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
for _, pod := range pods {
ctr_errs, err := pod.Pause()

View file

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

View file

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

View file

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

View file

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

View file

@ -7,54 +7,49 @@ import (
"encoding/json"
tm "github.com/buger/goterm"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/ulule/deepcopier"
"github.com/urfave/cli"
)
var (
podStatsFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Show stats for all pods. Only running pods are shown by default.",
},
cli.BoolFlag{
Name: "no-stream",
Usage: "Disable streaming stats and only pull the first result, default setting is false",
},
cli.BoolFlag{
Name: "no-reset",
Usage: "Disable resetting the screen between intervals",
},
cli.StringFlag{
Name: "format",
Usage: "Pretty-print container statistics to JSON or using a Go template",
}, LatestPodFlag,
}
podStatsCommand cliconfig.PodStatsValues
podStatsDescription = "Display a live stream of resource usage statistics for the containers in or more pods"
podStatsCommand = cli.Command{
Name: "stats",
Usage: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one or more pods",
Description: podStatsDescription,
Flags: sortFlags(podStatsFlags),
Action: podStatsCmd,
ArgsUsage: "[POD_NAME_OR_ID]",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_podStatsCommand = &cobra.Command{
Use: "stats",
Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one or more pods",
Long: podStatsDescription,
RunE: func(cmd *cobra.Command, args []string) error {
podStatsCommand.InputArgs = args
podStatsCommand.GlobalFlags = MainGlobalOpts
return podStatsCmd(&podStatsCommand)
},
Example: "[POD_NAME_OR_ID]",
}
)
func podStatsCmd(c *cli.Context) error {
func init() {
podStatsCommand.Command = _podStatsCommand
flags := podStatsCommand.Flags()
flags.BoolVarP(&podStatsCommand.All, "all", "a", false, "Provide stats for all running pods")
flags.StringVar(&podStatsCommand.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template")
flags.BoolVarP(&podStatsCommand.Latest, "latest", "l", false, "Provide stats on the latest pod podman is aware of")
flags.BoolVar(&podStatsCommand.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false")
flags.BoolVar(&podStatsCommand.NoReset, "no-reset", false, "Disable resetting the screen between intervals")
}
func podStatsCmd(c *cliconfig.PodStatsValues) error {
var (
podFunc func() ([]*libpod.Pod, error)
)
format := c.String("format")
all := c.Bool("all")
latest := c.Bool("latest")
format := c.Format
all := c.All
latest := c.Latest
ctr := 0
if all {
ctr += 1
@ -62,7 +57,7 @@ func podStatsCmd(c *cli.Context) error {
if latest {
ctr += 1
}
if len(c.Args()) > 0 {
if len(c.InputArgs) > 0 {
ctr += 1
}
@ -73,19 +68,19 @@ func podStatsCmd(c *cli.Context) error {
all = true
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
times := -1
if c.Bool("no-stream") {
if c.NoStream {
times = 1
}
if len(c.Args()) > 0 {
podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.Args(), runtime) }
if len(c.InputArgs) > 0 {
podFunc = func() ([]*libpod.Pod, error) { return getPodsByList(c.InputArgs, runtime) }
} else if latest {
podFunc = func() ([]*libpod.Pod, error) {
latestPod, err := runtime.GetLatestPod()
@ -159,7 +154,7 @@ func podStatsCmd(c *cli.Context) error {
newStats = append(newStats, &newPod)
}
//Output
if strings.ToLower(format) != formats.JSONString && !c.Bool("no-reset") {
if strings.ToLower(format) != formats.JSONString && !c.NoReset {
tm.Clear()
tm.MoveCursor(1, 1)
tm.Flush()

View file

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

View file

@ -6,21 +6,17 @@ import (
"strings"
"text/tabwriter"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
podTopFlags = []cli.Flag{
LatestFlag,
cli.BoolFlag{
Name: "list-descriptors",
Hidden: true,
},
}
podTopCommand cliconfig.PodTopValues
podTopDescription = fmt.Sprintf(`Display the running processes containers in a pod. Specify format descriptors
to alter the output. You may run "podman pod top -l pid pcpu seccomp" to print
the process ID, the CPU percentage and the seccomp mode of each process of
@ -28,24 +24,34 @@ the latest pod.
%s
`, getDescriptorString())
podTopCommand = cli.Command{
Name: "top",
Usage: "Display the running processes of containers in a pod",
Description: podTopDescription,
Flags: sortFlags(podTopFlags),
Action: podTopCmd,
ArgsUsage: "POD-NAME [format descriptors]",
SkipArgReorder: true,
OnUsageError: usageErrorHandler,
_podTopCommand = &cobra.Command{
Use: "top",
Short: "Display the running processes of containers in a pod",
Long: podTopDescription,
RunE: func(cmd *cobra.Command, args []string) error {
podTopCommand.InputArgs = args
podTopCommand.GlobalFlags = MainGlobalOpts
return podTopCmd(&podTopCommand)
},
Example: "POD-NAME [format descriptors]",
}
)
func podTopCmd(c *cli.Context) error {
func init() {
podTopCommand.Command = _podTopCommand
flags := podTopCommand.Flags()
flags.BoolVarP(&podTopCommand.Latest, "latest,", "l", false, "Act on the latest pod podman is aware of")
flags.BoolVar(&podTopCommand.ListDescriptors, "list-descriptors", false, "")
flags.MarkHidden("list-descriptors")
}
func podTopCmd(c *cliconfig.PodTopValues) error {
var pod *libpod.Pod
var err error
args := c.Args()
args := c.InputArgs
if c.Bool("list-descriptors") {
if c.ListDescriptors {
descriptors, err := libpod.GetContainerPidInformationDescriptors()
if err != nil {
return err
@ -54,21 +60,18 @@ func podTopCmd(c *cli.Context) error {
return nil
}
if len(args) < 1 && !c.Bool("latest") {
if len(args) < 1 && !c.Latest {
return errors.Errorf("you must provide the name or id of a running pod")
}
if err := validateFlags(c, podTopFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
var descriptors []string
if c.Bool("latest") {
if c.Latest {
descriptors = args
pod, err = runtime.GetLatestPod()
} else {

View file

@ -3,42 +3,42 @@ package main
import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
podUnpauseFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Unpause all paused pods",
podUnpauseCommand cliconfig.PodUnpauseValues
podUnpauseDescription = `Unpauses one or more pods. The pod name or ID can be used.`
_podUnpauseCommand = &cobra.Command{
Use: "unpause",
Short: "Unpause one or more pods",
Long: podUnpauseDescription,
RunE: func(cmd *cobra.Command, args []string) error {
podUnpauseCommand.InputArgs = args
podUnpauseCommand.GlobalFlags = MainGlobalOpts
return podUnpauseCmd(&podUnpauseCommand)
},
LatestPodFlag,
}
podUnpauseDescription = `
Unpauses one or more pods. The pod name or ID can be used.
`
podUnpauseCommand = cli.Command{
Name: "unpause",
Usage: "Unpause one or more pods",
Description: podUnpauseDescription,
Flags: sortFlags(podUnpauseFlags),
Action: podUnpauseCmd,
ArgsUsage: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
Example: "POD-NAME|POD-ID [POD-NAME|POD-ID ...]",
}
)
func podUnpauseCmd(c *cli.Context) error {
if err := checkMutuallyExclusiveFlags(c); err != nil {
func init() {
podUnpauseCommand.Command = _podUnpauseCommand
flags := podUnpauseCommand.Flags()
flags.BoolVarP(&podUnpauseCommand.All, "all", "a", false, "Unpause all running pods")
flags.BoolVarP(&podUnpauseCommand.Latest, "latest", "l", false, "Unpause the latest pod podman is aware of")
}
func podUnpauseCmd(c *cliconfig.PodUnpauseValues) error {
if err := checkMutuallyExclusiveFlags(&c.PodmanCommand); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
@ -47,7 +47,7 @@ func podUnpauseCmd(c *cli.Context) error {
// getPodsFromContext returns an error when a requested pod
// isn't found. The only fatal error scenerio is when there are no pods
// in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime)
pods, lastError := getPodsFromContext(&c.PodmanCommand, runtime)
for _, pod := range pods {
ctr_errs, err := pod.Unpause()

View file

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

View file

@ -12,6 +12,7 @@ import (
"text/tabwriter"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
@ -21,7 +22,7 @@ import (
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/fields"
)
@ -153,112 +154,78 @@ func (a psSortedSize) Less(i, j int) bool {
}
var (
psFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Show all the containers, default is only running containers",
},
cli.StringSliceFlag{
Name: "filter, f",
Usage: "Filter output based on conditions given",
},
cli.StringFlag{
Name: "format",
Usage: "Pretty-print containers to JSON or using a Go template",
},
cli.IntFlag{
Name: "last, n",
Usage: "Print the n last created containers (all states)",
Value: -1,
},
cli.BoolFlag{
Name: "latest, l",
Usage: "Show the latest container created (all states)",
},
cli.BoolFlag{
Name: "namespace, ns",
Usage: "Display namespace information",
},
cli.BoolFlag{
Name: "no-trunc",
Usage: "Display the extended information",
},
cli.BoolFlag{
Name: "pod, p",
Usage: "Print the ID and name of the pod the containers are associated with",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Print the numeric IDs of the containers only",
},
cli.BoolFlag{
Name: "size, s",
Usage: "Display the total file sizes",
},
cli.StringFlag{
Name: "sort",
Usage: "Sort output by command, created, id, image, names, runningfor, size, or status",
Value: "created",
},
cli.BoolFlag{
Name: "sync",
Usage: "Sync container state with OCI runtime",
},
}
psCommand cliconfig.PsValues
psDescription = "Prints out information about the containers"
psCommand = cli.Command{
Name: "list",
Aliases: []string{"ls", "ps"},
Usage: "List containers",
Description: psDescription,
Flags: sortFlags(psFlags),
Action: psCmd,
ArgsUsage: "",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_psCommand = &cobra.Command{
Use: "list",
Aliases: []string{"ls", "ps"},
Short: "List containers",
Long: psDescription,
RunE: func(cmd *cobra.Command, args []string) error {
psCommand.InputArgs = args
psCommand.GlobalFlags = MainGlobalOpts
return psCmd(&psCommand)
},
Example: "",
}
)
func psCmd(c *cli.Context) error {
func init() {
psCommand.Command = _psCommand
flags := psCommand.Flags()
flags.BoolVarP(&psCommand.All, "all", "a", false, "Show all the containers, default is only running containers")
flags.StringSliceVarP(&psCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions given")
flags.StringVar(&psCommand.Format, "format", "", "Pretty-print containers to JSON or using a Go template")
flags.IntVarP(&psCommand.Last, "last", "n", -1, "Print the n last created containers (all states)")
flags.BoolVarP(&psCommand.Latest, "latest", "l", false, "Show the latest container created (all states)")
flags.BoolVar(&psCommand.Namespace, "namespace", false, "Display namespace information")
flags.BoolVar(&psCommand.Namespace, "ns", false, "Display namespace information")
flags.BoolVar(&psCommand.NoTrunct, "no-trunc", false, "Display the extended information")
flags.BoolVarP(&psCommand.Pod, "pod", "p", false, "Print the ID and name of the pod the containers are associated with")
flags.BoolVarP(&psCommand.Quiet, "quiet", "q", false, "Print the numeric IDs of the containers only")
flags.BoolVarP(&psCommand.Size, "size", "s", false, "Display the total file sizes")
flags.StringVar(&psCommand.Sort, "sort", "created", "Sort output by command, created, id, image, names, runningfor, size, or status")
flags.BoolVar(&psCommand.Sync, "sync", false, "Sync container state with OCI runtime")
rootCmd.AddCommand(psCommand.Command)
}
func psCmd(c *cliconfig.PsValues) error {
var (
filterFuncs []libpod.ContainerFilter
outputContainers []*libpod.Container
)
if err := validateFlags(c, psFlags); err != nil {
return err
}
if err := checkFlagsPassed(c); err != nil {
return errors.Wrapf(err, "error with flags passed")
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
if len(c.Args()) > 0 {
if len(c.InputArgs) > 0 {
return errors.Errorf("too many arguments, ps takes no arguments")
}
opts := shared.PsOptions{
All: c.Bool("all"),
Format: c.String("format"),
Last: c.Int("last"),
Latest: c.Bool("latest"),
NoTrunc: c.Bool("no-trunc"),
Pod: c.Bool("pod"),
Quiet: c.Bool("quiet"),
Size: c.Bool("size"),
Namespace: c.Bool("namespace"),
Sort: c.String("sort"),
Sync: c.Bool("sync"),
All: c.All,
Format: c.Format,
Last: c.Last,
Latest: c.Latest,
NoTrunc: c.NoTrunct,
Pod: c.Pod,
Quiet: c.Quiet,
Size: c.Size,
Namespace: c.Namespace,
Sort: c.Sort,
Sync: c.Sync,
}
filters := c.StringSlice("filter")
filters := c.Filter
if len(filters) > 0 {
for _, f := range filters {
filterSplit := strings.SplitN(f, "=", 2)
@ -299,7 +266,7 @@ func psCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("ps")
if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers")
maxWorkers = c.GlobalFlags.MaxWorks
}
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
@ -384,20 +351,20 @@ func printQuiet(containers []shared.PsContainerOutput) error {
}
// checkFlagsPassed checks if mutually exclusive flags are passed together
func checkFlagsPassed(c *cli.Context) error {
func checkFlagsPassed(c *cliconfig.PsValues) error {
// latest, and last are mutually exclusive.
if c.Int("last") >= 0 && c.Bool("latest") {
if c.Last >= 0 && c.Latest {
return errors.Errorf("last and latest are mutually exclusive")
}
// Quiet conflicts with size, namespace, and format with a Go template
if c.Bool("quiet") {
if c.Bool("size") || c.Bool("namespace") || (c.IsSet("format") &&
c.String("format") != formats.JSONString) {
if c.Quiet {
if c.Size || c.Namespace || (c.Flag("format").Changed &&
c.Format != formats.JSONString) {
return errors.Errorf("quiet conflicts with size, namespace, and format with go template")
}
}
// Size and namespace conflict with each other
if c.Bool("size") && c.Bool("namespace") {
if c.Size && c.Namespace {
return errors.Errorf("size and namespace options conflict")
}
return nil

View file

@ -9,68 +9,58 @@ import (
dockerarchive "github.com/containers/image/docker/archive"
"github.com/containers/image/transports/alltransports"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter"
image2 "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
pullFlags = []cli.Flag{
cli.StringFlag{
Name: "authfile",
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
},
cli.StringFlag{
Name: "cert-dir",
Usage: "`pathname` of a directory containing TLS certificates and keys",
},
cli.StringFlag{
Name: "creds",
Usage: "`credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Suppress output information when pulling images",
},
cli.StringFlag{
Name: "signature-policy",
Usage: "`pathname` of signature policy file (not usually used)",
},
cli.BoolTFlag{
Name: "tls-verify",
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
},
}
pullCommand cliconfig.PullValues
pullDescription = `
Pulls an image from a registry and stores it locally.
An image can be pulled using its tag or digest. If a tag is not
specified, the image with the 'latest' tag (if it exists) is pulled
`
pullCommand = cli.Command{
Name: "pull",
Usage: "Pull an image from a registry",
Description: pullDescription,
Flags: sortFlags(pullFlags),
Action: pullCmd,
ArgsUsage: "",
OnUsageError: usageErrorHandler,
_pullCommand = &cobra.Command{
Use: "pull",
Short: "Pull an image from a registry",
Long: pullDescription,
RunE: func(cmd *cobra.Command, args []string) error {
pullCommand.InputArgs = args
pullCommand.GlobalFlags = MainGlobalOpts
return pullCmd(&pullCommand)
},
Example: "",
}
)
func init() {
pullCommand.Command = _pullCommand
flags := pullCommand.Flags()
flags.StringVar(&pullCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&pullCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.StringVar(&pullCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.BoolVarP(&pullCommand.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
flags.StringVar(&pullCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.BoolVar(&pullCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
rootCmd.AddCommand(pullCommand.Command)
}
// pullCmd gets the data from the command line and calls pullImage
// to copy an image from a registry to a local machine
func pullCmd(c *cli.Context) error {
runtime, err := adapter.GetRuntime(c)
func pullCmd(c *cliconfig.PullValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
args := c.Args()
args := c.InputArgs
if len(args) == 0 {
logrus.Errorf("an image name must be specified")
return nil
@ -79,15 +69,12 @@ func pullCmd(c *cli.Context) error {
logrus.Errorf("too many arguments. Requires exactly 1")
return nil
}
if err := validateFlags(c, pullFlags); err != nil {
return err
}
image := args[0]
var registryCreds *types.DockerAuthConfig
if c.IsSet("creds") {
creds, err := util.ParseRegistryCreds(c.String("creds"))
if c.Flag("creds").Changed {
creds, err := util.ParseRegistryCreds(c.Creds)
if err != nil {
return err
}
@ -98,16 +85,16 @@ func pullCmd(c *cli.Context) error {
writer io.Writer
imgID string
)
if !c.Bool("quiet") {
if !c.Quiet {
writer = os.Stderr
}
dockerRegistryOptions := image2.DockerRegistryOptions{
DockerRegistryCreds: registryCreds,
DockerCertPath: c.String("cert-dir"),
DockerCertPath: c.CertDir,
}
if c.IsSet("tls-verify") {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
// Possible for docker-archive to have multiple tags, so use LoadFromArchiveReference instead
@ -116,14 +103,14 @@ func pullCmd(c *cli.Context) error {
if err != nil {
return errors.Wrapf(err, "error parsing %q", image)
}
newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.String("signature-policy"), writer)
newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.SignaturePolicy, writer)
if err != nil {
return errors.Wrapf(err, "error pulling image from %q", image)
}
imgID = newImage[0].ID()
} else {
authfile := getAuthFile(c.String("authfile"))
newImage, err := runtime.New(getContext(), image, c.String("signature-policy"), authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil)
authfile := getAuthFile(c.Authfile)
newImage, err := runtime.New(getContext(), image, c.SignaturePolicy, authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil)
if err != nil {
return errors.Wrapf(err, "error pulling image %q", image)
}

View file

@ -2,6 +2,8 @@ package main
import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
"io"
"os"
"strings"
@ -14,76 +16,52 @@ import (
"github.com/containers/libpod/pkg/util"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
pushFlags = []cli.Flag{
cli.StringFlag{
Name: "signature-policy",
Usage: "`Pathname` of signature policy file (not usually used)",
Hidden: true,
},
cli.StringFlag{
Name: "creds",
Usage: "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
},
cli.StringFlag{
Name: "cert-dir",
Usage: "`Pathname` of a directory containing TLS certificates and keys",
},
cli.BoolFlag{
Name: "compress",
Usage: "Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)",
},
cli.StringFlag{
Name: "format, f",
Usage: "Manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir:' transport (default is manifest type of source)",
},
cli.BoolTFlag{
Name: "tls-verify",
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
},
cli.BoolFlag{
Name: "remove-signatures",
Usage: "Discard any pre-existing signatures in the image",
},
cli.StringFlag{
Name: "sign-by",
Usage: "Add a signature at the destination using the specified key",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Don't output progress information when pushing images",
},
cli.StringFlag{
Name: "authfile",
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
},
}
pushCommand cliconfig.PushValues
pushDescription = fmt.Sprintf(`
Pushes an image to a specified location.
The Image "DESTINATION" uses a "transport":"details" format.
See podman-push(1) section "DESTINATION" for the expected format`)
pushCommand = cli.Command{
Name: "push",
Usage: "Push an image to a specified destination",
Description: pushDescription,
Flags: sortFlags(pushFlags),
Action: pushCmd,
ArgsUsage: "IMAGE DESTINATION",
OnUsageError: usageErrorHandler,
_pushCommand = &cobra.Command{
Use: "push",
Short: "Push an image to a specified destination",
Long: pushDescription,
RunE: func(cmd *cobra.Command, args []string) error {
pushCommand.InputArgs = args
pushCommand.GlobalFlags = MainGlobalOpts
return pushCmd(&pushCommand)
},
Example: "IMAGE DESTINATION",
}
)
func pushCmd(c *cli.Context) error {
func init() {
pushCommand.Command = _pushCommand
flags := pushCommand.Flags()
flags.MarkHidden("signature-policy")
flags.StringVar(&pushCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&pushCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.BoolVar(&pushCommand.Compress, "compress", false, "Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)")
flags.StringVar(&pushCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.StringVarP(&pushCommand.Format, "format", "f", "", "Manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir:' transport (default is manifest type of source)")
flags.BoolVarP(&pushCommand.Quiet, "quiet", "q", false, "Don't output progress information when pushing images")
flags.BoolVar(&pushCommand.RemoveSignatures, "remove-signatures", false, "Discard any pre-existing signatures in the image")
flags.StringVar(&pushCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.StringVar(&pushCommand.SignBy, "sign-by", "", "Add a signature at the destination using the specified key")
flags.BoolVar(&pushCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
rootCmd.AddCommand(pushCommand.Command)
}
func pushCmd(c *cliconfig.PushValues) error {
var (
registryCreds *types.DockerAuthConfig
destName string
)
args := c.Args()
args := c.InputArgs
if len(args) == 0 || len(args) > 2 {
return errors.New("podman push requires at least one image name, and optionally a second to specify a different destination name")
}
@ -94,43 +72,40 @@ func pushCmd(c *cli.Context) error {
case 2:
destName = args[1]
}
if err := validateFlags(c, pushFlags); err != nil {
return err
}
// --compress and --format can only be used for the "dir" transport
splitArg := strings.SplitN(destName, ":", 2)
if c.IsSet("compress") || c.IsSet("format") {
if c.Flag("compress").Changed || c.Flag("format").Changed {
if splitArg[0] != directory.Transport.Name() {
return errors.Errorf("--compress and --format can be set only when pushing to a directory using the 'dir' transport")
}
}
certPath := c.String("cert-dir")
removeSignatures := c.Bool("remove-signatures")
signBy := c.String("sign-by")
certPath := c.CertDir
removeSignatures := c.RemoveSignatures
signBy := c.SignBy
if c.IsSet("creds") {
creds, err := util.ParseRegistryCreds(c.String("creds"))
if c.Flag("creds").Changed {
creds, err := util.ParseRegistryCreds(c.Creds)
if err != nil {
return err
}
registryCreds = creds
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not create runtime")
}
defer runtime.Shutdown(false)
var writer io.Writer
if !c.Bool("quiet") {
if !c.Quiet {
writer = os.Stderr
}
var manifestType string
if c.IsSet("format") {
if c.Flag("format").Changed {
switch c.String("format") {
case "oci":
manifestType = imgspecv1.MediaTypeImageManifest
@ -147,8 +122,8 @@ func pushCmd(c *cli.Context) error {
DockerRegistryCreds: registryCreds,
DockerCertPath: certPath,
}
if c.IsSet("tls-verify") {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
so := image.SigningOptions{
@ -161,7 +136,7 @@ func pushCmd(c *cli.Context) error {
return err
}
authfile := getAuthFile(c.String("authfile"))
authfile := getAuthFile(c.Authfile)
return newImage.PushImageToHeuristicDestination(getContext(), destName, manifestType, authfile, c.String("signature-policy"), writer, c.Bool("compress"), so, &dockerRegistryOptions, nil)
return newImage.PushImageToHeuristicDestination(getContext(), destName, manifestType, authfile, c.SignaturePolicy, writer, c.Compress, so, &dockerRegistryOptions, nil)
}

View file

@ -4,37 +4,38 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
refreshFlags = []cli.Flag{}
refreshCommand cliconfig.RefreshValues
refreshDescription = "The refresh command resets the state of all containers to handle database changes after a Podman upgrade. All running containers will be restarted."
refreshCommand = cli.Command{
Name: "refresh",
Usage: "Refresh container state",
Description: refreshDescription,
Flags: sortFlags(refreshFlags),
Action: refreshCmd,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_refreshCommand = &cobra.Command{
Use: "refresh",
Short: "Refresh container state",
Long: refreshDescription,
RunE: func(cmd *cobra.Command, args []string) error {
refreshCommand.InputArgs = args
refreshCommand.GlobalFlags = MainGlobalOpts
return refreshCmd(&refreshCommand)
},
}
)
func refreshCmd(c *cli.Context) error {
if len(c.Args()) > 0 {
func init() {
refreshCommand.Command = _refreshCommand
rootCmd.AddCommand(refreshCommand.Command)
}
func refreshCmd(c *cliconfig.RefreshValues) error {
if len(c.InputArgs) > 0 {
return errors.Errorf("refresh does not accept any arguments")
}
if err := validateFlags(c, refreshFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}

View file

@ -4,47 +4,45 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
restartFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Restart all non-running containers",
},
cli.BoolFlag{
Name: "running",
Usage: "Restart only running containers when --all is used",
},
cli.UintFlag{
Name: "timeout, time, t",
Usage: "Seconds to wait for stop before killing the container",
Value: libpod.CtrRemoveTimeout,
},
LatestFlag,
}
restartCommand cliconfig.RestartValues
restartDescription = `Restarts one or more running containers. The container ID or name can be used. A timeout before forcibly stopping can be set, but defaults to 10 seconds`
restartCommand = cli.Command{
Name: "restart",
Usage: "Restart one or more containers",
Description: restartDescription,
Flags: sortFlags(restartFlags),
Action: restartCmd,
ArgsUsage: "CONTAINER [CONTAINER ...]",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_restartCommand = &cobra.Command{
Use: "restart",
Short: "Restart one or more containers",
Long: restartDescription,
RunE: func(cmd *cobra.Command, args []string) error {
restartCommand.InputArgs = args
restartCommand.GlobalFlags = MainGlobalOpts
return restartCmd(&restartCommand)
},
Example: "CONTAINER [CONTAINER ...]",
}
)
func restartCmd(c *cli.Context) error {
func init() {
restartCommand.Command = _restartCommand
flags := restartCommand.Flags()
flags.BoolVarP(&restartCommand.All, "all", "a", false, "Restart all non-running containers")
flags.BoolVarP(&restartCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&restartCommand.Running, "running", false, "Restart only running containers when --all is used")
flags.UintVarP(&restartCommand.Timeout, "timeout", "t", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
flags.UintVar(&restartCommand.Timeout, "time", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
rootCmd.AddCommand(restartCommand.Command)
}
func restartCmd(c *cliconfig.RestartValues) error {
var (
restartFuncs []shared.ParallelWorkerInput
containers []*libpod.Container
@ -55,34 +53,31 @@ func restartCmd(c *cli.Context) error {
rootless.SetSkipStorageSetup(true)
}
args := c.Args()
runOnly := c.Bool("running")
all := c.Bool("all")
if len(args) < 1 && !c.Bool("latest") && !all {
args := c.InputArgs
runOnly := c.Running
all := c.All
if len(args) < 1 && !c.Latest && !all {
return errors.Wrapf(libpod.ErrInvalidArg, "you must provide at least one container name or ID")
}
if err := validateFlags(c, restartFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
timeout := c.Uint("timeout")
useTimeout := c.IsSet("timeout")
timeout := c.Timeout
useTimeout := c.Flag("timeout").Changed
// Handle --latest
if c.Bool("latest") {
if c.Latest {
lastCtr, err := runtime.GetLatestContainer()
if err != nil {
return errors.Wrapf(err, "unable to get latest container")
}
restartContainers = append(restartContainers, lastCtr)
} else if runOnly {
containers, err = getAllOrLatestContainers(c, runtime, libpod.ContainerStateRunning, "running")
containers, err = getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
if err != nil {
return err
}
@ -105,7 +100,7 @@ func restartCmd(c *cli.Context) error {
maxWorkers := shared.Parallelize("restart")
if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalInt("max-workers")
maxWorkers = c.GlobalFlags.MaxWorks
}
logrus.Debugf("Setting maximum workers to %d", maxWorkers)

View file

@ -5,68 +5,67 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
restoreCommand cliconfig.RestoreValues
restoreDescription = `
podman container restore
Restores a container from a checkpoint. The container name or ID can be used.
`
restoreFlags = []cli.Flag{
cli.BoolFlag{
Name: "keep, k",
Usage: "Keep all temporary checkpoint files",
_restoreCommand = &cobra.Command{
Use: "restore",
Short: "Restores one or more containers from a checkpoint",
Long: restoreDescription,
RunE: func(cmd *cobra.Command, args []string) error {
restoreCommand.InputArgs = args
restoreCommand.GlobalFlags = MainGlobalOpts
return restoreCmd(&restoreCommand)
},
// restore --all would make more sense if there would be
// dedicated state for container which are checkpointed.
// TODO: add ContainerStateCheckpointed
cli.BoolFlag{
Name: "tcp-established",
Usage: "Checkpoint a container with established TCP connections",
},
cli.BoolFlag{
Name: "all, a",
Usage: "Restore all checkpointed containers",
},
LatestFlag,
}
restoreCommand = cli.Command{
Name: "restore",
Usage: "Restores one or more containers from a checkpoint",
Description: restoreDescription,
Flags: sortFlags(restoreFlags),
Action: restoreCmd,
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
}
)
func restoreCmd(c *cli.Context) error {
func init() {
restoreCommand.Command = _restoreCommand
flags := restoreCommand.Flags()
flags.BoolVarP(&restoreCommand.All, "all", "a", false, "Restore all checkpointed containers")
flags.BoolVarP(&restoreCommand.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
flags.BoolVarP(&restoreCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
// TODO: add ContainerStateCheckpointed
flags.BoolVar(&restoreCommand.TcpEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
rootCmd.AddCommand(restoreCommand.Command)
}
func restoreCmd(c *cliconfig.RestoreValues) error {
if rootless.IsRootless() {
return errors.New("restoring a container requires root")
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
options := libpod.ContainerCheckpointOptions{
Keep: c.Bool("keep"),
TCPEstablished: c.Bool("tcp-established"),
Keep: c.Keep,
TCPEstablished: c.TcpEstablished,
}
if err := checkAllAndLatest(c); err != nil {
if err := checkAllAndLatest(&c.PodmanCommand); err != nil {
return err
}
containers, lastError := getAllOrLatestContainers(c, runtime, libpod.ContainerStateExited, "checkpointed")
containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateExited, "checkpointed")
for _, ctr := range containers {
if err = ctr.Restore(context.TODO(), options); err != nil {

View file

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

View file

@ -4,47 +4,39 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter"
"github.com/containers/storage"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
rmiCommand cliconfig.RmiValues
rmiDescription = "Removes one or more locally stored images."
rmiFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Remove all images",
_rmiCommand = &cobra.Command{
Use: "rmi",
Short: "Removes one or more images from local storage",
Long: rmiDescription,
RunE: func(cmd *cobra.Command, args []string) error {
rmiCommand.InputArgs = args
rmiCommand.GlobalFlags = MainGlobalOpts
return rmiCmd(&rmiCommand)
},
cli.BoolFlag{
Name: "force, f",
Usage: "Force removal of the image",
},
}
rmiCommand = cli.Command{
Name: "rmi",
Usage: "Remove one or more images from local storage",
Description: rmiDescription,
Action: rmiCmd,
ArgsUsage: "IMAGE-NAME-OR-ID [...]",
Flags: sortFlags(rmiFlags),
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
}
rmImageCommand = cli.Command{
Name: "rm",
Usage: "Removes one or more images from local storage",
Description: rmiDescription,
Action: rmiCmd,
ArgsUsage: "IMAGE-NAME-OR-ID [...]",
Flags: rmiFlags,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
Example: "IMAGE-NAME-OR-ID [...]",
}
)
func rmiCmd(c *cli.Context) error {
func init() {
rmiCommand.Command = _rmiCommand
flags := rmiCommand.Flags()
flags.BoolVarP(&rmiCommand.All, "all", "a", false, "Remove all images")
flags.BoolVarP(&rmiCommand.Force, "force", "f", false, "Force Removal of the image")
rootCmd.AddCommand(rmiCommand.Command)
}
func rmiCmd(c *cliconfig.RmiValues) error {
var (
lastError error
deleted bool
@ -53,17 +45,14 @@ func rmiCmd(c *cli.Context) error {
)
ctx := getContext()
if err := validateFlags(c, rmiFlags); err != nil {
return err
}
removeAll := c.Bool("all")
runtime, err := adapter.GetRuntime(c)
removeAll := c.All
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
args := c.Args()
args := c.InputArgs
if len(args) == 0 && !removeAll {
return errors.Errorf("image name or ID must be specified")
}
@ -75,7 +64,7 @@ func rmiCmd(c *cli.Context) error {
removeImage := func(img *adapter.ContainerImage) {
deleted = true
msg, deleteErr = runtime.RemoveImage(ctx, img, c.Bool("force"))
msg, deleteErr = runtime.RemoveImage(ctx, img, c.Force)
if deleteErr != nil {
if errors.Cause(deleteErr) == storage.ErrImageUsedByContainer {
fmt.Printf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID())

View file

@ -8,49 +8,57 @@ import (
"strconv"
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var runDescription = "Runs a command in a new container from the given image"
var (
runCommmand cliconfig.RunValues
var runFlags []cli.Flag = append(createFlags, cli.BoolTFlag{
Name: "sig-proxy",
Usage: "Proxy received signals to the process (default true)",
})
runDescription = "Runs a command in a new container from the given image"
_runCommmand = &cobra.Command{
Use: "run",
Short: "Run a command in a new container",
Long: runDescription,
RunE: func(cmd *cobra.Command, args []string) error {
runCommmand.InputArgs = args
runCommmand.GlobalFlags = MainGlobalOpts
return runCmd(&runCommmand)
},
Example: "IMAGE [COMMAND [ARG...]]",
}
)
var runCommand = cli.Command{
Name: "run",
Usage: "Run a command in a new container",
Description: runDescription,
Flags: sortFlags(runFlags),
Action: runCmd,
ArgsUsage: "IMAGE [COMMAND [ARG...]]",
HideHelp: true,
SkipArgReorder: true,
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
func init() {
runCommmand.Command = _runCommmand
flags := runCommmand.Flags()
flags.SetInterspersed(false)
flags.Bool("sig-proxy", true, "Proxy received signals to the process (default true)")
getCreateFlags(&runCommmand.PodmanCommand)
rootCmd.AddCommand(runCommmand.Command)
}
func runCmd(c *cli.Context) error {
if err := createInit(c); err != nil {
func runCmd(c *cliconfig.RunValues) error {
if err := createInit(&c.PodmanCommand); err != nil {
return err
}
if os.Geteuid() != 0 {
rootless.SetSkipStorageSetup(true)
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
ctr, createConfig, err := createContainer(c, runtime)
ctr, createConfig, err := createContainer(&c.PodmanCommand, runtime)
if err != nil {
return err
}
@ -110,7 +118,7 @@ func runCmd(c *cli.Context) error {
}
}
}
if err := startAttachCtr(ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.BoolT("sig-proxy"), true); err != nil {
if err := startAttachCtr(ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true); err != nil {
// This means the command did not exist
exitCode = 127
if strings.Index(err.Error(), "permission denied") > -1 {

View file

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

View file

@ -7,88 +7,59 @@ import (
"strings"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/utils"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
runlabelFlags = []cli.Flag{
cli.StringFlag{
Name: "authfile",
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
},
cli.BoolFlag{
Name: "display",
Usage: "Preview the command that the label would run",
},
cli.StringFlag{
Name: "cert-dir",
Usage: "`Pathname` of a directory containing TLS certificates and keys",
},
cli.StringFlag{
Name: "creds",
Usage: "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
},
cli.StringFlag{
Name: "name",
Usage: "Assign a name to the container",
},
cli.StringFlag{
Name: "opt1",
Usage: "Optional parameter to pass for install",
Hidden: true,
},
cli.StringFlag{
Name: "opt2",
Usage: "Optional parameter to pass for install",
Hidden: true,
},
cli.StringFlag{
Name: "opt3",
Usage: "Optional parameter to pass for install",
Hidden: true,
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Suppress output information when installing images",
},
cli.BoolFlag{
Name: "pull, p",
Usage: "Pull the image if it does not exist locally prior to executing the label contents",
},
cli.StringFlag{
Name: "signature-policy",
Usage: "`Pathname` of signature policy file (not usually used)",
},
cli.BoolTFlag{
Name: "tls-verify",
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
},
}
runlabelCommand cliconfig.RunlabelValues
runlabelDescription = `
Executes a command as described by a container image label.
`
runlabelCommand = cli.Command{
Name: "runlabel",
Usage: "Execute the command described by an image label",
Description: runlabelDescription,
Flags: sortFlags(runlabelFlags),
Action: runlabelCmd,
ArgsUsage: "",
SkipArgReorder: true,
OnUsageError: usageErrorHandler,
_runlabelCommand = &cobra.Command{
Use: "runlabel",
Short: "Execute the command described by an image label",
Long: runlabelDescription,
RunE: func(cmd *cobra.Command, args []string) error {
runlabelCommand.InputArgs = args
runlabelCommand.GlobalFlags = MainGlobalOpts
return runlabelCmd(&runlabelCommand)
},
Example: "",
}
)
func init() {
runlabelCommand.Command = _runlabelCommand
flags := runlabelCommand.Flags()
flags.StringVar(&runlabelCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&runlabelCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.StringVar(&runlabelCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
flags.BoolVar(&runlabelCommand.Display, "display", false, "Preview the command that the label would run")
flags.StringVar(&runlabelCommand.Name, "name", "", "Assign a name to the container")
flags.StringVar(&runlabelCommand.Opt1, "opt1", "", "Optional parameter to pass for install")
flags.StringVar(&runlabelCommand.Opt2, "opt2", "", "Optional parameter to pass for install")
flags.StringVar(&runlabelCommand.Opt3, "opt3", "", "Optional parameter to pass for install")
flags.MarkHidden("opt1")
flags.MarkHidden("opt3")
flags.MarkHidden("opt3")
flags.BoolVarP(&runlabelCommand.Pull, "pull", "p", false, "Pull the image if it does not exist locally prior to executing the label contents")
flags.BoolVarP(&runlabelCommand.Quiet, "quiet", "q", false, "Suppress output information when installing images")
flags.StringVar(&runlabelCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.BoolVar(&runlabelCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
}
// installCmd gets the data from the command line and calls installImage
// to copy an image from a registry to a local machine
func runlabelCmd(c *cli.Context) error {
func runlabelCmd(c *cliconfig.RunlabelValues) error {
var (
imageName string
stdErr, stdOut io.Writer
@ -105,40 +76,38 @@ func runlabelCmd(c *cli.Context) error {
}
opts := make(map[string]string)
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
args := c.Args()
args := c.InputArgs
if len(args) < 2 {
logrus.Errorf("the runlabel command requires at least 2 arguments: LABEL IMAGE")
return nil
}
if err := validateFlags(c, runlabelFlags); err != nil {
return err
}
if c.Bool("display") && c.Bool("quiet") {
if c.Display && c.Quiet {
return errors.Errorf("the display and quiet flags cannot be used together.")
}
if len(args) > 2 {
extraArgs = args[2:]
}
pull := c.Bool("pull")
pull := c.Pull
label := args[0]
runlabelImage := args[1]
if c.IsSet("opt1") {
opts["opt1"] = c.String("opt1")
if c.Flag("opt1").Changed {
opts["opt1"] = c.Opt1
}
if c.IsSet("opt2") {
opts["opt2"] = c.String("opt2")
if c.Flag("opt2").Changed {
opts["opt2"] = c.Opt2
}
if c.IsSet("opt3") {
opts["opt3"] = c.String("opt3")
if c.Flag("opt3").Changed {
opts["opt3"] = c.Opt3
}
ctx := getContext()
@ -147,21 +116,21 @@ func runlabelCmd(c *cli.Context) error {
stdOut = os.Stdout
stdIn = os.Stdin
if c.Bool("quiet") {
if c.Quiet {
stdErr = nil
stdOut = nil
stdIn = nil
}
dockerRegistryOptions := image.DockerRegistryOptions{
DockerCertPath: c.String("cert-dir"),
DockerCertPath: c.CertDir,
}
if c.IsSet("tls-verify") {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
if c.Flag("tls-verify").Changed {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
authfile := getAuthFile(c.String("authfile"))
runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, pull, c.String("creds"), dockerRegistryOptions, authfile, c.String("signature-policy"), stdOut)
authfile := getAuthFile(c.Authfile)
runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, pull, c.Creds, dockerRegistryOptions, authfile, c.SignaturePolicy, stdOut)
if err != nil {
return err
}
@ -169,13 +138,13 @@ func runlabelCmd(c *cli.Context) error {
return errors.Errorf("%s does not have a label of %s", runlabelImage, label)
}
cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, c.String("name"), opts, extraArgs)
cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, c.Name, opts, extraArgs)
if err != nil {
return err
}
if !c.Bool("quiet") {
if !c.Quiet {
fmt.Printf("Command: %s\n", strings.Join(cmd, " "))
if c.Bool("display") {
if c.Display {
return nil
}
}

View file

@ -12,12 +12,13 @@ import (
"github.com/containers/image/manifest"
ociarchive "github.com/containers/image/oci/archive"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
libpodImage "github.com/containers/libpod/libpod/image"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
const (
@ -26,67 +27,58 @@ const (
)
var (
saveFlags = []cli.Flag{
cli.BoolFlag{
Name: "compress",
Usage: "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)",
},
cli.StringFlag{
Name: "output, o",
Usage: "Write to a file, default is STDOUT",
Value: "/dev/stdout",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "Suppress the output",
},
cli.StringFlag{
Name: "format",
Usage: "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-dir (directory with v2s2 manifest type)",
},
}
saveCommand cliconfig.SaveValues
saveDescription = `
Save an image to docker-archive or oci-archive on the local machine.
Default is docker-archive`
saveCommand = cli.Command{
Name: "save",
Usage: "Save image to an archive",
Description: saveDescription,
Flags: sortFlags(saveFlags),
Action: saveCmd,
ArgsUsage: "",
SkipArgReorder: true,
OnUsageError: usageErrorHandler,
_saveCommand = &cobra.Command{
Use: "save",
Short: "Save image to an archive",
Long: saveDescription,
RunE: func(cmd *cobra.Command, args []string) error {
saveCommand.InputArgs = args
saveCommand.GlobalFlags = MainGlobalOpts
return saveCmd(&saveCommand)
},
Example: "",
}
)
func init() {
saveCommand.Command = _saveCommand
flags := saveCommand.Flags()
flags.BoolVar(&saveCommand.Compress, "compress", false, "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)")
flags.StringVar(&saveCommand.Format, "format", "", "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-dir (directory with v2s2 manifest type)")
flags.StringVarP(&saveCommand.Output, "output", "o", "/dev/stdout", "Write to a file, default is STDOUT")
flags.BoolVarP(&saveCommand.Quiet, "quiet", "q", false, "Suppress the output")
rootCmd.AddCommand(saveCommand.Command)
}
// saveCmd saves the image to either docker-archive or oci
func saveCmd(c *cli.Context) error {
args := c.Args()
func saveCmd(c *cliconfig.SaveValues) error {
args := c.InputArgs
if len(args) == 0 {
return errors.Errorf("need at least 1 argument")
}
if err := validateFlags(c, saveFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not create runtime")
}
defer runtime.Shutdown(false)
if c.IsSet("compress") && (c.String("format") != ociManifestDir && c.String("format") != v2s2ManifestDir && c.String("format") == "") {
if c.Flag("compress").Changed && (c.Format != ociManifestDir && c.Format != v2s2ManifestDir && c.Format == "") {
return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'")
}
var writer io.Writer
if !c.Bool("quiet") {
if !c.Quiet {
writer = os.Stderr
}
output := c.String("output")
output := c.Output
if output == "/dev/stdout" {
fi := os.Stdout
if logrus.IsTerminal(fi) {
@ -105,7 +97,7 @@ func saveCmd(c *cli.Context) error {
var destRef types.ImageReference
var manifestType string
switch c.String("format") {
switch c.Format {
case "oci-archive":
destImageName := imageNameForSaveDestination(newImage, source)
destRef, err = ociarchive.NewReference(output, destImageName) // destImageName may be ""

View file

@ -8,13 +8,14 @@ import (
"github.com/containers/image/docker"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/libpod/common"
sysreg "github.com/containers/libpod/pkg/registries"
"github.com/docker/distribution/reference"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
const (
@ -23,46 +24,36 @@ const (
)
var (
searchFlags = []cli.Flag{
cli.StringFlag{
Name: "authfile",
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ",
},
cli.StringSliceFlag{
Name: "filter, f",
Usage: "Filter output based on conditions provided (default [])",
},
cli.StringFlag{
Name: "format",
Usage: "Change the output format to a Go template",
},
cli.IntFlag{
Name: "limit",
Usage: "Limit the number of results",
},
cli.BoolFlag{
Name: "no-trunc",
Usage: "Do not truncate the output",
},
cli.BoolTFlag{
Name: "tls-verify",
Usage: "Require HTTPS and verify certificates when contacting registries (default: true)",
},
}
searchCommand cliconfig.SearchValues
searchDescription = `
Search registries for a given image. Can search all the default registries or a specific registry.
Can limit the number of results, and filter the output based on certain conditions.`
searchCommand = cli.Command{
Name: "search",
Usage: "Search registry for image",
Description: searchDescription,
Flags: sortFlags(searchFlags),
Action: searchCmd,
ArgsUsage: "TERM",
OnUsageError: usageErrorHandler,
_searchCommand = &cobra.Command{
Use: "search",
Short: "Search registry for image",
Long: searchDescription,
RunE: func(cmd *cobra.Command, args []string) error {
searchCommand.InputArgs = args
searchCommand.GlobalFlags = MainGlobalOpts
return searchCmd(&searchCommand)
},
Example: "TERM",
}
)
func init() {
searchCommand.Command = _searchCommand
flags := searchCommand.Flags()
flags.StringVar(&searchCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringSliceVarP(&searchCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
flags.StringVar(&searchCommand.Format, "format", "", "Change the output format to a Go template")
flags.IntVar(&searchCommand.Limit, "limit", 0, "Limit the number of results")
flags.BoolVar(&searchCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
flags.BoolVar(&searchCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
rootCmd.AddCommand(searchCommand.Command)
}
type searchParams struct {
Index string
Name string
@ -87,8 +78,8 @@ type searchFilterParams struct {
isOfficial *bool
}
func searchCmd(c *cli.Context) error {
args := c.Args()
func searchCmd(c *cliconfig.SearchValues) error {
args := c.InputArgs
if len(args) > 1 {
return errors.Errorf("too many arguments. Requires exactly 1")
}
@ -106,20 +97,16 @@ func searchCmd(c *cli.Context) error {
term = term[len(registry)+1:]
}
if err := validateFlags(c, searchFlags); err != nil {
return err
}
format := genSearchFormat(c.String("format"))
format := genSearchFormat(c.Format)
opts := searchOpts{
format: format,
noTrunc: c.Bool("no-trunc"),
limit: c.Int("limit"),
filter: c.StringSlice("filter"),
authfile: getAuthFile(c.String("authfile")),
noTrunc: c.NoTrunc,
limit: c.Limit,
filter: c.Filter,
authfile: getAuthFile(c.Authfile),
}
if c.IsSet("tls-verify") {
opts.insecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
if c.Flag("tls-verify").Changed {
opts.insecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
registries, err := getRegistries(registry)
if err != nil {

View file

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

View file

@ -5,84 +5,75 @@ import (
"fmt"
"os"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
cc "github.com/containers/libpod/pkg/spec"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
startFlags = []cli.Flag{
cli.BoolFlag{
Name: "attach, a",
Usage: "Attach container's STDOUT and STDERR",
},
cli.StringFlag{
Name: "detach-keys",
Usage: "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _.",
},
cli.BoolFlag{
Name: "interactive, i",
Usage: "Keep STDIN open even if not attached",
},
cli.BoolTFlag{
Name: "sig-proxy",
Usage: "Proxy received signals to the process (default true if attaching, false otherwise)",
},
LatestFlag,
}
startCommand cliconfig.StartValues
startDescription = `
podman start
Starts one or more containers. The container name or ID can be used.
`
startCommand = cli.Command{
Name: "start",
Usage: "Start one or more containers",
Description: startDescription,
Flags: sortFlags(startFlags),
Action: startCmd,
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
_startCommand = &cobra.Command{
Use: "start",
Short: "Start one or more containers",
Long: startDescription,
RunE: func(cmd *cobra.Command, args []string) error {
startCommand.InputArgs = args
startCommand.GlobalFlags = MainGlobalOpts
return startCmd(&startCommand)
},
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
}
)
func startCmd(c *cli.Context) error {
args := c.Args()
if len(args) < 1 && !c.Bool("latest") {
func init() {
startCommand.Command = _startCommand
flags := startCommand.Flags()
flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
flags.StringVar(&startCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&startCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true if attaching, false otherwise)")
rootCmd.AddCommand(startCommand.Command)
}
func startCmd(c *cliconfig.StartValues) error {
args := c.InputArgs
if len(args) < 1 && !c.Latest {
return errors.Errorf("you must provide at least one container name or id")
}
attach := c.Bool("attach")
attach := c.Attach
if len(args) > 1 && attach {
return errors.Errorf("you cannot start and attach multiple containers at once")
}
if err := validateFlags(c, startFlags); err != nil {
return err
}
sigProxy := c.BoolT("sig-proxy")
sigProxy := c.SigProxy
if sigProxy && !attach {
if c.IsSet("sig-proxy") {
if c.Flag("sig-proxy").Changed {
return errors.Wrapf(libpod.ErrInvalidArg, "you cannot use sig-proxy without --attach")
} else {
sigProxy = false
}
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
if c.Bool("latest") {
if c.Latest {
lastCtr, err := runtime.GetLatestContainer()
if err != nil {
return errors.Wrapf(err, "unable to get latest container")
@ -112,12 +103,12 @@ func startCmd(c *cli.Context) error {
if attach {
inputStream := os.Stdin
if !c.Bool("interactive") {
if !c.Interactive {
inputStream = nil
}
// attach to the container and also start it not already running
err = startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.String("detach-keys"), sigProxy, !ctrRunning)
err = startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, sigProxy, !ctrRunning)
if ctrRunning {
return err
}

View file

@ -8,12 +8,13 @@ import (
"time"
tm "github.com/buger/goterm"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
type statsOutputParams struct {
@ -28,48 +29,41 @@ type statsOutputParams struct {
}
var (
statsFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Show all containers. Only running containers are shown by default. The default is false",
},
cli.BoolFlag{
Name: "no-stream",
Usage: "Disable streaming stats and only pull the first result, default setting is false",
},
cli.StringFlag{
Name: "format",
Usage: "Pretty-print container statistics to JSON or using a Go template",
},
cli.BoolFlag{
Name: "no-reset",
Usage: "Disable resetting the screen between intervals",
}, LatestFlag,
}
statsCommand cliconfig.StatsValues
statsDescription = "Display a live stream of one or more containers' resource usage statistics"
statsCommand = cli.Command{
Name: "stats",
Usage: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers",
Description: statsDescription,
Flags: sortFlags(statsFlags),
Action: statsCmd,
ArgsUsage: "",
OnUsageError: usageErrorHandler,
statsDescription = "display a live stream of one or more containers' resource usage statistics"
_statsCommand = &cobra.Command{
Use: "stats",
Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers",
Long: statsDescription,
RunE: func(cmd *cobra.Command, args []string) error {
statsCommand.InputArgs = args
statsCommand.GlobalFlags = MainGlobalOpts
return statsCmd(&statsCommand)
},
Example: "",
}
)
func statsCmd(c *cli.Context) error {
if err := validateFlags(c, statsFlags); err != nil {
return err
}
func init() {
statsCommand.Command = _statsCommand
flags := statsCommand.Flags()
flags.BoolVarP(&statsCommand.All, "all", "a", false, "Show all containers. Only running containers are shown by default. The default is false")
flags.StringVar(&statsCommand.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template")
flags.BoolVarP(&statsCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&statsCommand.NoReset, "no-reset", false, "Disable resetting the screen between intervals")
flags.BoolVar(&statsCommand.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false")
rootCmd.AddCommand(statsCommand.Command)
}
func statsCmd(c *cliconfig.StatsValues) error {
if os.Geteuid() != 0 {
return errors.New("stats is not supported for rootless containers")
}
all := c.Bool("all")
latest := c.Bool("latest")
all := c.All
latest := c.Latest
ctr := 0
if all {
ctr += 1
@ -77,7 +71,7 @@ func statsCmd(c *cli.Context) error {
if latest {
ctr += 1
}
if len(c.Args()) > 0 {
if len(c.InputArgs) > 0 {
ctr += 1
}
@ -87,14 +81,14 @@ func statsCmd(c *cli.Context) error {
return errors.Errorf("you must specify --all, --latest, or at least one container")
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
times := -1
if c.Bool("no-stream") {
if c.NoStream {
times = 1
}
@ -102,8 +96,8 @@ func statsCmd(c *cli.Context) error {
var containerFunc func() ([]*libpod.Container, error)
containerFunc = runtime.GetRunningContainers
if len(c.Args()) > 0 {
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.Args()) }
if len(c.InputArgs) > 0 {
containerFunc = func() ([]*libpod.Container, error) { return runtime.GetContainersByList(c.InputArgs) }
} else if latest {
containerFunc = func() ([]*libpod.Container, error) {
lastCtr, err := runtime.GetLatestContainer()
@ -126,7 +120,7 @@ func statsCmd(c *cli.Context) error {
initialStats, err := ctr.GetContainerStats(&libpod.ContainerStats{})
if err != nil {
// when doing "all", dont worry about containers that are not running
if c.Bool("all") && errors.Cause(err) == libpod.ErrCtrRemoved || errors.Cause(err) == libpod.ErrNoSuchCtr || errors.Cause(err) == libpod.ErrCtrStateInvalid {
if c.All && errors.Cause(err) == libpod.ErrCtrRemoved || errors.Cause(err) == libpod.ErrNoSuchCtr || errors.Cause(err) == libpod.ErrCtrStateInvalid {
continue
}
return err
@ -134,7 +128,7 @@ func statsCmd(c *cli.Context) error {
containerStats[ctr.ID()] = initialStats
}
format := genStatsFormat(c.String("format"))
format := genStatsFormat(c.Format)
step := 1
if times == -1 {
@ -168,7 +162,7 @@ func statsCmd(c *cli.Context) error {
if err != nil {
return err
}
if strings.ToLower(format) != formats.JSONString && !c.Bool("no-reset") {
if strings.ToLower(format) != formats.JSONString && !c.NoReset {
tm.Clear()
tm.MoveCursor(1, 1)
tm.Flush()

View file

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

View file

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

View file

@ -6,50 +6,50 @@ import (
"os"
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
pruneSystemCommand cliconfig.SystemPruneValues
pruneSystemDescription = `
podman system prune
Remove unused data
`
pruneSystemFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Remove all unused data",
_pruneSystemCommand = &cobra.Command{
Use: "prune",
Short: "Remove unused data",
Long: pruneSystemDescription,
RunE: func(cmd *cobra.Command, args []string) error {
pruneSystemCommand.InputArgs = args
pruneSystemCommand.GlobalFlags = MainGlobalOpts
return pruneSystemCmd(&pruneSystemCommand)
},
cli.BoolFlag{
Name: "force, f",
Usage: "Do not prompt for confirmation",
},
cli.BoolFlag{
Name: "volumes",
Usage: "Prune volumes",
},
}
pruneSystemCommand = cli.Command{
Name: "prune",
Usage: "Remove unused data",
Description: pruneSystemDescription,
Action: pruneSystemCmd,
OnUsageError: usageErrorHandler,
Flags: pruneSystemFlags,
}
)
func pruneSystemCmd(c *cli.Context) error {
func init() {
pruneSystemCommand.Command = _pruneSystemCommand
flags := pruneSystemCommand.Flags()
flags.BoolVarP(&pruneSystemCommand.All, "all", "a", false, "Remove all unused data")
flags.BoolVarP(&pruneSystemCommand.Force, "force", "f", false, "Do not prompt for confirmation")
flags.BoolVar(&pruneSystemCommand.Volume, "volumes", false, "Prune volumes")
}
func pruneSystemCmd(c *cliconfig.SystemPruneValues) error {
// Prompt for confirmation if --force is not set
if !c.Bool("force") {
if !c.Force {
reader := bufio.NewReader(os.Stdin)
volumeString := ""
if c.Bool("volumes") {
if c.Volume {
volumeString = `
- all volumes not used by at least one container`
}
@ -68,7 +68,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
}
}
runtime, err := adapter.GetRuntime(c)
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
@ -90,7 +90,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
// Call prune; if any cids are returned, print them and then
// return err in case an error also came up
pruneCids, err := runtime.PruneImages(c.Bool("all"))
pruneCids, err := runtime.PruneImages(c.All)
if len(pruneCids) > 0 {
fmt.Println("Deleted Images")
for _, cid := range pruneCids {

View file

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

View file

@ -6,11 +6,12 @@ import (
"strings"
"text/tabwriter"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
func getDescriptorString() string {
@ -24,13 +25,7 @@ Format Descriptors:
}
var (
topFlags = []cli.Flag{
LatestFlag,
cli.BoolFlag{
Name: "list-descriptors",
Hidden: true,
},
}
topCommand cliconfig.TopValues
topDescription = fmt.Sprintf(`Display the running processes of the container. Specify format descriptors
to alter the output. You may run "podman top -l pid pcpu seccomp" to print
the process ID, the CPU percentage and the seccomp mode of each process of
@ -38,24 +33,35 @@ the latest container.
%s
`, getDescriptorString())
topCommand = cli.Command{
Name: "top",
Usage: "Display the running processes of a container",
Description: topDescription,
Flags: sortFlags(topFlags),
Action: topCmd,
ArgsUsage: "CONTAINER-NAME [format descriptors]",
SkipArgReorder: true,
OnUsageError: usageErrorHandler,
_topCommand = &cobra.Command{
Use: "top",
Short: "Display the running processes of a container",
Long: topDescription,
RunE: func(cmd *cobra.Command, args []string) error {
topCommand.InputArgs = args
topCommand.GlobalFlags = MainGlobalOpts
return topCmd(&topCommand)
},
Example: "CONTAINER-NAME [format descriptors]",
}
)
func topCmd(c *cli.Context) error {
func init() {
topCommand.Command = _topCommand
flags := topCommand.Flags()
flags.BoolVar(&topCommand.ListDescriptors, "list-descriptors", false, "")
flags.MarkHidden("list-descriptors")
flags.BoolVarP(&topCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
rootCmd.AddCommand(topCommand.Command)
}
func topCmd(c *cliconfig.TopValues) error {
var container *libpod.Container
var err error
args := c.Args()
args := c.InputArgs
if c.Bool("list-descriptors") {
if c.ListDescriptors {
descriptors, err := libpod.GetContainerPidInformationDescriptors()
if err != nil {
return err
@ -64,22 +70,19 @@ func topCmd(c *cli.Context) error {
return nil
}
if len(args) < 1 && !c.Bool("latest") {
if len(args) < 1 && !c.Latest {
return errors.Errorf("you must provide the name or id of a running container")
}
if err := validateFlags(c, topFlags); err != nil {
return err
}
rootless.SetSkipStorageSetup(true)
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
var descriptors []string
if c.Bool("latest") {
if c.Latest {
descriptors = args
container, err = runtime.GetLatestContainer()
} else {

View file

@ -1,369 +1,21 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/trust"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
)
var (
setTrustFlags = []cli.Flag{
cli.StringFlag{
Name: "type, t",
Usage: "Trust type, accept values: signedBy(default), accept, reject.",
Value: "signedBy",
trustCommand = cliconfig.PodmanCommand{
Command: &cobra.Command{
Use: "trust",
Short: "Manage container image trust policy",
Long: "podman image trust command",
},
cli.StringSliceFlag{
Name: "pubkeysfile, f",
Usage: `Path of installed public key(s) to trust for TARGET.
Absolute path to keys is added to policy.json. May
used multiple times to define multiple public keys.
File(s) must exist before using this command.`,
},
cli.StringFlag{
Name: "policypath",
Hidden: true,
},
}
showTrustFlags = []cli.Flag{
cli.BoolFlag{
Name: "raw",
Usage: "Output raw policy file",
},
cli.BoolFlag{
Name: "json, j",
Usage: "Output as json",
},
cli.StringFlag{
Name: "policypath",
Hidden: true,
},
cli.StringFlag{
Name: "registrypath",
Hidden: true,
},
}
setTrustDescription = "Set default trust policy or add a new trust policy for a registry"
setTrustCommand = cli.Command{
Name: "set",
Usage: "Set default trust policy or a new trust policy for a registry",
Description: setTrustDescription,
Flags: sortFlags(setTrustFlags),
ArgsUsage: "default | REGISTRY[/REPOSITORY]",
Action: setTrustCmd,
OnUsageError: usageErrorHandler,
}
showTrustDescription = "Display trust policy for the system"
showTrustCommand = cli.Command{
Name: "show",
Usage: "Display trust policy for the system",
Description: showTrustDescription,
Flags: sortFlags(showTrustFlags),
Action: showTrustCmd,
ArgsUsage: "",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
}
trustSubCommands = []cli.Command{
setTrustCommand,
showTrustCommand,
}
trustDescription = fmt.Sprintf(`Manages the trust policy of the host system. (%s)
Trust policy describes a registry scope that must be signed by public keys.`, getDefaultPolicyPath())
trustCommand = cli.Command{
Name: "trust",
Usage: "Manage container image trust policy",
Description: trustDescription,
ArgsUsage: "{set,show} ...",
Subcommands: trustSubCommands,
OnUsageError: usageErrorHandler,
}
)
func showTrustCmd(c *cli.Context) error {
runtime, err := libpodruntime.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "could not create runtime")
}
var (
policyPath string
systemRegistriesDirPath string
outjson interface{}
)
if c.IsSet("policypath") {
policyPath = c.String("policypath")
} else {
policyPath = trust.DefaultPolicyPath(runtime.SystemContext())
}
policyContent, err := ioutil.ReadFile(policyPath)
if err != nil {
return errors.Wrapf(err, "unable to read %s", policyPath)
}
if c.IsSet("registrypath") {
systemRegistriesDirPath = c.String("registrypath")
} else {
systemRegistriesDirPath = trust.RegistriesDirPath(runtime.SystemContext())
}
if c.Bool("raw") {
_, err := os.Stdout.Write(policyContent)
if err != nil {
return errors.Wrap(err, "could not read trust policies")
}
return nil
}
policyContentStruct, err := trust.GetPolicy(policyPath)
if err != nil {
return errors.Wrapf(err, "could not read trust policies")
}
if c.Bool("json") {
policyJSON, err := getPolicyJSON(policyContentStruct, systemRegistriesDirPath)
if err != nil {
return errors.Wrapf(err, "could not show trust policies in JSON format")
}
outjson = policyJSON
out := formats.JSONStruct{Output: outjson}
return formats.Writer(out).Out()
}
showOutputMap, err := getPolicyShowOutput(policyContentStruct, systemRegistriesDirPath)
if err != nil {
return errors.Wrapf(err, "could not show trust policies")
}
out := formats.StdoutTemplateArray{Output: showOutputMap, Template: "{{.Repo}}\t{{.Trusttype}}\t{{.GPGid}}\t{{.Sigstore}}"}
return formats.Writer(out).Out()
}
func setTrustCmd(c *cli.Context) error {
runtime, err := libpodruntime.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "could not create runtime")
}
var (
policyPath string
policyContentStruct trust.PolicyContent
newReposContent []trust.RepoContent
)
args := c.Args()
if len(args) != 1 {
return errors.Errorf("default or a registry name must be specified")
}
valid, err := image.IsValidImageURI(args[0])
if err != nil || !valid {
return errors.Wrapf(err, "invalid image uri %s", args[0])
}
trusttype := c.String("type")
if !isValidTrustType(trusttype) {
return errors.Errorf("invalid choice: %s (choose from 'accept', 'reject', 'signedBy')", trusttype)
}
if trusttype == "accept" {
trusttype = "insecureAcceptAnything"
}
pubkeysfile := c.StringSlice("pubkeysfile")
if len(pubkeysfile) == 0 && trusttype == "signedBy" {
return errors.Errorf("At least one public key must be defined for type 'signedBy'")
}
if c.IsSet("policypath") {
policyPath = c.String("policypath")
} else {
policyPath = trust.DefaultPolicyPath(runtime.SystemContext())
}
_, err = os.Stat(policyPath)
if !os.IsNotExist(err) {
policyContent, err := ioutil.ReadFile(policyPath)
if err != nil {
return errors.Wrapf(err, "unable to read %s", policyPath)
}
if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil {
return errors.Errorf("could not read trust policies")
}
}
if len(pubkeysfile) != 0 {
for _, filepath := range pubkeysfile {
newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype, KeyType: "GPGKeys", KeyPath: filepath})
}
} else {
newReposContent = append(newReposContent, trust.RepoContent{Type: trusttype})
}
if args[0] == "default" {
policyContentStruct.Default = newReposContent
} else {
if len(policyContentStruct.Default) == 0 {
return errors.Errorf("Default trust policy must be set.")
}
registryExists := false
for transport, transportval := range policyContentStruct.Transports {
_, registryExists = transportval[args[0]]
if registryExists {
policyContentStruct.Transports[transport][args[0]] = newReposContent
break
}
}
if !registryExists {
if policyContentStruct.Transports == nil {
policyContentStruct.Transports = make(map[string]trust.RepoMap)
}
if policyContentStruct.Transports["docker"] == nil {
policyContentStruct.Transports["docker"] = make(map[string][]trust.RepoContent)
}
policyContentStruct.Transports["docker"][args[0]] = append(policyContentStruct.Transports["docker"][args[0]], newReposContent...)
}
}
data, err := json.MarshalIndent(policyContentStruct, "", " ")
if err != nil {
return errors.Wrapf(err, "error setting trust policy")
}
err = ioutil.WriteFile(policyPath, data, 0644)
if err != nil {
return errors.Wrapf(err, "error setting trust policy")
}
return nil
}
func sortShowOutputMapKey(m map[string]trust.ShowOutput) []string {
keys := make([]string, len(m))
i := 0
for k := range m {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}
func isValidTrustType(t string) bool {
if t == "accept" || t == "insecureAcceptAnything" || t == "reject" || t == "signedBy" {
return true
}
return false
}
func getDefaultPolicyPath() string {
return trust.DefaultPolicyPath(&types.SystemContext{})
}
func getPolicyJSON(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) (map[string]map[string]interface{}, error) {
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
if err != nil {
return nil, err
}
policyJSON := make(map[string]map[string]interface{})
if len(policyContentStruct.Default) > 0 {
policyJSON["* (default)"] = make(map[string]interface{})
policyJSON["* (default)"]["type"] = policyContentStruct.Default[0].Type
}
for transname, transval := range policyContentStruct.Transports {
for repo, repoval := range transval {
policyJSON[repo] = make(map[string]interface{})
policyJSON[repo]["type"] = repoval[0].Type
policyJSON[repo]["transport"] = transname
keyarr := []string{}
uids := []string{}
for _, repoele := range repoval {
if len(repoele.KeyPath) > 0 {
keyarr = append(keyarr, repoele.KeyPath)
uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...)
}
if len(repoele.KeyData) > 0 {
keyarr = append(keyarr, string(repoele.KeyData))
uids = append(uids, trust.GetGPGIdFromKeyData(string(repoele.KeyData))...)
}
}
policyJSON[repo]["keys"] = keyarr
policyJSON[repo]["sigstore"] = ""
registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs)
if registryNamespace != nil {
policyJSON[repo]["sigstore"] = registryNamespace.SigStore
}
}
}
return policyJSON, nil
}
var typeDescription = map[string]string{"insecureAcceptAnything": "accept", "signedBy": "signed", "reject": "reject"}
func trustTypeDescription(trustType string) string {
trustDescription, exist := typeDescription[trustType]
if !exist {
logrus.Warnf("invalid trust type %s", trustType)
}
return trustDescription
}
func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]interface{}, error) {
var output []interface{}
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
if err != nil {
return nil, err
}
trustShowOutputMap := make(map[string]trust.ShowOutput)
if len(policyContentStruct.Default) > 0 {
defaultPolicyStruct := trust.ShowOutput{
Repo: "default",
Trusttype: trustTypeDescription(policyContentStruct.Default[0].Type),
}
trustShowOutputMap["* (default)"] = defaultPolicyStruct
}
for _, transval := range policyContentStruct.Transports {
for repo, repoval := range transval {
tempTrustShowOutput := trust.ShowOutput{
Repo: repo,
Trusttype: repoval[0].Type,
}
keyarr := []string{}
uids := []string{}
for _, repoele := range repoval {
if len(repoele.KeyPath) > 0 {
keyarr = append(keyarr, repoele.KeyPath)
uids = append(uids, trust.GetGPGIdFromKeyPath(repoele.KeyPath)...)
}
if len(repoele.KeyData) > 0 {
keyarr = append(keyarr, string(repoele.KeyData))
uids = append(uids, trust.GetGPGIdFromKeyData(string(repoele.KeyData))...)
}
}
tempTrustShowOutput.GPGid = strings.Join(uids, ", ")
registryNamespace := trust.HaveMatchRegistry(repo, registryConfigs)
if registryNamespace != nil {
tempTrustShowOutput.Sigstore = registryNamespace.SigStore
}
trustShowOutputMap[repo] = tempTrustShowOutput
}
}
sortedRepos := sortShowOutputMapKey(trustShowOutputMap)
for _, reponame := range sortedRepos {
showOutput, exists := trustShowOutputMap[reponame]
if exists {
output = append(output, interface{}(showOutput))
}
}
return output, nil
func init() {
trustCommand.AddCommand(getTrustSubCommands()...)
imageCommand.AddCommand(trustCommand.Command)
}

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,20 +6,41 @@ import (
"text/tabwriter"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/libpod"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
versionCommand cliconfig.VersionValues
_versionCommand = &cobra.Command{
Use: "version",
Short: "Display the Podman Version Information",
RunE: func(cmd *cobra.Command, args []string) error {
versionCommand.InputArgs = args
versionCommand.GlobalFlags = MainGlobalOpts
return versionCmd(&versionCommand)
},
}
)
func init() {
versionCommand.Command = _versionCommand
flags := versionCommand.Flags()
flags.StringVarP(&versionCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
rootCmd.AddCommand(versionCommand.Command)
}
// versionCmd gets and prints version info for version command
func versionCmd(c *cli.Context) error {
func versionCmd(c *cliconfig.VersionValues) error {
output, err := libpod.GetVersion()
if err != nil {
errors.Wrapf(err, "unable to determine version")
}
versionOutputFormat := c.String("format")
versionOutputFormat := c.Format
if versionOutputFormat != "" {
var out formats.Writer
switch versionOutputFormat {
@ -46,19 +67,3 @@ func versionCmd(c *cli.Context) error {
fmt.Fprintf(w, "OS/Arch:\t%s\n", output.OsArch)
return nil
}
// Cli command to print out the full version of podman
var (
versionCommand = cli.Command{
Name: "version",
Usage: "Display the Podman Version Information",
Action: versionCmd,
Flags: versionFlags,
}
versionFlags = []cli.Flag{
cli.StringFlag{
Name: "format, f",
Usage: "Change the output format to JSON or a Go template",
},
}
)

View file

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

View file

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

View file

@ -1,60 +1,56 @@
package main
import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var volumeInspectDescription = `
var (
volumeInspectCommand cliconfig.VolumeInspectValues
volumeInspectDescription = `
podman volume inspect
Display detailed information on one or more volumes. Can change the format
from JSON to a Go template.
`
_volumeInspectCommand = &cobra.Command{
Use: "inspect",
Short: "Display detailed information on one or more volumes",
Long: volumeInspectDescription,
RunE: func(cmd *cobra.Command, args []string) error {
volumeInspectCommand.InputArgs = args
volumeInspectCommand.GlobalFlags = MainGlobalOpts
return volumeInspectCmd(&volumeInspectCommand)
},
Example: "[VOLUME-NAME ...]",
}
)
func init() {
volumeInspectCommand.Command = _volumeInspectCommand
flags := volumeInspectCommand.Flags()
flags.BoolVarP(&volumeInspectCommand.All, "all", "a", false, "Inspect all volumes")
flags.StringVarP(&volumeInspectCommand.Format, "format", "f", "json", "Format volume output using Go template")
var volumeInspectFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Inspect all volumes",
},
cli.StringFlag{
Name: "format, f",
Usage: "Format volume output using Go template",
Value: "json",
},
}
var volumeInspectCommand = cli.Command{
Name: "inspect",
Usage: "Display detailed information on one or more volumes",
Description: volumeInspectDescription,
Flags: volumeInspectFlags,
Action: volumeInspectCmd,
SkipArgReorder: true,
ArgsUsage: "[VOLUME-NAME ...]",
UseShortOptionHandling: true,
}
func volumeInspectCmd(c *cli.Context) error {
func volumeInspectCmd(c *cliconfig.VolumeInspectValues) error {
var err error
if err = validateFlags(c, volumeInspectFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
opts := volumeLsOptions{
Format: c.String("format"),
Format: c.Format,
}
vols, lastError := getVolumesFromContext(c, runtime)
vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
if lastError != nil {
logrus.Errorf("%q", lastError)
}

View file

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

View file

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

View file

@ -3,51 +3,47 @@ package main
import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var volumeRmDescription = `
var (
volumeRmCommand cliconfig.VolumeRmValues
volumeRmDescription = `
podman volume rm
Remove one or more existing volumes. Will only remove volumes that are
not being used by any containers. To remove the volumes anyways, use the
--force flag.
`
_volumeRmCommand = &cobra.Command{
Use: "rm",
Aliases: []string{"remove"},
Short: "Remove one or more volumes",
Long: volumeRmDescription,
RunE: func(cmd *cobra.Command, args []string) error {
volumeRmCommand.InputArgs = args
volumeRmCommand.GlobalFlags = MainGlobalOpts
return volumeRmCmd(&volumeRmCommand)
},
Example: "[VOLUME-NAME ...]",
}
)
var volumeRmFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Remove all volumes",
},
cli.BoolFlag{
Name: "force, f",
Usage: "Remove a volume by force, even if it is being used by a container",
},
func init() {
volumeRmCommand.Command = _volumeRmCommand
flags := volumeRmCommand.Flags()
flags.BoolVarP(&volumeRmCommand.All, "all", "a", false, "Remove all volumes")
flags.BoolVarP(&volumeRmCommand.Force, "force", "f", false, "Remove a volume by force, even if it is being used by a container")
}
var volumeRmCommand = cli.Command{
Name: "rm",
Aliases: []string{"remove"},
Usage: "Remove one or more volumes",
Description: volumeRmDescription,
Flags: volumeRmFlags,
Action: volumeRmCmd,
ArgsUsage: "[VOLUME-NAME ...]",
SkipArgReorder: true,
UseShortOptionHandling: true,
}
func volumeRmCmd(c *cli.Context) error {
func volumeRmCmd(c *cliconfig.VolumeRmValues) error {
var err error
if err = validateFlags(c, volumeRmFlags); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
@ -55,9 +51,9 @@ func volumeRmCmd(c *cli.Context) error {
ctx := getContext()
vols, lastError := getVolumesFromContext(c, runtime)
vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
for _, vol := range vols {
err = runtime.RemoveVolume(ctx, vol, c.Bool("force"), false)
err = runtime.RemoveVolume(ctx, vol, c.Force, false)
if err != nil {
if lastError != nil {
logrus.Errorf("%q", lastError)

View file

@ -5,43 +5,49 @@ import (
"os"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/spf13/cobra"
)
var (
waitCommand cliconfig.WaitValues
waitDescription = `
podman wait
Block until one or more containers stop and then print their exit codes
`
waitFlags = []cli.Flag{
cli.UintFlag{
Name: "interval, i",
Usage: "Milliseconds to wait before polling for completion",
Value: 250,
_waitCommand = &cobra.Command{
Use: "wait",
Short: "Block on one or more containers",
Long: waitDescription,
RunE: func(cmd *cobra.Command, args []string) error {
waitCommand.InputArgs = args
waitCommand.GlobalFlags = MainGlobalOpts
return waitCmd(&waitCommand)
},
LatestFlag,
}
waitCommand = cli.Command{
Name: "wait",
Usage: "Block on one or more containers",
Description: waitDescription,
Flags: sortFlags(waitFlags),
Action: waitCmd,
ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
OnUsageError: usageErrorHandler,
Example: "CONTAINER-NAME [CONTAINER-NAME ...]",
}
)
func waitCmd(c *cli.Context) error {
args := c.Args()
if len(args) < 1 && !c.Bool("latest") {
func init() {
waitCommand.Command = _waitCommand
flags := waitCommand.Flags()
flags.UintVarP(&waitCommand.Interval, "interval", "i", 250, "Milliseconds to wait before polling for completion")
flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
rootCmd.AddCommand(waitCommand.Command)
}
func waitCmd(c *cliconfig.WaitValues) error {
args := c.InputArgs
if len(args) < 1 && !c.Latest {
return errors.Errorf("you must provide at least one container name or id")
}
runtime, err := libpodruntime.GetRuntime(c)
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
@ -52,7 +58,7 @@ func waitCmd(c *cli.Context) error {
}
var lastError error
if c.Bool("latest") {
if c.Latest {
latestCtr, err := runtime.GetLatestContainer()
if err != nil {
return errors.Wrapf(err, "unable to wait on latest container")
@ -65,10 +71,10 @@ func waitCmd(c *cli.Context) error {
if err != nil {
return errors.Wrapf(err, "unable to find container %s", container)
}
if c.Uint("interval") == 0 {
if c.Interval == 0 {
return errors.Errorf("interval must be greater then 0")
}
returnCode, err := ctr.WaitWithInterval(time.Duration(c.Uint("interval")) * time.Millisecond)
returnCode, err := ctr.WaitWithInterval(time.Duration(c.Interval) * time.Millisecond)
if err != nil {
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)

View file

@ -11,11 +11,11 @@ import (
"strconv"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless"
"github.com/urfave/cli"
)
// LocalRuntime describes a typical libpod runtime
@ -35,7 +35,7 @@ type Container struct {
}
// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it
func GetRuntime(c *cli.Context) (*LocalRuntime, error) {
func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) {
runtime, err := libpodruntime.GetRuntime(c)
if err != nil {
return nil, err

View file

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

View file

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

View file

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

View file

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

View file

@ -8,6 +8,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"time"
"github.com/containers/buildah/docker"
"github.com/containers/buildah/util"
@ -25,7 +26,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
Version = "1.6-dev"
Version = "1.7-dev"
// The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to
@ -175,6 +176,15 @@ type Builder struct {
// after processing the AddCapabilities set, when running commands in the container.
// If a capability appears in both lists, it will be dropped.
DropCapabilities []string
// PrependedEmptyLayers are history entries that we'll add to a
// committed image, after any history items that we inherit from a base
// image, but before the history item for the layer that we're
// committing.
PrependedEmptyLayers []v1.History
// AppendedEmptyLayers are history entries that we'll add to a
// committed image after the history item for the layer that we're
// committing.
AppendedEmptyLayers []v1.History
CommonBuildOpts *CommonBuildOptions
// TopLayer is the top layer of the image
@ -209,11 +219,24 @@ type BuilderInfo struct {
DefaultCapabilities []string
AddCapabilities []string
DropCapabilities []string
History []v1.History
}
// GetBuildInfo gets a pointer to a Builder object and returns a BuilderInfo object from it.
// This is used in the inspect command to display Manifest and Config as string and not []byte.
func GetBuildInfo(b *Builder) BuilderInfo {
history := copyHistory(b.OCIv1.History)
history = append(history, copyHistory(b.PrependedEmptyLayers)...)
now := time.Now().UTC()
created := &now
history = append(history, v1.History{
Created: created,
CreatedBy: b.ImageCreatedBy,
Author: b.Maintainer(),
Comment: b.ImageHistoryComment,
EmptyLayer: false,
})
history = append(history, copyHistory(b.AppendedEmptyLayers)...)
return BuilderInfo{
Type: b.Type,
FromImage: b.FromImage,
@ -239,6 +262,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
DefaultCapabilities: append([]string{}, util.DefaultCapabilities...),
AddCapabilities: append([]string{}, b.AddCapabilities...),
DropCapabilities: append([]string{}, b.DropCapabilities...),
History: history,
}
}

View file

@ -351,21 +351,6 @@ func runUsingChrootMain() {
defer stdoutRead.Close()
defer stderrRead.Close()
}
// A helper that returns false if err is an error that would cause us
// to give up.
logIfNotRetryable := func(err error, what string) (retry bool) {
if err == nil {
return true
}
if errno, isErrno := err.(syscall.Errno); isErrno {
switch errno {
case syscall.EINTR, syscall.EAGAIN:
return true
}
}
logrus.Error(what)
return false
}
for readFd, writeFd := range relays {
if err := unix.SetNonblock(readFd, true); err != nil {
logrus.Errorf("error setting descriptor %d (%s) non-blocking: %v", readFd, fdDesc[readFd], err)
@ -388,7 +373,7 @@ func runUsingChrootMain() {
fds = append(fds, unix.PollFd{Fd: int32(fd), Events: unix.POLLIN | unix.POLLHUP})
}
_, err := unix.Poll(fds, pollTimeout)
if !logIfNotRetryable(err, fmt.Sprintf("poll: %v", err)) {
if !util.LogIfNotRetryable(err, fmt.Sprintf("poll: %v", err)) {
return
}
removeFds := make(map[int]struct{})
@ -405,7 +390,7 @@ func runUsingChrootMain() {
}
b := make([]byte, 8192)
nread, err := unix.Read(int(rfd.Fd), b)
logIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
util.LogIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
if nread > 0 {
if wfd, ok := relays[int(rfd.Fd)]; ok {
nwritten, err := buffers[wfd].Write(b[:nread])
@ -422,7 +407,7 @@ func runUsingChrootMain() {
// from this descriptor, read as much as there is to read.
for rfd.Revents&unix.POLLHUP == unix.POLLHUP {
nr, err := unix.Read(int(rfd.Fd), b)
logIfNotRetryable(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
util.LogIfUnexpectedWhileDraining(err, fmt.Sprintf("read %s: %v", fdDesc[int(rfd.Fd)], err))
if nr <= 0 {
break
}
@ -447,7 +432,7 @@ func runUsingChrootMain() {
for wfd, buffer := range buffers {
if buffer.Len() > 0 {
nwritten, err := unix.Write(wfd, buffer.Bytes())
logIfNotRetryable(err, fmt.Sprintf("write %s: %v", fdDesc[wfd], err))
util.LogIfNotRetryable(err, fmt.Sprintf("write %s: %v", fdDesc[wfd], err))
if nwritten >= 0 {
_ = buffer.Next(nwritten)
}

View file

@ -67,6 +67,10 @@ type CommitOptions struct {
OnBuild []string
// Parent is the base image that this image was created by.
Parent string
// OmitTimestamp forces epoch 0 as created timestamp to allow for
// deterministic, content-addressable builds.
OmitTimestamp bool
}
// PushOptions can be used to alter how an image is copied somewhere.
@ -97,6 +101,10 @@ type PushOptions struct {
// regenerate from on-disk layers, substituting them in the list of
// blobs to copy whenever possible.
BlobDirectory string
// Quiet is a boolean value that determines if minimal output to
// the user will be displayed, this is best used for logging.
// The default is false.
Quiet bool
}
// Commit writes the contents of the container, along with its updated
@ -140,7 +148,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
}
}
}
src, err := b.makeImageRef(options.PreferredManifestType, options.Parent, exportBaseLayers, options.Squash, options.BlobDirectory, options.Compression, options.HistoryTimestamp)
src, err := b.makeImageRef(options.PreferredManifestType, options.Parent, exportBaseLayers, options.Squash, options.BlobDirectory, options.Compression, options.HistoryTimestamp, options.OmitTimestamp)
if err != nil {
return imgID, nil, "", errors.Wrapf(err, "error computing layer digests and building metadata for container %q", b.ContainerID)
}
@ -224,6 +232,9 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
func Push(ctx context.Context, image string, dest types.ImageReference, options PushOptions) (reference.Canonical, digest.Digest, error) {
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
if options.Quiet {
options.ReportWriter = nil // Turns off logging output
}
blocked, err := isReferenceBlocked(dest, systemContext)
if err != nil {
return nil, "", errors.Wrapf(err, "error checking if pushing to registry for %q is blocked", transports.ImageName(dest))

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"
// github.com/moby/moby/image/rootfs.go
// RootFS describes images root filesystem
// V2S2RootFS describes images root filesystem
// This is currently a placeholder that only supports layers. In the future
// this can be made into an interface that supports different implementations.
type V2S2RootFS struct {
@ -27,7 +27,7 @@ type V2S2RootFS struct {
}
// github.com/moby/moby/image/image.go
// History stores build commands that were used to create an image
// V2S2History stores build commands that were used to create an image
type V2S2History struct {
// Created is the timestamp at which the image was created
Created time.Time `json:"created"`
@ -158,7 +158,7 @@ type V1Image struct {
}
// github.com/moby/moby/image/image.go
// Image stores the image configuration
// V2Image stores the image configuration
type V2Image struct {
V1Image
Parent ID `json:"parent,omitempty"`
@ -176,7 +176,7 @@ type V2Image struct {
}
// github.com/docker/distribution/manifest/versioned.go
// Versioned provides a struct with the manifest schemaVersion and mediaType.
// V2Versioned provides a struct with the manifest schemaVersion and mediaType.
// Incoming content with unknown schema version can be decoded against this
// struct to check the version.
type V2Versioned struct {
@ -188,21 +188,21 @@ type V2Versioned struct {
}
// github.com/docker/distribution/manifest/schema1/manifest.go
// FSLayer is a container struct for BlobSums defined in an image manifest
// V2S1FSLayer is a container struct for BlobSums defined in an image manifest
type V2S1FSLayer struct {
// BlobSum is the tarsum of the referenced filesystem image layer
BlobSum digest.Digest `json:"blobSum"`
}
// github.com/docker/distribution/manifest/schema1/manifest.go
// History stores unstructured v1 compatibility information
// V2S1History stores unstructured v1 compatibility information
type V2S1History struct {
// V1Compatibility is the raw v1 compatibility information
V1Compatibility string `json:"v1Compatibility"`
}
// github.com/docker/distribution/manifest/schema1/manifest.go
// Manifest provides the base accessible fields for working with V2 image
// V2S1Manifest provides the base accessible fields for working with V2 image
// format in the registry.
type V2S1Manifest struct {
V2Versioned
@ -225,7 +225,7 @@ type V2S1Manifest struct {
}
// github.com/docker/distribution/blobs.go
// Descriptor describes targeted content. Used in conjunction with a blob
// V2S2Descriptor describes targeted content. Used in conjunction with a blob
// store, a descriptor can be used to fetch, store and target any kind of
// blob. The struct also describes the wire protocol format. Fields should
// only be added but never changed.
@ -250,7 +250,7 @@ type V2S2Descriptor struct {
}
// github.com/docker/distribution/manifest/schema2/manifest.go
// Manifest defines a schema2 manifest.
// V2S2Manifest defines a schema2 manifest.
type V2S2Manifest struct {
V2Versioned

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