summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/commands.go11
-rw-r--r--cmd/podman/commit.go12
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/images.go59
-rw-r--r--cmd/podman/libpodruntime/runtime.go58
-rw-r--r--cmd/podman/ps.go10
-rw-r--r--cmd/podman/pull.go111
-rw-r--r--cmd/podman/shared/container.go5
-rw-r--r--cmd/podman/shared/create.go24
-rw-r--r--cmd/podman/shared/intermediate.go1
10 files changed, 165 insertions, 130 deletions
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index ebd7aeb0c..d6018a6f4 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -26,9 +26,6 @@ func getMainCommands() []*cobra.Command {
if len(_varlinkCommand.Use) > 0 {
rootCommands = append(rootCommands, _varlinkCommand)
}
- if len(_serviceCommand.Use) > 0 {
- rootCommands = append(rootCommands, _serviceCommand)
- }
return rootCommands
}
@@ -71,9 +68,15 @@ func getTrustSubCommands() []*cobra.Command {
// Commands that the local client implements
func getSystemSubCommands() []*cobra.Command {
- return []*cobra.Command{
+ systemCommands := []*cobra.Command{
_renumberCommand,
_dfSystemCommand,
_migrateCommand,
}
+
+ if len(_serviceCommand.Use) > 0 {
+ systemCommands = append(systemCommands, _serviceCommand)
+ }
+
+ return systemCommands
}
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index 604e8d31c..b4d249c66 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -6,7 +6,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
- "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -65,17 +64,6 @@ func commitCmd(c *cliconfig.CommitValues) error {
if len(args) > 1 {
reference = args[1]
}
- if c.Flag("change").Changed {
- for _, change := range c.Change {
- splitChange := strings.Split(strings.ToUpper(change), "=")
- if len(splitChange) == 1 {
- splitChange = strings.Split(strings.ToUpper(change), " ")
- }
- if !util.StringInSlice(splitChange[0], ChangeCmds) {
- return errors.Errorf("invalid syntax for --change: %s", change)
- }
- }
- }
iid, err := runtime.Commit(getContext(), c, container, reference)
if err != nil {
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 7610edbc0..6fa2b3c71 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -257,6 +257,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"Add a host device to the container (default [])",
)
createFlags.StringSlice(
+ "device-cgroup-rule", []string{},
+ "Add a rule to the cgroup allowed devices list",
+ )
+ createFlags.StringSlice(
"device-read-bps", []string{},
"Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
)
diff --git a/cmd/podman/images.go b/cmd/podman/images.go
index 115f30d9b..de61690ae 100644
--- a/cmd/podman/images.go
+++ b/cmd/podman/images.go
@@ -21,16 +21,16 @@ import (
)
type imagesTemplateParams struct {
- Repository string
- Tag string
- ID string
- Digest digest.Digest
- Digests []digest.Digest
- Created string
- CreatedTime time.Time
- Size string
- ReadOnly bool
- History string
+ Repository string
+ Tag string
+ ID string
+ Digest digest.Digest
+ Digests []digest.Digest
+ CreatedAt time.Time
+ CreatedSince string
+ Size string
+ ReadOnly bool
+ History string
}
type imagesJSONParams struct {
@@ -65,7 +65,7 @@ func (a imagesSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type imagesSortedCreated struct{ imagesSorted }
func (a imagesSortedCreated) Less(i, j int) bool {
- return a.imagesSorted[i].CreatedTime.After(a.imagesSorted[j].CreatedTime)
+ return a.imagesSorted[i].CreatedAt.After(a.imagesSorted[j].CreatedAt)
}
type imagesSortedID struct{ imagesSorted }
@@ -185,7 +185,17 @@ func imagesCmd(c *cliconfig.ImagesValues) error {
history: c.History,
}
- opts.outputformat = opts.setOutputFormat()
+ outputformat := opts.setOutputFormat()
+ // These fields were renamed, so we need to provide backward compat for
+ // the old names.
+ if strings.Contains(outputformat, "{{.Created}}") {
+ outputformat = strings.Replace(outputformat, "{{.Created}}", "{{.CreatedSince}}", -1)
+ }
+ if strings.Contains(outputformat, "{{.CreatedTime}}") {
+ outputformat = strings.Replace(outputformat, "{{.CreatedTime}}", "{{.CreatedAt}}", -1)
+ }
+ opts.outputformat = outputformat
+
filteredImages, err := runtime.GetFilteredImages(filters, false)
if err != nil {
return errors.Wrapf(err, "unable to get images")
@@ -216,7 +226,7 @@ func (i imagesOptions) setOutputFormat() string {
if i.digests {
format += "{{.Digest}}\t"
}
- format += "{{.ID}}\t{{.Created}}\t{{.Size}}\t"
+ format += "{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t"
if i.history {
format += "{{if .History}}{{.History}}{{else}}<none>{{end}}\t"
}
@@ -301,16 +311,16 @@ func getImagesTemplateOutput(ctx context.Context, images []*adapter.ContainerIma
imageDigest = img.Digest()
}
params := imagesTemplateParams{
- Repository: repo,
- Tag: tag,
- ID: imageID,
- Digest: imageDigest,
- Digests: img.Digests(),
- CreatedTime: createdTime,
- Created: units.HumanDuration(time.Since(createdTime)) + " ago",
- Size: sizeStr,
- ReadOnly: img.IsReadOnly(),
- History: strings.Join(img.NamesHistory(), ", "),
+ Repository: repo,
+ Tag: tag,
+ ID: imageID,
+ Digest: imageDigest,
+ Digests: img.Digests(),
+ CreatedAt: createdTime,
+ CreatedSince: 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
@@ -384,6 +394,9 @@ func GenImageOutputMap() map[string]string {
values[key] = "R/O"
continue
}
+ if value == "CreatedSince" {
+ value = "created"
+ }
values[key] = strings.ToUpper(splitCamelCase(value))
}
return values
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index 9425cfb9c..e9dc87de1 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -13,32 +13,66 @@ import (
"github.com/pkg/errors"
)
+type runtimeOptions struct {
+ name string
+ renumber bool
+ migrate bool
+ noStore bool
+ withFDS bool
+}
+
// GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers
func GetRuntimeMigrate(ctx context.Context, c *cliconfig.PodmanCommand, newRuntime string) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, true, false, true, newRuntime)
+ return getRuntime(ctx, c, &runtimeOptions{
+ name: newRuntime,
+ renumber: false,
+ migrate: true,
+ noStore: false,
+ withFDS: true,
+ })
}
// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify
func GetRuntimeDisableFDs(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, false, false, false, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: false,
+ migrate: false,
+ noStore: false,
+ withFDS: false,
+ })
}
// GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber
func GetRuntimeRenumber(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, true, false, false, true, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: true,
+ migrate: false,
+ noStore: false,
+ withFDS: true,
+ })
}
// GetRuntime generates a new libpod runtime configured by command line options
func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, false, false, true, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: false,
+ migrate: false,
+ noStore: false,
+ withFDS: true,
+ })
}
// GetRuntimeNoStore generates a new libpod runtime configured by command line options
func GetRuntimeNoStore(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, false, true, true, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: false,
+ migrate: false,
+ noStore: true,
+ withFDS: true,
+ })
}
-func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore, withFDS bool, newRuntime string) (*libpod.Runtime, error) {
+func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, opts *runtimeOptions) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
storageOpts := storage.StoreOptions{}
storageSet := false
@@ -86,14 +120,14 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
storageSet = true
storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts
}
- if migrate {
+ if opts.migrate {
options = append(options, libpod.WithMigrate())
- if newRuntime != "" {
- options = append(options, libpod.WithMigrateRuntime(newRuntime))
+ if opts.name != "" {
+ options = append(options, libpod.WithMigrateRuntime(opts.name))
}
}
- if renumber {
+ if opts.renumber {
options = append(options, libpod.WithRenumber())
}
@@ -102,7 +136,7 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
options = append(options, libpod.WithStorageConfig(storageOpts))
}
- if !storageSet && noStore {
+ if !storageSet && opts.noStore {
options = append(options, libpod.WithNoStore())
}
// TODO CLI flags for image config?
@@ -174,7 +208,7 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
options = append(options, libpod.WithDefaultInfraCommand(infraCommand))
}
- if !withFDS {
+ if !opts.withFDS {
options = append(options, libpod.WithEnableSDNotify())
}
if c.Flags().Changed("config") {
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index d93ccc24c..accd5b51a 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -205,9 +205,15 @@ func checkFlagsPassed(c *cliconfig.PsValues) error {
if c.Last >= 0 && c.Latest {
return errors.Errorf("last and latest are mutually exclusive")
}
- // Filter forces all
+ // Filter on status forces all
if len(c.Filter) > 0 {
- c.All = true
+ for _, filter := range c.Filter {
+ splitFilter := strings.SplitN(filter, "=", 2)
+ if strings.ToLower(splitFilter[0]) == "status" {
+ c.All = true
+ break
+ }
+ }
}
// Quiet conflicts with size and namespace and is overridden by a Go
// template.
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index 1cbb3f45e..f800d68fe 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -4,7 +4,6 @@ import (
"fmt"
"io"
"os"
- "strings"
buildahcli "github.com/containers/buildah/pkg/cli"
"github.com/containers/image/v5/docker"
@@ -15,6 +14,7 @@ import (
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/util"
+ "github.com/docker/distribution/reference"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -101,18 +101,32 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
}
}
- arr := strings.SplitN(args[0], ":", 2)
- if len(arr) == 2 {
- if c.Bool("all-tags") {
- return errors.Errorf("tag can't be used with --all-tags")
+ ctx := getContext()
+ imageName := args[0]
+
+ imageRef, err := alltransports.ParseImageName(imageName)
+ if err != nil {
+ imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s://%s", docker.Transport.Name(), imageName))
+ if err != nil {
+ return errors.Errorf("invalid image reference %q", imageName)
}
}
- ctx := getContext()
- imgArg := args[0]
+ var writer io.Writer
+ if !c.Quiet {
+ writer = os.Stderr
+ }
+ // Special-case for docker-archive which allows multiple tags.
+ if imageRef.Transport().Name() == dockerarchive.Transport.Name() {
+ newImage, err := runtime.LoadFromArchiveReference(getContext(), imageRef, c.SignaturePolicy, writer)
+ if err != nil {
+ return errors.Wrapf(err, "error pulling image %q", imageName)
+ }
+ fmt.Println(newImage[0].ID())
+ return nil
+ }
var registryCreds *types.DockerAuthConfig
-
if c.Flag("creds").Changed {
creds, err := util.ParseRegistryCreds(c.Creds)
if err != nil {
@@ -120,14 +134,6 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
}
registryCreds = creds
}
-
- var (
- writer io.Writer
- )
- if !c.Quiet {
- writer = os.Stderr
- }
-
dockerRegistryOptions := image.DockerRegistryOptions{
DockerRegistryCreds: registryCreds,
DockerCertPath: c.CertDir,
@@ -138,79 +144,52 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
- // Special-case for docker-archive which allows multiple tags.
- if strings.HasPrefix(imgArg, dockerarchive.Transport.Name()+":") {
- srcRef, err := alltransports.ParseImageName(imgArg)
- if err != nil {
- return errors.Wrapf(err, "error parsing %q", imgArg)
- }
- newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.SignaturePolicy, writer)
- if err != nil {
- return errors.Wrapf(err, "error pulling image from %q", imgArg)
- }
- fmt.Println(newImage[0].ID())
-
- return nil
- }
-
- // FIXME: the default pull consults the registries.conf's search registries
- // while the all-tags pull does not. This behavior must be fixed in the
- // future and span across c/buildah, c/image and c/libpod to avoid redundant
- // and error prone code.
- //
- // See https://bugzilla.redhat.com/show_bug.cgi?id=1701922 for background
- // information.
if !c.Bool("all-tags") {
- newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
+ newImage, err := runtime.New(getContext(), imageName, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
if err != nil {
- return errors.Wrapf(err, "error pulling image %q", imgArg)
+ return errors.Wrapf(err, "error pulling image %q", imageName)
}
fmt.Println(newImage.ID())
return nil
}
- // FIXME: all-tags should use the libpod backend instead of baking its own bread.
- spec := imgArg
- systemContext := image.GetSystemContext("", c.Authfile, false)
- srcRef, err := alltransports.ParseImageName(spec)
+ // --all-tags requires the docker transport
+ if imageRef.Transport().Name() != docker.Transport.Name() {
+ return errors.New("--all-tags requires docker transport")
+ }
+
+ // all-tags doesn't work with a tagged reference, so let's check early
+ namedRef, err := reference.Parse(imageName)
if err != nil {
- dockerTransport := "docker://"
- logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, dockerTransport, err)
- spec = dockerTransport + spec
- srcRef2, err2 := alltransports.ParseImageName(spec)
- if err2 != nil {
- return errors.Wrapf(err2, "error parsing image name %q", imgArg)
- }
- srcRef = srcRef2
+ return errors.Wrapf(err, "error parsing %q", imageName)
}
- var names []string
- if srcRef.DockerReference() == nil {
- return errors.New("Non-docker transport is currently not supported")
+ if _, isTagged := namedRef.(reference.Tagged); isTagged {
+ return errors.New("--all-tags requires a reference without a tag")
+
}
- tags, err := docker.GetRepositoryTags(ctx, systemContext, srcRef)
+
+ systemContext := image.GetSystemContext("", c.Authfile, false)
+ tags, err := docker.GetRepositoryTags(ctx, systemContext, imageRef)
if err != nil {
return errors.Wrapf(err, "error getting repository tags")
}
- for _, tag := range tags {
- name := spec + ":" + tag
- names = append(names, name)
- }
var foundIDs []string
- foundImage := true
- for _, name := range names {
+ for _, tag := range tags {
+ name := imageName + ":" + tag
newImage, err := runtime.New(getContext(), name, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
if err != nil {
logrus.Errorf("error pulling image %q", name)
- foundImage = false
continue
}
foundIDs = append(foundIDs, newImage.ID())
}
- if len(names) == 1 && !foundImage {
- return errors.Wrapf(err, "error pulling image %q", imgArg)
+
+ if len(tags) != len(foundIDs) {
+ return errors.Errorf("error pulling image %q", imageName)
}
- if len(names) > 1 {
+
+ if len(foundIDs) > 1 {
fmt.Println("Pulled Images:")
}
for _, id := range foundIDs {
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index 9459247ed..ff3846e70 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -640,6 +640,11 @@ func GetNamespaces(pid int) *Namespace {
}
}
+// GetNamespaceInfo is an exported wrapper for getNamespaceInfo
+func GetNamespaceInfo(path string) (string, error) {
+ return getNamespaceInfo(path)
+}
+
func getNamespaceInfo(path string) (string, error) {
val, err := os.Readlink(path)
if err != nil {
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index 2f637694b..be5adcccb 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -22,6 +22,7 @@ import (
"github.com/containers/libpod/pkg/inspect"
ns "github.com/containers/libpod/pkg/namespaces"
"github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/seccomp"
cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/util"
"github.com/docker/go-connections/nat"
@@ -31,10 +32,6 @@ import (
"github.com/sirupsen/logrus"
)
-// seccompLabelKey is the key of the image annotation embedding a seccomp
-// profile.
-const seccompLabelKey = "io.containers.seccomp.profile"
-
func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
var (
healthCheck *manifest.Schema2HealthConfig
@@ -109,11 +106,11 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
if overrideOS == "" && imageData.Os != goruntime.GOOS {
- return nil, nil, errors.Errorf("incompatible image OS %q on %q host", imageData.Os, goruntime.GOOS)
+ logrus.Infof("Using %q (OS) image on %q host", imageData.Os, goruntime.GOOS)
}
if overrideArch == "" && imageData.Architecture != goruntime.GOARCH {
- return nil, nil, errors.Errorf("incompatible image architecture %q on %q host", imageData.Architecture, goruntime.GOARCH)
+ logrus.Infof("Using %q (architecture) on %q host", imageData.Architecture, goruntime.GOARCH)
}
names := newImage.Names()
@@ -309,9 +306,13 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
if c.String("memory-swap") != "" {
- memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory-swap")
+ if c.String("memory-swap") == "-1" {
+ memorySwap = -1
+ } else {
+ memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid value for memory-swap")
+ }
}
}
if c.String("kernel-memory") != "" {
@@ -709,11 +710,11 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
// SECCOMP
if data != nil {
- if value, exists := labels[seccompLabelKey]; exists {
+ if value, exists := labels[seccomp.ContainerImageLabel]; exists {
secConfig.SeccompProfileFromImage = value
}
}
- if policy, err := cc.LookupSeccompPolicy(c.String("seccomp-policy")); err != nil {
+ if policy, err := seccomp.LookupPolicy(c.String("seccomp-policy")); err != nil {
return nil, err
} else {
secConfig.SeccompPolicy = policy
@@ -757,6 +758,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
CPURtPeriod: c.Uint64("cpu-rt-period"),
CPURtRuntime: c.Int64("cpu-rt-runtime"),
CPUs: c.Float64("cpus"),
+ DeviceCgroupRules: c.StringSlice("device-cgroup-rule"),
DeviceReadBps: c.StringSlice("device-read-bps"),
DeviceReadIOps: c.StringSlice("device-read-iops"),
DeviceWriteBps: c.StringSlice("device-write-bps"),
diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go
index cfb3f612c..ee212234f 100644
--- a/cmd/podman/shared/intermediate.go
+++ b/cmd/podman/shared/intermediate.go
@@ -386,6 +386,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes
m["detach"] = newCRBool(c, "detach")
m["detach-keys"] = newCRString(c, "detach-keys")
m["device"] = newCRStringSlice(c, "device")
+ m["device-cgroup-rule"] = newCRStringSlice(c, "device-cgroup-rule")
m["device-read-bps"] = newCRStringSlice(c, "device-read-bps")
m["device-read-iops"] = newCRStringSlice(c, "device-read-iops")
m["device-write-bps"] = newCRStringSlice(c, "device-write-bps")