diff options
Diffstat (limited to 'cmd/podman/create.go')
-rw-r--r-- | cmd/podman/create.go | 134 |
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() } |