summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml16
-rw-r--r--Makefile4
-rw-r--r--changelog.txt17
-rw-r--r--cmd/podman/cliconfig/config.go1
-rw-r--r--cmd/podman/create.go2
-rw-r--r--cmd/podman/exec.go30
-rw-r--r--cmd/podman/kill.go73
-rw-r--r--cmd/podman/rm.go3
-rw-r--r--cmd/podman/top.go2
-rwxr-xr-xcontrib/cirrus/integration_test.sh2
-rw-r--r--contrib/cirrus/lib.sh15
-rw-r--r--contrib/cirrus/packer/centos_setup.sh1
-rw-r--r--contrib/cirrus/packer/fedora_setup.sh1
-rw-r--r--contrib/cirrus/packer/rhel_setup.sh1
-rw-r--r--contrib/cirrus/packer/ubuntu_setup.sh1
-rwxr-xr-xcontrib/cirrus/setup_environment.sh4
-rw-r--r--docs/podman-exec.1.md4
-rw-r--r--libpod/container_api.go4
-rw-r--r--libpod/container_internal.go17
-rw-r--r--libpod/container_internal_linux.go48
-rw-r--r--libpod/oci.go13
-rw-r--r--libpod/runtime.go25
-rw-r--r--pkg/adapter/containers.go24
-rw-r--r--pkg/adapter/containers_remote.go25
-rw-r--r--pkg/logs/logs.go5
-rw-r--r--pkg/rootless/rootless_linux.go9
-rw-r--r--test/e2e/pod_infra_container_test.go17
27 files changed, 271 insertions, 93 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 4521866d1..b473980ea 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -27,11 +27,11 @@ env:
####
#### Cache-image names to test with
###
- FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-7f4cd1f7"
- PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-7f4cd1f7"
- UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-84514d8b"
+ FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-d6d53e40"
+ PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-d6d53e40"
+ UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-d6d53e40"
# RHEL_CACHE_IMAGE_NAME: "rhel-8-notready"
- PRIOR_RHEL_CACHE_IMAGE_NAME: "rhel-7-libpod-7f4cd1f7"
+ PRIOR_RHEL_CACHE_IMAGE_NAME: "rhel-7-libpod-d6d53e40"
# CENTOS_CACHE_IMAGE_NAME: "centos-7-notready"
####
@@ -169,9 +169,9 @@ testing_task:
image_name: "${FEDORA_CACHE_IMAGE_NAME}"
image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}"
image_name: "${UBUNTU_CACHE_IMAGE_NAME}"
- image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}"
- # TODO: tests fail
+ # TODO: Make these work (also optional_testing_task below)
+ # image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}"
# image_name: "${RHEL_CACHE_IMAGE_NAME}"
# image_name: "${CENTOS_CACHE_IMAGE_NAME}"
@@ -206,9 +206,9 @@ optional_testing_task:
image_name: "${FEDORA_CACHE_IMAGE_NAME}"
image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}"
image_name: "${UBUNTU_CACHE_IMAGE_NAME}"
- image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}"
- # TODO: Make these work (also build_images_task below)
+ # TODO: Make these work (also testing_task above)
# image_name: "${RHEL_CACHE_IMAGE_NAME}"
+ # image_name: "${PRIOR_RHEL_CACHE_IMAGE_NAME}"
# image_name: "${CENTOS_CACHE_IMAGE_NAME}"
timeout_in: 60m
diff --git a/Makefile b/Makefile
index 60fb3eda7..cb351f917 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
GO ?= go
DESTDIR ?= /
-EPOCH_TEST_COMMIT ?= cabfc9b6fb16c5b55d70140182496bbe129f6a4b
+EPOCH_TEST_COMMIT ?= 4b80517b6a638ff06f8ad432f0f0f5839283d058
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
@@ -44,7 +44,7 @@ LIBSECCOMP_COMMIT := release-2.3
# Rarely if ever should integration tests take more than 50min,
# caller may override in special circumstances if needed.
-GINKGOTIMEOUT ?= -timeout=50m
+GINKGOTIMEOUT ?= -timeout=90m
# If GOPATH not specified, use one in the local directory
ifeq ($(GOPATH),)
diff --git a/changelog.txt b/changelog.txt
index 9dd0ae2d1..7db579f3a 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,20 @@
+- Changelog for v1.1.2 (2019-03-04)
+ * Fix #2521
+ * Update release notes for v1.1.2
+ * Change timestamp format for podman logs
+ * Don't extract tar file in podman cp
+ * runtime: fill a proper default tmpdir when --config is used
+ * Add additional defense against 0-length log segfaults
+ * When logging with timestamps, append only until newline
+ * Ensure that each log line is newline-terminated
+ * A few more usage-message tweaks
+ * Add missing short flag -l for run/create
+ * Fix aliased commands to actually work
+ * Support podman-remote stop container(s)
+ * Add tests to make sure podman container and podman image commands work
+ * Bump gitvalidation epoch
+ * Bump to v1.2.0-dev
+
- Changelog for v1.1.1 (2019-03-01)
* Update release notes for v1.1.1
* Pull image for runlabel if not local
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 702e20040..ea99aafc2 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -100,6 +100,7 @@ type ExecValues struct {
User string
Latest bool
Workdir string
+ PreserveFDs int
}
type ImageExistsValues struct {
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 95cb732d9..129c886b2 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -869,7 +869,7 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l
}
return false, -1, errors.Errorf("dependency container %s is not running", ctr.ID())
}
- return rootless.JoinNS(uint(pid))
+ return rootless.JoinNS(uint(pid), 0)
}
}
return rootless.BecomeRootInUserNS()
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index 4917fb606..32a6e4bb5 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -4,7 +4,9 @@ import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/spf13/cobra"
+ "io/ioutil"
"os"
+ "strconv"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
@@ -47,6 +49,7 @@ func init() {
flags.BoolVarP(&execCommand.Tty, "tty", "t", false, "Allocate a pseudo-TTY. The default is false")
flags.StringVarP(&execCommand.User, "user", "u", "", "Sets the username or UID used and optionally the groupname or GID for the specified command")
+ flags.IntVar(&execCommand.PreserveFDs, "preserve-fds", 0, "Pass N additional file descriptors to the container")
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
markFlagHiddenForRemoteClient("latest", flags)
}
@@ -82,11 +85,34 @@ func execCmd(c *cliconfig.ExecValues) error {
return errors.Wrapf(err, "unable to exec into %s", args[0])
}
+ if c.PreserveFDs > 0 {
+ entries, err := ioutil.ReadDir("/proc/self/fd")
+ if err != nil {
+ return errors.Wrapf(err, "unable to read /proc/self/fd")
+ }
+ m := make(map[int]bool)
+ for _, e := range entries {
+ i, err := strconv.Atoi(e.Name())
+ if err != nil {
+ if err != nil {
+ return errors.Wrapf(err, "cannot parse %s in /proc/self/fd", e.Name())
+ }
+ }
+ m[i] = true
+ }
+ for i := 3; i < 3+c.PreserveFDs; i++ {
+ if _, found := m[i]; !found {
+ return errors.New("invalid --preserve-fds=N specified. Not enough FDs available")
+ }
+ }
+
+ }
+
pid, err := ctr.PID()
if err != nil {
return err
}
- became, ret, err := rootless.JoinNS(uint(pid))
+ became, ret, err := rootless.JoinNS(uint(pid), c.PreserveFDs)
if err != nil {
return err
}
@@ -113,5 +139,5 @@ func execCmd(c *cliconfig.ExecValues) error {
streams.AttachError = true
streams.AttachInput = true
- return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams)
+ return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams, c.PreserveFDs)
}
diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go
index 76d2516b7..82a257e23 100644
--- a/cmd/podman/kill.go
+++ b/cmd/podman/kill.go
@@ -2,16 +2,15 @@ package main
import (
"fmt"
- "syscall"
+ "reflect"
+
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/opentracing/opentracing-go"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
- "github.com/containers/libpod/cmd/podman/shared"
- "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/docker/docker/pkg/signal"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -51,54 +50,44 @@ func init() {
// killCmd kills one or more containers with a signal
func killCmd(c *cliconfig.KillValues) error {
- var (
- killFuncs []shared.ParallelWorkerInput
- killSignal uint = uint(syscall.SIGTERM)
- )
+ if c.Bool("trace") {
+ span, _ := opentracing.StartSpanFromContext(Ctx, "killCmd")
+ defer span.Finish()
+ }
+
+ // Check if the signalString provided by the user is valid
+ // Invalid signals will return err
+ killSignal, err := signal.ParseSignal(c.Signal)
+ if err != nil {
+ return err
+ }
rootless.SetSkipStorageSetup(true)
- 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)
- if c.Signal != "" {
- // Check if the signalString provided by the user is valid
- // Invalid signals will return err
- sysSignal, err := signal.ParseSignal(c.Signal)
- if err != nil {
- return err
- }
- killSignal = uint(sysSignal)
- }
-
- containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
+ ok, failures, err := runtime.KillContainers(getContext(), c, killSignal)
if err != nil {
- if len(containers) == 0 {
- return err
- }
- fmt.Println(err.Error())
+ return err
}
- for _, ctr := range containers {
- con := ctr
- f := func() error {
- return con.Kill(killSignal)
- }
-
- killFuncs = append(killFuncs, shared.ParallelWorkerInput{
- ContainerID: con.ID(),
- ParallelFunc: f,
- })
+ for _, id := range ok {
+ fmt.Println(id)
}
- maxWorkers := shared.Parallelize("kill")
- if c.GlobalIsSet("max-workers") {
- maxWorkers = c.GlobalFlags.MaxWorks
- }
- logrus.Debugf("Setting maximum workers to %d", maxWorkers)
+ if len(failures) > 0 {
+ keys := reflect.ValueOf(failures).MapKeys()
+ lastKey := keys[len(keys)-1].String()
+ lastErr := failures[lastKey]
+ delete(failures, lastKey)
- killErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, killFuncs)
- return printParallelOutput(killErrors, errCount)
+ for _, err := range failures {
+ outputError(err)
+ }
+ return lastErr
+ }
+ return nil
}
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index 61b049840..d23f8228c 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -80,6 +80,9 @@ func rmCmd(c *cliconfig.RmValues) error {
return err
}
if err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ exitCode = 1
+ }
fmt.Println(err.Error())
}
}
diff --git a/cmd/podman/top.go b/cmd/podman/top.go
index cdf270fa7..d96402f1a 100644
--- a/cmd/podman/top.go
+++ b/cmd/podman/top.go
@@ -108,7 +108,7 @@ func topCmd(c *cliconfig.TopValues) error {
if err != nil {
return err
}
- became, ret, err := rootless.JoinNS(uint(pid))
+ became, ret, err := rootless.JoinNS(uint(pid), 0)
if err != nil {
return err
}
diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh
index 0fd86dfdc..58c8af289 100755
--- a/contrib/cirrus/integration_test.sh
+++ b/contrib/cirrus/integration_test.sh
@@ -19,7 +19,7 @@ case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in
ubuntu-18)
make install PREFIX=/usr ETCDIR=/etc
make test-binaries
- SKIP_USERNS=1 make localintegration GINKGOTIMEOUT=90m
+ SKIP_USERNS=1 make localintegration
;;
fedora-29) ;& # Continue to the next item
fedora-28) ;&
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index 8be696933..acd2447c0 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -300,21 +300,6 @@ EOF
fi
}
-# Runs in testing VM, not image building
-install_testing_dependencies() {
- echo "Installing ginkgo, gomega, and easyjson into \$GOPATH=$GOPATH"
- req_env_var "
- GOPATH $GOPATH
- GOSRC $GOSRC
- "
- cd "$GOSRC"
- ooe.sh go get -u github.com/onsi/ginkgo/ginkgo
- ooe.sh install -D -m 755 "$GOPATH"/bin/ginkgo /usr/bin/
- ooe.sh go get github.com/onsi/gomega/...
- ooe.sh go get -u github.com/mailru/easyjson/...
- sudo install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
-}
-
install_packer_copied_files(){
# Install cni config, policy and registry config
sudo install -D -m 755 /tmp/libpod/cni/87-podman-bridge.conflist \
diff --git a/contrib/cirrus/packer/centos_setup.sh b/contrib/cirrus/packer/centos_setup.sh
index 923f2563b..d947a1d7f 100644
--- a/contrib/cirrus/packer/centos_setup.sh
+++ b/contrib/cirrus/packer/centos_setup.sh
@@ -27,6 +27,7 @@ ooe.sh sudo yum -y install centos-release-scl epel-release
ooe.sh sudo yum -y install \
PyYAML \
atomic-registries \
+ bats \
btrfs-progs-devel \
bzip2 \
device-mapper-devel \
diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh
index de7ad4506..84aee7667 100644
--- a/contrib/cirrus/packer/fedora_setup.sh
+++ b/contrib/cirrus/packer/fedora_setup.sh
@@ -26,6 +26,7 @@ ooe.sh sudo dnf update -y
ooe.sh sudo dnf install -y \
atomic-registries \
+ bats \
btrfs-progs-devel \
bzip2 \
device-mapper-devel \
diff --git a/contrib/cirrus/packer/rhel_setup.sh b/contrib/cirrus/packer/rhel_setup.sh
index ac6866a57..20be97f9b 100644
--- a/contrib/cirrus/packer/rhel_setup.sh
+++ b/contrib/cirrus/packer/rhel_setup.sh
@@ -33,6 +33,7 @@ ooe.sh sudo yum -y update
ooe.sh sudo yum -y install \
PyYAML \
atomic-registries \
+ bats \
btrfs-progs-devel \
bzip2 \
device-mapper-devel \
diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh
index 5b7e1d714..24f1cce21 100644
--- a/contrib/cirrus/packer/ubuntu_setup.sh
+++ b/contrib/cirrus/packer/ubuntu_setup.sh
@@ -38,6 +38,7 @@ ooe.sh sudo -E apt-get -qq install \
apparmor \
autoconf \
automake \
+ bats \
bison \
btrfs-tools \
build-essential \
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 77c20d9bd..c3276bb6f 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -78,10 +78,6 @@ then
cd "${GOSRC}/"
source "$SCRIPT_BASE/lib.sh"
-
- # Only testing-VMs need deps installed, not image-builder VM
- echo "$CIRRUS_TASK_NAME" | grep -q 'image' || \
- install_testing_dependencies # must exist in $GOPATH
fi
record_timestamp "env. setup end"
diff --git a/docs/podman-exec.1.md b/docs/podman-exec.1.md
index 14088b468..b74713b0b 100644
--- a/docs/podman-exec.1.md
+++ b/docs/podman-exec.1.md
@@ -26,6 +26,10 @@ to run containers such as CRI-O, the last started container could be from eithe
The latest option is not supported on the remote client.
+**--preserve-fds=N**
+
+Pass down to the process N additional file descriptors (in addition to 0, 1, 2). The total FDs will be 3+N.
+
**--privileged**
Give the process extended Linux capabilities when running the command in container.
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 6bef3c47d..4a76e1434 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -204,7 +204,7 @@ func (c *Container) Kill(signal uint) error {
// Exec starts a new process inside the container
// TODO investigate allowing exec without attaching
-func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams) error {
+func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams, preserveFDs int) error {
var capList []string
locked := false
@@ -266,7 +266,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir
logrus.Debugf("Creating new exec session in container %s with session id %s", c.ID(), sessionID)
- execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams)
+ execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams, preserveFDs)
if err != nil {
return errors.Wrapf(err, "error exec %s", c.ID())
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index e3753d825..08945c410 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1231,6 +1231,23 @@ func (c *Container) writeStringToRundir(destFile, output string) (string, error)
return filepath.Join(c.state.DestinationRunDir, destFile), nil
}
+// appendStringToRundir appends the provided string to the runtimedir file
+func (c *Container) appendStringToRundir(destFile, output string) (string, error) {
+ destFileName := filepath.Join(c.state.RunDir, destFile)
+
+ f, err := os.OpenFile(destFileName, os.O_APPEND|os.O_WRONLY, 0600)
+ if err != nil {
+ return "", errors.Wrapf(err, "unable to open %s", destFileName)
+ }
+ defer f.Close()
+
+ if _, err := f.WriteString(output); err != nil {
+ return "", errors.Wrapf(err, "unable to write %s", destFileName)
+ }
+
+ return filepath.Join(c.state.DestinationRunDir, destFile), nil
+}
+
// Save OCI spec to disk, replacing any existing specs for the container
func (c *Container) saveSpec(spec *spec.Spec) error {
// If the OCI spec already exists, we need to replace it
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 0e9a5124e..5f9e5a20c 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -698,13 +698,29 @@ func (c *Container) makeBindMounts() error {
// If it doesn't, don't copy them
resolvPath, exists := bindMounts["/etc/resolv.conf"]
if exists {
-
c.state.BindMounts["/etc/resolv.conf"] = resolvPath
}
+
+ // check if dependency container has an /etc/hosts file
hostsPath, exists := bindMounts["/etc/hosts"]
- if exists {
- c.state.BindMounts["/etc/hosts"] = hostsPath
+ if !exists {
+ return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
+ }
+
+ depCtr.lock.Lock()
+ // generate a hosts file for the dependency container,
+ // based on either its old hosts file, or the default,
+ // and add the relevant information from the new container (hosts and IP)
+ hostsPath, err = depCtr.appendHosts(hostsPath, c)
+
+ if err != nil {
+ depCtr.lock.Unlock()
+ return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID())
}
+ depCtr.lock.Unlock()
+
+ // finally, save it in the new container
+ c.state.BindMounts["/etc/hosts"] = hostsPath
} else {
newResolv, err := c.generateResolvConf()
if err != nil {
@@ -712,7 +728,7 @@ func (c *Container) makeBindMounts() error {
}
c.state.BindMounts["/etc/resolv.conf"] = newResolv
- newHosts, err := c.generateHosts()
+ newHosts, err := c.generateHosts("/etc/hosts")
if err != nil {
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
}
@@ -854,12 +870,28 @@ func (c *Container) generateResolvConf() (string, error) {
}
// generateHosts creates a containers hosts file
-func (c *Container) generateHosts() (string, error) {
- orig, err := ioutil.ReadFile("/etc/hosts")
+func (c *Container) generateHosts(path string) (string, error) {
+ orig, err := ioutil.ReadFile(path)
if err != nil {
- return "", errors.Wrapf(err, "unable to read /etc/hosts")
+ return "", errors.Wrapf(err, "unable to read %s", path)
}
hosts := string(orig)
+ hosts += c.getHosts()
+ return c.writeStringToRundir("hosts", hosts)
+}
+
+// appendHosts appends a container's config and state pertaining to hosts to a container's
+// local hosts file. netCtr is the container from which the netNS information is
+// taken.
+// path is the basis of the hosts file, into which netCtr's netNS information will be appended.
+func (c *Container) appendHosts(path string, netCtr *Container) (string, error) {
+ return c.appendStringToRundir("hosts", netCtr.getHosts())
+}
+
+// getHosts finds the pertinent information for a container's host file in its config and state
+// and returns a string in a format that can be written to the host file
+func (c *Container) getHosts() string {
+ var hosts string
if len(c.config.HostAdd) > 0 {
for _, host := range c.config.HostAdd {
// the host format has already been verified at this point
@@ -871,7 +903,7 @@ func (c *Container) generateHosts() (string, error) {
ipAddress := strings.Split(c.state.NetworkStatus[0].IPs[0].Address.String(), "/")[0]
hosts += fmt.Sprintf("%s\t%s\n", ipAddress, c.Hostname())
}
- return c.writeStringToRundir("hosts", hosts)
+ return hosts
}
// generatePasswd generates a container specific passwd file,
diff --git a/libpod/oci.go b/libpod/oci.go
index 2b3cc5db5..2cbf25699 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -733,7 +733,7 @@ func (r *OCIRuntime) unpauseContainer(ctr *Container) error {
// TODO: Add --detach support
// TODO: Convert to use conmon
// TODO: add --pid-file and use that to generate exec session tracking
-func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams) (*exec.Cmd, error) {
+func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams, preserveFDs int) (*exec.Cmd, error) {
if len(cmd) == 0 {
return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute")
}
@@ -770,6 +770,9 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
args = append(args, "--user", user)
}
+ if preserveFDs > 0 {
+ args = append(args, fmt.Sprintf("--preserve-fds=%d", preserveFDs))
+ }
if c.config.Spec.Process.NoNewPrivileges {
args = append(args, "--no-new-privs")
}
@@ -806,6 +809,14 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty
return nil, errors.Wrapf(err, "cannot start container %s", c.ID())
}
+ if preserveFDs > 0 {
+ for fd := 3; fd < 3+preserveFDs; fd++ {
+ // These fds were passed down to the runtime. Close them
+ // and not interfere
+ os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)).Close()
+ }
+ }
+
return execCmd, nil
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 112b6820a..482cd9d73 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -333,7 +333,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
storageConf, err := util.GetDefaultStoreOptions()
if err != nil {
- return nil, errors.Wrapf(err, "error retrieving rootless storage config")
+ return nil, errors.Wrapf(err, "error retrieving storage config")
}
runtime.config.StorageConfig = storageConf
runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod")
@@ -365,8 +365,7 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
// containers/image uses XDG_RUNTIME_DIR to locate the auth file.
// So make sure the env variable is set.
- err = SetXdgRuntimeDir(runtimeDir)
- if err != nil {
+ if err := SetXdgRuntimeDir(runtimeDir); err != nil {
return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
}
@@ -475,13 +474,31 @@ func NewRuntimeFromConfig(configPath string, options ...RuntimeOption) (runtime
// Set three fields not in the TOML config
runtime.config.StateType = defaultRuntimeConfig.StateType
runtime.config.OCIRuntime = defaultRuntimeConfig.OCIRuntime
- runtime.config.StorageConfig = storage.StoreOptions{}
+
+ storageConf, err := util.GetDefaultStoreOptions()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error retrieving storage config")
+ }
+ runtime.config.StorageConfig = storageConf
+ runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod")
+ runtime.config.VolumePath = filepath.Join(storageConf.GraphRoot, "volumes")
tmpDir, err := getDefaultTmpDir()
if err != nil {
return nil, err
}
runtime.config.TmpDir = tmpDir
+ if rootless.IsRootless() {
+ runtimeDir, err := util.GetRootlessRuntimeDir()
+ if err != nil {
+ return nil, err
+ }
+ // containers/image uses XDG_RUNTIME_DIR to locate the auth file.
+ // So make sure the env variable is set.
+ if err := SetXdgRuntimeDir(runtimeDir); err != nil {
+ return nil, errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR")
+ }
+ }
// Check to see if the given configuration file exists
if _, err := os.Stat(configPath); err != nil {
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 7514f30d2..fcce9bb86 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -4,6 +4,7 @@ package adapter
import (
"context"
+ "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
@@ -79,3 +80,26 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
}
return ok, failures, nil
}
+
+// KillContainers sends signal to container(s) based on CLI inputs.
+// Returns list of successful id(s), map of failed id(s) + error, or error not from container
+func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, c := range ctrs {
+ if err := c.Kill(uint(signal)); err == nil {
+ ok = append(ok, c.ID())
+ } else {
+ failures[c.ID()] = err
+ }
+ }
+ return ok, failures, nil
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index df40c8efd..45926ccf9 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -6,6 +6,7 @@ import (
"context"
"encoding/json"
"errors"
+ "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
@@ -148,6 +149,30 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
return ok, failures, nil
}
+// KillContainers sends signal to container(s) based on CLI inputs.
+// Returns list of successful id(s), map of failed id(s) + error, or error not from container
+func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, id := range ids {
+ killed, err := iopodman.KillContainer().Call(r.Conn, id, int64(signal))
+ if err != nil {
+ failures[id] = err
+ } else {
+ ok = append(ok, killed)
+ }
+ }
+ return ok, failures, nil
+}
+
// BatchContainerOp is wrapper func to mimic shared's function with a similar name meant for libpod
func BatchContainerOp(ctr *Container, opts shared.PsOptions) (shared.BatchContainerStruct, error) {
// TODO If pod ps ever shows container's sizes, re-enable this code; otherwise it isn't needed
diff --git a/pkg/logs/logs.go b/pkg/logs/logs.go
index bbd5509b1..7fb5c7ea8 100644
--- a/pkg/logs/logs.go
+++ b/pkg/logs/logs.go
@@ -35,7 +35,10 @@ import (
const (
// timeFormat is the time format used in the log.
- timeFormat = time.RFC3339Nano
+ // It is a modified version of RFC3339Nano that guarantees trailing
+ // zeroes are not trimmed, taken from
+ // https://github.com/golang/go/issues/19635
+ timeFormat = "2006-01-02T15:04:05.000000000Z07:00"
)
// LogStreamType is the type of the stream in CRI container log.
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 98692707f..55fba900e 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -102,7 +102,7 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
// JoinNS re-exec podman in a new userNS and join the user namespace of the specified
// PID.
-func JoinNS(pid uint) (bool, int, error) {
+func JoinNS(pid uint, preserveFDs int) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
return false, -1, nil
}
@@ -117,6 +117,13 @@ func JoinNS(pid uint) (bool, int, error) {
if int(pidC) < 0 {
return false, -1, errors.Errorf("cannot re-exec process")
}
+ if preserveFDs > 0 {
+ for fd := 3; fd < 3+preserveFDs; fd++ {
+ // These fds were passed down to the runtime. Close them
+ // and not interfere
+ os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)).Close()
+ }
+ }
ret := C.reexec_in_user_namespace_wait(pidC)
if ret < 0 {
diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go
index ed5002ca7..d9e5d380a 100644
--- a/test/e2e/pod_infra_container_test.go
+++ b/test/e2e/pod_infra_container_test.go
@@ -360,4 +360,21 @@ var _ = Describe("Podman pod create", func() {
Expect(result.OutputToString()).To(ContainSubstring(infraID))
})
+
+ It("podman run --add-host in pod", func() {
+ session := podmanTest.Podman([]string{"pod", "create"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ podID := session.OutputToString()
+
+ // verify we can add a host to the infra's /etc/hosts
+ session = podmanTest.Podman([]string{"run", "--pod", podID, "--add-host", "foobar:127.0.0.1", BB, "ping", "-c", "1", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // verify we can see the other hosts of infra's /etc/hosts
+ session = podmanTest.Podman([]string{"run", "--pod", podID, BB, "ping", "-c", "1", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
})