summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/checkpoint.go22
-rw-r--r--cmd/podman/commands.go7
-rw-r--r--cmd/podman/generate.go7
-rw-r--r--cmd/podman/generate_kube.go40
-rw-r--r--cmd/podman/main.go1
-rw-r--r--cmd/podman/pull.go9
-rw-r--r--cmd/podman/restore.go23
-rw-r--r--cmd/podman/shared/container.go35
-rw-r--r--cmd/podman/varlink/io.podman.varlink11
-rw-r--r--install.md7
-rw-r--r--libpod/container.go2
-rw-r--r--libpod/container_internal.go2
-rw-r--r--libpod/kube.go2
-rw-r--r--libpod/runtime_ctr.go10
-rw-r--r--pkg/adapter/containers.go69
-rw-r--r--pkg/adapter/containers_remote.go72
-rw-r--r--pkg/adapter/runtime.go29
-rw-r--r--pkg/adapter/runtime_remote.go19
-rw-r--r--pkg/rootless/rootless_linux.c7
-rw-r--r--pkg/rootless/rootless_linux.go14
-rw-r--r--pkg/varlinkapi/generate.go30
-rw-r--r--test/e2e/create_test.go11
-rw-r--r--test/e2e/pull_test.go6
-rw-r--r--test/system/030-run.bats12
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