summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/podmanimage/stable/Dockerfile2
-rw-r--r--contrib/podmanimage/testing/Dockerfile2
-rw-r--r--contrib/podmanimage/upstream/Dockerfile2
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--pkg/api/handlers/compat/images.go35
-rw-r--r--pkg/specgen/generate/kube/kube.go95
-rw-r--r--test/apiv2/10-images.at5
-rwxr-xr-xtest/apiv2/test-apiv24
-rw-r--r--test/e2e/play_kube_test.go100
-rw-r--r--test/system/250-systemd.bats39
-rw-r--r--test/system/255-auto-update.bats11
-rw-r--r--test/system/270-socket-activation.bats17
-rw-r--r--test/system/500-networking.bats2
-rw-r--r--test/system/helpers.bash18
-rw-r--r--test/system/helpers.systemd.bash30
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/user/user.go92
-rw-r--r--vendor/modules.txt2
18 files changed, 349 insertions, 113 deletions
diff --git a/contrib/podmanimage/stable/Dockerfile b/contrib/podmanimage/stable/Dockerfile
index 2f86dd4ae..a5d485e7f 100644
--- a/contrib/podmanimage/stable/Dockerfile
+++ b/contrib/podmanimage/stable/Dockerfile
@@ -11,7 +11,7 @@ FROM registry.fedoraproject.org/fedora:latest
# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
-RUN dnf -y update; yum -y reinstall shadow-utils; \
+RUN dnf -y update; rpm --restore --quiet shadow-utils; \
yum -y install podman fuse-overlayfs --exclude container-selinux; \
rm -rf /var/cache /var/log/dnf* /var/log/yum.*
diff --git a/contrib/podmanimage/testing/Dockerfile b/contrib/podmanimage/testing/Dockerfile
index 63b31252f..1090fed00 100644
--- a/contrib/podmanimage/testing/Dockerfile
+++ b/contrib/podmanimage/testing/Dockerfile
@@ -13,7 +13,7 @@ FROM registry.fedoraproject.org/fedora:latest
# Don't include container-selinux and remove
# directories used by yum that are just taking
# up space.
-RUN yum -y update; yum -y reinstall shadow-utils; yum -y install podman fuse-overlayfs --exclude container-selinux --enablerepo updates-testing; rm -rf /var/cache /var/log/dnf* /var/log/yum.*
+RUN yum -y update; rpm --restore --quiet shadow-utils; yum -y install podman fuse-overlayfs --exclude container-selinux --enablerepo updates-testing; rm -rf /var/cache /var/log/dnf* /var/log/yum.*
RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
diff --git a/contrib/podmanimage/upstream/Dockerfile b/contrib/podmanimage/upstream/Dockerfile
index 922eee748..01666e453 100644
--- a/contrib/podmanimage/upstream/Dockerfile
+++ b/contrib/podmanimage/upstream/Dockerfile
@@ -17,7 +17,7 @@ ENV GOPATH=/root/podman
# to the container.
# Finally remove the podman directory and a few other packages
# that are needed for building but not running Podman
-RUN yum -y update; yum -y reinstall shadow-utils; yum -y install --exclude container-selinux \
+RUN yum -y update; rpm --restore --quiet shadow-utils; yum -y install --exclude container-selinux \
--enablerepo=updates-testing \
btrfs-progs-devel \
containernetworking-cni \
diff --git a/go.mod b/go.mod
index da54d9a3c..156ec6ef1 100644
--- a/go.mod
+++ b/go.mod
@@ -46,7 +46,7 @@ require (
github.com/onsi/gomega v1.14.0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
- github.com/opencontainers/runc v1.0.0
+ github.com/opencontainers/runc v1.0.1
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/opencontainers/runtime-tools v0.9.0
github.com/opencontainers/selinux v1.8.2
diff --git a/go.sum b/go.sum
index 5c932e575..b42ab330b 100644
--- a/go.sum
+++ b/go.sum
@@ -146,6 +146,7 @@ github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/cilium/ebpf v0.6.1/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
+github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -729,8 +730,9 @@ github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rm
github.com/opencontainers/runc v1.0.0-rc91/go.mod h1:3Sm6Dt7OT8z88EbdQqqcRN2oCT54jbi72tT/HqgflT8=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM=
-github.com/opencontainers/runc v1.0.0 h1:QOhAQAYUlKeofuyeKdR6ITvOnXLPbEAjPMjz9wCUXcU=
github.com/opencontainers/runc v1.0.0/go.mod h1:MU2S3KEB2ZExnhnAQYbwjdYV6HwKtDlNbA2Z2OeNDeA=
+github.com/opencontainers/runc v1.0.1 h1:G18PGckGdAm3yVQRWDVQ1rLSLntiniKJ0cNRT2Tm5gs=
+github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 7baa1145a..6f8fb21f0 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -266,41 +266,26 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
}
defer auth.RemoveAuthfile(authfile)
- platformSpecs := strings.Split(query.Platform, "/") // split query into its parts
-
- addOS := true // default assume true due to structure of if/else below
- addArch := false
- addVariant := false
-
- if len(platformSpecs) > 1 { // if we have two arguments then we have os and arch
- addArch = true
- if len(platformSpecs) > 2 { // if we have 3 arguments then we have os arch and variant
- addVariant = true
- }
- } else if len(platformSpecs) == 0 {
- addOS = false
- }
-
pullOptions := &libimage.PullOptions{}
pullOptions.AuthFilePath = authfile
if authConf != nil {
pullOptions.Username = authConf.Username
pullOptions.Password = authConf.Password
pullOptions.IdentityToken = authConf.IdentityToken
- if addOS { // if the len is not 0
- pullOptions.OS = platformSpecs[0]
- if addArch {
- pullOptions.Architecture = platformSpecs[1]
- }
- if addVariant {
- pullOptions.Variant = platformSpecs[2]
- }
- }
}
pullOptions.Writer = os.Stderr // allows for debugging on the server
- progress := make(chan types.ProgressProperties)
+ // Handle the platform.
+ platformSpecs := strings.Split(query.Platform, "/")
+ pullOptions.OS = platformSpecs[0] // may be empty
+ if len(platformSpecs) > 1 {
+ pullOptions.Architecture = platformSpecs[1]
+ if len(platformSpecs) > 2 {
+ pullOptions.Variant = platformSpecs[2]
+ }
+ }
+ progress := make(chan types.ProgressProperties)
pullOptions.Progress = progress
pullResChan := make(chan pullResult)
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index fb563f935..37cacdaa3 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -6,10 +6,12 @@ import (
"fmt"
"net"
"strings"
+ "time"
"github.com/containers/common/libimage"
"github.com/containers/common/pkg/parse"
"github.com/containers/common/pkg/secrets"
+ "github.com/containers/image/v5/manifest"
ann "github.com/containers/podman/v3/pkg/annotations"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/specgen/generate"
@@ -129,6 +131,10 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
}
setupSecurityContext(s, opts.Container)
+ err := setupLivenessProbe(s, opts.Container, opts.RestartPolicy)
+ if err != nil {
+ return nil, errors.Wrap(err, "Failed to configure livenessProbe")
+ }
// Since we prefix the container name with pod name to work-around the uniqueness requirement,
// the seccomp profile should reference the actual container name from the YAML
@@ -332,6 +338,95 @@ func parseMountPath(mountPath string, readOnly bool) (string, []string, error) {
return dest, options, nil
}
+func setupLivenessProbe(s *specgen.SpecGenerator, containerYAML v1.Container, restartPolicy string) error {
+ var err error
+ if containerYAML.LivenessProbe == nil {
+ return nil
+ }
+ emptyHandler := v1.Handler{}
+ if containerYAML.LivenessProbe.Handler != emptyHandler {
+ var commandString string
+ failureCmd := "exit 1"
+ probe := containerYAML.LivenessProbe
+ probeHandler := probe.Handler
+
+ // append `exit 1` to `cmd` so healthcheck can be marked as `unhealthy`.
+ // append `kill 1` to `cmd` if appropriate restart policy is configured.
+ if restartPolicy == "always" || restartPolicy == "onfailure" {
+ // container will be restarted so we can kill init.
+ failureCmd = "kill 1"
+ }
+
+ // configure healthcheck on the basis of Handler Actions.
+ if probeHandler.Exec != nil {
+ execString := strings.Join(probeHandler.Exec.Command, " ")
+ commandString = fmt.Sprintf("%s || %s", execString, failureCmd)
+ } else if probeHandler.HTTPGet != nil {
+ commandString = fmt.Sprintf("curl %s://%s:%d/%s || %s", probeHandler.HTTPGet.Scheme, probeHandler.HTTPGet.Host, probeHandler.HTTPGet.Port.IntValue(), probeHandler.HTTPGet.Path, failureCmd)
+ } else if probeHandler.TCPSocket != nil {
+ commandString = fmt.Sprintf("nc -z -v %s %d || %s", probeHandler.TCPSocket.Host, probeHandler.TCPSocket.Port.IntValue(), failureCmd)
+ }
+ s.HealthConfig, err = makeHealthCheck(commandString, probe.PeriodSeconds, probe.FailureThreshold, probe.TimeoutSeconds, probe.InitialDelaySeconds)
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ return nil
+}
+
+func makeHealthCheck(inCmd string, interval int32, retries int32, timeout int32, startPeriod int32) (*manifest.Schema2HealthConfig, error) {
+ // Every healthcheck requires a command
+ if len(inCmd) == 0 {
+ return nil, errors.New("Must define a healthcheck command for all healthchecks")
+ }
+
+ // first try to parse option value as JSON array of strings...
+ cmd := []string{}
+
+ if inCmd == "none" {
+ cmd = []string{"NONE"}
+ } else {
+ err := json.Unmarshal([]byte(inCmd), &cmd)
+ if err != nil {
+ // ...otherwise pass it to "/bin/sh -c" inside the container
+ cmd = []string{"CMD-SHELL"}
+ cmd = append(cmd, strings.Split(inCmd, " ")...)
+ }
+ }
+ hc := manifest.Schema2HealthConfig{
+ Test: cmd,
+ }
+
+ if interval < 1 {
+ //kubernetes interval defaults to 10 sec and cannot be less than 1
+ interval = 10
+ }
+ hc.Interval = (time.Duration(interval) * time.Second)
+ if retries < 1 {
+ //kubernetes retries defaults to 3
+ retries = 3
+ }
+ hc.Retries = int(retries)
+ if timeout < 1 {
+ //kubernetes timeout defaults to 1
+ timeout = 1
+ }
+ timeoutDuration := (time.Duration(timeout) * time.Second)
+ if timeoutDuration < time.Duration(1) {
+ return nil, errors.New("healthcheck-timeout must be at least 1 second")
+ }
+ hc.Timeout = timeoutDuration
+
+ startPeriodDuration := (time.Duration(startPeriod) * time.Second)
+ if startPeriodDuration < time.Duration(0) {
+ return nil, errors.New("healthcheck-start-period must be 0 seconds or greater")
+ }
+ hc.StartPeriod = startPeriodDuration
+
+ return &hc, nil
+}
+
func setupSecurityContext(s *specgen.SpecGenerator, containerYAML v1.Container) {
if containerYAML.SecurityContext == nil {
return
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 9e464dbc7..195b11ff0 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -45,6 +45,11 @@ t POST "images/create?fromImage=alpine" 200 .error~null .status~".*Download comp
t POST "images/create?fromImage=alpine&tag=latest" 200
+# 10977 - handle platform parameter correctly
+t POST "images/create?fromImage=alpine&platform=linux/arm64" 200
+t GET "images/alpine/json" 200 \
+ .Architecture=arm64
+
# Make sure that new images are pulled
old_iid=$(podman image inspect --format "{{.ID}}" docker.io/library/alpine:latest)
podman rmi -f docker.io/library/alpine:latest
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index 9f6bf257f..26619ae03 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -442,10 +442,10 @@ function random_string() {
function wait_for_port() {
local host=$1 # Probably "localhost"
local port=$2 # Numeric port
- local timeout=${3:-5} # Optional; default to 5 seconds
+ local _timeout=${3:-5} # Optional; default to 5 seconds
# Wait
- while [ $timeout -gt 0 ]; do
+ while [ $_timeout -gt 0 ]; do
{ exec 3<> /dev/tcp/$host/$port; } &>/dev/null && return
sleep 1
_timeout=$(( $_timeout - 1 ))
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 42bb0cb64..5e303bf2f 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -9,6 +9,7 @@ import (
"strconv"
"strings"
"text/template"
+ "time"
"github.com/containers/podman/v3/pkg/util"
. "github.com/containers/podman/v3/test/utils"
@@ -67,6 +68,75 @@ spec:
shareProcessNamespace: true
status: {}
`
+var livenessProbePodYaml = `
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: liveness-probe
+ labels:
+ app: alpine
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: alpine
+ template:
+ metadata:
+ labels:
+ app: alpine
+ spec:
+ containers:
+ - command:
+ - top
+ - -d
+ - "1.5"
+ name: alpine
+ image: quay.io/libpod/alpine:latest
+ ports:
+ - containerPort: 80
+ livenessProbe:
+ exec:
+ command:
+ - echo
+ - hello
+ initialDelaySeconds: 5
+ periodSeconds: 5
+`
+var livenessProbeUnhealthyPodYaml = `
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: liveness-unhealthy-probe
+ labels:
+ app: alpine
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: alpine
+ template:
+ metadata:
+ labels:
+ app: alpine
+ spec:
+ restartPolicy: Never
+ containers:
+ - command:
+ - top
+ - -d
+ - "1.5"
+ name: alpine
+ image: quay.io/libpod/alpine:latest
+ ports:
+ - containerPort: 80
+ livenessProbe:
+ exec:
+ command:
+ - cat
+ - /randomfile
+ initialDelaySeconds: 0
+ periodSeconds: 1
+`
var selinuxLabelPodYaml = `
apiVersion: v1
@@ -1061,6 +1131,36 @@ var _ = Describe("Podman play kube", func() {
Expect(sharednamespaces).To(ContainSubstring("pid"))
})
+ It("podman play kube support container liveness probe", func() {
+ err := writeYaml(livenessProbePodYaml, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", "liveness-probe-pod-0-alpine", "--format", "'{{ .Config.Healthcheck }}'"})
+ inspect.WaitWithDefaultTimeout()
+ healthcheckcmd := inspect.OutputToString()
+ // check if CMD-SHELL based equivalent health check is added to container
+ Expect(healthcheckcmd).To(ContainSubstring("CMD-SHELL"))
+ })
+
+ It("podman play kube liveness probe should fail", func() {
+ err := writeYaml(livenessProbeUnhealthyPodYaml, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ time.Sleep(2 * time.Second)
+ hc := podmanTest.Podman([]string{"healthcheck", "run", "liveness-unhealthy-probe-pod-0-alpine"})
+ hc.WaitWithDefaultTimeout()
+ hcoutput := hc.OutputToString()
+ Expect(hcoutput).To(ContainSubstring("unhealthy"))
+ })
+
It("podman play kube fail with nonexistent authfile", func() {
err := generateKubeYaml("pod", getPod(), kubeYaml)
Expect(err).To(BeNil())
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index aafe385c8..ee951ff21 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -4,17 +4,10 @@
#
load helpers
+load helpers.systemd
SERVICE_NAME="podman_test_$(random_string)"
-SYSTEMCTL="systemctl"
-UNIT_DIR="/usr/lib/systemd/system"
-if is_rootless; then
- UNIT_DIR="$HOME/.config/systemd/user"
- mkdir -p $UNIT_DIR
-
- SYSTEMCTL="$SYSTEMCTL --user"
-fi
UNIT_FILE="$UNIT_DIR/$SERVICE_NAME.service"
function setup() {
@@ -24,38 +17,28 @@ function setup() {
}
function teardown() {
- run '?' $SYSTEMCTL stop "$SERVICE_NAME"
+ run '?' systemctl stop "$SERVICE_NAME"
rm -f "$UNIT_FILE"
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
run_podman rmi -a
basic_teardown
}
-# Helper to setup xdg runtime for rootless
-function xdg_rootless() {
- # podman initializes this if unset, but systemctl doesn't
- if is_rootless; then
- if [ -z "$XDG_RUNTIME_DIR" ]; then
- export XDG_RUNTIME_DIR=/run/user/$(id -u)
- fi
- fi
-}
-
# Helper to start a systemd service running a container
function service_setup() {
run_podman generate systemd --new $cname
echo "$output" > "$UNIT_FILE"
run_podman rm $cname
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
- run $SYSTEMCTL start "$SERVICE_NAME"
+ run systemctl start "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Error starting systemd unit $SERVICE_NAME, output: $output"
fi
- run $SYSTEMCTL status "$SERVICE_NAME"
+ run systemctl status "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Non-zero status of systemd unit $SERVICE_NAME, output: $output"
fi
@@ -63,20 +46,18 @@ function service_setup() {
# Helper to stop a systemd service running a container
function service_cleanup() {
- run $SYSTEMCTL stop "$SERVICE_NAME"
+ run systemctl stop "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Error stopping systemd unit $SERVICE_NAME, output: $output"
fi
rm -f "$UNIT_FILE"
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
}
# These tests can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman generate - systemd - basic" {
- xdg_rootless
-
cname=$(random_string)
# See #7407 for --pull=always.
run_podman create --pull=always --name $cname --label "io.containers.autoupdate=registry" $IMAGE top
@@ -100,8 +81,6 @@ function service_cleanup() {
}
@test "podman autoupdate local" {
- xdg_rootless
-
cname=$(random_string)
run_podman create --name $cname --label "io.containers.autoupdate=local" $IMAGE top
@@ -128,8 +107,6 @@ function service_cleanup() {
# These tests can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman generate systemd - envar" {
- xdg_rootless
-
cname=$(random_string)
FOO=value BAR=%s run_podman create --name $cname --env FOO -e BAR --env MYVAR=myval \
$IMAGE sh -c 'printenv && sleep 100'
diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats
index a73ed94e8..25eaba45b 100644
--- a/test/system/255-auto-update.bats
+++ b/test/system/255-auto-update.bats
@@ -4,14 +4,12 @@
#
load helpers
+load helpers.systemd
-UNIT_DIR="/usr/lib/systemd/system"
SNAME_FILE=$BATS_TMPDIR/services
function setup() {
skip_if_remote "systemd tests are meaningless over remote"
- skip_if_rootless
-
basic_setup
}
@@ -29,7 +27,7 @@ function teardown() {
rm -f $SNAME_FILE
run_podman ? rmi quay.io/libpod/alpine:latest
- run_podman ? rmi quay.io/libpod/alpine_nginx:latest
+ run_podman ? rmi quay.io/libpod/busybox:latest
run_podman ? rmi quay.io/libpod/localtest:latest
basic_teardown
}
@@ -58,8 +56,7 @@ function generate_service() {
fi
run_podman run -d --name $cname $label $target_img top -d 120
- run_podman generate systemd --new $cname
- echo "$output" > "$UNIT_DIR/container-$cname.service"
+ (cd $UNIT_DIR; run_podman generate systemd --new --files --name $cname)
echo "container-$cname" >> $SNAME_FILE
run_podman rm -f $cname
@@ -185,7 +182,7 @@ function _confirm_update() {
do
local img_base="alpine"
if [[ $auto_update == "registry" ]]; then
- img_base="alpine_nginx"
+ img_base="busybox"
elif [[ $auto_update == "local" ]]; then
img_base="localtest"
fi
diff --git a/test/system/270-socket-activation.bats b/test/system/270-socket-activation.bats
index 25206c6a7..031ba161b 100644
--- a/test/system/270-socket-activation.bats
+++ b/test/system/270-socket-activation.bats
@@ -4,21 +4,12 @@
#
load helpers
+load helpers.systemd
SERVICE_NAME="podman_test_$(random_string)"
-SYSTEMCTL="systemctl"
-UNIT_DIR="/usr/lib/systemd/system"
SERVICE_SOCK_ADDR="/run/podman/podman.sock"
-
if is_rootless; then
- UNIT_DIR="$HOME/.config/systemd/user"
- mkdir -p $UNIT_DIR
-
- SYSTEMCTL="$SYSTEMCTL --user"
- if [ -z "$XDG_RUNTIME_DIR" ]; then
- export XDG_RUNTIME_DIR=/run/user/$(id -u)
- fi
SERVICE_SOCK_ADDR="$XDG_RUNTIME_DIR/podman/podman.sock"
fi
@@ -66,13 +57,13 @@ EOF
rm -f $pause_pid
fi
fi
- $SYSTEMCTL start "$SERVICE_NAME.socket"
+ systemctl start "$SERVICE_NAME.socket"
}
function teardown() {
- $SYSTEMCTL stop "$SERVICE_NAME.socket"
+ systemctl stop "$SERVICE_NAME.socket"
rm -f "$SERVICE_FILE" "$SOCKET_FILE"
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
basic_teardown
}
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 4feb57807..419d325b0 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -139,6 +139,8 @@ load helpers
$IMAGE nc -l -n -v -p $myport
cid="$output"
+ wait_for_port 127.0.0.1 $myport
+
# emit random string, and check it
teststring=$(random_string 30)
echo "$teststring" | nc 127.0.0.1 $myport
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 1859a2168..02fd7252c 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -278,6 +278,24 @@ function wait_for_ready {
wait_for_output 'READY' "$@"
}
+###################
+# wait_for_port # Returns once port is available on host
+###################
+function wait_for_port() {
+ local host=$1 # Probably "localhost"
+ local port=$2 # Numeric port
+ local _timeout=${3:-5} # Optional; default to 5 seconds
+
+ # Wait
+ while [ $_timeout -gt 0 ]; do
+ { exec 3<> /dev/tcp/$host/$port; } &>/dev/null && return
+ sleep 1
+ _timeout=$(( $_timeout - 1 ))
+ done
+
+ die "Timed out waiting for $host:$port"
+}
+
# END podman helpers
###############################################################################
# BEGIN miscellaneous tools
diff --git a/test/system/helpers.systemd.bash b/test/system/helpers.systemd.bash
new file mode 100644
index 000000000..4bde912a4
--- /dev/null
+++ b/test/system/helpers.systemd.bash
@@ -0,0 +1,30 @@
+# -*- bash -*-
+#
+# BATS helpers for systemd-related functionality
+#
+
+# podman initializes this if unset, but systemctl doesn't
+if [ -z "$XDG_RUNTIME_DIR" ]; then
+ if is_rootless; then
+ export XDG_RUNTIME_DIR=/run/user/$(id -u)
+ fi
+fi
+
+# For tests which write systemd unit files
+UNIT_DIR="/run/systemd/system"
+_DASHUSER=
+if is_rootless; then
+ UNIT_DIR="${XDG_RUNTIME_DIR}/systemd/user"
+ # Why isn't systemd smart enough to figure this out on its own?
+ _DASHUSER="--user"
+fi
+
+mkdir -p $UNIT_DIR
+
+systemctl() {
+ command systemctl $_DASHUSER "$@"
+}
+
+journalctl() {
+ command journalctl $_DASHUSER "$@"
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
index d2c16f7fd..cc7a106be 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
@@ -2,6 +2,7 @@ package user
import (
"bufio"
+ "bytes"
"errors"
"fmt"
"io"
@@ -55,11 +56,11 @@ type IDMap struct {
Count int64
}
-func parseLine(line string, v ...interface{}) {
- parseParts(strings.Split(line, ":"), v...)
+func parseLine(line []byte, v ...interface{}) {
+ parseParts(bytes.Split(line, []byte(":")), v...)
}
-func parseParts(parts []string, v ...interface{}) {
+func parseParts(parts [][]byte, v ...interface{}) {
if len(parts) == 0 {
return
}
@@ -75,16 +76,16 @@ func parseParts(parts []string, v ...interface{}) {
// This is legit.
switch e := v[i].(type) {
case *string:
- *e = p
+ *e = string(p)
case *int:
// "numbers", with conversion errors ignored because of some misbehaving configuration files.
- *e, _ = strconv.Atoi(p)
+ *e, _ = strconv.Atoi(string(p))
case *int64:
- *e, _ = strconv.ParseInt(p, 10, 64)
+ *e, _ = strconv.ParseInt(string(p), 10, 64)
case *[]string:
// Comma-separated lists.
- if p != "" {
- *e = strings.Split(p, ",")
+ if len(p) != 0 {
+ *e = strings.Split(string(p), ",")
} else {
*e = []string{}
}
@@ -128,8 +129,8 @@ func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
)
for s.Scan() {
- line := strings.TrimSpace(s.Text())
- if line == "" {
+ line := bytes.TrimSpace(s.Bytes())
+ if len(line) == 0 {
continue
}
@@ -179,15 +180,53 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
if r == nil {
return nil, fmt.Errorf("nil source for group-formatted data")
}
+ rd := bufio.NewReader(r)
+ out := []Group{}
- var (
- s = bufio.NewScanner(r)
- out = []Group{}
- )
+ // Read the file line-by-line.
+ for {
+ var (
+ isPrefix bool
+ wholeLine []byte
+ err error
+ )
- for s.Scan() {
- text := s.Text()
- if text == "" {
+ // Read the next line. We do so in chunks (as much as reader's
+ // buffer is able to keep), check if we read enough columns
+ // already on each step and store final result in wholeLine.
+ for {
+ var line []byte
+ line, isPrefix, err = rd.ReadLine()
+
+ if err != nil {
+ // We should return no error if EOF is reached
+ // without a match.
+ if err == io.EOF { //nolint:errorlint // comparison with io.EOF is legit, https://github.com/polyfloyd/go-errorlint/pull/12
+ err = nil
+ }
+ return out, err
+ }
+
+ // Simple common case: line is short enough to fit in a
+ // single reader's buffer.
+ if !isPrefix && len(wholeLine) == 0 {
+ wholeLine = line
+ break
+ }
+
+ wholeLine = append(wholeLine, line...)
+
+ // Check if we read the whole line already.
+ if !isPrefix {
+ break
+ }
+ }
+
+ // There's no spec for /etc/passwd or /etc/group, but we try to follow
+ // the same rules as the glibc parser, which allows comments and blank
+ // space at the beginning of a line.
+ wholeLine = bytes.TrimSpace(wholeLine)
+ if len(wholeLine) == 0 || wholeLine[0] == '#' {
continue
}
@@ -197,17 +236,12 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
// root:x:0:root
// adm:x:4:root,adm,daemon
p := Group{}
- parseLine(text, &p.Name, &p.Pass, &p.Gid, &p.List)
+ parseLine(wholeLine, &p.Name, &p.Pass, &p.Gid, &p.List)
if filter == nil || filter(p) {
out = append(out, p)
}
}
- if err := s.Err(); err != nil {
- return nil, err
- }
-
- return out, nil
}
type ExecUser struct {
@@ -278,7 +312,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
// Allow for userArg to have either "user" syntax, or optionally "user:group" syntax
var userArg, groupArg string
- parseLine(userSpec, &userArg, &groupArg)
+ parseLine([]byte(userSpec), &userArg, &groupArg)
// Convert userArg and groupArg to be numeric, so we don't have to execute
// Atoi *twice* for each iteration over lines.
@@ -496,8 +530,8 @@ func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
)
for s.Scan() {
- line := strings.TrimSpace(s.Text())
- if line == "" {
+ line := bytes.TrimSpace(s.Bytes())
+ if len(line) == 0 {
continue
}
@@ -549,14 +583,14 @@ func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
)
for s.Scan() {
- line := strings.TrimSpace(s.Text())
- if line == "" {
+ line := bytes.TrimSpace(s.Bytes())
+ if len(line) == 0 {
continue
}
// see: man 7 user_namespaces
p := IDMap{}
- parseParts(strings.Fields(line), &p.ID, &p.ParentID, &p.Count)
+ parseParts(bytes.Fields(line), &p.ID, &p.ParentID, &p.Count)
if filter == nil || filter(p) {
out = append(out, p)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index cdda0641f..337d85442 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -503,7 +503,7 @@ github.com/opencontainers/go-digest
# github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1
-# github.com/opencontainers/runc v1.0.0
+# github.com/opencontainers/runc v1.0.1
github.com/opencontainers/runc/libcontainer/apparmor
github.com/opencontainers/runc/libcontainer/cgroups
github.com/opencontainers/runc/libcontainer/configs