aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2018-02-04 07:29:47 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-02-05 15:39:40 +0000
commit989f5e30627eb90a66fa06f87c40d161476395ed (patch)
tree87b4eabb2bfc27a9d4862db8063cb3cddb98bb23
parent095aaaa639ab57c594bb80bfefbfaed2a2fdff92 (diff)
downloadpodman-989f5e30627eb90a66fa06f87c40d161476395ed.tar.gz
podman-989f5e30627eb90a66fa06f87c40d161476395ed.tar.bz2
podman-989f5e30627eb90a66fa06f87c40d161476395ed.zip
Pass NOTIFY_SOCKET and LISTEN_FDS env to OCI RUntime if set
In order to have sd_notify from systemd to work in containers we need to pass down the NOTIFY_SOCKET environment variable to the container. LISTEN_FDS, tells the application inside of the container to use socket activation and grab the FDS that are leaked into the container. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #271 Approved by: umohnani8
-rw-r--r--libpod/oci.go9
-rw-r--r--test/e2e/run_test.go11
-rw-r--r--vendor/github.com/coreos/go-systemd/activation/files.go52
-rw-r--r--vendor/github.com/coreos/go-systemd/activation/listeners.go60
-rw-r--r--vendor/github.com/coreos/go-systemd/activation/packetconns.go37
5 files changed, 169 insertions, 0 deletions
diff --git a/libpod/oci.go b/libpod/oci.go
index 4183267b8..4ca0bfbef 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -13,6 +13,7 @@ import (
"time"
"github.com/containerd/cgroups"
+ "github.com/coreos/go-systemd/activation"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -210,6 +211,14 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string) (err e
// 0, 1 and 2 are stdin, stdout and stderr
cmd.Env = append(r.conmonEnv, fmt.Sprintf("_OCI_SYNCPIPE=%d", 3))
cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_STARTPIPE=%d", 4))
+ if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
+ cmd.Env = append(cmd.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify))
+ }
+ if listenfds, ok := os.LookupEnv("LISTEN_FDS"); ok {
+ cmd.Env = append(cmd.Env, fmt.Sprintf("LISTEN_FDS=%s", listenfds))
+ fds := activation.Files(false)
+ cmd.ExtraFiles = append(cmd.ExtraFiles, fds...)
+ }
err = cmd.Start()
if err != nil {
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index f364b6952..7bd42edc4 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -185,6 +185,17 @@ var _ = Describe("Podman run", func() {
Expect(session.OutputToString()).To(ContainSubstring("15"))
})
+ It("podman run notify_socket", func() {
+ sock := "/run/sock"
+ os.Setenv("NOTIFY_SOCKET", sock)
+ session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "NOTIFY_SOCKET"})
+ session.Wait(10)
+ Expect(session.ExitCode()).To(Equal(0))
+ match, _ := session.GrepString(sock)
+ Expect(match).Should(BeTrue())
+ os.Unsetenv("NOTIFY_SOCKET")
+ })
+
It("podman run log-opt", func() {
log := filepath.Join(podmanTest.TempDir, "/container.log")
session := podmanTest.Podman([]string{"run", "--rm", "--log-opt", fmt.Sprintf("path=%s", log), ALPINE, "ls"})
diff --git a/vendor/github.com/coreos/go-systemd/activation/files.go b/vendor/github.com/coreos/go-systemd/activation/files.go
new file mode 100644
index 000000000..c8e85fcd5
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/activation/files.go
@@ -0,0 +1,52 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package activation implements primitives for systemd socket activation.
+package activation
+
+import (
+ "os"
+ "strconv"
+ "syscall"
+)
+
+// based on: https://gist.github.com/alberts/4640792
+const (
+ listenFdsStart = 3
+)
+
+func Files(unsetEnv bool) []*os.File {
+ if unsetEnv {
+ defer os.Unsetenv("LISTEN_PID")
+ defer os.Unsetenv("LISTEN_FDS")
+ }
+
+ pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
+ if err != nil || pid != os.Getpid() {
+ return nil
+ }
+
+ nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS"))
+ if err != nil || nfds == 0 {
+ return nil
+ }
+
+ files := make([]*os.File, 0, nfds)
+ for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ {
+ syscall.CloseOnExec(fd)
+ files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd)))
+ }
+
+ return files
+}
diff --git a/vendor/github.com/coreos/go-systemd/activation/listeners.go b/vendor/github.com/coreos/go-systemd/activation/listeners.go
new file mode 100644
index 000000000..fd5dfc709
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/activation/listeners.go
@@ -0,0 +1,60 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package activation
+
+import (
+ "crypto/tls"
+ "net"
+)
+
+// Listeners returns a slice containing a net.Listener for each matching socket type
+// passed to this process.
+//
+// The order of the file descriptors is preserved in the returned slice.
+// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
+// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener}
+func Listeners(unsetEnv bool) ([]net.Listener, error) {
+ files := Files(unsetEnv)
+ listeners := make([]net.Listener, len(files))
+
+ for i, f := range files {
+ if pc, err := net.FileListener(f); err == nil {
+ listeners[i] = pc
+ }
+ }
+ return listeners, nil
+}
+
+// TLSListeners returns a slice containing a net.listener for each matching TCP socket type
+// passed to this process.
+// It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig.
+func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error) {
+ listeners, err := Listeners(unsetEnv)
+
+ if listeners == nil || err != nil {
+ return nil, err
+ }
+
+ if tlsConfig != nil && err == nil {
+ for i, l := range listeners {
+ // Activate TLS only for TCP sockets
+ if l.Addr().Network() == "tcp" {
+ listeners[i] = tls.NewListener(l, tlsConfig)
+ }
+ }
+ }
+
+ return listeners, err
+}
diff --git a/vendor/github.com/coreos/go-systemd/activation/packetconns.go b/vendor/github.com/coreos/go-systemd/activation/packetconns.go
new file mode 100644
index 000000000..48b2ca029
--- /dev/null
+++ b/vendor/github.com/coreos/go-systemd/activation/packetconns.go
@@ -0,0 +1,37 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package activation
+
+import (
+ "net"
+)
+
+// PacketConns returns a slice containing a net.PacketConn for each matching socket type
+// passed to this process.
+//
+// The order of the file descriptors is preserved in the returned slice.
+// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
+// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn}
+func PacketConns(unsetEnv bool) ([]net.PacketConn, error) {
+ files := Files(unsetEnv)
+ conns := make([]net.PacketConn, len(files))
+
+ for i, f := range files {
+ if pc, err := net.FilePacketConn(f); err == nil {
+ conns[i] = pc
+ }
+ }
+ return conns, nil
+}