diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-runlabel.1.md | 2 | ||||
-rw-r--r-- | nix/nixpkgs.json | 8 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_build.go | 16 | ||||
-rw-r--r-- | pkg/bindings/images/build.go | 16 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers_runlabel.go | 25 | ||||
-rwxr-xr-x | test/compose/test-compose | 31 | ||||
-rw-r--r-- | test/system/037-runlabel.bats | 32 | ||||
-rw-r--r-- | test/system/050-stop.bats | 1 |
9 files changed, 93 insertions, 40 deletions
@@ -389,7 +389,7 @@ nixpkgs: -f channel:nixos-20.09 nix-prefetch-git \ -c nix-prefetch-git \ --no-deepClone \ - https://github.com/nixos/nixpkgs refs/head/nixos-20.09 > nix/nixpkgs.json + https://github.com/nixos/nixpkgs refs/heads/nixos-20.09 > nix/nixpkgs.json # Build statically linked binary .PHONY: static diff --git a/docs/source/markdown/podman-container-runlabel.1.md b/docs/source/markdown/podman-container-runlabel.1.md index 84d283cf8..9557303b6 100644 --- a/docs/source/markdown/podman-container-runlabel.1.md +++ b/docs/source/markdown/podman-container-runlabel.1.md @@ -13,7 +13,7 @@ exist, `podman container runlabel` will just exit. If the container image has a LABEL INSTALL instruction like the following: -`LABEL INSTALL /usr/bin/podman run -t -i --rm \${OPT1} --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=\${NAME} -e IMAGE=\${IMAGE} -e CONFDIR=\/etc/${NAME} -e LOGDIR=/var/log/\${NAME} -e DATADIR=/var/lib/\${NAME} \${IMAGE} \${OPT2} /bin/install.sh \${OPT3}` +`LABEL INSTALL /usr/bin/podman run -t -i --rm \${OPT1} --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=\${NAME} -e IMAGE=\${IMAGE} -e CONFDIR=/etc/\${NAME} -e LOGDIR=/var/log/\${NAME} -e DATADIR=/var/lib/\${NAME} \${IMAGE} \${OPT2} /bin/install.sh \${OPT3}` `podman container runlabel` will set the following environment variables for use in the command: diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json index 8d2f76a28..54ddb8978 100644 --- a/nix/nixpkgs.json +++ b/nix/nixpkgs.json @@ -1,9 +1,9 @@ { "url": "https://github.com/nixos/nixpkgs", - "rev": "42a03e4728fc05cb9f123057670e41967f628360", - "date": "2021-04-02T23:08:32+02:00", - "path": "/nix/store/d1vqa0kpa69zzcaj5kqgkmrxr3s7vli1-nixpkgs", - "sha256": "0wrn5nayxckj11z2qlvsya2lzssbccbk50llxmgdm0qb5y14shfk", + "rev": "cce26cd83d20356ee96ac9cf1de748e87fcc50b5", + "date": "2021-04-12T22:14:24+02:00", + "path": "/nix/store/0flgsv9kn7q0b2ipqz35lkxq65p5cv83-nixpkgs", + "sha256": "0ji00jz18fvppbi5y98gcalxq2mrsg7dhh9l64yf38jpb5rx3sd4", "fetchSubmodules": false, "deepClone": false, "leaveDotGit": false diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 700881926..ec40fdd2d 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -462,12 +462,18 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { buildOptions.Timestamp = &ts } + var ( + imageID string + success bool + ) + runCtx, cancel := context.WithCancel(context.Background()) - var imageID string go func() { defer cancel() imageID, _, err = runtime.Build(r.Context(), buildOptions, query.Dockerfile) - if err != nil { + if err == nil { + success = true + } else { stderr.Write([]byte(err.Error() + "\n")) } }() @@ -483,8 +489,6 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") flush() - var failed bool - body := w.(io.Writer) if logrus.IsLevelEnabled(logrus.DebugLevel) { if v, found := os.LookupEnv("PODMAN_RETAIN_BUILD_ARTIFACT"); found { @@ -525,14 +529,14 @@ loop: } flush() case e := <-stderr.Chan(): - failed = true m.Error = string(e) if err := enc.Encode(m); err != nil { logrus.Warnf("Failed to json encode error %v", err) } flush() case <-runCtx.Done(): - if !failed { + flush() + if success { if !utils.IsLibpodRequest(r) { m.Stream = fmt.Sprintf("Successfully built %12.12s\n", imageID) if err := enc.Encode(m); err != nil { diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 34d6cee05..c0e5706a5 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -340,6 +340,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO re := regexp.MustCompile(`[0-9a-f]{12}`) var id string + var mErr error for { var s struct { Stream string `json:"stream,omitempty"` @@ -347,11 +348,21 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } if err := dec.Decode(&s); err != nil { if errors.Is(err, io.EOF) { - return &entities.BuildReport{ID: id}, nil + if mErr == nil && id == "" { + mErr = errors.New("stream dropped, unexpected failure") + } + break } s.Error = err.Error() + "\n" } + select { + case <-response.Request.Context().Done(): + return &entities.BuildReport{ID: id}, mErr + default: + // non-blocking select + } + switch { case s.Stream != "": stdout.Write([]byte(s.Stream)) @@ -359,11 +370,12 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO id = strings.TrimSuffix(s.Stream, "\n") } case s.Error != "": - return nil, errors.New(s.Error) + mErr = errors.New(s.Error) default: return &entities.BuildReport{ID: id}, errors.New("failed to parse build results stream, unexpected input") } } + return &entities.BuildReport{ID: id}, mErr } func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { diff --git a/pkg/domain/infra/abi/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go index 8de383926..2cabab988 100644 --- a/pkg/domain/infra/abi/containers_runlabel.go +++ b/pkg/domain/infra/abi/containers_runlabel.go @@ -177,6 +177,16 @@ func generateRunlabelCommand(runlabel string, img *image.Image, args []string, o return cmd, env, nil } +func replaceName(arg, name string) string { + newarg := strings.ReplaceAll(arg, "$NAME", name) + return strings.ReplaceAll(newarg, "${NAME}", name) +} + +func replaceImage(arg, image string) string { + newarg := strings.ReplaceAll(arg, "$IMAGE", image) + return strings.ReplaceAll(newarg, "${IMAGE}", image) +} + // generateCommand takes a label (string) and converts it to an executable command func generateCommand(command, imageName, name, globalOpts string) ([]string, error) { if name == "" { @@ -196,26 +206,15 @@ func generateCommand(command, imageName, name, globalOpts string) ([]string, err for _, arg := range cmd[1:] { var newArg string switch arg { - case "IMAGE": - newArg = imageName - case "$IMAGE": - newArg = imageName case "IMAGE=IMAGE": newArg = fmt.Sprintf("IMAGE=%s", imageName) - case "IMAGE=$IMAGE": - newArg = fmt.Sprintf("IMAGE=%s", imageName) - case "NAME": - newArg = name case "NAME=NAME": newArg = fmt.Sprintf("NAME=%s", name) - case "NAME=$NAME": - newArg = fmt.Sprintf("NAME=%s", name) - case "$NAME": - newArg = name case "$GLOBAL_OPTS": newArg = globalOpts default: - newArg = arg + newArg = replaceName(arg, name) + newArg = replaceImage(newArg, imageName) } newCommand = append(newCommand, newArg) } diff --git a/test/compose/test-compose b/test/compose/test-compose index abb957b43..c4c484190 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -136,8 +136,11 @@ function _show_ok() { local expect=$3 local actual=$4 printf "${red}not ok $count $testname${reset}\n" - printf "${red}# expected: %s${reset}\n" "$expect" - printf "${red}# actual: ${bold}%s${reset}\n" "$actual" + # Not all errors include actual/expect + if [[ -n "$expect" || -n "$actual" ]]; then + printf "${red}# expected: %s${reset}\n" "$expect" + printf "${red}# actual: ${bold}%s${reset}\n" "$actual" + fi echo "not ok $count $testname" >>$LOG echo " expected: $expect" >>$LOG @@ -164,20 +167,22 @@ function test_port() { local expect="$3" # what to expect from curl output # -s -S means "silent, but show errors" - local actual=$(curl --retry 3 --retry-all-errors -s -S http://127.0.0.1:$port/) + local actual + actual=$(curl --retry 3 --retry-all-errors -s -S http://127.0.0.1:$port/) local curl_rc=$? - # FIXME 2021-04-13: test is flaking, curl succeeds but returns empty result. - # Could it be that the container is not actually ready? Wait, and retry. - if [[ $curl_rc -eq 0 && -z "$actual" ]]; then - sleep 1 - echo "# Retrying curl:" - actual=$(curl --retry 3 --retry-all-errors -s -S http://127.0.0.1:$port/) - curl_rc=$? - fi - if [ $curl_rc -ne 0 ]; then - _show_ok 0 "$testname - curl failed with status $curl_rc" + _show_ok 0 "$testname - curl (port $port) failed with status $curl_rc" + # FIXME: is this useful? What else can we do to diagnose? + echo "# docker-compose logs:" + docker-compose logs + echo "# podman ps -a:" + $PODMAN_BIN --root $WORKDIR/root --runroot $WORKDIR/runroot ps -a + if type -p ss; then + echo "# ss -tulpn:" + ss -tulpn + fi + return fi case "$op" in diff --git a/test/system/037-runlabel.bats b/test/system/037-runlabel.bats new file mode 100644 index 000000000..8e18f40d3 --- /dev/null +++ b/test/system/037-runlabel.bats @@ -0,0 +1,32 @@ +#!/usr/bin/env bats + +load helpers + +@test "podman container runlabel test" { + skip_if_remote "container runlabel is not supported for remote" + tmpdir=$PODMAN_TMPDIR/runlabel-test + mkdir -p $tmpdir + containerfile=$tmpdir/Containerfile + rand1=$(random_string 30) + rand2=$(random_string 30) + rand3=$(random_string 30) + cat >$containerfile <<EOF +FROM $IMAGE +LABEL INSTALL /usr/bin/podman run -t -i --rm \\\${OPT1} --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=\\\${NAME} -e IMAGE=\\\${IMAGE} -e CONFDIR=/etc/\\\${NAME} -e LOGDIR=/var/log/\\\${NAME} -e DATADIR=/var/lib/\\\${NAME} \\\${IMAGE} \\\${OPT2} /bin/install.sh \\\${OPT3} +EOF + + run_podman build -t runlabel_image $tmpdir + + run_podman container runlabel --opt1=${rand1} --opt2=${rand2} --opt3=${rand3} --name test1 --display install runlabel_image + is "$output" "command: ${PODMAN} run -t -i --rm ${rand1} --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=test1 -e IMAGE=localhost/runlabel_image:latest -e CONFDIR=/etc/test1 -e LOGDIR=/var/log/test1 -e DATADIR=/var/lib/test1 localhost/runlabel_image:latest ${rand2} /bin/install.sh ${rand3}" "generating runlabel install command" + + run_podman container runlabel --opt3=${rand3} --display install runlabel_image + is "$output" "command: ${PODMAN} run -t -i --rm --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=runlabel_image -e IMAGE=localhost/runlabel_image:latest -e CONFDIR=/etc/runlabel_image -e LOGDIR=/var/log/runlabel_image -e DATADIR=/var/lib/runlabel_image localhost/runlabel_image:latest /bin/install.sh ${rand3}" "generating runlabel without name and --opt1, --opt2" + + run_podman 125 container runlabel --opt1=${rand1} --opt2=${rand2} --opt3=${rand3} --name test1 --display run runlabel_image + is "$output" "Error: cannot find the value of label: run in image: runlabel_image" "generating runlabel run command" + + run_podman rmi -f runlabel_image +} + +# vim: filetype=sh diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats index 0652a97e4..a9495e350 100644 --- a/test/system/050-stop.bats +++ b/test/system/050-stop.bats @@ -132,6 +132,7 @@ load helpers is "$output" "stopping" "Status of container should be 'stopping'" run_podman kill stopme + run_podman wait stopme # Exit code should be 137 as it was killed run_podman inspect --format '{{.State.ExitCode}}' stopme |