aboutsummaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/attach.go5
-rw-r--r--cmd/podman/checkpoint.go2
-rw-r--r--cmd/podman/cleanup.go2
-rw-r--r--cmd/podman/cliconfig/config.go37
-rw-r--r--cmd/podman/common.go43
-rw-r--r--cmd/podman/containers_prune.go21
-rw-r--r--cmd/podman/cp.go2
-rw-r--r--cmd/podman/exec.go5
-rw-r--r--cmd/podman/imagefilters/filters.go121
-rw-r--r--cmd/podman/images.go91
-rw-r--r--cmd/podman/images_prune.go20
-rw-r--r--cmd/podman/init.go2
-rw-r--r--cmd/podman/kill.go2
-rw-r--r--cmd/podman/libpodruntime/runtime.go2
-rw-r--r--cmd/podman/main_local.go6
-rw-r--r--cmd/podman/mount.go2
-rw-r--r--cmd/podman/network_create.go11
-rw-r--r--cmd/podman/pod_kill.go2
-rw-r--r--cmd/podman/pod_pause.go2
-rw-r--r--cmd/podman/pod_restart.go2
-rw-r--r--cmd/podman/pod_rm.go6
-rw-r--r--cmd/podman/pod_start.go2
-rw-r--r--cmd/podman/pod_stop.go4
-rw-r--r--cmd/podman/pod_unpause.go2
-rw-r--r--cmd/podman/pods_prune.go4
-rw-r--r--cmd/podman/port.go2
-rw-r--r--cmd/podman/remoteclientconfig/configfile_test.go2
-rw-r--r--cmd/podman/reset.go71
-rw-r--r--cmd/podman/restart.go2
-rw-r--r--cmd/podman/restore.go2
-rw-r--r--cmd/podman/rm.go14
-rw-r--r--cmd/podman/shared/container.go28
-rw-r--r--cmd/podman/shared/create.go52
-rw-r--r--cmd/podman/shared/parallel.go2
-rw-r--r--cmd/podman/shared/parse/parse_test.go4
-rw-r--r--cmd/podman/shared/workers.go2
-rw-r--r--cmd/podman/start.go3
-rw-r--r--cmd/podman/stats.go2
-rw-r--r--cmd/podman/stop.go6
-rw-r--r--cmd/podman/system.go1
-rw-r--r--cmd/podman/system_prune.go6
-rw-r--r--cmd/podman/system_renumber.go4
-rw-r--r--cmd/podman/tree.go2
-rw-r--r--cmd/podman/umount.go2
-rw-r--r--cmd/podman/varlink/io.podman.varlink14
-rw-r--r--cmd/podman/version.go66
46 files changed, 386 insertions, 299 deletions
diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go
index b03673f29..7d32c57af 100644
--- a/cmd/podman/attach.go
+++ b/cmd/podman/attach.go
@@ -33,11 +33,14 @@ func init() {
attachCommand.SetUsageTemplate(UsageTemplate())
flags := attachCommand.Flags()
flags.StringVar(&attachCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`")
+ // Clear the default, the value specified in the config file should have the
+ // priority
+ attachCommand.DetachKeys = ""
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")
flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
markFlagHiddenForRemoteClient("latest", flags)
- // TODO allow for passing of a new deatch keys
+ // TODO allow for passing of a new detach keys
markFlagHiddenForRemoteClient("detach-keys", flags)
}
diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go
index 22cdb1f39..07db519f8 100644
--- a/cmd/podman/checkpoint.go
+++ b/cmd/podman/checkpoint.go
@@ -26,7 +26,7 @@ var (
return checkpointCmd(&checkpointCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman container checkpoint --keep ctrID
podman container checkpoint --all
diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go
index c00654162..a8bc0c116 100644
--- a/cmd/podman/cleanup.go
+++ b/cmd/podman/cleanup.go
@@ -27,7 +27,7 @@ var (
return cleanupCmd(&cleanupCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman container cleanup --latest
podman container cleanup ctrID1 ctrID2 ctrID3
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 780b68333..e81756808 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -64,6 +64,7 @@ type ImagesValues struct {
NoTrunc bool
Quiet bool
Sort string
+ History bool
}
type EventValues struct {
@@ -127,6 +128,7 @@ type ExecValues struct {
PodmanCommand
DetachKeys string
Env []string
+ EnvFile []string
Privileged bool
Interactive bool
Tty bool
@@ -175,12 +177,15 @@ type HistoryValues struct {
}
type PruneImagesValues struct {
PodmanCommand
- All bool
+ All bool
+ Force bool
+ Filter []string
}
type PruneContainersValues struct {
PodmanCommand
- Force bool
+ Force bool
+ Filter []string
}
type PodPruneValues struct {
@@ -274,6 +279,7 @@ type NetworkCreateValues struct {
IPRange net.IPNet
IPV6 bool
Network net.IPNet
+ MacVLAN string
}
type NetworkListValues struct {
@@ -366,6 +372,7 @@ type PodRestartValues struct {
type PodRmValues struct {
PodmanCommand
All bool
+ Ignore bool
Force bool
Latest bool
}
@@ -387,6 +394,7 @@ type PodStatsValues struct {
type PodStopValues struct {
PodmanCommand
All bool
+ Ignore bool
Latest bool
Timeout uint
}
@@ -480,11 +488,13 @@ type RestoreValues struct {
type RmValues struct {
PodmanCommand
- All bool
- Force bool
- Latest bool
- Storage bool
- Volumes bool
+ All bool
+ Force bool
+ Ignore bool
+ Latest bool
+ Storage bool
+ Volumes bool
+ CIDFiles []string
}
type RmiValues struct {
@@ -557,9 +567,11 @@ type StatsValues struct {
type StopValues struct {
PodmanCommand
- All bool
- Latest bool
- Timeout uint
+ All bool
+ Ignore bool
+ Latest bool
+ Timeout uint
+ CIDFiles []string
}
type TopValues struct {
@@ -649,6 +661,11 @@ type SystemPruneValues struct {
Volume bool
}
+type SystemResetValues struct {
+ PodmanCommand
+ Force bool
+}
+
type SystemRenumberValues struct {
PodmanCommand
}
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 4db043f31..69365201e 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -39,24 +39,45 @@ func shortID(id string) string {
return id
}
-// checkAllAndLatest checks that --all and --latest are used correctly
-func checkAllAndLatest(c *cobra.Command, args []string, ignoreArgLen bool) error {
+// checkAllLatestAndCIDFile checks that --all and --latest are used correctly.
+// If cidfile is set, also check for the --cidfile flag.
+func checkAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool, cidfile bool) error {
argLen := len(args)
if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil {
- return errors.New("unable to lookup values for 'latest' or 'all'")
+ if !cidfile {
+ return errors.New("unable to lookup values for 'latest' or 'all'")
+ } else if c.Flags().Lookup("cidfile") == nil {
+ return errors.New("unable to lookup values for 'latest', 'all' or 'cidfile'")
+ }
+ }
+
+ specifiedAll, _ := c.Flags().GetBool("all")
+ specifiedLatest, _ := c.Flags().GetBool("latest")
+ specifiedCIDFile := false
+ if cid, _ := c.Flags().GetStringArray("cidfile"); len(cid) > 0 {
+ specifiedCIDFile = true
}
- all, _ := c.Flags().GetBool("all")
- latest, _ := c.Flags().GetBool("latest")
- if all && latest {
+
+ if specifiedCIDFile && (specifiedAll || specifiedLatest) {
+ return errors.Errorf("--all, --latest and --cidfile cannot be used together")
+ } else if specifiedAll && specifiedLatest {
return errors.Errorf("--all and --latest cannot be used together")
}
+
if ignoreArgLen {
return nil
}
- if (all || latest) && argLen > 0 {
+ if (argLen > 0) && (specifiedAll || specifiedLatest) {
return errors.Errorf("no arguments are needed with --all or --latest")
+ } else if cidfile && (argLen > 0) && (specifiedAll || specifiedLatest || specifiedCIDFile) {
+ return errors.Errorf("no arguments are needed with --all, --latest or --cidfile")
}
- if argLen < 1 && !all && !latest {
+
+ if specifiedCIDFile {
+ return nil
+ }
+
+ if argLen < 1 && !specifiedAll && !specifiedLatest && !specifiedCIDFile {
return errors.Errorf("you must provide at least one name or id")
}
return nil
@@ -187,10 +208,14 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"detach", "d", false,
"Run container in background and print container ID",
)
- createFlags.String(
+ detachKeys := createFlags.String(
"detach-keys", define.DefaultDetachKeys,
"Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`",
)
+ // Clear the default, the value specified in the config file should have the
+ // priority
+ *detachKeys = ""
+
createFlags.StringSlice(
"device", []string{},
"Add a host device to the container (default [])",
diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go
index 3d0fef37d..78c50268c 100644
--- a/cmd/podman/containers_prune.go
+++ b/cmd/podman/containers_prune.go
@@ -1,6 +1,11 @@
package main
import (
+ "bufio"
+ "fmt"
+ "os"
+ "strings"
+
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/define"
@@ -36,9 +41,23 @@ func init() {
pruneContainersCommand.SetUsageTemplate(UsageTemplate())
flags := pruneContainersCommand.Flags()
flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
+ flags.StringArrayVar(&pruneContainersCommand.Filter, "filter", []string{}, "Provide filter values (e.g. 'until=<timestamp>')")
}
func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
+ if !c.Force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Printf(`WARNING! This will remove all stopped containers.
+Are you sure you want to continue? [y/N] `)
+ ans, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(ans)[0] != 'y' {
+ return nil
+ }
+ }
+
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
@@ -49,7 +68,7 @@ func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
if c.GlobalIsSet("max-workers") {
maxWorkers = c.GlobalFlags.MaxWorks
}
- ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force)
+ ok, failures, err := runtime.Prune(getContext(), maxWorkers, c.Force, c.Filter)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchCtr {
if len(c.InputArgs) > 1 {
diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go
index c53a97df3..762d70252 100644
--- a/cmd/podman/cp.go
+++ b/cmd/podman/cp.go
@@ -192,7 +192,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
} else if isBindMount, mount := isBindMountDestName(srcPath, ctr); isBindMount {
path, err := pathWithBindMountSource(mount, srcPath)
if err != nil {
- return errors.Wrapf(err, "error getting source path from bind moutn %s", mount.Destination)
+ return errors.Wrapf(err, "error getting source path from bind mount %s", mount.Destination)
}
srcPath = path
} else if filepath.IsAbs(srcPath) {
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index afa701897..6e5799396 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -36,7 +36,11 @@ func init() {
flags := execCommand.Flags()
flags.SetInterspersed(false)
flags.StringVar(&execCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select 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 _")
+ // Clear the default, the value specified in the config file should have the
+ // priority
+ execCommand.DetachKeys = ""
flags.StringArrayVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables")
+ flags.StringSliceVar(&execCommand.EnvFile, "env-file", []string{}, "Read in a file of environment variables")
flags.BoolVarP(&execCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
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")
@@ -45,6 +49,7 @@ func init() {
flags.IntVar(&execCommand.PreserveFDs, "preserve-fds", 0, "Pass N additional file descriptors to the container")
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
+ markFlagHiddenForRemoteClient("env-file", flags)
markFlagHiddenForRemoteClient("latest", flags)
markFlagHiddenForRemoteClient("preserve-fds", flags)
}
diff --git a/cmd/podman/imagefilters/filters.go b/cmd/podman/imagefilters/filters.go
deleted file mode 100644
index 0b08314ce..000000000
--- a/cmd/podman/imagefilters/filters.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package imagefilters
-
-import (
- "context"
- "fmt"
- "path/filepath"
- "strings"
- "time"
-
- "github.com/containers/libpod/pkg/adapter"
- "github.com/containers/libpod/pkg/inspect"
- "github.com/sirupsen/logrus"
-)
-
-// ResultFilter is a mock function for image filtering
-type ResultFilter func(*adapter.ContainerImage) bool
-
-// Filter is a function to determine whether an image is included in
-// command output. Images to be outputted are tested using the function. A true
-// return will include the image, a false return will exclude it.
-type Filter func(*adapter.ContainerImage, *inspect.ImageData) bool
-
-// CreatedBeforeFilter allows you to filter on images created before
-// the given time.Time
-func CreatedBeforeFilter(createTime time.Time) ResultFilter {
- return func(i *adapter.ContainerImage) bool {
- return i.Created().Before(createTime)
- }
-}
-
-// CreatedAfterFilter allows you to filter on images created after
-// the given time.Time
-func CreatedAfterFilter(createTime time.Time) ResultFilter {
- return func(i *adapter.ContainerImage) bool {
- return i.Created().After(createTime)
- }
-}
-
-// DanglingFilter allows you to filter images for dangling images
-func DanglingFilter(danglingImages bool) ResultFilter {
- return func(i *adapter.ContainerImage) bool {
- if danglingImages {
- return i.Dangling()
- }
- return !i.Dangling()
- }
-}
-
-// ReadOnlyFilter allows you to filter images based on read/only and read/write
-func ReadOnlyFilter(readOnly bool) ResultFilter {
- return func(i *adapter.ContainerImage) bool {
- if readOnly {
- return i.IsReadOnly()
- }
- return !i.IsReadOnly()
- }
-}
-
-// LabelFilter allows you to filter by images labels key and/or value
-func LabelFilter(ctx context.Context, labelfilter string) ResultFilter {
- // We need to handle both label=key and label=key=value
- return func(i *adapter.ContainerImage) bool {
- var value string
- splitFilter := strings.Split(labelfilter, "=")
- key := splitFilter[0]
- if len(splitFilter) > 1 {
- value = splitFilter[1]
- }
- labels, err := i.Labels(ctx)
- if err != nil {
- return false
- }
- if len(strings.TrimSpace(labels[key])) > 0 && len(strings.TrimSpace(value)) == 0 {
- return true
- }
- return labels[key] == value
- }
-}
-
-// ReferenceFilter allows you to filter by image name
-// Replacing all '/' with '|' so that filepath.Match() can work
-// '|' character is not valid in image name, so this is safe
-func ReferenceFilter(ctx context.Context, referenceFilter string) ResultFilter {
- filter := fmt.Sprintf("*%s*", referenceFilter)
- filter = strings.Replace(filter, "/", "|", -1)
- return func(i *adapter.ContainerImage) bool {
- for _, name := range i.Names() {
- newName := strings.Replace(name, "/", "|", -1)
- match, err := filepath.Match(filter, newName)
- if err != nil {
- logrus.Errorf("failed to match %s and %s, %q", name, referenceFilter, err)
- }
- if match {
- return true
- }
- }
- return false
- }
-}
-
-// OutputImageFilter allows you to filter by an a specific image name
-func OutputImageFilter(userImage *adapter.ContainerImage) ResultFilter {
- return func(i *adapter.ContainerImage) bool {
- return userImage.ID() == i.ID()
- }
-}
-
-// FilterImages filters images using a set of predefined filter funcs
-func FilterImages(images []*adapter.ContainerImage, filters []ResultFilter) []*adapter.ContainerImage {
- var filteredImages []*adapter.ContainerImage
- for _, image := range images {
- include := true
- for _, filter := range filters {
- include = include && filter(image)
- }
- if include {
- filteredImages = append(filteredImages, image)
- }
- }
- return filteredImages
-}
diff --git a/cmd/podman/images.go b/cmd/podman/images.go
index 7d498517c..e42546a55 100644
--- a/cmd/podman/images.go
+++ b/cmd/podman/images.go
@@ -5,14 +5,12 @@ import (
"fmt"
"reflect"
"sort"
- "strconv"
"strings"
"time"
"unicode"
"github.com/containers/buildah/pkg/formats"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/imagefilters"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/adapter"
"github.com/docker/go-units"
@@ -32,6 +30,7 @@ type imagesTemplateParams struct {
CreatedTime time.Time
Size string
ReadOnly bool
+ History string
}
type imagesJSONParams struct {
@@ -42,6 +41,7 @@ type imagesJSONParams struct {
Created time.Time `json:"created"`
Size *uint64 `json:"size"`
ReadOnly bool `json:"readonly"`
+ History []string `json:"history"`
}
type imagesOptions struct {
@@ -53,6 +53,7 @@ type imagesOptions struct {
outputformat string
sort string
all bool
+ history bool
}
// Type declaration and functions for sorting the images output
@@ -124,6 +125,7 @@ func imagesInit(command *cliconfig.ImagesValues) {
flags.BoolVar(&command.NoTrunc, "no-trunc", false, "Do not truncate output")
flags.BoolVarP(&command.Quiet, "quiet", "q", false, "Display only image IDs")
flags.StringVar(&command.Sort, "sort", "created", "Sort by created, id, repository, size, or tag")
+ flags.BoolVarP(&command.History, "history", "", false, "Display the image name history")
}
@@ -134,10 +136,10 @@ func init() {
func imagesCmd(c *cliconfig.ImagesValues) error {
var (
- filterFuncs []imagefilters.ResultFilter
- image string
+ image string
)
+ ctx := getContext()
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "Could not get runtime")
@@ -152,15 +154,9 @@ func imagesCmd(c *cliconfig.ImagesValues) error {
if len(c.Filter) > 0 && image != "" {
return errors.New("can not specify an image and a filter")
}
- ctx := getContext()
-
- if len(c.Filter) > 0 {
- filterFuncs, err = CreateFilterFuncs(ctx, runtime, c.Filter, nil)
- } else {
- filterFuncs, err = CreateFilterFuncs(ctx, runtime, []string{fmt.Sprintf("reference=%s", image)}, nil)
- }
- if err != nil {
- return err
+ filters := c.Filter
+ if len(filters) < 1 {
+ filters = append(filters, fmt.Sprintf("reference=%s", image))
}
opts := imagesOptions{
@@ -171,29 +167,21 @@ func imagesCmd(c *cliconfig.ImagesValues) error {
format: c.Format,
sort: c.Sort,
all: c.All,
+ history: c.History,
}
opts.outputformat = opts.setOutputFormat()
- images, err := runtime.GetImages()
+ filteredImages, err := runtime.GetFilteredImages(filters, false)
if err != nil {
return errors.Wrapf(err, "unable to get images")
}
- for _, image := range images {
+ for _, image := range filteredImages {
if image.IsReadOnly() {
opts.outputformat += "{{.ReadOnly}}\t"
break
}
}
-
- var filteredImages []*adapter.ContainerImage
- //filter the images
- if len(c.Filter) > 0 || len(c.InputArgs) == 1 {
- filteredImages = imagefilters.FilterImages(images, filterFuncs)
- } else {
- filteredImages = images
- }
-
return generateImagesOutput(ctx, filteredImages, opts)
}
@@ -214,6 +202,9 @@ func (i imagesOptions) setOutputFormat() string {
format += "{{.Digest}}\t"
}
format += "{{.ID}}\t{{.Created}}\t{{.Size}}\t"
+ if i.history {
+ format += "{{if .History}}{{.History}}{{else}}<none>{{end}}\t"
+ }
return format
}
@@ -306,6 +297,7 @@ func getImagesTemplateOutput(ctx context.Context, images []*adapter.ContainerIma
Created: units.HumanDuration(time.Since(createdTime)) + " ago",
Size: sizeStr,
ReadOnly: img.IsReadOnly(),
+ History: strings.Join(img.NamesHistory(), ", "),
}
imagesOutput = append(imagesOutput, params)
if opts.quiet { // Show only one image ID when quiet
@@ -336,6 +328,7 @@ func getImagesJSONOutput(ctx context.Context, images []*adapter.ContainerImage)
Created: img.Created(),
Size: size,
ReadOnly: img.IsReadOnly(),
+ History: img.NamesHistory(),
}
imagesOutput = append(imagesOutput, params)
}
@@ -382,53 +375,3 @@ func GenImageOutputMap() map[string]string {
}
return values
}
-
-// 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, filters []string, img *adapter.ContainerImage) ([]imagefilters.ResultFilter, error) {
- var filterFuncs []imagefilters.ResultFilter
- for _, filter := range filters {
- splitFilter := strings.Split(filter, "=")
- if len(splitFilter) < 2 {
- return nil, errors.Errorf("invalid filter syntax %s", filter)
- }
- switch splitFilter[0] {
- case "before":
- before, err := r.NewImageFromLocal(splitFilter[1])
- if err != nil {
- return nil, errors.Wrapf(err, "unable to find image %s in local stores", splitFilter[1])
- }
- filterFuncs = append(filterFuncs, imagefilters.CreatedBeforeFilter(before.Created()))
- case "after":
- after, err := r.NewImageFromLocal(splitFilter[1])
- if err != nil {
- return nil, errors.Wrapf(err, "unable to find image %s in local stores", splitFilter[1])
- }
- filterFuncs = append(filterFuncs, imagefilters.CreatedAfterFilter(after.Created()))
- case "readonly":
- readonly, err := strconv.ParseBool(splitFilter[1])
- if err != nil {
- return nil, errors.Wrapf(err, "invalid filter readonly=%s", splitFilter[1])
- }
- filterFuncs = append(filterFuncs, imagefilters.ReadOnlyFilter(readonly))
- case "dangling":
- danglingImages, err := strconv.ParseBool(splitFilter[1])
- if err != nil {
- return nil, errors.Wrapf(err, "invalid filter dangling=%s", splitFilter[1])
- }
- filterFuncs = append(filterFuncs, imagefilters.DanglingFilter(danglingImages))
- case "label":
- labelFilter := strings.Join(splitFilter[1:], "=")
- filterFuncs = append(filterFuncs, imagefilters.LabelFilter(ctx, labelFilter))
- case "reference":
- referenceFilter := strings.Join(splitFilter[1:], "=")
- filterFuncs = append(filterFuncs, imagefilters.ReferenceFilter(ctx, referenceFilter))
- default:
- return nil, errors.Errorf("invalid filter %s ", splitFilter[0])
- }
- }
- if img != nil {
- filterFuncs = append(filterFuncs, imagefilters.OutputImageFilter(img))
- }
- return filterFuncs, nil
-}
diff --git a/cmd/podman/images_prune.go b/cmd/podman/images_prune.go
index 5745edd6b..2b498f83d 100644
--- a/cmd/podman/images_prune.go
+++ b/cmd/podman/images_prune.go
@@ -1,7 +1,10 @@
package main
import (
+ "bufio"
"fmt"
+ "os"
+ "strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
@@ -34,9 +37,24 @@ func init() {
pruneImagesCommand.SetUsageTemplate(UsageTemplate())
flags := pruneImagesCommand.Flags()
flags.BoolVarP(&pruneImagesCommand.All, "all", "a", false, "Remove all unused images, not just dangling ones")
+ flags.BoolVarP(&pruneImagesCommand.Force, "force", "f", false, "Do not prompt for confirmation")
+ flags.StringArrayVar(&pruneImagesCommand.Filter, "filter", []string{}, "Provide filter values (e.g. 'label=<key>=<value>')")
}
func pruneImagesCmd(c *cliconfig.PruneImagesValues) error {
+ if !c.Force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Printf(`
+WARNING! This will remove all dangling images.
+Are you sure you want to continue? [y/N] `)
+ ans, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(ans)[0] != 'y' {
+ return nil
+ }
+ }
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
@@ -45,7 +63,7 @@ func pruneImagesCmd(c *cliconfig.PruneImagesValues) 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(getContext(), c.All)
+ pruneCids, err := runtime.PruneImages(getContext(), c.All, c.Filter)
if len(pruneCids) > 0 {
for _, cid := range pruneCids {
fmt.Println(cid)
diff --git a/cmd/podman/init.go b/cmd/podman/init.go
index 3f97824fc..2e0b33828 100644
--- a/cmd/podman/init.go
+++ b/cmd/podman/init.go
@@ -23,7 +23,7 @@ var (
return initCmd(&initCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman init --latest
podman init 3c45ef19d893
diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go
index d5056d86d..aba2008ca 100644
--- a/cmd/podman/kill.go
+++ b/cmd/podman/kill.go
@@ -24,7 +24,7 @@ var (
return killCmd(&killCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman kill mywebserver
podman kill 860a4b23
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index dd8c3f173..9425cfb9c 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -157,7 +157,7 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
// TODO flag to set CNI plugins dir?
- // TODO I dont think these belong here?
+ // TODO I don't think these belong here?
// Will follow up with a different PR to address
//
// Pod create options
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index f630f1210..bc46e4652 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -64,12 +64,12 @@ func init() {
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
+ // -s is deprecated 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().StringArrayVar(&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")
- rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n")
rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Trace, "trace", false, "Enable opentracing output")
}
@@ -159,7 +159,7 @@ func setupRootless(cmd *cobra.Command, args []string) error {
Remote: remoteclient,
}
- runtime, err := libpodruntime.GetRuntime(getContext(), &podmanCmd)
+ runtime, err := libpodruntime.GetRuntimeNoStore(getContext(), &podmanCmd)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go
index b14827592..526a236fd 100644
--- a/cmd/podman/mount.go
+++ b/cmd/podman/mount.go
@@ -35,7 +35,7 @@ var (
return mountCmd(&mountCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, true)
+ return checkAllLatestAndCIDFile(cmd, args, true, false)
},
}
)
diff --git a/cmd/podman/network_create.go b/cmd/podman/network_create.go
index 6710883ae..886607885 100644
--- a/cmd/podman/network_create.go
+++ b/cmd/podman/network_create.go
@@ -41,6 +41,7 @@ func init() {
flags.IPVar(&networkCreateCommand.Gateway, "gateway", nil, "IPv4 or IPv6 gateway for the subnet")
flags.BoolVar(&networkCreateCommand.Internal, "internal", false, "restrict external access from this network")
flags.IPNetVar(&networkCreateCommand.IPRange, "ip-range", net.IPNet{}, "allocate container IP from range")
+ flags.StringVar(&networkCreateCommand.MacVLAN, "macvlan", "", "create a Macvlan connection based on this device")
// TODO not supported yet
//flags.StringVar(&networkCreateCommand.IPamDriver, "ipam-driver", "", "IP Address Management Driver")
// TODO enable when IPv6 is working
@@ -50,6 +51,10 @@ func init() {
}
func networkcreateCmd(c *cliconfig.NetworkCreateValues) error {
+ var (
+ fileName string
+ err error
+ )
if err := network.IsSupportedDriver(c.Driver); err != nil {
return err
}
@@ -66,7 +71,11 @@ func networkcreateCmd(c *cliconfig.NetworkCreateValues) error {
if err != nil {
return err
}
- fileName, err := runtime.NetworkCreate(c)
+ if len(c.MacVLAN) > 0 {
+ fileName, err = runtime.NetworkCreateMacVLAN(c)
+ } else {
+ fileName, err = runtime.NetworkCreateBridge(c)
+ }
if err == nil {
fmt.Println(fileName)
}
diff --git a/cmd/podman/pod_kill.go b/cmd/podman/pod_kill.go
index 9bda77471..064946f72 100644
--- a/cmd/podman/pod_kill.go
+++ b/cmd/podman/pod_kill.go
@@ -28,7 +28,7 @@ var (
return podKillCmd(&podKillCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod kill podID
podman pod kill --signal TERM mywebserver
diff --git a/cmd/podman/pod_pause.go b/cmd/podman/pod_pause.go
index 45e1319ff..320072919 100644
--- a/cmd/podman/pod_pause.go
+++ b/cmd/podman/pod_pause.go
@@ -25,7 +25,7 @@ var (
return podPauseCmd(&podPauseCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod pause podID1 podID2
podman pod pause --latest
diff --git a/cmd/podman/pod_restart.go b/cmd/podman/pod_restart.go
index cc090bd6e..cb9f3770f 100644
--- a/cmd/podman/pod_restart.go
+++ b/cmd/podman/pod_restart.go
@@ -26,7 +26,7 @@ var (
return podRestartCmd(&podRestartCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod restart podID1 podID2
podman pod restart --latest
diff --git a/cmd/podman/pod_rm.go b/cmd/podman/pod_rm.go
index 82d0eb977..02daf8764 100644
--- a/cmd/podman/pod_rm.go
+++ b/cmd/podman/pod_rm.go
@@ -12,7 +12,7 @@ import (
var (
podRmCommand cliconfig.PodRmValues
- podRmDescription = fmt.Sprintf(`podman rm will remove one or more pods from the host.
+ podRmDescription = fmt.Sprintf(`podman rm will remove one or more stopped pods and their containers 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 = &cobra.Command{
@@ -26,7 +26,7 @@ var (
return podRmCmd(&podRmCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod rm mywebserverpod
podman pod rm -f 860a4b23
@@ -41,7 +41,9 @@ func init() {
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.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing")
flags.BoolVarP(&podRmCommand.Latest, "latest", "l", false, "Remove the latest pod podman is aware of")
+ markFlagHiddenForRemoteClient("ignore", flags)
markFlagHiddenForRemoteClient("latest", flags)
}
diff --git a/cmd/podman/pod_start.go b/cmd/podman/pod_start.go
index 64c951b43..aa2e09e98 100644
--- a/cmd/podman/pod_start.go
+++ b/cmd/podman/pod_start.go
@@ -26,7 +26,7 @@ var (
return podStartCmd(&podStartCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod start podID
podman pod start --latest
diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go
index edda99550..7d3951ec4 100644
--- a/cmd/podman/pod_stop.go
+++ b/cmd/podman/pod_stop.go
@@ -27,7 +27,7 @@ var (
return podStopCmd(&podStopCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod stop mywebserverpod
podman pod stop --latest
@@ -41,8 +41,10 @@ func init() {
podStopCommand.SetUsageTemplate(UsageTemplate())
flags := podStopCommand.Flags()
flags.BoolVarP(&podStopCommand.All, "all", "a", false, "Stop all running pods")
+ flags.BoolVarP(&podStopCommand.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing")
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")
+ markFlagHiddenForRemoteClient("ignore", flags)
markFlagHiddenForRemoteClient("latest", flags)
}
diff --git a/cmd/podman/pod_unpause.go b/cmd/podman/pod_unpause.go
index 833434c3f..1f80a7c79 100644
--- a/cmd/podman/pod_unpause.go
+++ b/cmd/podman/pod_unpause.go
@@ -26,7 +26,7 @@ var (
return podUnpauseCmd(&podUnpauseCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod unpause podID1 podID2
podman pod unpause --all
diff --git a/cmd/podman/pods_prune.go b/cmd/podman/pods_prune.go
index d40e37bdb..1c5c0bb58 100644
--- a/cmd/podman/pods_prune.go
+++ b/cmd/podman/pods_prune.go
@@ -17,7 +17,7 @@ var (
_prunePodsCommand = &cobra.Command{
Use: "prune",
Args: noSubArgs,
- Short: "Remove all stopped pods",
+ Short: "Remove all stopped pods and their containers",
Long: podPruneDescription,
RunE: func(cmd *cobra.Command, args []string) error {
podPruneCommand.InputArgs = args
@@ -32,7 +32,7 @@ func init() {
podPruneCommand.SetHelpTemplate(HelpTemplate())
podPruneCommand.SetUsageTemplate(UsageTemplate())
flags := podPruneCommand.Flags()
- flags.BoolVarP(&podPruneCommand.Force, "force", "f", false, "Force removal of a running pods. The default is false")
+ flags.BoolVarP(&podPruneCommand.Force, "force", "f", false, "Force removal of all running pods. The default is false")
}
func podPruneCmd(c *cliconfig.PodPruneValues) error {
diff --git a/cmd/podman/port.go b/cmd/podman/port.go
index 4e1f9642c..eef3d4b1d 100644
--- a/cmd/podman/port.go
+++ b/cmd/podman/port.go
@@ -26,7 +26,7 @@ var (
return portCmd(&portCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, true)
+ return checkAllLatestAndCIDFile(cmd, args, true, false)
},
Example: `podman port --all
podman port ctrID 80/tcp
diff --git a/cmd/podman/remoteclientconfig/configfile_test.go b/cmd/podman/remoteclientconfig/configfile_test.go
index 0bcac29a8..1710ee83f 100644
--- a/cmd/podman/remoteclientconfig/configfile_test.go
+++ b/cmd/podman/remoteclientconfig/configfile_test.go
@@ -88,7 +88,7 @@ func TestReadRemoteConfig(t *testing.T) {
{"good", args{reader: strings.NewReader(goodConfig)}, makeGoodResult(), false},
// a connection with no destination is an error
{"nodest", args{reader: strings.NewReader(noDest)}, nil, true},
- // a connnection with no user is OK
+ // a connection with no user is OK
{"nouser", args{reader: strings.NewReader(noUser)}, makeNoUserResult(), false},
}
for _, tt := range tests {
diff --git a/cmd/podman/reset.go b/cmd/podman/reset.go
new file mode 100644
index 000000000..9d16dc978
--- /dev/null
+++ b/cmd/podman/reset.go
@@ -0,0 +1,71 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ systemResetCommand cliconfig.SystemResetValues
+ systemResetDescription = `Reset podman storage back to default state"
+
+ All containers will be stopped and removed, and all images, volumes and container content will be removed.
+`
+ _systemResetCommand = &cobra.Command{
+ Use: "reset",
+ Args: noSubArgs,
+ Short: "Reset podman storage",
+ Long: systemResetDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ systemResetCommand.InputArgs = args
+ systemResetCommand.GlobalFlags = MainGlobalOpts
+ systemResetCommand.Remote = remoteclient
+ return systemResetCmd(&systemResetCommand)
+ },
+ }
+)
+
+func init() {
+ systemResetCommand.Command = _systemResetCommand
+ flags := systemResetCommand.Flags()
+ flags.BoolVarP(&systemResetCommand.Force, "force", "f", false, "Do not prompt for confirmation")
+
+ systemResetCommand.SetHelpTemplate(HelpTemplate())
+ systemResetCommand.SetUsageTemplate(UsageTemplate())
+}
+
+func systemResetCmd(c *cliconfig.SystemResetValues) error {
+ // Prompt for confirmation if --force is not set
+ if !c.Force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Print(`
+WARNING! This will remove:
+ - all containers
+ - all pods
+ - all images
+ - all build cache
+Are you sure you want to continue? [y/N] `)
+ ans, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(ans)[0] != 'y' {
+ return nil
+ }
+ }
+
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "error creating libpod runtime")
+ }
+ // No shutdown, since storage will be destroyed when command completes
+
+ return runtime.Reset()
+}
diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go
index c97fb0dc1..996a9f7ce 100644
--- a/cmd/podman/restart.go
+++ b/cmd/podman/restart.go
@@ -23,7 +23,7 @@ var (
return restartCmd(&restartCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman restart ctrID
podman restart --latest
diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go
index caefadb6d..a8db7fa94 100644
--- a/cmd/podman/restore.go
+++ b/cmd/podman/restore.go
@@ -26,7 +26,7 @@ var (
return restoreCmd(&restoreCommand, cmd)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, true)
+ return checkAllLatestAndCIDFile(cmd, args, true, false)
},
Example: `podman container restore ctrID
podman container restore --latest
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index 6329a9d8e..e69565e95 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -25,7 +25,7 @@ var (
return rmCmd(&rmCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, true)
},
Example: `podman rm imageID
podman rm mywebserver myflaskserver 860a4b23
@@ -40,12 +40,16 @@ func init() {
rmCommand.SetUsageTemplate(UsageTemplate())
flags := rmCommand.Flags()
flags.BoolVarP(&rmCommand.All, "all", "a", false, "Remove all containers")
+ flags.BoolVarP(&rmCommand.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing")
flags.BoolVarP(&rmCommand.Force, "force", "f", false, "Force removal of a running or unusable container. The default is false")
flags.BoolVarP(&rmCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&rmCommand.Storage, "storage", false, "Remove container from storage library")
flags.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove anonymous volumes associated with the container")
- markFlagHiddenForRemoteClient("storage", flags)
+ flags.StringArrayVarP(&rmCommand.CIDFiles, "cidfile", "", nil, "Read the container ID from the file")
+ markFlagHiddenForRemoteClient("ignore", flags)
+ markFlagHiddenForRemoteClient("cidfile", flags)
markFlagHiddenForRemoteClient("latest", flags)
+ markFlagHiddenForRemoteClient("storage", flags)
}
// rmCmd removes one or more containers
@@ -56,10 +60,10 @@ func rmCmd(c *cliconfig.RmValues) error {
}
defer runtime.DeferredShutdown(false)
- // Storage conflicts with --all/--latest/--volumes
+ // Storage conflicts with --all/--latest/--volumes/--cidfile/--ignore
if c.Storage {
- if c.All || c.Latest || c.Volumes {
- return errors.Errorf("--storage conflicts with --volumes, --all, and --latest")
+ if c.All || c.Ignore || c.Latest || c.Volumes || c.CIDFiles != nil {
+ return errors.Errorf("--storage conflicts with --volumes, --all, --latest, --ignore and --cidfile")
}
}
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index bc64d63a9..4f2002992 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/timetype"
"github.com/containers/libpod/pkg/util"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-units"
@@ -195,6 +196,8 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput
status = "Paused"
case define.ContainerStateCreated.String(), define.ContainerStateConfigured.String():
status = "Created"
+ case define.ContainerStateRemoving.String():
+ status = "Removing"
default:
status = "Error"
}
@@ -272,7 +275,8 @@ func worker(wg *sync.WaitGroup, jobs <-chan workerInput, results chan<- PsContai
}
}
-func generateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
+// GenerateContainerFilterFuncs return ContainerFilter functions based of filter.
+func GenerateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) {
switch filter {
case "id":
return func(c *libpod.Container) bool {
@@ -394,6 +398,22 @@ func generateContainerFilterFuncs(filter, filterValue string, r *libpod.Runtime)
}
return hcStatus == filterValue
}, nil
+ case "until":
+ ts, err := timetype.GetTimestamp(filterValue, time.Now())
+ if err != nil {
+ return nil, err
+ }
+ seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
+ if err != nil {
+ return nil, err
+ }
+ until := time.Unix(seconds, nanoseconds)
+ return func(c *libpod.Container) bool {
+ if !until.IsZero() && c.CreatedTime().After((until)) {
+ return true
+ }
+ return false
+ }, nil
}
return nil, errors.Errorf("%s is an invalid filter", filter)
}
@@ -411,7 +431,7 @@ func GetPsContainerOutput(r *libpod.Runtime, opts PsOptions, filters []string, m
if len(filterSplit) < 2 {
return nil, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
}
- generatedFunc, err := generateContainerFilterFuncs(filterSplit[0], filterSplit[1], r)
+ generatedFunc, err := GenerateContainerFilterFuncs(filterSplit[0], filterSplit[1], r)
if err != nil {
return nil, errors.Wrapf(err, "invalid filter")
}
@@ -453,7 +473,7 @@ func PBatch(containers []*libpod.Container, workers int, opts PsOptions) []PsCon
psResults := []PsContainerOutput{}
// If the number of containers in question is less than the number of
- // proposed parallel operations, we shouldnt spawn so many workers.
+ // proposed parallel operations, we shouldn't spawn so many workers.
if workers > len(containers) {
workers = len(containers)
}
@@ -694,7 +714,7 @@ func portsToString(ports []ocicni.PortMapping) string {
portgroup, ok := portGroupMap[portMapKey]
if !ok {
portGroupMap[portMapKey] = &portGroup{first: v.ContainerPort, last: v.ContainerPort}
- // This list is required to travese portGroupMap.
+ // This list is required to traverse portGroupMap.
groupKeyList = append(groupKeyList, portMapKey)
continue
}
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index c7ea2e389..bb4e9cd12 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
+ goruntime "runtime"
"strconv"
"strings"
"syscall"
@@ -88,9 +89,11 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
return nil, nil, err
}
+ overrideOS := c.String("override-os")
+ overrideArch := c.String("override-arch")
dockerRegistryOptions := image.DockerRegistryOptions{
- OSChoice: c.String("override-os"),
- ArchitectureChoice: c.String("override-arch"),
+ OSChoice: overrideOS,
+ ArchitectureChoice: overrideArch,
}
newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType)
@@ -101,6 +104,15 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
if err != nil {
return nil, nil, err
}
+
+ if overrideOS == "" && data.Os != goruntime.GOOS {
+ return nil, nil, errors.Errorf("incompatible image OS %q on %q host", data.Os, goruntime.GOOS)
+ }
+
+ if overrideArch == "" && data.Architecture != goruntime.GOARCH {
+ return nil, nil, errors.Errorf("incompatible image architecture %q on %q host", data.Architecture, goruntime.GOARCH)
+ }
+
names := newImage.Names()
if len(names) > 0 {
imageName = names[0]
@@ -111,7 +123,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
// if the user disabled the healthcheck with "none", we skip adding it
healthCheckCommandInput := c.String("healthcheck-command")
- // the user didnt disable the healthcheck but did pass in a healthcheck command
+ // the user didn't disable the healthcheck but did pass in a healthcheck command
// now we need to make a healthcheck from the commandline input
if healthCheckCommandInput != "none" {
if len(healthCheckCommandInput) > 0 {
@@ -214,24 +226,24 @@ func configureEntrypoint(c *GenericCLIResults, data *inspect.ImageData) []string
return entrypoint
}
-func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) {
+func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, string, error) {
pod, err := runtime.LookupPod(podName)
if err != nil {
- return namespaces, err
+ return namespaces, "", err
}
podInfraID, err := pod.InfraContainerID()
if err != nil {
- return namespaces, err
+ return namespaces, "", err
}
hasUserns := false
if podInfraID != "" {
podCtr, err := runtime.GetContainer(podInfraID)
if err != nil {
- return namespaces, err
+ return namespaces, "", err
}
mappings, err := podCtr.IDMappings()
if err != nil {
- return namespaces, err
+ return namespaces, "", err
}
hasUserns = len(mappings.UIDMap) > 0
}
@@ -251,7 +263,7 @@ func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[
if (namespaces["uts"] == cc.Pod) || (!c.IsSet("uts") && pod.SharesUTS()) {
namespaces["uts"] = fmt.Sprintf("container:%s", podInfraID)
}
- return namespaces, nil
+ return namespaces, podInfraID, nil
}
// Parses CLI options related to container creation into a config which can be
@@ -359,6 +371,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
if len(podName) < 1 && c.IsSet("pod") {
return nil, errors.Errorf("new pod name must be at least one character")
}
+
+ // If we are adding a container to a pod, we would like to add an annotation for the infra ID
+ // so kata containers can share VMs inside the pod
+ var podInfraID string
if c.IsSet("pod") {
if strings.HasPrefix(originalPodName, "new:") {
// pod does not exist; lets make it
@@ -387,7 +403,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
// The container now cannot have port bindings; so we reset the map
portBindings = make(map[nat.Port][]nat.PortBinding)
}
- namespaces, err = configurePod(c, runtime, namespaces, podName)
+ namespaces, podInfraID, err = configurePod(c, runtime, namespaces, podName)
if err != nil {
return nil, err
}
@@ -485,12 +501,26 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
// ANNOTATIONS
annotations := make(map[string]string)
+
// First, add our default annotations
- annotations[ann.ContainerType] = "sandbox"
annotations[ann.TTY] = "false"
if tty {
annotations[ann.TTY] = "true"
}
+
+ // in the event this container is in a pod, and the pod has an infra container
+ // we will want to configure it as a type "container" instead defaulting to
+ // the behavior of a "sandbox" container
+ // In Kata containers:
+ // - "sandbox" is the annotation that denotes the container should use its own
+ // VM, which is the default behavior
+ // - "container" denotes the container should join the VM of the SandboxID
+ // (the infra container)
+ if podInfraID != "" {
+ annotations[ann.SandboxID] = podInfraID
+ annotations[ann.ContainerType] = ann.ContainerTypeContainer
+ }
+
if data != nil {
// Next, add annotations from the image
for key, value := range data.Annotations {
diff --git a/cmd/podman/shared/parallel.go b/cmd/podman/shared/parallel.go
index e6ce50f95..eb1d40073 100644
--- a/cmd/podman/shared/parallel.go
+++ b/cmd/podman/shared/parallel.go
@@ -72,7 +72,7 @@ func ParallelExecuteWorkerPool(workers int, functions []ParallelWorkerInput) (ma
}
// Parallelize provides the maximum number of parallel workers (int) as calculated by a basic
-// heuristic. This can be overriden by the --max-workers primary switch to podman.
+// heuristic. This can be overridden by the --max-workers primary switch to podman.
func Parallelize(job string) int {
numCpus := runtime.NumCPU()
switch job {
diff --git a/cmd/podman/shared/parse/parse_test.go b/cmd/podman/shared/parse/parse_test.go
index 0a221c244..1359076a0 100644
--- a/cmd/podman/shared/parse/parse_test.go
+++ b/cmd/podman/shared/parse/parse_test.go
@@ -82,8 +82,8 @@ func TestValidateFileName(t *testing.T) {
args args
wantErr bool
}{
- {name: "good", args: args{filename: "/som/rand/path"}, wantErr: false},
- {name: "good", args: args{filename: "som/rand/path"}, wantErr: false},
+ {name: "good", args: args{filename: "/some/rand/path"}, wantErr: false},
+ {name: "good", args: args{filename: "some/rand/path"}, wantErr: false},
{name: "good", args: args{filename: "/"}, wantErr: false},
{name: "bad", args: args{filename: "/:"}, wantErr: true},
{name: "bad", args: args{filename: ":/"}, wantErr: true},
diff --git a/cmd/podman/shared/workers.go b/cmd/podman/shared/workers.go
index b6e3f10e7..a9d6bb77e 100644
--- a/cmd/podman/shared/workers.go
+++ b/cmd/podman/shared/workers.go
@@ -106,7 +106,7 @@ func (p *Pool) newWorker(slot int) {
}
// DefaultPoolSize provides the maximum number of parallel workers (int) as calculated by a basic
-// heuristic. This can be overriden by the --max-workers primary switch to podman.
+// heuristic. This can be overridden by the --max-workers primary switch to podman.
func DefaultPoolSize(name string) int {
numCpus := runtime.NumCPU()
switch name {
diff --git a/cmd/podman/start.go b/cmd/podman/start.go
index d4b4534bb..a070cd18d 100644
--- a/cmd/podman/start.go
+++ b/cmd/podman/start.go
@@ -35,6 +35,9 @@ func init() {
startCommand.SetUsageTemplate(UsageTemplate())
flags := startCommand.Flags()
flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
+ // Clear the default, the value specified in the config file should have the
+ // priority
+ startCommand.DetachKeys = ""
flags.StringVar(&startCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `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")
diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go
index f8c476386..f53e09412 100644
--- a/cmd/podman/stats.go
+++ b/cmd/podman/stats.go
@@ -128,7 +128,7 @@ func statsCmd(c *cliconfig.StatsValues) error {
for _, ctr := range ctrs {
initialStats, err := ctr.GetContainerStats(&libpod.ContainerStats{})
if err != nil {
- // when doing "all", dont worry about containers that are not running
+ // when doing "all", don't worry about containers that are not running
cause := errors.Cause(err)
if c.All && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) {
continue
diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go
index e04d8a12b..c62da80df 100644
--- a/cmd/podman/stop.go
+++ b/cmd/podman/stop.go
@@ -25,7 +25,7 @@ var (
return stopCmd(&stopCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, true)
},
Example: `podman stop ctrID
podman stop --latest
@@ -39,10 +39,14 @@ func init() {
stopCommand.SetUsageTemplate(UsageTemplate())
flags := stopCommand.Flags()
flags.BoolVarP(&stopCommand.All, "all", "a", false, "Stop all running containers")
+ flags.BoolVarP(&stopCommand.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing")
+ flags.StringArrayVarP(&stopCommand.CIDFiles, "cidfile", "", nil, "Read the container ID from the file")
flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.UintVar(&stopCommand.Timeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
flags.UintVarP(&stopCommand.Timeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
markFlagHiddenForRemoteClient("latest", flags)
+ markFlagHiddenForRemoteClient("cidfile", flags)
+ markFlagHiddenForRemoteClient("ignore", flags)
}
// stopCmd stops a container or containers
diff --git a/cmd/podman/system.go b/cmd/podman/system.go
index 80080bf44..921d0c037 100644
--- a/cmd/podman/system.go
+++ b/cmd/podman/system.go
@@ -19,6 +19,7 @@ var (
)
var systemCommands = []*cobra.Command{
+ _systemResetCommand,
_infoCommand,
_pruneSystemCommand,
}
diff --git a/cmd/podman/system_prune.go b/cmd/podman/system_prune.go
index b499d8dd2..74fdcde99 100644
--- a/cmd/podman/system_prune.go
+++ b/cmd/podman/system_prune.go
@@ -82,7 +82,6 @@ Are you sure you want to continue? [y/N] `, volumeString)
fmt.Println("Deleted Pods")
pruneValues := cliconfig.PodPruneValues{
PodmanCommand: c.PodmanCommand,
- Force: c.Force,
}
ctx := getContext()
ok, failures, lasterr := runtime.PrunePods(ctx, &pruneValues)
@@ -93,7 +92,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
rmWorkers := shared.Parallelize("rm")
fmt.Println("Deleted Containers")
- ok, failures, err = runtime.Prune(ctx, rmWorkers, false)
+ ok, failures, err = runtime.Prune(ctx, rmWorkers, false, []string{})
if err != nil {
if lasterr != nil {
logrus.Errorf("%q", err)
@@ -117,7 +116,8 @@ 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(ctx, c.All)
+ // TODO: support for filters in system prune
+ pruneCids, err := runtime.PruneImages(ctx, c.All, []string{})
if len(pruneCids) > 0 {
fmt.Println("Deleted Images")
for _, cid := range pruneCids {
diff --git a/cmd/podman/system_renumber.go b/cmd/podman/system_renumber.go
index 81752a177..4e90a2d8c 100644
--- a/cmd/podman/system_renumber.go
+++ b/cmd/podman/system_renumber.go
@@ -44,9 +44,7 @@ func renumberCmd(c *cliconfig.SystemRenumberValues) error {
if err != nil {
return errors.Wrapf(err, "error renumbering locks")
}
- if err := r.Shutdown(false); err != nil {
- return err
- }
+ _ = r.Shutdown(false)
return nil
}
diff --git a/cmd/podman/tree.go b/cmd/podman/tree.go
index 904a0d375..cb1b3fc9c 100644
--- a/cmd/podman/tree.go
+++ b/cmd/podman/tree.go
@@ -115,7 +115,7 @@ func printImageChildren(layerMap map[string]*image.LayerInfo, layerID string, pr
// add continueItem i.e. '|' for next iteration prefix
prefix = prefix + continueItem
} else if len(ll.ChildID) > 1 || len(ll.ChildID) == 0 {
- // The above condition ensure, alignment happens for node, which has more then 1 childern.
+ // The above condition ensure, alignment happens for node, which has more then 1 children.
// If node is last in printing hierarchy, it should not be printed as middleItem i.e. ├──
intend = lastItem
prefix = prefix + " "
diff --git a/cmd/podman/umount.go b/cmd/podman/umount.go
index c3d81d3a8..6ad485c2c 100644
--- a/cmd/podman/umount.go
+++ b/cmd/podman/umount.go
@@ -28,7 +28,7 @@ var (
return umountCmd(&umountCommand)
},
Args: func(cmd *cobra.Command, args []string) error {
- return checkAllAndLatest(cmd, args, false)
+ return checkAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman umount ctrID
podman umount ctrID1 ctrID2 ctrID3
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index f9339fccb..2251050c3 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -70,7 +70,8 @@ type Image (
labels: [string]string,
isParent: bool,
topLayer: string,
- readOnly: bool
+ readOnly: bool,
+ history: []string
)
# ImageHistory describes the returned structure from ImageHistory.
@@ -535,6 +536,10 @@ method GetVersion() -> (
remote_api_version: int
)
+# Reset resets Podman back to its initial state.
+# Removes all Pods, Containers, Images and Volumes
+method Reset() -> ()
+
# GetInfo returns a [PodmanInfo](#PodmanInfo) struct that describes podman and its host such as storage stats,
# build information of Podman, and system-wide registries.
method GetInfo() -> (info: PodmanInfo)
@@ -779,6 +784,11 @@ method DeleteStoppedContainers() -> (containers: []string)
# See also [InspectImage](#InspectImage).
method ListImages() -> (images: []Image)
+# ListImagesWithFilters returns information about the images that are currently in storage
+# after one or more filters has been applied.
+# See also [InspectImage](#InspectImage).
+method ListImagesWithFilters(filters: []string) -> (images: []Image)
+
# GetImage returns information about a single image in storage.
# If the image caGetImage returns be found, [ImageNotFound](#ImageNotFound) will be returned.
method GetImage(id: string) -> (image: Image)
@@ -1217,7 +1227,7 @@ method UnmountContainer(name: string, force: bool) -> ()
# ImagesPrune removes all unused images from the local store. Upon successful pruning,
# the IDs of the removed images are returned.
-method ImagesPrune(all: bool) -> (pruned: []string)
+method ImagesPrune(all: bool, filter: []string) -> (pruned: []string)
# This function is not implemented yet.
# method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
diff --git a/cmd/podman/version.go b/cmd/podman/version.go
index 314b2e266..5907241ff 100644
--- a/cmd/podman/version.go
+++ b/cmd/podman/version.go
@@ -37,13 +37,40 @@ func init() {
flags := versionCommand.Flags()
flags.StringVarP(&versionCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
}
+func getRemoteVersion(c *cliconfig.VersionValues) (version define.Version, err error) {
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return version, errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.DeferredShutdown(false)
+
+ return runtime.GetVersion()
+}
+
+type versionStruct struct {
+ Client define.Version
+ Server define.Version
+}
// versionCmd gets and prints version info for version command
func versionCmd(c *cliconfig.VersionValues) error {
- clientVersion, err := define.GetVersion()
+
+ var (
+ v versionStruct
+ err error
+ )
+ v.Client, err = define.GetVersion()
if err != nil {
return errors.Wrapf(err, "unable to determine version")
}
+ if remote {
+ v.Server, err = getRemoteVersion(c)
+ if err != nil {
+ return err
+ }
+ } else {
+ v.Server = v.Client
+ }
versionOutputFormat := c.Format
if versionOutputFormat != "" {
@@ -53,11 +80,20 @@ func versionCmd(c *cliconfig.VersionValues) error {
var out formats.Writer
switch versionOutputFormat {
case formats.JSONString:
- out = formats.JSONStruct{Output: clientVersion}
+ out = formats.JSONStruct{Output: v}
+ return out.Out()
default:
- out = formats.StdoutTemplate{Output: clientVersion, Template: versionOutputFormat}
+ out = formats.StdoutTemplate{Output: v, Template: versionOutputFormat}
+ err := out.Out()
+ if err != nil {
+ // On Failure, assume user is using older version of podman version --format and check client
+ out = formats.StdoutTemplate{Output: v.Client, Template: versionOutputFormat}
+ if err1 := out.Out(); err1 != nil {
+ return err
+ }
+ }
}
- return out.Out()
+ return nil
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
defer w.Flush()
@@ -66,25 +102,13 @@ func versionCmd(c *cliconfig.VersionValues) error {
if _, err := fmt.Fprintf(w, "Client:\n"); err != nil {
return err
}
- }
- formatVersion(w, clientVersion)
-
- if remote {
- if _, err := fmt.Fprintf(w, "\nService:\n"); err != nil {
- return err
- }
-
- runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
- if err != nil {
- return errors.Wrapf(err, "could not get runtime")
- }
- defer runtime.DeferredShutdown(false)
-
- serviceVersion, err := runtime.GetVersion()
- if err != nil {
+ formatVersion(w, v.Client)
+ if _, err := fmt.Fprintf(w, "\nServer:\n"); err != nil {
return err
}
- formatVersion(w, serviceVersion)
+ formatVersion(w, v.Server)
+ } else {
+ formatVersion(w, v.Client)
}
return nil
}