diff options
-rw-r--r-- | OWNERS | 14 | ||||
-rw-r--r-- | libpod/container_api.go | 20 | ||||
-rw-r--r-- | libpod/kube.go | 8 | ||||
-rw-r--r-- | libpod/oci_attach_linux.go | 5 | ||||
-rw-r--r-- | libpod/oci_attach_unsupported.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 6 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 7 | ||||
-rw-r--r-- | pkg/errorhandling/errorhandling.go | 8 | ||||
-rw-r--r-- | test/e2e/generate_kube_test.go | 29 |
9 files changed, 85 insertions, 14 deletions
@@ -1,20 +1,22 @@ approvers: - - mheon - baude + - edsantiago + - giuseppe + - jwhonce + - mheon - mrunalp - rhatdan - TomSweeneyRedHat - umohnani8 - - giuseppe - vrothberg - - jwhonce reviewers: - - mheon - baude + - edsantiago + - giuseppe + - jwhonce + - mheon - mrunalp - rhatdan - TomSweeneyRedHat - umohnani8 - - giuseppe - vrothberg - - jwhonce diff --git a/libpod/container_api.go b/libpod/container_api.go index 0d7bbacd0..aef37dd59 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -9,6 +9,7 @@ import ( "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/libpod/events" + "github.com/containers/podman/v2/pkg/signal" "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -129,7 +130,7 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *define.AttachSt // Attach to the container before starting it go func() { - if err := c.attach(streams, keys, resize, true, startedChan); err != nil { + if err := c.attach(streams, keys, resize, true, startedChan, nil); err != nil { attachChan <- err } close(attachChan) @@ -243,8 +244,23 @@ func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <- return errors.Wrapf(define.ErrCtrStateInvalid, "can only attach to created or running containers") } + // HACK: This is really gross, but there isn't a better way without + // splitting attach into separate versions for StartAndAttach and normal + // attaching, and I really do not want to do that right now. + // Send a SIGWINCH after attach succeeds so that most programs will + // redraw the screen for the new attach session. + attachRdy := make(chan bool) + if c.config.Spec.Process != nil && c.config.Spec.Process.Terminal { + go func() { + <-attachRdy + if err := c.ociRuntime.KillContainer(c, uint(signal.SIGWINCH), false); err != nil { + logrus.Warnf("Unable to send SIGWINCH to container %s after attach: %v", c.ID(), err) + } + }() + } + c.newContainerEvent(events.Attach) - return c.attach(streams, keys, resize, false, nil) + return c.attach(streams, keys, resize, false, nil, attachRdy) } // HTTPAttach forwards an attach session over a hijacked HTTP session. diff --git a/libpod/kube.go b/libpod/kube.go index 864bc78c7..9d5cbe68b 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -69,12 +69,20 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { return nil, servicePorts, err } servicePorts = containerPortsToServicePorts(ports) + } pod, err := p.podWithContainers(allContainers, ports) if err != nil { return nil, servicePorts, err } pod.Spec.HostAliases = extraHost + + if p.SharesPID() { + // unfortunately, go doesn't have a nice way to specify a pointer to a bool + b := true + pod.Spec.ShareProcessNamespace = &b + } + return pod, servicePorts, nil } diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index 622c613d9..74af449ed 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -31,7 +31,7 @@ const ( // Attach to the given container // Does not check if state is appropriate // started is only required if startContainer is true -func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error { +func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error { if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput { return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to") } @@ -74,6 +74,9 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <- } receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys) + if attachRdy != nil { + attachRdy <- true + } return readStdio(streams, receiveStdoutError, stdinDone) } diff --git a/libpod/oci_attach_unsupported.go b/libpod/oci_attach_unsupported.go index cd7c674b2..317dfdc90 100644 --- a/libpod/oci_attach_unsupported.go +++ b/libpod/oci_attach_unsupported.go @@ -9,7 +9,7 @@ import ( "k8s.io/client-go/tools/remotecommand" ) -func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error { +func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error { return define.ErrNotImplemented } diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 47d1c48f2..6dfb52c63 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -132,7 +132,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY libpod.WithInfraContainer(), libpod.WithPodName(podName), } - // TODO for now we just used the default kernel namespaces; we need to add/subtract this from yaml + // TODO we only configure Process namespace. We also need to account for Host{IPC,Network,PID} + // which is not currently possible with pod create + if podYAML.Spec.ShareProcessNamespace != nil && *podYAML.Spec.ShareProcessNamespace { + podOptions = append(podOptions, libpod.WithPodPID()) + } hostname := podYAML.Spec.Hostname if hostname == "" { diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 062b38a70..35550b9be 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -19,6 +19,7 @@ import ( "github.com/containers/podman/v2/pkg/bindings" "github.com/containers/podman/v2/pkg/bindings/containers" "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/errorhandling" "github.com/containers/podman/v2/pkg/specgen" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -537,8 +538,8 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta // de-spaghetti the code. defer func() { if err := containers.Remove(ic.ClientCxt, con.ID, bindings.PFalse, bindings.PTrue); err != nil { - if errors.Cause(err) == define.ErrNoSuchCtr || - errors.Cause(err) == define.ErrCtrRemoved { + if errorhandling.Contains(err, define.ErrNoSuchCtr) || + errorhandling.Contains(err, define.ErrCtrRemoved) { logrus.Warnf("Container %s does not exist: %v", con.ID, err) } else { logrus.Errorf("Error removing container %s: %v", con.ID, err) @@ -556,7 +557,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta // Determine why the wait failed. If the container doesn't exist, // consult the events. - if !strings.Contains(waitErr.Error(), define.ErrNoSuchCtr.Error()) { + if !errorhandling.Contains(waitErr, define.ErrNoSuchCtr) { return &report, waitErr } diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index 3117b0ca4..ca6b60bc5 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -57,3 +57,11 @@ func CloseQuiet(f *os.File) { logrus.Errorf("unable to close file %s: %q", f.Name(), err) } } + +// Contains checks if err's message contains sub's message. Contains should be +// used iff either err or sub has lost type information (e.g., due to +// marshaling). For typed errors, please use `errors.Contains(...)` or `Is()` +// in recent version of Go. +func Contains(err error, sub error) bool { + return strings.Contains(err.Error(), sub.Error()) +} diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 3c3fb5a4d..e886c6000 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -348,4 +348,33 @@ var _ = Describe("Podman generate kube", func() { Expect(inspect.ExitCode()).To(Equal(0)) Expect(inspect.OutputToString()).To(ContainSubstring(vol1)) }) + + It("podman generate kube sharing pid namespace", func() { + podName := "test" + podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--share", "pid"}) + podSession.WaitWithDefaultTimeout() + Expect(podSession.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"create", "--pod", podName, "--name", "test1", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml") + kube := podmanTest.Podman([]string{"generate", "kube", podName, "-f", outputFile}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + rm := podmanTest.Podman([]string{"pod", "rm", "-f", podName}) + rm.WaitWithDefaultTimeout() + Expect(rm.ExitCode()).To(Equal(0)) + + play := podmanTest.Podman([]string{"play", "kube", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"pod", "inspect", podName}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"pid"`)) + }) }) |