diff options
-rw-r--r-- | .cirrus.yml | 15 | ||||
-rw-r--r-- | cmd/podman/images/build.go | 2 | ||||
-rw-r--r-- | contrib/cirrus/required_host_ports.txt | 1 | ||||
-rwxr-xr-x | contrib/cirrus/runner.sh | 17 | ||||
-rw-r--r-- | libpod/oci_conmon_exec_linux.go | 48 | ||||
-rw-r--r-- | libpod/util.go | 17 | ||||
-rw-r--r-- | nix/nixpkgs.json | 8 | ||||
-rw-r--r-- | test/system/070-build.bats | 23 | ||||
-rw-r--r-- | test/system/075-exec.bats | 2 |
9 files changed, 93 insertions, 40 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 5a4815e1c..5b0d9ee6c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -351,14 +351,13 @@ static_alt_build_task: ALT_NAME: 'Static build' # Do not use 'latest', fixed-version tag for runtime stability. CTR_FQIN: "docker.io/nixos/nix:2.3.6" - # This is critical, it helps to avoid a very lengthy process of - # statically building every dependency needed to build podman. - # Assuming the dependency and build description hasn't changed, - # this cache ensures only the static podman binary is built. - nix_cache: - folder: '/var/cache/nix' - # Cirrus will calculate/use sha of this output as the cache key - fingerprint_script: echo "${IMAGE_SUFFIX}" && cat nix/* + # Authentication token for pushing the build cache to cachix. + # This is critical, it helps to avoid a very lengthy process of + # statically building every dependency needed to build podman. + # Assuming the pinned nix dependencies in nix/nixpkgs.json have not + # changed, this cache will ensure that only the static podman binary is + # built. + CACHIX_AUTH_TOKEN: ENCRYPTED[df0d4d0a67474e8ea49cc503221dcb912b7e2ba45c8ec4bf2e5fd9c49a18ac21c24bacee59b5393355ed9e4358d2baef] setup_script: *setup main_script: *main always: *binary_artifacts diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index 4219e325b..957c0ac2d 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -266,7 +266,7 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil pullPolicy := imagebuildah.PullIfMissing if c.Flags().Changed("pull") && flags.Pull { - pullPolicy = imagebuildah.PullAlways + pullPolicy = imagebuildah.PullIfNewer } if flags.PullAlways { pullPolicy = imagebuildah.PullAlways diff --git a/contrib/cirrus/required_host_ports.txt b/contrib/cirrus/required_host_ports.txt index 9248e497a..5f066e059 100644 --- a/contrib/cirrus/required_host_ports.txt +++ b/contrib/cirrus/required_host_ports.txt @@ -2,3 +2,4 @@ github.com 22 docker.io 443 quay.io 443 registry.fedoraproject.org 443 +podman.cachix.org 443 diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index 50bc1102f..3292cea84 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -241,15 +241,14 @@ function _run_altbuild() { req_env_vars CTR_FQIN [[ "$UID" -eq 0 ]] || \ die "Static build must execute nixos container as root on host" - mkdir -p /var/cache/nix - podman run -i --rm -v /var/cache/nix:/mnt/nix:Z \ - $CTR_FQIN cp -rfT /nix /mnt/nix - podman run -i --rm -v /var/cache/nix:/nix:Z \ - -v $PWD:$PWD:Z -w $PWD $CTR_FQIN \ - nix --print-build-logs --option cores 4 --option max-jobs 4 \ - build --file ./nix/ - # result symlink is absolute from container perspective :( - cp /var/cache/$(readlink result)/bin/podman ./ # for cirrus-ci artifact + podman run -i --rm \ + -e CACHIX_AUTH_TOKEN \ + -v $PWD:$PWD:Z -w $PWD $CTR_FQIN sh -c \ + "nix-env -iA cachix -f https://cachix.org/api/v1/install && \ + cachix use podman && \ + nix-build nix && \ + nix-store -qR --include-outputs \$(nix-instantiate nix/default.nix) | grep -v podman | cachix push podman && \ + cp -R result/bin ." rm result # makes cirrus puke ;; *) diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index dc5dd03df..faf86ea5b 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -126,20 +126,25 @@ func (r *ConmonOCIRuntime) ExecContainerHTTP(ctr *Container, sessionID string, o }() attachChan := make(chan error) + conmonPipeDataChan := make(chan conmonPipeData) go func() { // attachToExec is responsible for closing pipes - attachChan <- attachExecHTTP(ctr, sessionID, req, w, streams, pipes, detachKeys, options.Terminal, cancel, hijackDone, holdConnOpen) + attachChan <- attachExecHTTP(ctr, sessionID, req, w, streams, pipes, detachKeys, options.Terminal, cancel, hijackDone, holdConnOpen, execCmd, conmonPipeDataChan, ociLog) close(attachChan) }() - // Wait for conmon to succeed, when return. - if err := execCmd.Wait(); err != nil { - return -1, nil, errors.Wrapf(err, "cannot run conmon") - } + // NOTE: the channel is needed to communicate conmon's data. In case + // of an error, the error will be written on the hijacked http + // connection such that remote clients will receive the error. + pipeData := <-conmonPipeDataChan - pid, err := readConmonPipeData(pipes.syncPipe, ociLog) + return pipeData.pid, attachChan, pipeData.err +} - return pid, attachChan, err +// conmonPipeData contains the data when reading from conmon's pipe. +type conmonPipeData struct { + pid int + err error } // ExecContainerDetached executes a command in a running container, but does @@ -488,9 +493,16 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex } // Attach to a container over HTTP -func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, pipes *execPipes, detachKeys []byte, isTerminal bool, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool) (deferredErr error) { +func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.ResponseWriter, streams *HTTPAttachStreams, pipes *execPipes, detachKeys []byte, isTerminal bool, cancel <-chan bool, hijackDone chan<- bool, holdConnOpen <-chan bool, execCmd *exec.Cmd, conmonPipeDataChan chan<- conmonPipeData, ociLog string) (deferredErr error) { + // NOTE: As you may notice, the attach code is quite complex. + // Many things happen concurrently and yet are interdependent. + // If you ever change this function, make sure to write to the + // conmonPipeDataChan in case of an error. + if pipes == nil || pipes.startPipe == nil || pipes.attachPipe == nil { - return errors.Wrapf(define.ErrInvalidArg, "must provide a start and attach pipe to finish an exec attach") + err := errors.Wrapf(define.ErrInvalidArg, "must provide a start and attach pipe to finish an exec attach") + conmonPipeDataChan <- conmonPipeData{-1, err} + return err } defer func() { @@ -509,17 +521,20 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp // set up the socket path, such that it is the correct length and location for exec sockPath, err := c.execAttachSocketPath(sessionID) if err != nil { + conmonPipeDataChan <- conmonPipeData{-1, err} return err } // 2: read from attachFd that the parent process has set up the console socket if _, err := readConmonPipeData(pipes.attachPipe, ""); err != nil { + conmonPipeDataChan <- conmonPipeData{-1, err} return err } // 2: then attach conn, err := openUnixSocket(sockPath) if err != nil { + conmonPipeDataChan <- conmonPipeData{-1, err} return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath) } defer func() { @@ -540,11 +555,13 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp // Perform hijack hijacker, ok := w.(http.Hijacker) if !ok { + conmonPipeDataChan <- conmonPipeData{-1, err} return errors.Errorf("unable to hijack connection") } httpCon, httpBuf, err := hijacker.Hijack() if err != nil { + conmonPipeDataChan <- conmonPipeData{-1, err} return errors.Wrapf(err, "error hijacking connection") } @@ -555,10 +572,23 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp // Force a flush after the header is written. if err := httpBuf.Flush(); err != nil { + conmonPipeDataChan <- conmonPipeData{-1, err} return errors.Wrapf(err, "error flushing HTTP hijack header") } go func() { + // Wait for conmon to succeed, when return. + if err := execCmd.Wait(); err != nil { + conmonPipeDataChan <- conmonPipeData{-1, err} + } else { + pid, err := readConmonPipeData(pipes.syncPipe, ociLog) + if err != nil { + hijackWriteError(err, c.ID(), isTerminal, httpBuf) + conmonPipeDataChan <- conmonPipeData{pid, err} + } else { + conmonPipeDataChan <- conmonPipeData{pid, err} + } + } // We need to hold the connection open until the complete exec // function has finished. This channel will be closed in a defer // in that function, so we can wait for it here. diff --git a/libpod/util.go b/libpod/util.go index bf9bf2542..391208fb9 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -235,20 +235,16 @@ func checkDependencyContainer(depCtr, ctr *Container) error { return nil } -// hijackWriteErrorAndClose writes an error to a hijacked HTTP session and -// closes it. Intended to HTTPAttach function. -// If error is nil, it will not be written; we'll only close the connection. -func hijackWriteErrorAndClose(toWrite error, cid string, terminal bool, httpCon io.Closer, httpBuf *bufio.ReadWriter) { +// hijackWriteError writes an error to a hijacked HTTP session. +func hijackWriteError(toWrite error, cid string, terminal bool, httpBuf *bufio.ReadWriter) { if toWrite != nil { - errString := []byte(fmt.Sprintf("%v\n", toWrite)) + errString := []byte(fmt.Sprintf("Error: %v\n", toWrite)) if !terminal { // We need a header. header := makeHTTPAttachHeader(2, uint32(len(errString))) if _, err := httpBuf.Write(header); err != nil { logrus.Errorf("Error writing header for container %s attach connection error: %v", cid, err) } - // TODO: May want to return immediately here to avoid - // writing garbage to the socket? } if _, err := httpBuf.Write(errString); err != nil { logrus.Errorf("Error writing error to container %s HTTP attach connection: %v", cid, err) @@ -257,6 +253,13 @@ func hijackWriteErrorAndClose(toWrite error, cid string, terminal bool, httpCon logrus.Errorf("Error flushing HTTP buffer for container %s HTTP attach connection: %v", cid, err) } } +} + +// hijackWriteErrorAndClose writes an error to a hijacked HTTP session and +// closes it. Intended to HTTPAttach function. +// If error is nil, it will not be written; we'll only close the connection. +func hijackWriteErrorAndClose(toWrite error, cid string, terminal bool, httpCon io.Closer, httpBuf *bufio.ReadWriter) { + hijackWriteError(toWrite, cid, terminal, httpBuf) if err := httpCon.Close(); err != nil { logrus.Errorf("Error closing container %s HTTP attach connection: %v", cid, err) diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json index d304de536..0cfb251f2 100644 --- a/nix/nixpkgs.json +++ b/nix/nixpkgs.json @@ -1,9 +1,9 @@ { "url": "https://github.com/nixos/nixpkgs", - "rev": "4a75203f0270f96cbc87f5dfa5d5185690237d87", - "date": "2020-12-29T03:18:48+01:00", - "path": "/nix/store/scswsm6r4jnhp9ki0f6s81kpj5x6jkn7-nixpkgs", - "sha256": "0h70fm9aa7s06wkalbadw70z5rscbs3p6nblb47z523nhlzgjxk9", + "rev": "ce7b327a52d1b82f82ae061754545b1c54b06c66", + "date": "2021-01-25T11:28:05+01:00", + "path": "/nix/store/dpsa6a1sy8hwhwjkklc52brs9z1k5fx9-nixpkgs", + "sha256": "1rc4if8nmy9lrig0ddihdwpzg2s8y36vf20hfywb8hph5hpsg4vj", "fetchSubmodules": false, "deepClone": false, "leaveDotGit": false diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 7a42a4c18..6b5bc68fb 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -29,6 +29,29 @@ EOF run_podman rmi -f build_test } +@test "podman build - basic test with --pull" { + rand_filename=$(random_string 20) + rand_content=$(random_string 50) + + run_podman tag $IMAGE localhost/localonly + + tmpdir=$PODMAN_TMPDIR/build-test + mkdir -p $tmpdir + dockerfile=$tmpdir/Dockerfile + cat >$dockerfile <<EOF +FROM localhost/localonly +RUN echo $rand_content > /$rand_filename +EOF + # With --pull, Podman would try to pull a newer image but use the local one + # if present. See #9111. + run_podman build --pull -t build_test $tmpdir + + run_podman run --rm build_test cat /$rand_filename + is "$output" "$rand_content" "reading generated file in image" + + run_podman rmi -f build_test localhost/localonly +} + @test "podman build - global runtime flags test" { skip_if_remote "--runtime-flag flag not supported for remote" diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats index c028e16c9..badf44c49 100644 --- a/test/system/075-exec.bats +++ b/test/system/075-exec.bats @@ -6,8 +6,6 @@ load helpers @test "podman exec - basic test" { - skip_if_remote "FIXME: pending #7241" - rand_filename=$(random_string 20) rand_content=$(random_string 50) |