summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--OWNERS14
-rw-r--r--libpod/container_api.go20
-rw-r--r--libpod/kube.go8
-rw-r--r--libpod/oci_attach_linux.go5
-rw-r--r--libpod/oci_attach_unsupported.go2
-rw-r--r--pkg/domain/infra/abi/play.go6
-rw-r--r--pkg/domain/infra/tunnel/containers.go7
-rw-r--r--pkg/errorhandling/errorhandling.go8
-rw-r--r--test/e2e/generate_kube_test.go29
9 files changed, 85 insertions, 14 deletions
diff --git a/OWNERS b/OWNERS
index 227c97d6a..9bd9eaac4 100644
--- a/OWNERS
+++ b/OWNERS
@@ -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"`))
+ })
})