diff options
-rw-r--r-- | cmd/podman/checkpoint.go | 22 | ||||
-rw-r--r-- | cmd/podman/commands.go | 7 | ||||
-rw-r--r-- | cmd/podman/generate.go | 7 | ||||
-rw-r--r-- | cmd/podman/generate_kube.go | 40 | ||||
-rw-r--r-- | cmd/podman/main.go | 1 | ||||
-rw-r--r-- | cmd/podman/pull.go | 9 | ||||
-rw-r--r-- | cmd/podman/restore.go | 23 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 35 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 11 | ||||
-rw-r--r-- | install.md | 7 | ||||
-rw-r--r-- | libpod/container.go | 2 | ||||
-rw-r--r-- | libpod/container_internal.go | 2 | ||||
-rw-r--r-- | libpod/kube.go | 2 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 10 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 69 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 72 | ||||
-rw-r--r-- | pkg/adapter/runtime.go | 29 | ||||
-rw-r--r-- | pkg/adapter/runtime_remote.go | 19 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.c | 7 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 14 | ||||
-rw-r--r-- | pkg/varlinkapi/generate.go | 30 | ||||
-rw-r--r-- | test/e2e/create_test.go | 11 | ||||
-rw-r--r-- | test/e2e/pull_test.go | 6 | ||||
-rw-r--r-- | test/system/030-run.bats | 12 |
24 files changed, 318 insertions, 129 deletions
diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go index dbf72c2cd..5b8d00ff9 100644 --- a/cmd/podman/checkpoint.go +++ b/cmd/podman/checkpoint.go @@ -1,13 +1,9 @@ package main import ( - "context" - "fmt" - "os" - "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/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -57,7 +53,7 @@ func checkpointCmd(c *cliconfig.CheckpointValues) error { return errors.New("checkpointing a container requires root") } - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } @@ -68,17 +64,5 @@ func checkpointCmd(c *cliconfig.CheckpointValues) error { KeepRunning: c.LeaveRunning, TCPEstablished: c.TcpEstablished, } - containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running") - - for _, ctr := range containers { - if err = ctr.Checkpoint(context.TODO(), options); err != nil { - if lastError != nil { - fmt.Fprintln(os.Stderr, lastError) - } - lastError = errors.Wrapf(err, "failed to checkpoint container %v", ctr.ID()) - } else { - fmt.Println(ctr.ID()) - } - } - return lastError + return runtime.Checkpoint(c, options) } diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index 9fea1494b..6156fc2f8 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -13,7 +13,6 @@ func getMainCommands() []*cobra.Command { rootCommands := []*cobra.Command{ _commitCommand, _execCommand, - _generateCommand, _playCommand, _loginCommand, _logoutCommand, @@ -71,12 +70,6 @@ func getContainerSubCommands() []*cobra.Command { } } -func getGenerateSubCommands() []*cobra.Command { - return []*cobra.Command{ - _containerKubeCommand, - } -} - // Commands that the local client implements func getPlaySubCommands() []*cobra.Command { return []*cobra.Command{ diff --git a/cmd/podman/generate.go b/cmd/podman/generate.go index 197fd26a6..a0637ecb2 100644 --- a/cmd/podman/generate.go +++ b/cmd/podman/generate.go @@ -14,10 +14,15 @@ var ( Long: generateDescription, RunE: commandRunE(), } + + // Commands that are universally implemented + generateCommands = []*cobra.Command{ + _containerKubeCommand, + } ) func init() { generateCommand.Command = _generateCommand - generateCommand.AddCommand(getGenerateSubCommands()...) + generateCommand.AddCommand(generateCommands...) generateCommand.SetUsageTemplate(UsageTemplate()) } diff --git a/cmd/podman/generate_kube.go b/cmd/podman/generate_kube.go index c58372899..30818403b 100644 --- a/cmd/podman/generate_kube.go +++ b/cmd/podman/generate_kube.go @@ -3,13 +3,11 @@ package main import ( "fmt" "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" podmanVersion "github.com/containers/libpod/version" "github.com/ghodss/yaml" "github.com/pkg/errors" "github.com/spf13/cobra" - "k8s.io/api/core/v1" ) var ( @@ -42,14 +40,12 @@ func init() { func generateKubeYAMLCmd(c *cliconfig.GenerateKubeValues) error { var ( - podYAML *v1.Pod - container *libpod.Container - err error - output []byte - pod *libpod.Pod + //podYAML *v1.Pod + err error + output []byte + //pod *libpod.Pod marshalledPod []byte marshalledService []byte - servicePorts []v1.ServicePort ) args := c.InputArgs @@ -57,43 +53,27 @@ func generateKubeYAMLCmd(c *cliconfig.GenerateKubeValues) error { return errors.Errorf("you must provide exactly one container|pod ID or name") } - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) - // Get the container in question - container, err = runtime.LookupContainer(args[0]) + podYAML, serviceYAML, err := runtime.GenerateKube(c) if err != nil { - pod, err = runtime.LookupPod(args[0]) - if err != nil { - return err - } - podYAML, servicePorts, err = pod.GenerateForKube() - } else { - if len(container.Dependencies()) > 0 { - return errors.Wrapf(libpod.ErrNotImplemented, "containers with dependencies") - } - podYAML, err = container.GenerateForKube() + return err } + // Marshall the results + marshalledPod, err = yaml.Marshal(podYAML) if err != nil { return err } - if c.Service { - serviceYAML := libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts) marshalledService, err = yaml.Marshal(serviceYAML) if err != nil { return err } } - // Marshall the results - marshalledPod, err = yaml.Marshal(podYAML) - if err != nil { - return err - } - header := `# Generation of Kubernetes YAML is still under development! # # Save the output of this file and use kubectl create -f to import diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 35a94b3db..e8c3e14ea 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -36,6 +36,7 @@ var mainCommands = []*cobra.Command{ _createCommand, _eventsCommand, _exportCommand, + _generateCommand, _historyCommand, &_imagesCommand, _importCommand, diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go index 491d3a8c2..7cc7b65b3 100644 --- a/cmd/podman/pull.go +++ b/cmd/podman/pull.go @@ -61,7 +61,12 @@ func init() { // pullCmd gets the data from the command line and calls pullImage // to copy an image from a registry to a local machine -func pullCmd(c *cliconfig.PullValues) error { +func pullCmd(c *cliconfig.PullValues) (retError error) { + defer func() { + if retError != nil && exitCode == 0 { + exitCode = 1 + } + }() if c.Bool("trace") { span, _ := opentracing.StartSpanFromContext(Ctx, "pullCmd") defer span.Finish() @@ -163,7 +168,7 @@ func pullCmd(c *cliconfig.PullValues) error { for _, name := range names { newImage, err := runtime.New(getContext(), name, c.String("signature-policy"), authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, true, nil) if err != nil { - println(errors.Wrapf(err, "error pulling image %q", name)) + logrus.Errorf("error pulling image %q", name) foundImage = false continue } diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go index 0f6828432..0f0150644 100644 --- a/cmd/podman/restore.go +++ b/cmd/podman/restore.go @@ -1,13 +1,9 @@ package main import ( - "context" - "fmt" - "os" - "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/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -57,7 +53,7 @@ func restoreCmd(c *cliconfig.RestoreValues) error { return errors.New("restoring a container requires root") } - runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) + runtime, err := adapter.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } @@ -67,18 +63,5 @@ func restoreCmd(c *cliconfig.RestoreValues) error { Keep: c.Keep, TCPEstablished: c.TcpEstablished, } - - containers, lastError := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateExited, "checkpointed") - - for _, ctr := range containers { - if err = ctr.Restore(context.TODO(), options); err != nil { - if lastError != nil { - fmt.Fprintln(os.Stderr, lastError) - } - lastError = errors.Wrapf(err, "failed to restore container %v", ctr.ID()) - } else { - fmt.Println(ctr.ID()) - } - } - return lastError + return runtime.Restore(c, options) } diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index 7bef62355..e14276bdf 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + v1 "k8s.io/api/core/v1" "os" "path/filepath" "regexp" @@ -938,3 +939,37 @@ func envSliceToMap(env []string) map[string]string { } return m } + +// GenerateKube generates kubernetes yaml based on a pod or container +func GenerateKube(name string, service bool, r *libpod.Runtime) (*v1.Pod, *v1.Service, error) { + var ( + pod *libpod.Pod + podYAML *v1.Pod + err error + container *libpod.Container + servicePorts []v1.ServicePort + serviceYAML v1.Service + ) + // Get the container in question + container, err = r.LookupContainer(name) + if err != nil { + pod, err = r.LookupPod(name) + if err != nil { + return nil, nil, err + } + podYAML, servicePorts, err = pod.GenerateForKube() + } else { + if len(container.Dependencies()) > 0 { + return nil, nil, errors.Wrapf(libpod.ErrNotImplemented, "containers with dependencies") + } + podYAML, err = container.GenerateForKube() + } + if err != nil { + return nil, nil, err + } + + if service { + serviceYAML = libpod.GenerateKubeServiceFromV1Pod(podYAML, servicePorts) + } + return podYAML, &serviceYAML, nil +} diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index c6997cd3f..b5295273a 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -98,6 +98,11 @@ type ImageSearchFilter ( star_count: int ) +type KubePodService ( + pod: string, + service: string +) + type Container ( id: string, image: string, @@ -1124,11 +1129,7 @@ method ImagesPrune(all: bool) -> (pruned: []string) # GenerateKube generates a Kubernetes v1 Pod description of a Podman container or pod # and its containers. The description is in YAML. See also [ReplayKube](ReplayKube). -# method GenerateKube() -> (notimplemented: NotImplemented) - -# GenerateKubeService generates a Kubernetes v1 Service description of a Podman container or pod -# and its containers. The description is in YAML. See also [GenerateKube](GenerateKube). -# method GenerateKubeService() -> (notimplemented: NotImplemented) +method GenerateKube(name: string, service: bool) -> (pod: KubePodService) # ReplayKube recreates a pod and its containers based on a Kubernetes v1 Pod description (in YAML) # like that created by GenerateKube. See also [GenerateKube](GenerateKube). diff --git a/install.md b/install.md index 80ae03208..548b38c1b 100644 --- a/install.md +++ b/install.md @@ -55,12 +55,14 @@ sudo yum module install -y container-tools:1.0 ```bash sudo apt-get update -qq -sudo apt-get install -qq -y software-properties-common +sudo apt-get install -qq -y software-properties-common uidmap sudo add-apt-repository -y ppa:projectatomic/ppa sudo apt-get update -qq sudo apt-get -qq -y install podman ``` +Take note of the [Build and Run Dependencies](#build-and-run-dependencies) listed below if you run into any issues. + ## Building from scratch ### Prerequisites @@ -130,7 +132,8 @@ apt-get install -y \ libprotobuf-c0-dev \ libseccomp-dev \ libselinux1-dev \ - pkg-config + pkg-config \ + uidmap ``` Debian, Ubuntu, and related distributions will also need to do the following setup: diff --git a/libpod/container.go b/libpod/container.go index de4674222..4bf9a1ba9 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -614,7 +614,7 @@ func (c *Container) NewNetNS() bool { func (c *Container) PortMappings() ([]ocicni.PortMapping, error) { // First check if the container belongs to a network namespace (like a pod) if len(c.config.NetNsCtr) > 0 { - netNsCtr, err := c.runtime.LookupContainer(c.config.NetNsCtr) + netNsCtr, err := c.runtime.GetContainer(c.config.NetNsCtr) if err != nil { return nil, errors.Wrapf(err, "unable to lookup network namespace for container %s", c.ID()) } diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 36b5e01df..aa6448f4a 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -676,7 +676,7 @@ func (c *Container) getAllDependencies(visited map[string]*Container) error { } for _, depID := range depIDs { if _, ok := visited[depID]; !ok { - dep, err := c.runtime.state.LookupContainer(depID) + dep, err := c.runtime.state.Container(depID) if err != nil { return err } diff --git a/libpod/kube.go b/libpod/kube.go index 484127870..260269b2e 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -69,7 +69,7 @@ func (p *Pod) getInfraContainer() (*Container, error) { if err != nil { return nil, err } - return p.runtime.LookupContainer(infraID) + return p.runtime.GetContainer(infraID) } // GenerateKubeServiceFromV1Pod creates a v1 service object from a v1 pod object diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 85b860268..48c254c0f 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -548,16 +548,6 @@ func (r *Runtime) GetLatestContainer() (*Container, error) { return ctrs[lastCreatedIndex], nil } -// Export is the libpod portion of exporting a container to a tar file -func (r *Runtime) Export(name string, path string) error { - ctr, err := r.LookupContainer(name) - if err != nil { - return err - } - return ctr.Export(path) - -} - // RemoveContainersFromStorage attempt to remove containers from storage that do not exist in libpod database func (r *Runtime) RemoveContainersFromStorage(ctrs []string) { for _, i := range ctrs { diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index d4e8e30d9..931c55a57 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -257,7 +257,10 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions) func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) { results := shared.NewIntermediateLayer(&c.PodmanCommand, false) ctr, _, err := shared.CreateContainer(ctx, &results, r.Runtime) - return ctr.ID(), err + if err != nil { + return "", err + } + return ctr.ID(), nil } // Run a libpod container @@ -443,3 +446,67 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er } return nil } + +// Checkpoint one or more containers +func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error { + var ( + containers []*libpod.Container + err, lastError error + ) + + if c.All { + containers, err = r.Runtime.GetRunningContainers() + } else { + containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime) + } + if err != nil { + return err + } + + for _, ctr := range containers { + if err = ctr.Checkpoint(context.TODO(), options); err != nil { + if lastError != nil { + fmt.Fprintln(os.Stderr, lastError) + } + lastError = errors.Wrapf(err, "failed to checkpoint container %v", ctr.ID()) + } else { + fmt.Println(ctr.ID()) + } + } + return lastError +} + +// Restore one or more containers +func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error { + var ( + containers []*libpod.Container + err, lastError error + filterFuncs []libpod.ContainerFilter + ) + + filterFuncs = append(filterFuncs, func(c *libpod.Container) bool { + state, _ := c.State() + return state == libpod.ContainerStateExited + }) + + if c.All { + containers, err = r.GetContainers(filterFuncs...) + } else { + containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime) + } + if err != nil { + return err + } + + for _, ctr := range containers { + if err = ctr.Restore(context.TODO(), options); err != nil { + if lastError != nil { + fmt.Fprintln(os.Stderr, lastError) + } + lastError = errors.Wrapf(err, "failed to restore container %v", ctr.ID()) + } else { + fmt.Println(ctr.ID()) + } + } + return lastError +} diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index 9ca823760..50cff9fa0 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -537,3 +537,75 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er } return <-errChan } + +// Checkpoint one or more containers +func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error { + var lastError error + ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs) + if err != nil { + return err + } + if c.All { + // We dont have a great way to get all the running containers, so need to get all and then + // check status on them bc checkpoint considers checkpointing a stopped container an error + var runningIds []string + for _, id := range ids { + ctr, err := r.LookupContainer(id) + if err != nil { + return err + } + if ctr.state.State == libpod.ContainerStateRunning { + runningIds = append(runningIds, id) + } + } + ids = runningIds + } + + for _, id := range ids { + if _, err := iopodman.ContainerCheckpoint().Call(r.Conn, id, options.Keep, options.KeepRunning, options.TCPEstablished); err != nil { + if lastError != nil { + fmt.Fprintln(os.Stderr, lastError) + } + lastError = errors.Wrapf(err, "failed to checkpoint container %v", id) + } else { + fmt.Println(id) + } + } + return lastError +} + +// Restore one or more containers +func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error { + var lastError error + ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs) + if err != nil { + return err + } + if c.All { + // We dont have a great way to get all the exited containers, so need to get all and then + // check status on them bc checkpoint considers restoring a running container an error + var exitedIDs []string + for _, id := range ids { + ctr, err := r.LookupContainer(id) + if err != nil { + return err + } + if ctr.state.State != libpod.ContainerStateRunning { + exitedIDs = append(exitedIDs, id) + } + } + ids = exitedIDs + } + + for _, id := range ids { + if _, err := iopodman.ContainerRestore().Call(r.Conn, id, options.Keep, options.TCPEstablished); err != nil { + if lastError != nil { + fmt.Fprintln(os.Stderr, lastError) + } + lastError = errors.Wrapf(err, "failed to restore container %v", id) + } else { + fmt.Println(id) + } + } + return lastError +} diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index d45bdb56d..6aafed550 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -7,6 +7,7 @@ import ( "context" "io" "io/ioutil" + "k8s.io/api/core/v1" "os" "text/template" @@ -404,27 +405,7 @@ func (r *LocalRuntime) Diff(c *cliconfig.DiffValues, to string) ([]archive.Chang return r.Runtime.GetDiff("", to) } -// func (r *LocalRuntime) joinContainerOrCreateRootlessUserNS(ctr *libpod.Container) (bool, int, error) { -// if os.Geteuid() == 0 { -// return false, 0, nil -// } -// s, err := ctr.State() -// if err != nil { -// return false, -1, err -// } -// opts := rootless.Opts{ -// Argument: ctr.ID(), -// } -// if s == libpod.ContainerStateRunning || s == libpod.ContainerStatePaused { -// data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile) -// if err != nil { -// return false, -1, errors.Wrapf(err, "Container %s cannot read conmon PID file %q", ctr.ID(), ctr.Config().ConmonPidFile) -// } -// conmonPid, err := strconv.Atoi(string(data)) -// if err != nil { -// return false, -1, errors.Wrapf(err, "Container %s cannot parse PID %q", ctr.ID(), data) -// } -// return rootless.JoinDirectUserAndMountNSWithOpts(uint(conmonPid), &opts) -// } -// return rootless.BecomeRootInUserNSWithOpts(&opts) -// } +// GenerateKube creates kubernetes email from containers and pods +func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, *v1.Service, error) { + return shared.GenerateKube(c.InputArgs[0], c.Service, r.Runtime) +} diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index 807a9ad8f..71f7380db 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -5,9 +5,11 @@ package adapter import ( "bufio" "context" + "encoding/json" "fmt" "io" "io/ioutil" + v1 "k8s.io/api/core/v1" "os" "strings" "text/template" @@ -858,3 +860,20 @@ func stringToChangeType(change string) archive.ChangeType { return archive.ChangeModify } } + +// GenerateKube creates kubernetes email from containers and pods +func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, *v1.Service, error) { + var ( + pod v1.Pod + service v1.Service + ) + reply, err := iopodman.GenerateKube().Call(r.Conn, c.InputArgs[0], c.Service) + if err != nil { + return nil, nil, errors.Wrap(err, "unable to create kubernetes YAML") + } + if err := json.Unmarshal([]byte(reply.Pod), &pod); err != nil { + return nil, nil, err + } + err = json.Unmarshal([]byte(reply.Service), &service) + return &pod, &service, err +} diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 9cb79ed4d..d6a2793a7 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -16,6 +16,8 @@ #include <sys/types.h> #include <sys/prctl.h> #include <dirent.h> +#include <termios.h> +#include <sys/ioctl.h> static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces"; static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone"; @@ -178,6 +180,11 @@ reexec_userns_join (int userns, int mountns) _exit (EXIT_FAILURE); } + if (isatty (1) && ioctl (1, TIOCSCTTY, 0) == -1) { + fprintf (stderr, "cannot ioctl(TIOCSCTTY): %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } + if (setns (userns, 0) < 0) { fprintf (stderr, "cannot setns: %s\n", strerror (errno)); diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 1d1b1713d..2c99f41a4 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -28,6 +28,10 @@ extern int reexec_userns_join(int userns, int mountns); */ import "C" +const ( + numSig = 65 // max number of signals +) + func runInUser() error { os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done") return nil @@ -283,7 +287,15 @@ func BecomeRootInUserNS() (bool, int, error) { c := make(chan os.Signal, 1) - gosignal.Notify(c) + signals := []os.Signal{} + for sig := 0; sig < numSig; sig++ { + if sig == int(syscall.SIGTSTP) { + continue + } + signals = append(signals, syscall.Signal(sig)) + } + + gosignal.Notify(c, signals...) defer gosignal.Reset() go func() { for s := range c { diff --git a/pkg/varlinkapi/generate.go b/pkg/varlinkapi/generate.go new file mode 100644 index 000000000..bc600c397 --- /dev/null +++ b/pkg/varlinkapi/generate.go @@ -0,0 +1,30 @@ +// +build varlink + +package varlinkapi + +import ( + "encoding/json" + "github.com/containers/libpod/cmd/podman/shared" + iopodman "github.com/containers/libpod/cmd/podman/varlink" +) + +// GenerateKube ... +func (i *LibpodAPI) GenerateKube(call iopodman.VarlinkCall, name string, service bool) error { + pod, serv, err := shared.GenerateKube(name, service, i.Runtime) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + podB, err := json.Marshal(pod) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + servB, err := json.Marshal(serv) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + return call.ReplyGenerateKube(iopodman.KubePodService{ + Pod: string(podB), + Service: string(servB), + }) +} diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 6ed5ad2d8..105cba37c 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -70,6 +70,17 @@ var _ = Describe("Podman create", func() { Expect(podmanTest.NumberOfContainers()).To(Equal(1)) }) + It("podman create using existing name", func() { + session := podmanTest.Podman([]string{"create", "--name=foo", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + session = podmanTest.Podman([]string{"create", "--name=foo", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + }) + It("podman create adds annotation", func() { session := podmanTest.Podman([]string{"create", "--annotation", "HELLO=WORLD", ALPINE, "ls"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go index de6d4ea09..4e4e80d56 100644 --- a/test/e2e/pull_test.go +++ b/test/e2e/pull_test.go @@ -38,6 +38,12 @@ var _ = Describe("Podman pull", func() { }) + It("podman pull from docker a not existing image", func() { + session := podmanTest.Podman([]string{"pull", "ibetthisdoesntexistthere:foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Not(Equal(0))) + }) + It("podman pull from docker with tag", func() { session := podmanTest.Podman([]string{"pull", "busybox:glibc"}) session.WaitWithDefaultTimeout() diff --git a/test/system/030-run.bats b/test/system/030-run.bats index eef05747f..bdbe724ef 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -34,11 +34,15 @@ echo $rand | 0 | $rand } @test "podman run - uidmapping has no /sys/kernel mounts" { - run_podman $expected_rc run --uidmapping 0:100:10000 $IMAGE mount | grep /sys/kernel - is "$output" "" "podman run $cmd - output" + skip_if_rootless "cannot umount as rootless" - run_podman $expected_rc run --net host --uidmapping 0:100:10000 $IMAGE mount | grep /sys/kernel - is "$output" "" "podman run $cmd - output" + run_podman run --rm --uidmap 0:100:10000 $IMAGE mount + run grep /sys/kernel <(echo "$output") + is "$output" "" "unwanted /sys/kernel in 'mount' output" + + run_podman run --rm --net host --uidmap 0:100:10000 $IMAGE mount + run grep /sys/kernel <(echo "$output") + is "$output" "" "unwanted /sys/kernel in 'mount' output (with --net=host)" } # vim: filetype=sh |