summaryrefslogtreecommitdiff
path: root/cmd/podman/shared
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/shared')
-rw-r--r--cmd/podman/shared/create.go145
-rw-r--r--cmd/podman/shared/funcs_linux_test.go119
-rw-r--r--cmd/podman/shared/funcs_test.go112
-rw-r--r--cmd/podman/shared/intermediate_varlink.go3
-rw-r--r--cmd/podman/shared/pod.go142
5 files changed, 365 insertions, 156 deletions
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index 8968f10e8..5fa8d6c0b 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -18,6 +18,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
ann "github.com/containers/libpod/pkg/annotations"
+ "github.com/containers/libpod/pkg/autoupdate"
envLib "github.com/containers/libpod/pkg/env"
"github.com/containers/libpod/pkg/errorhandling"
"github.com/containers/libpod/pkg/inspect"
@@ -25,6 +26,7 @@ import (
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/seccomp"
cc "github.com/containers/libpod/pkg/spec"
+ systemdGen "github.com/containers/libpod/pkg/systemd/generate"
"github.com/containers/libpod/pkg/util"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
@@ -69,6 +71,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
imageName := ""
+ rawImageName := ""
var imageData *inspect.ImageData = nil
// Set the storage if there is no rootfs specified
@@ -78,9 +81,8 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
writer = os.Stderr
}
- name := ""
if len(c.InputArgs) != 0 {
- name = c.InputArgs[0]
+ rawImageName = c.InputArgs[0]
} else {
return nil, nil, errors.Errorf("error, image name not provided")
}
@@ -97,7 +99,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
ArchitectureChoice: overrideArch,
}
- newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType)
+ newImage, err := runtime.ImageRuntime().New(ctx, rawImageName, rtc.Engine.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType)
if err != nil {
return nil, nil, err
}
@@ -174,11 +176,32 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
- createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, imageData)
+ createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, rawImageName, imageData)
if err != nil {
return nil, nil, err
}
+ // (VR): Ideally we perform the checks _before_ pulling the image but that
+ // would require some bigger code refactoring of `ParseCreateOpts` and the
+ // logic here. But as the creation code will be consolidated in the future
+ // and given auto updates are experimental, we can live with that for now.
+ // In the end, the user may only need to correct the policy or the raw image
+ // name.
+ autoUpdatePolicy, autoUpdatePolicySpecified := createConfig.Labels[autoupdate.Label]
+ if autoUpdatePolicySpecified {
+ if _, err := autoupdate.LookupPolicy(autoUpdatePolicy); err != nil {
+ return nil, nil, err
+ }
+ // Now we need to make sure we're having a fully-qualified image reference.
+ if rootfs != "" {
+ return nil, nil, errors.Errorf("auto updates do not work with --rootfs")
+ }
+ // Make sure the input image is a docker.
+ if err := autoupdate.ValidateImageReference(rawImageName); err != nil {
+ return nil, nil, err
+ }
+ }
+
// Because parseCreateOpts does derive anything from the image, we add health check
// at this point. The rest is done by WithOptions.
createConfig.HealthCheck = healthCheck
@@ -270,7 +293,7 @@ func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[
// 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 *GenericCLIResults, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
+func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime, imageName string, rawImageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
var (
inputCommand, command []string
memoryLimit, memoryReservation, memorySwap, memoryKernel int64
@@ -481,12 +504,16 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
"container": "podman",
}
+ // First transform the os env into a map. We need it for the labels later in
+ // any case.
+ osEnv, err := envLib.ParseSlice(os.Environ())
+ if err != nil {
+ return nil, errors.Wrap(err, "error parsing host environment variables")
+ }
+
// Start with env-host
+
if c.Bool("env-host") {
- osEnv, err := envLib.ParseSlice(os.Environ())
- if err != nil {
- return nil, errors.Wrap(err, "error parsing host environment variables")
- }
env = envLib.Join(env, osEnv)
}
@@ -534,6 +561,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
+ if systemdUnit, exists := osEnv[systemdGen.EnvVariable]; exists {
+ labels[systemdGen.EnvVariable] = systemdUnit
+ }
+
// ANNOTATIONS
annotations := make(map[string]string)
@@ -605,7 +636,6 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
if err != nil {
return nil, errors.Wrapf(err, "unable to translate --shm-size")
}
-
// Verify the additional hosts are in correct format
for _, host := range c.StringSlice("add-host") {
if _, err := parse.ValidateExtraHost(host); err != nil {
@@ -613,24 +643,35 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
- // Check for . and dns-search domains
- if util.StringInSlice(".", c.StringSlice("dns-search")) && len(c.StringSlice("dns-search")) > 1 {
- return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
+ var (
+ dnsSearches []string
+ dnsServers []string
+ dnsOptions []string
+ )
+ if c.Changed("dns-search") {
+ dnsSearches = c.StringSlice("dns-search")
+ // Check for explicit dns-search domain of ''
+ if len(dnsSearches) == 0 {
+ return nil, errors.Errorf("'' is not a valid domain")
+ }
+ // Validate domains are good
+ for _, dom := range dnsSearches {
+ if dom == "." {
+ if len(dnsSearches) > 1 {
+ return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'")
+ }
+ continue
+ }
+ if _, err := parse.ValidateDomain(dom); err != nil {
+ return nil, err
+ }
+ }
}
-
- // Check for explicit dns-search domain of ''
- if c.Changed("dns-search") && len(c.StringSlice("dns-search")) == 0 {
- return nil, errors.Errorf("'' is not a valid domain")
+ if c.IsSet("dns") {
+ dnsServers = append(dnsServers, c.StringSlice("dns")...)
}
-
- // Validate domains are good
- for _, dom := range c.StringSlice("dns-search") {
- if dom == "." {
- continue
- }
- if _, err := parse.ValidateDomain(dom); err != nil {
- return nil, err
- }
+ if c.IsSet("dns-opt") {
+ dnsOptions = c.StringSlice("dns-opt")
}
var ImageVolumes map[string]struct{}
@@ -676,7 +717,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
pidsLimit := c.Int64("pids-limit")
if c.String("cgroups") == "disabled" && !c.Changed("pids-limit") {
- pidsLimit = 0
+ pidsLimit = -1
}
pid := &cc.PidConfig{
@@ -706,11 +747,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
HostAdd: c.StringSlice("add-host"),
Hostname: c.String("hostname"),
}
-
net := &cc.NetworkConfig{
- DNSOpt: c.StringSlice("dns-opt"),
- DNSSearch: c.StringSlice("dns-search"),
- DNSServers: c.StringSlice("dns"),
+ DNSOpt: dnsOptions,
+ DNSSearch: dnsSearches,
+ DNSServers: dnsServers,
HTTPProxy: c.Bool("http-proxy"),
MacAddress: c.String("mac-address"),
Network: c.String("network"),
@@ -721,9 +761,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
PortBindings: portBindings,
}
- sysctl, err := validateSysctl(c.StringSlice("sysctl"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for sysctl")
+ sysctl := map[string]string{}
+ if c.Changed("sysctl") {
+ sysctl, err = util.ValidateSysctls(c.StringSlice("sysctl"))
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid value for sysctl")
+ }
}
secConfig := &cc.SecurityConfig{
@@ -735,8 +778,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
Sysctl: sysctl,
}
- if err := secConfig.SetSecurityOpts(runtime, c.StringArray("security-opt")); err != nil {
- return nil, err
+ if c.Changed("security-opt") {
+ if err := secConfig.SetSecurityOpts(runtime, c.StringArray("security-opt")); err != nil {
+ return nil, err
+ }
}
// SECCOMP
@@ -750,6 +795,19 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
} else {
secConfig.SeccompPolicy = policy
}
+ rtc, err := runtime.GetConfig()
+ if err != nil {
+ return nil, err
+ }
+ volumes := rtc.Containers.Volumes
+ if c.Changed("volume") {
+ volumes = append(volumes, c.StringSlice("volume")...)
+ }
+
+ devices := rtc.Containers.Devices
+ if c.Changed("device") {
+ devices = append(devices, c.StringSlice("device")...)
+ }
config := &cc.CreateConfig{
Annotations: annotations,
@@ -760,15 +818,16 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
Command: command,
UserCommand: userCommand,
Detach: c.Bool("detach"),
- Devices: c.StringSlice("device"),
+ Devices: devices,
Entrypoint: entrypoint,
Env: env,
// ExposedPorts: ports,
- Init: c.Bool("init"),
- InitPath: c.String("init-path"),
- Image: imageName,
- ImageID: imageID,
- Interactive: c.Bool("interactive"),
+ Init: c.Bool("init"),
+ InitPath: c.String("init-path"),
+ Image: imageName,
+ RawImageName: rawImageName,
+ ImageID: imageID,
+ Interactive: c.Bool("interactive"),
// IP6Address: c.String("ipv6"), // Not implemented yet - needs CNI support for static v6
Labels: labels,
// LinkLocalIP: c.StringSlice("link-local-ip"), // Not implemented yet
@@ -814,7 +873,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
Tmpfs: c.StringArray("tmpfs"),
Tty: tty,
MountsFlag: c.StringArray("mount"),
- Volumes: c.StringArray("volume"),
+ Volumes: volumes,
WorkDir: workDir,
Rootfs: rootfs,
VolumesFrom: c.StringSlice("volumes-from"),
diff --git a/cmd/podman/shared/funcs_linux_test.go b/cmd/podman/shared/funcs_linux_test.go
new file mode 100644
index 000000000..88571153f
--- /dev/null
+++ b/cmd/podman/shared/funcs_linux_test.go
@@ -0,0 +1,119 @@
+package shared
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGenerateCommand(t *testing.T) {
+ inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo \"hello world\""
+ correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo hello world"
+ newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "")
+ assert.Nil(t, err)
+ assert.Equal(t, "hello world", newCommand[11])
+ assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
+}
+
+func TestGenerateCommandCheckSubstitution(t *testing.T) {
+ type subsTest struct {
+ input string
+ expected string
+ shouldFail bool
+ }
+
+ absTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestAbsolutePath")
+ assert.Nil(t, err, "error creating tempfile")
+ defer os.Remove(absTmpFile.Name())
+
+ relTmpFile, err := ioutil.TempFile("./", "podmanRunlabelTestRelativePath")
+ assert.Nil(t, err, "error creating tempfile")
+ defer os.Remove(relTmpFile.Name())
+ relTmpCmd, err := filepath.Abs(relTmpFile.Name())
+ assert.Nil(t, err, "error getting absolute path for relative tmpfile")
+
+ // this has a (low) potential of race conditions but no other way
+ removedTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestRemove")
+ assert.Nil(t, err, "error creating tempfile")
+ os.Remove(removedTmpFile.Name())
+
+ absTmpCmd := fmt.Sprintf("%s --flag1 --flag2 --args=foo", absTmpFile.Name())
+ tests := []subsTest{
+ {
+ input: "docker run -it alpine:latest",
+ expected: "/proc/self/exe run -it alpine:latest",
+ shouldFail: false,
+ },
+ {
+ input: "podman run -it alpine:latest",
+ expected: "/proc/self/exe run -it alpine:latest",
+ shouldFail: false,
+ },
+ {
+ input: absTmpCmd,
+ expected: absTmpCmd,
+ shouldFail: false,
+ },
+ {
+ input: "./" + relTmpFile.Name(),
+ expected: relTmpCmd,
+ shouldFail: false,
+ },
+ {
+ input: "ls -la",
+ expected: "ls -la",
+ shouldFail: false,
+ },
+ {
+ input: removedTmpFile.Name(),
+ expected: "",
+ shouldFail: true,
+ },
+ }
+
+ for _, test := range tests {
+ newCommand, err := GenerateCommand(test.input, "foo", "bar", "")
+ if test.shouldFail {
+ assert.NotNil(t, err)
+ } else {
+ assert.Nil(t, err)
+ }
+ assert.Equal(t, test.expected, strings.Join(newCommand, " "))
+ }
+}
+
+func TestGenerateCommandPath(t *testing.T) {
+ inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
+ correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
+ newCommand, _ := GenerateCommand(inputCommand, "foo", "bar", "")
+ assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
+}
+
+func TestGenerateCommandNoSetName(t *testing.T) {
+ inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
+ correctCommand := "/proc/self/exe run -it --name foo -e NAME=foo -e IMAGE=foo foo echo install"
+ newCommand, err := GenerateCommand(inputCommand, "foo", "", "")
+ assert.Nil(t, err)
+ assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
+}
+
+func TestGenerateCommandNoName(t *testing.T) {
+ inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
+ correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install"
+ newCommand, err := GenerateCommand(inputCommand, "foo", "", "")
+ assert.Nil(t, err)
+ assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
+}
+
+func TestGenerateCommandAlreadyPodman(t *testing.T) {
+ inputCommand := "podman run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
+ correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
+ newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "")
+ assert.Nil(t, err)
+ assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
+}
diff --git a/cmd/podman/shared/funcs_test.go b/cmd/podman/shared/funcs_test.go
index c05348242..dd856166e 100644
--- a/cmd/podman/shared/funcs_test.go
+++ b/cmd/podman/shared/funcs_test.go
@@ -1,11 +1,6 @@
package shared
import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
"testing"
"github.com/containers/libpod/pkg/util"
@@ -17,113 +12,6 @@ var (
imageName = "bar"
)
-func TestGenerateCommand(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo \"hello world\""
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo hello world"
- newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "")
- assert.Nil(t, err)
- assert.Equal(t, "hello world", newCommand[11])
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandCheckSubstitution(t *testing.T) {
- type subsTest struct {
- input string
- expected string
- shouldFail bool
- }
-
- absTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestAbsolutePath")
- assert.Nil(t, err, "error creating tempfile")
- defer os.Remove(absTmpFile.Name())
-
- relTmpFile, err := ioutil.TempFile("./", "podmanRunlabelTestRelativePath")
- assert.Nil(t, err, "error creating tempfile")
- defer os.Remove(relTmpFile.Name())
- relTmpCmd, err := filepath.Abs(relTmpFile.Name())
- assert.Nil(t, err, "error getting absolute path for relative tmpfile")
-
- // this has a (low) potential of race conditions but no other way
- removedTmpFile, err := ioutil.TempFile("", "podmanRunlabelTestRemove")
- assert.Nil(t, err, "error creating tempfile")
- os.Remove(removedTmpFile.Name())
-
- absTmpCmd := fmt.Sprintf("%s --flag1 --flag2 --args=foo", absTmpFile.Name())
- tests := []subsTest{
- {
- input: "docker run -it alpine:latest",
- expected: "/proc/self/exe run -it alpine:latest",
- shouldFail: false,
- },
- {
- input: "podman run -it alpine:latest",
- expected: "/proc/self/exe run -it alpine:latest",
- shouldFail: false,
- },
- {
- input: absTmpCmd,
- expected: absTmpCmd,
- shouldFail: false,
- },
- {
- input: "./" + relTmpFile.Name(),
- expected: relTmpCmd,
- shouldFail: false,
- },
- {
- input: "ls -la",
- expected: "ls -la",
- shouldFail: false,
- },
- {
- input: removedTmpFile.Name(),
- expected: "",
- shouldFail: true,
- },
- }
-
- for _, test := range tests {
- newCommand, err := GenerateCommand(test.input, "foo", "bar", "")
- if test.shouldFail {
- assert.NotNil(t, err)
- } else {
- assert.Nil(t, err)
- }
- assert.Equal(t, test.expected, strings.Join(newCommand, " "))
- }
-}
-
-func TestGenerateCommandPath(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
- newCommand, _ := GenerateCommand(inputCommand, "foo", "bar", "")
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandNoSetName(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name foo -e NAME=foo -e IMAGE=foo foo echo install"
- newCommand, err := GenerateCommand(inputCommand, "foo", "", "")
- assert.Nil(t, err)
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandNoName(t *testing.T) {
- inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install"
- newCommand, err := GenerateCommand(inputCommand, "foo", "", "")
- assert.Nil(t, err)
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
-func TestGenerateCommandAlreadyPodman(t *testing.T) {
- inputCommand := "podman run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
- newCommand, err := GenerateCommand(inputCommand, "foo", "bar", "")
- assert.Nil(t, err)
- assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
-}
-
func TestGenerateRunEnvironment(t *testing.T) {
opts := make(map[string]string)
opts["opt1"] = "one"
diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go
index 691c4f92d..d2b048025 100644
--- a/cmd/podman/shared/intermediate_varlink.go
+++ b/cmd/podman/shared/intermediate_varlink.go
@@ -316,6 +316,7 @@ func intFromVarlink(v *int64, flagName string, defaultValue *int) CRInt {
// structure.
func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults {
+ defaultContainerConfig := cliconfig.GetDefaultConfig()
// TODO | WARN
// We do not get a default network over varlink. Unlike the other default values for some cli
// elements, it seems it gets set to the default anyway.
@@ -405,7 +406,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults {
m["rm"] = boolFromVarlink(opts.Rm, "rm", false)
m["rootfs"] = boolFromVarlink(opts.Rootfs, "rootfs", false)
m["security-opt"] = stringArrayFromVarlink(opts.SecurityOpt, "security-opt", nil)
- m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &cliconfig.DefaultShmSize)
+ m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &defaultContainerConfig.Containers.ShmSize)
m["stop-signal"] = stringFromVarlink(opts.StopSignal, "stop-signal", nil)
m["stop-timeout"] = uintFromVarlink(opts.StopTimeout, "stop-timeout", nil)
m["storage-opt"] = stringSliceFromVarlink(opts.StorageOpt, "storage-opt", nil)
diff --git a/cmd/podman/shared/pod.go b/cmd/podman/shared/pod.go
index 7b0b497fc..50bd88e08 100644
--- a/cmd/podman/shared/pod.go
+++ b/cmd/podman/shared/pod.go
@@ -2,9 +2,11 @@ package shared
import (
"strconv"
+ "strings"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/util"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
@@ -134,4 +136,144 @@ func CreatePortBindings(ports []string) ([]ocicni.PortMapping, error) {
return portBindings, nil
}
+// GetPodsWithFilters uses the cliconfig to categorize if the latest pod is required.
+func GetPodsWithFilters(r *libpod.Runtime, filters string) ([]*libpod.Pod, error) {
+ filterFuncs, err := GenerateFilterFunction(r, strings.Split(filters, ","))
+ if err != nil {
+ return nil, err
+ }
+ return FilterAllPodsWithFilterFunc(r, filterFuncs...)
+}
+
+// FilterAllPodsWithFilterFunc retrieves all pods
+// Filters can be provided which will determine which pods are included in the
+// output. Multiple filters are handled by ANDing their output, so only pods
+// matching all filters are returned
+func FilterAllPodsWithFilterFunc(r *libpod.Runtime, filters ...libpod.PodFilter) ([]*libpod.Pod, error) {
+ pods, err := r.Pods(filters...)
+ if err != nil {
+ return nil, err
+ }
+ return pods, nil
+}
+
+// GenerateFilterFunction basically gets the filters based on the input by the user
+// and filter the pod list based on the criteria.
+func GenerateFilterFunction(r *libpod.Runtime, filters []string) ([]libpod.PodFilter, error) {
+ var filterFuncs []libpod.PodFilter
+ for _, f := range filters {
+ filterSplit := strings.SplitN(f, "=", 2)
+ if len(filterSplit) < 2 {
+ return nil, errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
+ }
+ generatedFunc, err := generatePodFilterFuncs(filterSplit[0], filterSplit[1])
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid filter")
+ }
+ filterFuncs = append(filterFuncs, generatedFunc)
+ }
+
+ return filterFuncs, nil
+}
+func generatePodFilterFuncs(filter, filterValue string) (
+ func(pod *libpod.Pod) bool, error) {
+ switch filter {
+ case "ctr-ids":
+ return func(p *libpod.Pod) bool {
+ ctrIds, err := p.AllContainersByID()
+ if err != nil {
+ return false
+ }
+ return util.StringInSlice(filterValue, ctrIds)
+ }, nil
+ case "ctr-names":
+ return func(p *libpod.Pod) bool {
+ ctrs, err := p.AllContainers()
+ if err != nil {
+ return false
+ }
+ for _, ctr := range ctrs {
+ if filterValue == ctr.Name() {
+ return true
+ }
+ }
+ return false
+ }, nil
+ case "ctr-number":
+ return func(p *libpod.Pod) bool {
+ ctrIds, err := p.AllContainersByID()
+ if err != nil {
+ return false
+ }
+
+ fVint, err2 := strconv.Atoi(filterValue)
+ if err2 != nil {
+ return false
+ }
+ return len(ctrIds) == fVint
+ }, nil
+ case "ctr-status":
+ if !util.StringInSlice(filterValue,
+ []string{"created", "restarting", "running", "paused",
+ "exited", "unknown"}) {
+ return nil, errors.Errorf("%s is not a valid status", filterValue)
+ }
+ return func(p *libpod.Pod) bool {
+ ctr_statuses, err := p.Status()
+ if err != nil {
+ return false
+ }
+ for _, ctr_status := range ctr_statuses {
+ state := ctr_status.String()
+ if ctr_status == define.ContainerStateConfigured {
+ state = "created"
+ }
+ if state == filterValue {
+ return true
+ }
+ }
+ return false
+ }, nil
+ case "id":
+ return func(p *libpod.Pod) bool {
+ return strings.Contains(p.ID(), filterValue)
+ }, nil
+ case "name":
+ return func(p *libpod.Pod) bool {
+ return strings.Contains(p.Name(), filterValue)
+ }, nil
+ case "status":
+ if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created"}) {
+ return nil, errors.Errorf("%s is not a valid pod status", filterValue)
+ }
+ return func(p *libpod.Pod) bool {
+ status, err := p.GetPodStatus()
+ if err != nil {
+ return false
+ }
+ if strings.ToLower(status) == filterValue {
+ return true
+ }
+ return false
+ }, nil
+ case "label":
+ var filterArray = strings.SplitN(filterValue, "=", 2)
+ var filterKey = filterArray[0]
+ if len(filterArray) > 1 {
+ filterValue = filterArray[1]
+ } else {
+ filterValue = ""
+ }
+ return func(p *libpod.Pod) bool {
+ for labelKey, labelValue := range p.Labels() {
+ if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
+ return true
+ }
+ }
+ return false
+ }, nil
+ }
+ return nil, errors.Errorf("%s is an invalid filter", filter)
+}
+
var DefaultKernelNamespaces = "cgroup,ipc,net,uts"