summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/build.go2
-rw-r--r--cmd/podman/cliconfig/config.go14
-rw-r--r--cmd/podman/commands.go2
-rw-r--r--cmd/podman/common.go2
-rw-r--r--cmd/podman/container.go4
-rw-r--r--cmd/podman/errors_remote.go2
-rw-r--r--cmd/podman/generate.go1
-rw-r--r--cmd/podman/generate_systemd.go70
-rw-r--r--cmd/podman/init.go64
-rw-r--r--cmd/podman/libpodruntime/runtime.go6
-rw-r--r--cmd/podman/main.go2
-rw-r--r--cmd/podman/play_kube.go6
-rw-r--r--cmd/podman/port.go35
-rw-r--r--cmd/podman/run_test.go162
-rw-r--r--cmd/podman/search.go13
-rw-r--r--cmd/podman/shared/create.go63
-rw-r--r--cmd/podman/shared/create_cli.go184
-rw-r--r--cmd/podman/shared/parse/parse.go353
-rw-r--r--cmd/podman/shared/parse/parse_test.go99
-rw-r--r--cmd/podman/shared/workers.go5
-rw-r--r--cmd/podman/varlink/io.podman.varlink17
21 files changed, 303 insertions, 803 deletions
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 647ff1e86..24be9bb46 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -267,7 +267,7 @@ func buildCmd(c *cliconfig.BuildValues) error {
MemorySwap: memorySwap,
ShmSize: c.ShmSize,
Ulimit: c.Ulimit,
- Volumes: c.Volume,
+ Volumes: c.Volumes,
}
options := imagebuildah.BuildOptions{
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 77156f47a..b770aaca0 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -136,12 +136,18 @@ type ExportValues struct {
PodmanCommand
Output string
}
-
type GenerateKubeValues struct {
PodmanCommand
Service bool
}
+type GenerateSystemdValues struct {
+ PodmanCommand
+ Name bool
+ RestartPolicy string
+ StopTimeout int
+}
+
type HistoryValues struct {
PodmanCommand
Human bool
@@ -177,6 +183,12 @@ type InfoValues struct {
Format string
}
+type InitValues struct {
+ PodmanCommand
+ All bool
+ Latest bool
+}
+
type InspectValues struct {
PodmanCommand
TypeObject string
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index 4b0641d82..14451d944 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -17,7 +17,6 @@ func getMainCommands() []*cobra.Command {
_loginCommand,
_logoutCommand,
_mountCommand,
- _portCommand,
_refreshCommand,
_searchCommand,
_statsCommand,
@@ -45,7 +44,6 @@ func getContainerSubCommands() []*cobra.Command {
_commitCommand,
_execCommand,
_mountCommand,
- _portCommand,
_refreshCommand,
_restoreCommand,
_runlabelCommand,
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index b02aa5990..8aca08248 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -315,7 +315,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
)
createFlags.Bool(
"http-proxy", true,
- "Set proxy environment variables in container based on the host proxy vars",
+ "Set proxy environment variables in the container based on the host proxy vars",
)
createFlags.String(
"image-volume", cliconfig.DefaultImageVolume,
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index b3058bf12..bbf01d1f8 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -56,12 +56,14 @@ var (
_diffCommand,
_exportCommand,
_createCommand,
+ _initCommand,
_killCommand,
_listSubCommand,
_logsCommand,
_pauseCommand,
- _restartCommand,
+ _portCommand,
_pruneContainersCommand,
+ _restartCommand,
_runCommand,
_rmCommand,
_startCommand,
diff --git a/cmd/podman/errors_remote.go b/cmd/podman/errors_remote.go
index ab255ea56..1e276be10 100644
--- a/cmd/podman/errors_remote.go
+++ b/cmd/podman/errors_remote.go
@@ -33,6 +33,8 @@ func outputError(err error) {
ne = errors.New(e.Reason)
case *iopodman.VolumeNotFound:
ne = errors.New(e.Reason)
+ case *iopodman.InvalidState:
+ ne = errors.New(e.Reason)
case *iopodman.ErrorOccurred:
ne = errors.New(e.Reason)
default:
diff --git a/cmd/podman/generate.go b/cmd/podman/generate.go
index a0637ecb2..98bfb00a1 100644
--- a/cmd/podman/generate.go
+++ b/cmd/podman/generate.go
@@ -18,6 +18,7 @@ var (
// Commands that are universally implemented
generateCommands = []*cobra.Command{
_containerKubeCommand,
+ _containerSystemdCommand,
}
)
diff --git a/cmd/podman/generate_systemd.go b/cmd/podman/generate_systemd.go
new file mode 100644
index 000000000..b4779e512
--- /dev/null
+++ b/cmd/podman/generate_systemd.go
@@ -0,0 +1,70 @@
+package main
+
+import (
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/containers/libpod/pkg/systemdgen"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ containerSystemdCommand cliconfig.GenerateSystemdValues
+ containerSystemdDescription = `Command generates a systemd unit file for a Podman container
+ `
+ _containerSystemdCommand = &cobra.Command{
+ Use: "systemd [flags] CONTAINER | POD",
+ Short: "Generate a systemd unit file for a Podman container",
+ Long: containerSystemdDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ containerSystemdCommand.InputArgs = args
+ containerSystemdCommand.GlobalFlags = MainGlobalOpts
+ containerSystemdCommand.Remote = remoteclient
+ return generateSystemdCmd(&containerSystemdCommand)
+ },
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) > 1 || len(args) < 1 {
+ return errors.New("provide only one container name or ID")
+ }
+ return nil
+ },
+ Example: `podman generate kube ctrID
+`,
+ }
+)
+
+func init() {
+ containerSystemdCommand.Command = _containerSystemdCommand
+ containerSystemdCommand.SetHelpTemplate(HelpTemplate())
+ containerSystemdCommand.SetUsageTemplate(UsageTemplate())
+ flags := containerSystemdCommand.Flags()
+ flags.BoolVarP(&containerSystemdCommand.Name, "name", "n", false, "use the container name instead of ID")
+ flags.IntVarP(&containerSystemdCommand.StopTimeout, "timeout", "t", -1, "stop timeout override")
+ flags.StringVar(&containerSystemdCommand.RestartPolicy, "restart-policy", "on-failure", "applicable systemd restart-policy")
+}
+
+func generateSystemdCmd(c *cliconfig.GenerateSystemdValues) error {
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.Shutdown(false)
+
+ // User input stop timeout must be 0 or greater
+ if c.Flag("timeout").Changed && c.StopTimeout < 0 {
+ return errors.New("timeout value must be 0 or greater")
+ }
+ // Make sure the input restart policy is valid
+ if err := systemdgen.ValidateRestartPolicy(c.RestartPolicy); err != nil {
+ return err
+ }
+
+ unit, err := runtime.GenerateSystemd(c)
+ if err != nil {
+ return err
+ }
+ fmt.Println(unit)
+ return nil
+}
diff --git a/cmd/podman/init.go b/cmd/podman/init.go
new file mode 100644
index 000000000..68c80631d
--- /dev/null
+++ b/cmd/podman/init.go
@@ -0,0 +1,64 @@
+package main
+
+import (
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/opentracing/opentracing-go"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ initCommand cliconfig.InitValues
+ initDescription = `Initialize one or more containers, creating the OCI spec and mounts for inspection. Container names or IDs can be used.`
+
+ _initCommand = &cobra.Command{
+ Use: "init [flags] CONTAINER [CONTAINER...]",
+ Short: "Initialize one or more containers",
+ Long: initDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ initCommand.InputArgs = args
+ initCommand.GlobalFlags = MainGlobalOpts
+ initCommand.Remote = remoteclient
+ return initCmd(&initCommand)
+ },
+ Args: func(cmd *cobra.Command, args []string) error {
+ return checkAllAndLatest(cmd, args, false)
+ },
+ Example: `podman init --latest
+ podman init 3c45ef19d893
+ podman init test1`,
+ }
+)
+
+func init() {
+ initCommand.Command = _initCommand
+ initCommand.SetHelpTemplate(HelpTemplate())
+ initCommand.SetUsageTemplate(UsageTemplate())
+ flags := initCommand.Flags()
+ flags.BoolVarP(&initCommand.All, "all", "a", false, "Initialize all containers")
+ flags.BoolVarP(&initCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ markFlagHiddenForRemoteClient("latest", flags)
+}
+
+// initCmd initializes a container
+func initCmd(c *cliconfig.InitValues) error {
+ if c.Bool("trace") {
+ span, _ := opentracing.StartSpanFromContext(Ctx, "initCmd")
+ defer span.Finish()
+ }
+
+ ctx := getContext()
+
+ runtime, err := adapter.GetRuntime(ctx, &c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.Shutdown(false)
+
+ ok, failures, err := runtime.InitContainers(ctx, c)
+ if err != nil {
+ return err
+ }
+ return printCmdResults(ok, failures)
+}
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index b03846bbc..b533dc056 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -78,8 +78,6 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber bool,
options = append(options, libpod.WithRenumber())
}
- options = append(options, libpod.WithContext(ctx))
-
// Only set this if the user changes storage config on the command line
if storageSet {
options = append(options, libpod.WithStorageConfig(storageOpts))
@@ -146,7 +144,7 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber bool,
options = append(options, libpod.WithDefaultInfraCommand(infraCommand))
}
if c.Flags().Changed("config") {
- return libpod.NewRuntimeFromConfig(c.GlobalFlags.Config, options...)
+ return libpod.NewRuntimeFromConfig(ctx, c.GlobalFlags.Config, options...)
}
- return libpod.NewRuntime(options...)
+ return libpod.NewRuntime(ctx, options...)
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index f501ee674..787dd55c0 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -39,12 +39,14 @@ var mainCommands = []*cobra.Command{
&_imagesCommand,
_importCommand,
_infoCommand,
+ _initCommand,
&_inspectCommand,
_killCommand,
_loadCommand,
_logsCommand,
_pauseCommand,
podCommand.Command,
+ _portCommand,
&_psCommand,
_pullCommand,
_pushCommand,
diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go
index 967798399..e778bafb9 100644
--- a/cmd/podman/play_kube.go
+++ b/cmd/podman/play_kube.go
@@ -205,7 +205,8 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues, ctx context.Context, runtime *
return pod, errors.Errorf("Directories are the only supported HostPath type")
}
}
- if err := shared.ValidateVolumeHostDir(hostPath.Path); err != nil {
+
+ if err := createconfig.ValidateVolumeHostDir(hostPath.Path); err != nil {
return pod, errors.Wrapf(err, "Error in parsing HostPath in YAML")
}
volumes[volume.Name] = hostPath.Path
@@ -281,7 +282,6 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container
// The default for MemorySwappiness is -1, not 0
containerConfig.Resources.MemorySwappiness = -1
- containerConfig.Runtime = runtime
containerConfig.Image = containerYAML.Image
containerConfig.ImageID = newImage.ID()
containerConfig.Name = containerYAML.Name
@@ -352,7 +352,7 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container
if !exists {
return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
}
- if err := shared.ValidateVolumeCtrDir(volume.MountPath); err != nil {
+ if err := createconfig.ValidateVolumeCtrDir(volume.MountPath); err != nil {
return nil, errors.Wrapf(err, "error in parsing MountPath")
}
containerConfig.Volumes = append(containerConfig.Volumes, fmt.Sprintf("%s:%s", host_path, volume.MountPath))
diff --git a/cmd/podman/port.go b/cmd/podman/port.go
index 7a9f01fe6..1bd2d623e 100644
--- a/cmd/podman/port.go
+++ b/cmd/podman/port.go
@@ -6,8 +6,7 @@ import (
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
- "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -51,10 +50,7 @@ func portCmd(c *cliconfig.PortValues) error {
var (
userProto, containerName string
userPort int
- container *libpod.Container
- containers []*libpod.Container
)
-
args := c.InputArgs
if c.Latest && c.All {
@@ -66,9 +62,6 @@ func portCmd(c *cliconfig.PortValues) error {
if len(args) == 0 && !c.Latest && !c.All {
return errors.Errorf("you must supply a running container name or id")
}
- if !c.Latest && !c.All {
- containerName = args[0]
- }
port := ""
if len(args) > 1 && !c.Latest {
@@ -98,36 +91,14 @@ func portCmd(c *cliconfig.PortValues) error {
}
}
- runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
- if !c.Latest && !c.All {
- container, err = runtime.LookupContainer(containerName)
- if err != nil {
- return errors.Wrapf(err, "unable to find container %s", containerName)
- }
- containers = append(containers, container)
- } else if c.Latest {
- container, err = runtime.GetLatestContainer()
- if err != nil {
- return errors.Wrapf(err, "unable to get last created container")
- }
- containers = append(containers, container)
- } else {
- containers, err = runtime.GetRunningContainers()
- if err != nil {
- return errors.Wrapf(err, "unable to get all containers")
- }
- }
-
+ containers, err := runtime.Port(c)
for _, con := range containers {
- if state, _ := con.State(); state != libpod.ContainerStateRunning {
- continue
- }
-
portmappings, err := con.PortMappings()
if err != nil {
return err
diff --git a/cmd/podman/run_test.go b/cmd/podman/run_test.go
deleted file mode 100644
index af9e6923c..000000000
--- a/cmd/podman/run_test.go
+++ /dev/null
@@ -1,162 +0,0 @@
-package main
-
-import (
- "runtime"
- "testing"
-
- "github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/shared"
- "github.com/containers/libpod/pkg/inspect"
- cc "github.com/containers/libpod/pkg/spec"
- "github.com/containers/libpod/pkg/sysinfo"
- "github.com/docker/go-units"
- ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/spf13/cobra"
- "github.com/stretchr/testify/assert"
-)
-
-var (
- sysInfo = sysinfo.New(true)
- cmd = []string{"podman", "test", "alpine"}
- CLI *cliconfig.PodmanCommand
-)
-
-// generates a mocked ImageData structure based on alpine
-func generateAlpineImageData() *inspect.ImageData {
- config := &ociv1.ImageConfig{
- User: "",
- ExposedPorts: nil,
- Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
- Entrypoint: []string{},
- Cmd: []string{"/bin/sh"},
- Volumes: nil,
- WorkingDir: "",
- Labels: nil,
- StopSignal: "",
- }
-
- data := &inspect.ImageData{
- ID: "e21c333399e0aeedfd70e8827c9fba3f8e9b170ef8a48a29945eb7702bf6aa5f",
- RepoTags: []string{"docker.io/library/alpine:latest"},
- RepoDigests: []string{"docker.io/library/alpine@sha256:5cb04fce748f576d7b72a37850641de8bd725365519673c643ef2d14819b42c6"},
- Comment: "Created:2017-12-01 18:48:48.949613376 +0000",
- Author: "",
- Architecture: "amd64",
- Os: "linux",
- Version: "17.06.2-ce",
- Config: config,
- }
- return data
-}
-
-// sets a global CLI
-func testCmd(c *cobra.Command) error {
- CLI = &cliconfig.PodmanCommand{Command: c}
- return nil
-}
-
-// creates the mocked cli pointing to our create flags
-// global flags like log-level are not implemented
-func createCLI(args []string) *cliconfig.PodmanCommand {
- var testCommand = &cliconfig.PodmanCommand{
- Command: &cobra.Command{
- Use: "test",
- RunE: func(cmd *cobra.Command, args []string) error {
- return testCmd(cmd)
- },
- },
- }
- rootCmd := testCommand
- getCreateFlags(rootCmd)
- rootCmd.ParseFlags(args)
- return rootCmd
-}
-
-func getRuntimeSpec(c *cliconfig.PodmanCommand) (*spec.Spec, error) {
- /*
- TODO: This test has never worked. Need to install content
- runtime, err := getRuntime(c)
- if err != nil {
- return nil, err
- }
- createConfig, err := parseCreateOpts(c, runtime, "alpine", generateAlpineImageData())
- */
- ctx := getContext()
- genericResults := shared.NewIntermediateLayer(c, false)
- createConfig, err := shared.ParseCreateOpts(ctx, &genericResults, nil, "alpine", generateAlpineImageData())
- if err != nil {
- return nil, err
- }
- runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig)
- if err != nil {
- return nil, err
- }
- return runtimeSpec, nil
-}
-
-// TestPIDsLimit verifies the inputted pid-limit is correctly defined in the spec
-func TestPIDsLimit(t *testing.T) {
- // The default configuration of podman enables seccomp, which is not available on non-Linux systems.
- // Thus, any tests that use the default seccomp setting would fail.
- // Skip the tests on non-Linux platforms rather than explicitly disable seccomp in the test and possibly affect the test result.
- if runtime.GOOS != "linux" {
- t.Skip("seccomp, which is enabled by default, is only supported on Linux")
- }
- if !sysInfo.PidsLimit {
- t.Skip("running test not supported by the host system")
- }
- args := []string{"--pids-limit", "22"}
- a := createCLI(args)
- a.InputArgs = args
- //a.Run(append(cmd, args...))
- runtimeSpec, err := getRuntimeSpec(a)
- if err != nil {
- t.Fatalf(err.Error())
- }
- assert.Equal(t, runtimeSpec.Linux.Resources.Pids.Limit, int64(22))
-}
-
-// TestBLKIOWeightDevice verifies the inputted blkio weigh device is correctly defined in the spec
-func TestBLKIOWeightDevice(t *testing.T) {
- // The default configuration of podman enables seccomp, which is not available on non-Linux systems.
- // Thus, any tests that use the default seccomp setting would fail.
- // Skip the tests on non-Linux platforms rather than explicitly disable seccomp in the test and possibly affect the test result.
- if runtime.GOOS != "linux" {
- t.Skip("seccomp, which is enabled by default, is only supported on Linux")
- }
- if !sysInfo.BlkioWeightDevice {
- t.Skip("running test not supported by the host system")
- }
- args := []string{"--blkio-weight-device", "/dev/zero:100"}
- a := createCLI(args)
- a.InputArgs = args
- runtimeSpec, err := getRuntimeSpec(a)
- if err != nil {
- t.Fatalf(err.Error())
- }
- assert.Equal(t, *runtimeSpec.Linux.Resources.BlockIO.WeightDevice[0].Weight, uint16(100))
-}
-
-// TestMemorySwap verifies that the inputted memory swap is correctly defined in the spec
-func TestMemorySwap(t *testing.T) {
- // The default configuration of podman enables seccomp, which is not available on non-Linux systems.
- // Thus, any tests that use the default seccomp setting would fail.
- // Skip the tests on non-Linux platforms rather than explicitly disable seccomp in the test and possibly affect the test result.
- if runtime.GOOS != "linux" {
- t.Skip("seccomp, which is enabled by default, is only supported on Linux")
- }
- if !sysInfo.SwapLimit {
- t.Skip("running test not supported by the host system")
- }
- args := []string{"--memory-swap", "45m", "--memory", "40m"}
- a := createCLI(args)
- a.InputArgs = args
- //a.Run(append(cmd, args...))
- runtimeSpec, err := getRuntimeSpec(a)
- if err != nil {
- t.Fatalf(err.Error())
- }
- mem, _ := units.RAMInBytes("45m")
- assert.Equal(t, *runtimeSpec.Linux.Resources.Memory.Swap, mem)
-}
diff --git a/cmd/podman/search.go b/cmd/podman/search.go
index 13948aef0..b236f3055 100644
--- a/cmd/podman/search.go
+++ b/cmd/podman/search.go
@@ -118,16 +118,3 @@ func searchToGeneric(params []image.SearchResult) (genericParams []interface{})
}
return genericParams
}
-
-func genSearchOutputMap() map[string]string {
- io := image.SearchResult{}
- v := reflect.Indirect(reflect.ValueOf(io))
- values := make(map[string]string)
-
- for i := 0; i < v.NumField(); i++ {
- key := v.Type().Field(i).Name
- value := key
- values[key] = strings.ToUpper(splitCamelCase(value))
- }
- return values
-}
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index 48476e177..81566326b 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -25,7 +25,6 @@ import (
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
"github.com/google/shlex"
- spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
@@ -114,6 +113,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
}
+
createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, data)
if err != nil {
return nil, nil, err
@@ -123,7 +123,16 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
// at this point. The rest is done by WithOptions.
createConfig.HealthCheck = healthCheck
- ctr, err := CreateContainerFromCreateConfig(runtime, createConfig, ctx, nil)
+ // TODO: Should be able to return this from ParseCreateOpts
+ var pod *libpod.Pod
+ if createConfig.Pod != "" {
+ pod, err = runtime.LookupPod(createConfig.Pod)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "error looking up pod to join")
+ }
+ }
+
+ ctr, err := CreateContainerFromCreateConfig(runtime, createConfig, ctx, pod)
if err != nil {
return nil, nil, err
}
@@ -139,7 +148,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
return ctr, createConfig, nil
}
-func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error {
+func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string, runtime *libpod.Runtime) error {
var (
labelOpts []string
)
@@ -147,7 +156,7 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error {
if config.PidMode.IsHost() {
labelOpts = append(labelOpts, label.DisableSecOpt()...)
} else if config.PidMode.IsContainer() {
- ctr, err := config.Runtime.LookupContainer(config.PidMode.Container())
+ ctr, err := runtime.LookupContainer(config.PidMode.Container())
if err != nil {
return errors.Wrapf(err, "container %q not found", config.PidMode.Container())
}
@@ -161,7 +170,7 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error {
if config.IpcMode.IsHost() {
labelOpts = append(labelOpts, label.DisableSecOpt()...)
} else if config.IpcMode.IsContainer() {
- ctr, err := config.Runtime.LookupContainer(config.IpcMode.Container())
+ ctr, err := runtime.LookupContainer(config.IpcMode.Container())
if err != nil {
return errors.Wrapf(err, "container %q not found", config.IpcMode.Container())
}
@@ -331,18 +340,6 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
blkioWeight = uint16(u)
}
- var mountList []spec.Mount
- if mountList, err = parseMounts(c.StringArray("mount")); err != nil {
- return nil, err
- }
-
- if err = parseVolumes(c.StringArray("volume")); err != nil {
- return nil, err
- }
-
- if err = parseVolumesFrom(c.StringSlice("volumes-from")); err != nil {
- return nil, err
- }
tty := c.Bool("tty")
@@ -604,7 +601,6 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
memorySwappiness := c.Int64("memory-swappiness")
config := &cc.CreateConfig{
- Runtime: runtime,
Annotations: annotations,
BuiltinImgVolumes: ImageVolumes,
ConmonPidFile: c.String("conmon-pidfile"),
@@ -627,6 +623,8 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
HTTPProxy: c.Bool("http-proxy"),
NoHosts: c.Bool("no-hosts"),
IDMappings: idmappings,
+ Init: c.Bool("init"),
+ InitPath: c.String("init-path"),
Image: imageName,
ImageID: imageID,
Interactive: c.Bool("interactive"),
@@ -687,31 +685,18 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
Tty: tty,
User: user,
UsernsMode: usernsMode,
- Mounts: mountList,
+ MountsFlag: c.StringArray("mount"),
Volumes: c.StringArray("volume"),
WorkDir: workDir,
Rootfs: rootfs,
VolumesFrom: c.StringSlice("volumes-from"),
Syslog: c.Bool("syslog"),
}
- if c.Bool("init") {
- initPath := c.String("init-path")
- if initPath == "" {
- rtc, err := runtime.GetConfig()
- if err != nil {
- return nil, err
- }
- initPath = rtc.InitPath
- }
- if err := config.AddContainerInitBinary(initPath); err != nil {
- return nil, err
- }
- }
if config.Privileged {
config.LabelOpts = label.DisableSecOpt()
} else {
- if err := parseSecurityOpt(config, c.StringArray("security-opt")); err != nil {
+ if err := parseSecurityOpt(config, c.StringArray("security-opt"), runtime); err != nil {
return nil, err
}
}
@@ -726,18 +711,8 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
return config, nil
}
-type namespace interface {
- IsContainer() bool
- Container() string
-}
-
func CreateContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context, pod *libpod.Pod) (*libpod.Container, error) {
- runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig)
- if err != nil {
- return nil, err
- }
-
- options, err := createConfig.GetContainerCreateOptions(r, pod)
+ runtimeSpec, options, err := createConfig.MakeContainerConfig(r, pod)
if err != nil {
return nil, err
}
diff --git a/cmd/podman/shared/create_cli.go b/cmd/podman/shared/create_cli.go
index 4f9cb1699..f731e8db5 100644
--- a/cmd/podman/shared/create_cli.go
+++ b/cmd/podman/shared/create_cli.go
@@ -2,15 +2,11 @@ package shared
import (
"fmt"
- "os"
- "path/filepath"
"strings"
"github.com/containers/libpod/cmd/podman/shared/parse"
cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/sysinfo"
- "github.com/docker/go-units"
- spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -78,186 +74,6 @@ func addWarning(warnings []string, msg string) []string {
return append(warnings, msg)
}
-// Format supported.
-// podman run --mount type=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
-// podman run --mount type=tmpfs,target=/dev/shm ..
-func parseMounts(mounts []string) ([]spec.Mount, error) {
- // TODO(vrothberg): the manual parsing can be replaced with a regular expression
- // to allow a more robust parsing of the mount format and to give
- // precise errors regarding supported format versus suppored options.
- var mountList []spec.Mount
- errInvalidSyntax := errors.Errorf("incorrect mount format: should be --mount type=<bind|tmpfs>,[src=<host-dir>,]target=<ctr-dir>[,options]")
- for _, mount := range mounts {
- var tokenCount int
- var mountInfo spec.Mount
-
- arr := strings.SplitN(mount, ",", 2)
- if len(arr) < 2 {
- return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
- }
- kv := strings.Split(arr[0], "=")
- if kv[0] != "type" {
- return nil, errors.Wrapf(errInvalidSyntax, "%q", mount)
- }
- switch kv[1] {
- case "bind":
- mountInfo.Type = string(cc.TypeBind)
- case "tmpfs":
- mountInfo.Type = string(cc.TypeTmpfs)
- mountInfo.Source = string(cc.TypeTmpfs)
- mountInfo.Options = append(mountInfo.Options, []string{"rprivate", "noexec", "nosuid", "nodev", "size=65536k"}...)
-
- default:
- return nil, errors.Errorf("invalid filesystem type %q", kv[1])
- }
-
- tokens := strings.Split(arr[1], ",")
- for i, val := range tokens {
- if i == (tokenCount - 1) {
- //Parse tokens before options.
- break
- }
- kv := strings.Split(val, "=")
- switch kv[0] {
- case "ro", "nosuid", "nodev", "noexec":
- mountInfo.Options = append(mountInfo.Options, kv[0])
- case "shared", "rshared", "private", "rprivate", "slave", "rslave", "Z", "z":
- if mountInfo.Type != "bind" {
- return nil, errors.Errorf("%s can only be used with bind mounts", kv[0])
- }
- mountInfo.Options = append(mountInfo.Options, kv[0])
- case "tmpfs-mode":
- if mountInfo.Type != "tmpfs" {
- return nil, errors.Errorf("%s can only be used with tmpfs mounts", kv[0])
- }
- mountInfo.Options = append(mountInfo.Options, fmt.Sprintf("mode=%s", kv[1]))
- case "tmpfs-size":
- if mountInfo.Type != "tmpfs" {
- return nil, errors.Errorf("%s can only be used with tmpfs mounts", kv[0])
- }
- shmSize, err := units.FromHumanSize(kv[1])
- if err != nil {
- return nil, errors.Wrapf(err, "unable to translate tmpfs-size")
- }
-
- mountInfo.Options = append(mountInfo.Options, fmt.Sprintf("size=%d", shmSize))
-
- case "bind-propagation":
- if mountInfo.Type != "bind" {
- return nil, errors.Errorf("%s can only be used with bind mounts", kv[0])
- }
- mountInfo.Options = append(mountInfo.Options, kv[1])
- case "src", "source":
- if mountInfo.Type == "tmpfs" {
- return nil, errors.Errorf("cannot use src= on a tmpfs file system")
- }
- if err := ValidateVolumeHostDir(kv[1]); err != nil {
- return nil, err
- }
- mountInfo.Source = kv[1]
- case "target", "dst", "destination":
- if err := ValidateVolumeCtrDir(kv[1]); err != nil {
- return nil, err
- }
- mountInfo.Destination = kv[1]
- default:
- return nil, errors.Errorf("incorrect mount option : %s", kv[0])
- }
- }
- mountList = append(mountList, mountInfo)
- }
- return mountList, nil
-}
-
-func parseVolumes(volumes []string) error {
- for _, volume := range volumes {
- arr := strings.SplitN(volume, ":", 3)
- if len(arr) < 2 {
- return errors.Errorf("incorrect volume format %q, should be host-dir:ctr-dir[:option]", volume)
- }
- if err := ValidateVolumeHostDir(arr[0]); err != nil {
- return err
- }
- if err := ValidateVolumeCtrDir(arr[1]); err != nil {
- return err
- }
- if len(arr) > 2 {
- if err := validateVolumeOpts(arr[2]); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func parseVolumesFrom(volumesFrom []string) error {
- for _, vol := range volumesFrom {
- arr := strings.SplitN(vol, ":", 2)
- if len(arr) == 2 {
- if strings.Contains(arr[1], "Z") || strings.Contains(arr[1], "private") || strings.Contains(arr[1], "slave") || strings.Contains(arr[1], "shared") {
- return errors.Errorf("invalid options %q, can only specify 'ro', 'rw', and 'z", arr[1])
- }
- if err := validateVolumeOpts(arr[1]); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-// ValidateVolumeHostDir ...
-func ValidateVolumeHostDir(hostDir string) error {
- if len(hostDir) == 0 {
- return errors.Errorf("host directory cannot be empty")
- }
- if filepath.IsAbs(hostDir) {
- if _, err := os.Stat(hostDir); err != nil {
- return errors.Wrapf(err, "error checking path %q", hostDir)
- }
- }
- // If hostDir is not an absolute path, that means the user wants to create a
- // named volume. This will be done later on in the code.
- return nil
-}
-
-// ValidateVolumeCtrDir ...
-func ValidateVolumeCtrDir(ctrDir string) error {
- if len(ctrDir) == 0 {
- return errors.Errorf("container directory cannot be empty")
- }
- if !filepath.IsAbs(ctrDir) {
- return errors.Errorf("invalid container path, must be an absolute path %q", ctrDir)
- }
- return nil
-}
-
-func validateVolumeOpts(option string) error {
- var foundRootPropagation, foundRWRO, foundLabelChange int
- options := strings.Split(option, ",")
- for _, opt := range options {
- switch opt {
- case "rw", "ro":
- foundRWRO++
- if foundRWRO > 1 {
- return errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", option)
- }
- case "z", "Z":
- foundLabelChange++
- if foundLabelChange > 1 {
- return errors.Errorf("invalid options %q, can only specify 1 'z' or 'Z' option", option)
- }
- case "private", "rprivate", "shared", "rshared", "slave", "rslave":
- foundRootPropagation++
- if foundRootPropagation > 1 {
- return errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private' or '[r]slave' option", option)
- }
- default:
- return errors.Errorf("invalid option type %q", option)
- }
- }
- return nil
-}
-
func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) {
warnings := []string{}
sysInfo := sysinfo.New(true)
diff --git a/cmd/podman/shared/parse/parse.go b/cmd/podman/shared/parse/parse.go
index a3751835b..7bc2652cb 100644
--- a/cmd/podman/shared/parse/parse.go
+++ b/cmd/podman/shared/parse/parse.go
@@ -5,15 +5,10 @@ package parse
import (
"bufio"
- "bytes"
- "encoding/json"
"fmt"
- "io/ioutil"
"net"
"os"
- "path"
"regexp"
- "strconv"
"strings"
"github.com/pkg/errors"
@@ -72,77 +67,6 @@ func validateIPAddress(val string) (string, error) {
return "", fmt.Errorf("%s is not an ip address", val)
}
-// validateAttach validates that the specified string is a valid attach option.
-// for attach flag
-func validateAttach(val string) (string, error) { //nolint
- s := strings.ToLower(val)
- for _, str := range []string{"stdin", "stdout", "stderr"} {
- if s == str {
- return s, nil
- }
- }
- return val, fmt.Errorf("valid streams are STDIN, STDOUT and STDERR")
-}
-
-// validate the blkioWeight falls in the range of 10 to 1000
-// for blkio-weight flag
-func validateBlkioWeight(val int64) (int64, error) { //nolint
- if val >= 10 && val <= 1000 {
- return val, nil
- }
- return -1, errors.Errorf("invalid blkio weight %q, should be between 10 and 1000", val)
-}
-
-func validatePath(val string, validator func(string) bool) (string, error) {
- var containerPath string
- var mode string
-
- if strings.Count(val, ":") > 2 {
- return val, fmt.Errorf("bad format for path: %s", val)
- }
-
- split := strings.SplitN(val, ":", 3)
- if split[0] == "" {
- return val, fmt.Errorf("bad format for path: %s", val)
- }
- switch len(split) {
- case 1:
- containerPath = split[0]
- val = path.Clean(containerPath)
- case 2:
- if isValid := validator(split[1]); isValid {
- containerPath = split[0]
- mode = split[1]
- val = fmt.Sprintf("%s:%s", path.Clean(containerPath), mode)
- } else {
- containerPath = split[1]
- val = fmt.Sprintf("%s:%s", split[0], path.Clean(containerPath))
- }
- case 3:
- containerPath = split[1]
- mode = split[2]
- if isValid := validator(split[2]); !isValid {
- return val, fmt.Errorf("bad mode specified: %s", mode)
- }
- val = fmt.Sprintf("%s:%s:%s", split[0], containerPath, mode)
- }
-
- if !path.IsAbs(containerPath) {
- return val, fmt.Errorf("%s is not an absolute path", containerPath)
- }
- return val, nil
-}
-
-// validateDNSSearch validates domain for resolvconf search configuration.
-// A zero length domain is represented by a dot (.).
-// for dns-search flag
-func validateDNSSearch(val string) (string, error) { //nolint
- if val = strings.Trim(val, " "); val == "." {
- return val, nil
- }
- return ValidateDomain(val)
-}
-
func ValidateDomain(val string) (string, error) {
if alphaRegexp.FindString(val) == "" {
return "", fmt.Errorf("%s is not a valid domain", val)
@@ -154,30 +78,6 @@ func ValidateDomain(val string) (string, error) {
return "", fmt.Errorf("%s is not a valid domain", val)
}
-// validateEnv validates an environment variable and returns it.
-// If no value is specified, it returns the current value using os.Getenv.
-// for env flag
-func validateEnv(val string) (string, error) { //nolint
- arr := strings.Split(val, "=")
- if len(arr) > 1 {
- return val, nil
- }
- if !doesEnvExist(val) {
- return val, nil
- }
- return fmt.Sprintf("%s=%s", val, os.Getenv(val)), nil
-}
-
-func doesEnvExist(name string) bool {
- for _, entry := range os.Environ() {
- parts := strings.SplitN(entry, "=", 2)
- if parts[0] == name {
- return true
- }
- }
- return false
-}
-
// reads a file of line terminated key=value pairs, and overrides any keys
// present in the file with additional pairs specified in the override parameter
// for env-file and labels-file flags
@@ -241,259 +141,6 @@ func parseEnvFile(env map[string]string, filename string) error {
return scanner.Err()
}
-// validateLabel validates that the specified string is a valid label, and returns it.
-// Labels are in the form on key=value.
-// for label flag
-func validateLabel(val string) (string, error) { //nolint
- if strings.Count(val, "=") < 1 {
- return "", fmt.Errorf("bad attribute format: %s", val)
- }
- return val, nil
-}
-
-// validateMACAddress validates a MAC address.
-// for mac-address flag
-func validateMACAddress(val string) (string, error) { //nolint
- _, err := net.ParseMAC(strings.TrimSpace(val))
- if err != nil {
- return "", err
- }
- return val, nil
-}
-
-// parseLoggingOpts validates the logDriver and logDriverOpts
-// for log-opt and log-driver flags
-func parseLoggingOpts(logDriver string, logDriverOpt []string) (map[string]string, error) { //nolint
- logOptsMap := convertKVStringsToMap(logDriverOpt)
- if logDriver == "none" && len(logDriverOpt) > 0 {
- return map[string]string{}, errors.Errorf("invalid logging opts for driver %s", logDriver)
- }
- return logOptsMap, nil
-}
-
-// parsePortSpecs receives port specs in the format of ip:public:private/proto and parses
-// these in to the internal types
-// for publish, publish-all, and expose flags
-func parsePortSpecs(ports []string) ([]*PortMapping, error) { //nolint
- var portMappings []*PortMapping
- for _, rawPort := range ports {
- portMapping, err := parsePortSpec(rawPort)
- if err != nil {
- return nil, err
- }
-
- portMappings = append(portMappings, portMapping...)
- }
- return portMappings, nil
-}
-
-func validateProto(proto string) bool {
- for _, availableProto := range []string{"tcp", "udp"} {
- if availableProto == proto {
- return true
- }
- }
- return false
-}
-
-// parsePortSpec parses a port specification string into a slice of PortMappings
-func parsePortSpec(rawPort string) ([]*PortMapping, error) {
- var proto string
- rawIP, hostPort, containerPort := splitParts(rawPort)
- proto, containerPort = splitProtoPort(containerPort)
-
- // Strip [] from IPV6 addresses
- ip, _, err := net.SplitHostPort(rawIP + ":")
- if err != nil {
- return nil, fmt.Errorf("Invalid ip address %v: %s", rawIP, err)
- }
- if ip != "" && net.ParseIP(ip) == nil {
- return nil, fmt.Errorf("Invalid ip address: %s", ip)
- }
- if containerPort == "" {
- return nil, fmt.Errorf("No port specified: %s<empty>", rawPort)
- }
-
- startPort, endPort, err := parsePortRange(containerPort)
- if err != nil {
- return nil, fmt.Errorf("Invalid containerPort: %s", containerPort)
- }
-
- var startHostPort, endHostPort uint64 = 0, 0
- if len(hostPort) > 0 {
- startHostPort, endHostPort, err = parsePortRange(hostPort)
- if err != nil {
- return nil, fmt.Errorf("Invalid hostPort: %s", hostPort)
- }
- }
-
- if hostPort != "" && (endPort-startPort) != (endHostPort-startHostPort) {
- // Allow host port range iff containerPort is not a range.
- // In this case, use the host port range as the dynamic
- // host port range to allocate into.
- if endPort != startPort {
- return nil, fmt.Errorf("Invalid ranges specified for container and host Ports: %s and %s", containerPort, hostPort)
- }
- }
-
- if !validateProto(strings.ToLower(proto)) {
- return nil, fmt.Errorf("invalid proto: %s", proto)
- }
-
- protocol := Protocol_TCP
- if strings.ToLower(proto) == "udp" {
- protocol = Protocol_UDP
- }
-
- var ports []*PortMapping
- for i := uint64(0); i <= (endPort - startPort); i++ {
- containerPort = strconv.FormatUint(startPort+i, 10)
- if len(hostPort) > 0 {
- hostPort = strconv.FormatUint(startHostPort+i, 10)
- }
- // Set hostPort to a range only if there is a single container port
- // and a dynamic host port.
- if startPort == endPort && startHostPort != endHostPort {
- hostPort = fmt.Sprintf("%s-%s", hostPort, strconv.FormatUint(endHostPort, 10))
- }
-
- ctrPort, err := strconv.ParseInt(containerPort, 10, 32)
- if err != nil {
- return nil, err
- }
- hPort, err := strconv.ParseInt(hostPort, 10, 32)
- if err != nil {
- return nil, err
- }
-
- port := &PortMapping{
- Protocol: protocol,
- ContainerPort: int32(ctrPort),
- HostPort: int32(hPort),
- HostIp: ip,
- }
-
- ports = append(ports, port)
- }
- return ports, nil
-}
-
-// parsePortRange parses and validates the specified string as a port-range (8000-9000)
-func parsePortRange(ports string) (uint64, uint64, error) {
- if ports == "" {
- return 0, 0, fmt.Errorf("empty string specified for ports")
- }
- if !strings.Contains(ports, "-") {
- start, err := strconv.ParseUint(ports, 10, 16)
- end := start
- return start, end, err
- }
-
- parts := strings.Split(ports, "-")
- start, err := strconv.ParseUint(parts[0], 10, 16)
- if err != nil {
- return 0, 0, err
- }
- end, err := strconv.ParseUint(parts[1], 10, 16)
- if err != nil {
- return 0, 0, err
- }
- if end < start {
- return 0, 0, fmt.Errorf("Invalid range specified for the Port: %s", ports)
- }
- return start, end, nil
-}
-
-// splitParts separates the different parts of rawPort
-func splitParts(rawport string) (string, string, string) {
- parts := strings.Split(rawport, ":")
- n := len(parts)
- containerport := parts[n-1]
-
- switch n {
- case 1:
- return "", "", containerport
- case 2:
- return "", parts[0], containerport
- case 3:
- return parts[0], parts[1], containerport
- default:
- return strings.Join(parts[:n-2], ":"), parts[n-2], containerport
- }
-}
-
-// splitProtoPort splits a port in the format of port/proto
-func splitProtoPort(rawPort string) (string, string) {
- parts := strings.Split(rawPort, "/")
- l := len(parts)
- if len(rawPort) == 0 || l == 0 || len(parts[0]) == 0 {
- return "", ""
- }
- if l == 1 {
- return "tcp", rawPort
- }
- if len(parts[1]) == 0 {
- return "tcp", parts[0]
- }
- return parts[1], parts[0]
-}
-
-// takes a local seccomp file and reads its file contents
-// for security-opt flag
-func parseSecurityOpts(securityOpts []string) ([]string, error) { //nolint
- for key, opt := range securityOpts {
- con := strings.SplitN(opt, "=", 2)
- if len(con) == 1 && con[0] != "no-new-privileges" {
- if strings.Index(opt, ":") != -1 {
- con = strings.SplitN(opt, ":", 2)
- } else {
- return securityOpts, fmt.Errorf("Invalid --security-opt: %q", opt)
- }
- }
- if con[0] == "seccomp" && con[1] != "unconfined" {
- f, err := ioutil.ReadFile(con[1])
- if err != nil {
- return securityOpts, fmt.Errorf("opening seccomp profile (%s) failed: %v", con[1], err)
- }
- b := bytes.NewBuffer(nil)
- if err := json.Compact(b, f); err != nil {
- return securityOpts, fmt.Errorf("compacting json for seccomp profile (%s) failed: %v", con[1], err)
- }
- securityOpts[key] = fmt.Sprintf("seccomp=%s", b.Bytes())
- }
- }
-
- return securityOpts, nil
-}
-
-// convertKVStringsToMap converts ["key=value"] to {"key":"value"}
-func convertKVStringsToMap(values []string) map[string]string {
- result := make(map[string]string, len(values))
- for _, value := range values {
- kv := strings.SplitN(value, "=", 2)
- if len(kv) == 1 {
- result[kv[0]] = ""
- } else {
- result[kv[0]] = kv[1]
- }
- }
-
- return result
-}
-
-// Takes a stringslice and converts to a uint32slice
-func stringSlicetoUint32Slice(inputSlice []string) ([]uint32, error) {
- var outputSlice []uint32
- for _, v := range inputSlice {
- u, err := strconv.ParseUint(v, 10, 32)
- if err != nil {
- return outputSlice, err
- }
- outputSlice = append(outputSlice, uint32(u))
- }
- return outputSlice, nil
-}
-
// ValidateFileName returns an error if filename contains ":"
// as it is currently not supported
func ValidateFileName(filename string) error {
diff --git a/cmd/podman/shared/parse/parse_test.go b/cmd/podman/shared/parse/parse_test.go
new file mode 100644
index 000000000..0a221c244
--- /dev/null
+++ b/cmd/podman/shared/parse/parse_test.go
@@ -0,0 +1,99 @@
+//nolint
+// most of these validate and parse functions have been taken from projectatomic/docker
+// and modified for cri-o
+package parse
+
+import (
+ "testing"
+)
+
+func TestValidateExtraHost(t *testing.T) {
+ type args struct {
+ val string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ wantErr bool
+ }{
+ //2001:0db8:85a3:0000:0000:8a2e:0370:7334
+ {name: "good-ipv4", args: args{val: "foobar:192.168.1.1"}, want: "foobar:192.168.1.1", wantErr: false},
+ {name: "bad-ipv4", args: args{val: "foobar:999.999.999.99"}, want: "", wantErr: true},
+ {name: "bad-ipv4", args: args{val: "foobar:999.999.999"}, want: "", wantErr: true},
+ {name: "noname-ipv4", args: args{val: "192.168.1.1"}, want: "", wantErr: true},
+ {name: "noname-ipv4", args: args{val: ":192.168.1.1"}, want: "", wantErr: true},
+ {name: "noip", args: args{val: "foobar:"}, want: "", wantErr: true},
+ {name: "noip", args: args{val: "foobar"}, want: "", wantErr: true},
+ {name: "good-ipv6", args: args{val: "foobar:2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "foobar:2001:0db8:85a3:0000:0000:8a2e:0370:7334", wantErr: false},
+ {name: "bad-ipv6", args: args{val: "foobar:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true},
+ {name: "bad-ipv6", args: args{val: "foobar:0db8:85a3:0000:0000:8a2e:0370:7334.0000.0000.000"}, want: "", wantErr: true},
+ {name: "noname-ipv6", args: args{val: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true},
+ {name: "noname-ipv6", args: args{val: ":2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ValidateExtraHost(tt.args.val)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("ValidateExtraHost() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("ValidateExtraHost() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_validateIPAddress(t *testing.T) {
+ type args struct {
+ val string
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ wantErr bool
+ }{
+ {name: "ipv4-good", args: args{val: "192.168.1.1"}, want: "192.168.1.1", wantErr: false},
+ {name: "ipv4-bad", args: args{val: "192.168.1.1.1"}, want: "", wantErr: true},
+ {name: "ipv4-bad", args: args{val: "192."}, want: "", wantErr: true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := validateIPAddress(tt.args.val)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("validateIPAddress() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("validateIPAddress() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestValidateFileName(t *testing.T) {
+ type args struct {
+ filename string
+ }
+ tests := []struct {
+ name string
+ 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: "/"}, wantErr: false},
+ {name: "bad", args: args{filename: "/:"}, wantErr: true},
+ {name: "bad", args: args{filename: ":/"}, wantErr: true},
+ {name: "bad", args: args{filename: "/some/rand:/path"}, wantErr: true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if err := ValidateFileName(tt.args.filename); (err != nil) != tt.wantErr {
+ t.Errorf("ValidateFileName() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
diff --git a/cmd/podman/shared/workers.go b/cmd/podman/shared/workers.go
index 112af89cc..b6e3f10e7 100644
--- a/cmd/podman/shared/workers.go
+++ b/cmd/podman/shared/workers.go
@@ -110,9 +110,14 @@ func (p *Pool) newWorker(slot int) {
func DefaultPoolSize(name string) int {
numCpus := runtime.NumCPU()
switch name {
+ case "init":
+ fallthrough
case "kill":
+ fallthrough
case "pause":
+ fallthrough
case "rm":
+ fallthrough
case "unpause":
if numCpus <= 3 {
return numCpus * 3
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 309f9765a..ace81646c 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -641,6 +641,14 @@ method StartContainer(name: string) -> (container: string)
# ~~~
method StopContainer(name: string, timeout: int) -> (container: string)
+# InitContainer initializes the given container. It accepts a container name or
+# ID, and will initialize the container matching that ID if possible, and error
+# if not. Containers can only be initialized when they are in the Created or
+# Exited states. Initialization prepares a container to be started, but does not
+# start the container. It is intended to be used to debug a container's state
+# prior to starting it.
+method InitContainer(name: string) -> (container: string)
+
# RestartContainer will restart a running container given a container name or ID and timeout value. The timeout
# value is the time before a forcible stop is used to stop the container. If the container cannot be found by
# name or ID, a [ContainerNotFound](#ContainerNotFound) error will be returned; otherwise, the ID of the
@@ -1210,6 +1218,8 @@ method GetLayersMapWithImageInfo() -> (layerMap: string)
# BuildImageHierarchyMap is for the development of Podman and should not be used.
method BuildImageHierarchyMap(name: string) -> (imageInfo: string)
+method GenerateSystemd(name: string, restart: string, timeout: int, useName: bool) -> (unit: string)
+
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
error ImageNotFound (id: string, reason: string)
@@ -1225,7 +1235,7 @@ error PodNotFound (name: string, reason: string)
# VolumeNotFound means the volume could not be found by the name or ID in local storage.
error VolumeNotFound (id: string, reason: string)
-# PodContainerError means a container associated with a pod failed to preform an operation. It contains
+# PodContainerError means a container associated with a pod failed to perform an operation. It contains
# a container ID of the container that failed.
error PodContainerError (podname: string, errors: []PodContainerErrorData)
@@ -1233,6 +1243,9 @@ error PodContainerError (podname: string, errors: []PodContainerErrorData)
# the pod ID.
error NoContainersInPod (name: string)
+# InvalidState indicates that a container or pod was in an improper state for the requested operation
+error InvalidState (id: string, reason: string)
+
# ErrorOccurred is a generic error for an error that occurs during the execution. The actual error message
# is includes as part of the error's text.
error ErrorOccurred (reason: string)
@@ -1241,4 +1254,4 @@ error ErrorOccurred (reason: string)
error RuntimeError (reason: string)
# The Podman endpoint requires that you use a streaming connection.
-error WantsMoreRequired (reason: string)
+error WantsMoreRequired (reason: string) \ No newline at end of file