summaryrefslogtreecommitdiff
path: root/cmd/podman/create.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/create.go')
-rw-r--r--cmd/podman/create.go134
1 files changed, 82 insertions, 52 deletions
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index bc010d047..fc0c71536 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -24,6 +24,7 @@ import (
"github.com/docker/docker/pkg/signal"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -57,6 +58,30 @@ var createCommand = cli.Command{
}
func createCmd(c *cli.Context) error {
+ if err := createInit(c); err != nil {
+ return err
+ }
+
+ if os.Geteuid() != 0 {
+ rootless.SetSkipStorageSetup(true)
+ }
+
+ runtime, err := libpodruntime.GetContainerRuntime(c)
+ if err != nil {
+ return errors.Wrapf(err, "error creating libpod runtime")
+ }
+ defer runtime.Shutdown(false)
+
+ ctr, _, err := createContainer(c, runtime)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("%s\n", ctr.ID())
+ return nil
+}
+
+func createInit(c *cli.Context) error {
// TODO should allow user to create based off a directory on the host not just image
// Need CLI support for this
@@ -83,63 +108,51 @@ func createCmd(c *cli.Context) error {
return errors.Errorf("image name or ID is required")
}
+ return nil
+}
+
+func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
+ rtc := runtime.GetConfig()
+ ctx := getContext()
rootfs := ""
if c.Bool("rootfs") {
rootfs = c.Args()[0]
}
- mappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidmap"), c.String("subgidmap"))
- if err != nil {
- return err
- }
- storageOpts, err := libpodruntime.GetDefaultStoreOptions()
- if err != nil {
- return err
- }
- storageOpts.UIDMap = mappings.UIDMap
- storageOpts.GIDMap = mappings.GIDMap
-
- if os.Geteuid() != 0 {
- rootless.SetSkipStorageSetup(true)
- }
-
- runtime, err := libpodruntime.GetRuntimeWithStorageOpts(c, &storageOpts)
- if err != nil {
- return errors.Wrapf(err, "error creating libpod runtime")
- }
- defer runtime.Shutdown(false)
-
- rtc := runtime.GetConfig()
- ctx := getContext()
-
imageName := ""
var data *inspect.ImageData = nil
+
if rootfs == "" && !rootless.SkipStorageSetup() {
newImage, err := runtime.ImageRuntime().New(ctx, c.Args()[0], rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{}, false, false)
if err != nil {
- return err
+ return nil, nil, err
}
data, err = newImage.Inspect(ctx)
- imageName = newImage.Names()[0]
+ names := newImage.Names()
+ if len(names) > 0 {
+ imageName = names[0]
+ } else {
+ imageName = newImage.ID()
+ }
}
createConfig, err := parseCreateOpts(ctx, c, runtime, imageName, data)
if err != nil {
- return err
+ return nil, nil, err
}
runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig)
if err != nil {
- return err
+ return nil, nil, err
}
options, err := createConfig.GetContainerCreateOptions(runtime)
if err != nil {
- return err
+ return nil, nil, err
}
became, ret, err := joinOrCreateRootlessUserNamespace(createConfig, runtime)
if err != nil {
- return err
+ return nil, nil, err
}
if became {
os.Exit(ret)
@@ -147,27 +160,25 @@ func createCmd(c *cli.Context) error {
ctr, err := runtime.NewContainer(ctx, runtimeSpec, options...)
if err != nil {
- return err
+ return nil, nil, err
}
createConfigJSON, err := json.Marshal(createConfig)
if err != nil {
- return err
+ return nil, nil, err
}
if err := ctr.AddArtifact("create-config", createConfigJSON); err != nil {
- return err
+ return nil, nil, err
}
- logrus.Debug("new container created ", ctr.ID())
-
if c.String("cidfile") != "" {
err := libpod.WriteFile(ctr.ID(), c.String("cidfile"))
if err != nil {
logrus.Error(err)
}
}
- fmt.Printf("%s\n", ctr.ID())
- return nil
+ logrus.Debugf("New container created %q", ctr.ID())
+ return ctr, createConfig, nil
}
// Checks if a user-specified AppArmor profile is loaded, or loads the default profile if
@@ -311,7 +322,7 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error {
}
}
}
- config.ProcessLabel, config.MountLabel, err = label.InitLabels(labelOpts)
+ config.LabelOpts = labelOpts
return err
}
@@ -449,6 +460,10 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
}
blkioWeight = uint16(u)
}
+ var mountList []spec.Mount
+ if mountList, err = parseMounts(c.StringSlice("mount")); err != nil {
+ return nil, err
+ }
if err = parseVolumes(c.StringSlice("volume")); err != nil {
return nil, err
@@ -518,17 +533,6 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
}
}
- shmDir := ""
- if ipcMode.IsHost() {
- shmDir = "/dev/shm"
- } else if ipcMode.IsContainer() {
- ctr, err := runtime.LookupContainer(ipcMode.Container())
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", ipcMode.Container())
- }
- shmDir = ctr.ShmDir()
- }
-
// USER
user := c.String("user")
if user == "" {
@@ -629,7 +633,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
command = append(command, data.ContainerConfig.Cmd...)
}
- if len(command) == 0 {
+ if data != nil && len(command) == 0 {
return nil, errors.Errorf("No command specified on command line or as CMD or ENTRYPOINT in this image")
}
@@ -681,7 +685,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
}
var systemd bool
- if c.BoolT("systemd") && ((filepath.Base(command[0]) == "init") || (filepath.Base(command[0]) == "systemd")) {
+ if command != nil && c.BoolT("systemd") && ((filepath.Base(command[0]) == "init") || (filepath.Base(command[0]) == "systemd")) {
systemd = true
if signalString == "" {
stopSignal, err = signal.ParseSignal("RTMIN+3")
@@ -765,7 +769,6 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
Ulimit: c.StringSlice("ulimit"),
},
Rm: c.Bool("rm"),
- ShmDir: shmDir,
StopSignal: stopSignal,
StopTimeout: c.Uint("stop-timeout"),
Sysctl: sysctl,
@@ -774,6 +777,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
Tty: tty,
User: user,
UsernsMode: usernsMode,
+ Mounts: mountList,
Volumes: c.StringSlice("volume"),
WorkDir: workDir,
Rootfs: rootfs,
@@ -796,6 +800,11 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
return config, nil
}
+type namespace interface {
+ IsContainer() bool
+ Container() string
+}
+
func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *libpod.Runtime) (bool, int, error) {
if os.Geteuid() == 0 {
return false, 0, nil
@@ -827,5 +836,26 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l
}
}
+ namespacesStr := []string{string(createConfig.IpcMode), string(createConfig.NetMode), string(createConfig.UsernsMode), string(createConfig.PidMode), string(createConfig.UtsMode)}
+ for _, i := range namespacesStr {
+ if cc.IsNS(i) {
+ return rootless.JoinNSPath(cc.NS(i))
+ }
+ }
+
+ namespaces := []namespace{createConfig.IpcMode, createConfig.NetMode, createConfig.UsernsMode, createConfig.PidMode, createConfig.UtsMode}
+ for _, i := range namespaces {
+ if i.IsContainer() {
+ ctr, err := runtime.LookupContainer(i.Container())
+ if err != nil {
+ return false, -1, err
+ }
+ pid, err := ctr.PID()
+ if err != nil {
+ return false, -1, err
+ }
+ return rootless.JoinNS(uint(pid))
+ }
+ }
return rootless.BecomeRootInUserNS()
}