#!/usr/bin/env bats -*- bats -*- # shellcheck disable=SC2096 # # Tests for podman build # load helpers # bats test_tags=distro-integration @test "podman build - basic test" { rand_filename=$(random_string 20) rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test mkdir -p $tmpdir dockerfile=$tmpdir/Dockerfile cat >$dockerfile < /$rand_filename EOF # The 'apk' command can take a long time to fetch files; bump timeout imgname="b-$(safename)" PODMAN_TIMEOUT=240 run_podman build -t $imgname --format=docker $tmpdir is "$output" ".*COMMIT" "COMMIT seen in log" # $IMAGE is preloaded, so we should never re-pull assert "$output" !~ "Trying to pull" "Default pull policy should be 'missing'" assert "$output" !~ "Writing manifest" "Default pull policy should be 'missing'" run_podman run --rm $imgname cat /$rand_filename is "$output" "$rand_content" "reading generated file in image" run_podman rmi -f $imgname } @test "podman buildx - basic test" { rand_filename=$(random_string 20) rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test mkdir -p $tmpdir dockerfile=$tmpdir/Dockerfile cat >$dockerfile < /$rand_filename VOLUME /a/b/c VOLUME ['/etc/foo', '/etc/bar'] EOF run_podman info --format '{{ .Host.BuildahVersion}}' BUILDAH_VERSION=$output run_podman buildx version is "$output" "buildah ${BUILDAH_VERSION}" "buildx version contains Buildah version" imgname="b-$(safename)" run_podman buildx build --load -t $imgname --format=docker $tmpdir is "$output" ".*COMMIT" "COMMIT seen in log" run_podman run --rm $imgname cat /$rand_filename is "$output" "$rand_content" "reading generated file in image" # Make sure the volumes are created at surprising yet Docker-compatible # destinations (see bugzilla.redhat.com/show_bug.cgi?id=2014149). run_podman run --rm $imgname find /[ /etc/bar\] -print is "$output" "/\[ /\[/etc /\[/etc/foo, /etc/bar]" "weird VOLUME gets converted to directories with brackets and comma" # Now confirm that each volume got a unique device ID run_podman run --rm $imgname stat -c '%D' / /a /a/b /a/b/c /\[ /\[/etc /\[/etc/foo, /etc /etc/bar\] # First, the non-volumes should all be the same... assert "${lines[0]}" = "${lines[1]}" "devnum( / ) = devnum( /a )" assert "${lines[0]}" = "${lines[2]}" "devnum( / ) = devnum( /a/b )" assert "${lines[0]}" = "${lines[4]}" "devnum( / ) = devnum( /[ )" assert "${lines[0]}" = "${lines[5]}" "devnum( / ) = devnum( /[etc )" assert "${lines[0]}" = "${lines[7]}" "devnum( / ) = devnum( /etc )" assert "${lines[6]}" = "${lines[8]}" "devnum( /[etc/foo, ) = devnum( /etc/bar] )" # ...then, check volumes; these differ between overlay and vfs. # Under Overlay (usual case), these will be different. On VFS, they're the same. local op="!=" if [[ "$(podman_storage_driver)" == "vfs" ]]; then op="=" fi assert "${lines[0]}" $op "${lines[3]}" "devnum( / ) $op devnum( volume0 )" assert "${lines[0]}" $op "${lines[6]}" "devnum( / ) $op devnum( volume1 )" # FIXME: is this expected? I thought /a/b/c and /[etc/foo, would differ assert "${lines[3]}" = "${lines[6]}" "devnum( volume0 ) = devnum( volume1 )" run_podman rmi -f $imgname } @test "podman build test -f -" { rand_filename=$(random_string 20) rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test mkdir -p $tmpdir containerfile=$PODMAN_TMPDIR/Containerfile cat >$containerfile < /$rand_filename EOF imgname="b-$(safename)" run_podman build -t $imgname -f - --format=docker $tmpdir < $containerfile is "$output" ".*COMMIT" "COMMIT seen in log" run_podman run --rm $imgname cat /$rand_filename is "$output" "$rand_content" "reading generated file in image" run_podman rmi -f $imgname # Now try without specifying a context dir run_podman build -t $imgname -f - < $containerfile is "$output" ".*COMMIT" "COMMIT seen in log" run_podman rmi -f $imgname } @test "podman build - global runtime flags test" { skip_if_remote "--runtime-flag flag not supported for remote" rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test mkdir -p $tmpdir containerfile=$tmpdir/Containerfile cat >$containerfile <$containerfile <$containersconf < $tmpdir/subtest/myfile1 tar -C $tmpdir -cJf $tmpdir/myfile.tar.xz subtest cat >$tmpdir/Dockerfile <| $tmpdir/subtest/myfile2 tar -C $tmpdir -cJf $tmpdir/myfile.tar.xz subtest run_podman build -t $imgname -f $tmpdir/Dockerfile $tmpdir is "$output" ".*COMMIT" "COMMIT seen in log" # Since the tarfile is modified, podman SHOULD NOT use a cached layer. if [[ "$output" =~ "Using cache" ]]; then is "$output" "[no instance of 'Using cache']" "no cache used" fi # Pre-buildah-1906, this fails with ENOENT because the tarfile was cached run_podman run --rm $imgname cat /subtest/myfile2 is "$output" "This is a NEW file" "file contents, second time" run_podman rmi -f $imgname $iid } @test "podman build test -f ./relative" { rand_filename=$(random_string 20) rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test mkdir -p $tmpdir mkdir -p $PODMAN_TMPDIR/reldir containerfile=$PODMAN_TMPDIR/reldir/Containerfile cat >$containerfile < /$rand_filename EOF # "TMPDIR=relative-path" tests buildah PR #5084. Prior to that, podman failed in RUN: # error running container: checking permissions on "sub-tmp-dir/buildah2917655141": ENOENT cd $PODMAN_TMPDIR mkdir sub-tmp-dir imgname="b-$(safename)" TMPDIR=sub-tmp-dir run_podman build -t $imgname -f ./reldir/Containerfile --format=docker $tmpdir is "$output" ".*COMMIT" "COMMIT seen in log" run_podman run --rm $imgname cat /$rand_filename is "$output" "$rand_content" "reading generated file in image" run_podman rmi -f $imgname } @test "podman parallel build should not race" { skip_if_remote "following test is not supported for remote clients" # Run thirty parallel builds using the same Containerfile cat >$PODMAN_TMPDIR/Containerfile < $PODMAN_TMPDIR/log.$i & done # Wait for all background builds to complete. Note that this succeeds # even if some of the individual builds fail! Our actual test is below. wait # For debugging, e.g., #21742 for log in $PODMAN_TMPDIR/log.*;do echo echo $log ":" cat $log done # Now delete all built images. If any image wasn't built, rmi will fail # and test will fail. run_podman rmi $(seq --format "$imgbase-%02g" 1 $count) } @test "podman build - URLs" { tmpdir=$PODMAN_TMPDIR/build-test mkdir -p $tmpdir cat >$tmpdir/Dockerfile <xyz', i.e. any string beginning with digit label_name=l$(random_string 8) label_value=$(random_string 12) # #8679: Create a secrets directory, and mount it in the container # (can only test locally; podman-remote has no --default-mounts-file opt) MOUNTS_CONF= secret_contents="ceci nest pas un secret" CAT_SECRET="echo $secret_contents" if ! is_remote; then mkdir $tmpdir/secrets echo $tmpdir/secrets:/run/secrets > $tmpdir/mounts.conf secret_filename=secretfile-$(random_string 20) secret_contents=shhh-$(random_string 30)-shhh echo $secret_contents >$tmpdir/secrets/$secret_filename MOUNTS_CONF=--default-mounts-file=$tmpdir/mounts.conf CAT_SECRET="cat /run/secrets/$secret_filename" fi # For --dns-search: a domain that is unlikely to exist local nosuchdomain=nx$(random_string 10).net # Command to run on container startup with no args cat >$tmpdir/mycmd <$PODMAN_TMPDIR/env-file1 <$PODMAN_TMPDIR/env-file2 <$tmpdir/Containerfile < expect=<$expect}>" is "$actual" "$expect" "jq .Config.$field" done # Bad symlink in volume. Prior to #7094, well, we wouldn't actually # get here because any 'podman run' on a volume that had symlinks, # be they dangling or valid, would barf with # Error: chown /_data/symlink: ENOENT run_podman run --rm $imgname \ stat -c'%u:%g:%N' /a/b/c/badsymlink \ /a/b/c/goodsymlink \ /bin/mydefaultcmd \ /a/b/c/myfile is "${lines[0]}" "1:2:'/a/b/c/badsymlink' -> '/no/such/nonesuch'" \ "bad symlink to nonexistent file is chowned and preserved" is "${lines[1]}" "1:2:'/a/b/c/goodsymlink' -> '/bin/mydefaultcmd'" \ "good symlink to existing file is chowned and preserved" is "${lines[2]}" "2:3:/bin/mydefaultcmd" "target of symlink is not chowned" is "${lines[3]}" "4:5:/a/b/c/myfile" "file in volume is chowned" # Hey, as long as we have an image with lots of layers, let's # confirm that 'image tree' works as expected run_podman image tree $imgname is "${lines[0]}" "Image ID: ${iid:0:12}" \ "image tree: first line" is "${lines[1]}" "Tags: \[localhost/$imgname:latest]" \ "image tree: second line" is "${lines[2]}" "Size: [0-9.]\+[kM]B" \ "image tree: third line" is "${lines[3]}" "Image Layers" \ "image tree: fourth line" # FIXME: if #14536 is ever fixed, rebuild testimage & s/5/4/ below. # Summary: this should be ${lines[4]}, not [5], and prior to 2022-06-15 # it was. Unfortunately, a nightmarish bug interaction makes it impossible # for us to use --squash-all on our testimage. Unless/until that bug is # fixed, we have an extra layer that all we can do is ignore. is "${lines[5]}" ".* ID: [0-9a-f]\{12\} Size: .* Top Layer of: \[$IMAGE]" \ "image tree: first layer line" is "${lines[-1]}" ".* ID: [0-9a-f]\{12\} Size: .* Top Layer of: \[localhost/$imgname:latest]" \ "image tree: last layer line" # FIXME: 'image tree --whatrequires' does not work via remote if ! is_remote; then run_podman image tree --whatrequires $IMAGE is "${lines[-1]}" \ ".*ID: .* Top Layer of: \\[localhost/$imgname:latest\\]" \ "'image tree --whatrequires' shows our built image" fi # Clean up run_podman rmi -f $imgname } @test "podman build - COPY with ignore" { local tmpdir=$PODMAN_TMPDIR/build-test-$(random_string 10) mkdir -p $tmpdir/subdir{1,2} # Create a bunch of files. Declare this as an array to avoid duplication # because we iterate over that list below, checking for each file. # A leading "-" indicates that the file SHOULD NOT exist in the built image # # Weird side effect of Buildah 3486, relating to subdirectories and # wildcard patterns. See that PR for details, it's way too confusing # to explain in a comment. local -a files=( -test1 -test1.txt test2 test2.txt subdir1/sub1 subdir1/sub1.txt -subdir1/sub2 -subdir1/sub2.txt subdir1/sub3 subdir1/sub3.txt -subdir2/sub1 -subdir2/sub1.txt -subdir2/sub2 -subdir2/sub2.txt -subdir2/sub3 -subdir2/sub3.txt this-file-does-not-match-anything-in-ignore-file -foo comment ) for f in "${files[@]}"; do # The magic '##-' strips off the '-' prefix echo "$f" > $tmpdir/${f##-} done # Directory that doesn't exist in the image; COPY should create it local newdir=/newdir-$(random_string 12) cat >$tmpdir/Containerfile <$tmpdir/$ignorefile <$tmpdir/Containerfile <$tmpdir/.dockerignore <$tmpdir/Containerfile <$tmpdir/context/.containerignore <$tmpdir/Containerfile <$containerfile <$containerfile1 <$containerfile2 <$tmpdir/Containerfile <$tmpdir/Containerfile <$dockerfile <$dockerfile <$dockerfile <$dockerfile <$containerfile1 <$containerfile2 <$tmpdir/.dockerignore <$tmpdir/Containerfile <$tmpdir/.containerignore <$tmpdir/.dockerignore <$tmpdir/Containerfile <$tmpdir/Dockerfile < $tmpdir/link/Dockerfile echo RUN echo hello >> $tmpdir/link/Dockerfile imgname="b-$(safename)" run_podman build -t $imgname $tmpdir/link # FIXME: test this somehow run_podman rmi $imgname } @test "podman build --squash --squash-all should conflict" { echo FROM scratch > $PODMAN_TMPDIR/Dockerfile imgname="b-$(safename)" run_podman 125 build -t $imgname --squash-all --squash $PODMAN_TMPDIR is "$output" "Error: cannot specify --squash-all with --squash" "--squash and --sqaush-all should conflict" } @test "podman build --volumes-from conflict" { rand_content=$(random_string 50) tmpdir=$PODMAN_TMPDIR/build-test mkdir -p $tmpdir dockerfile=$tmpdir/Dockerfile cat >$dockerfile <$containerfile imgname="b-$(safename)" run_podman build -t $imgname -f $containerfile $buildcontextdir assert "$output" !~ "EOF" "output should not contain EOF error" run_podman rmi -f $imgname } @test "podman build --file=https" { imgname="b-$(safename)" run_podman build -t $imgname --file=https://raw.githubusercontent.com/containers/podman/main/test/build/from-scratch/Dockerfile $PODMAN_TMPDIR run_podman rmi -f $imgname } function teardown() { # A timeout or other error in 'build' can leave behind stale images # that podman can't even see and which will cascade into subsequent # test failures. Try a last-ditch force-rm in cleanup, ignoring errors. run_podman '?' rm -t 0 -a -f run_podman '?' rmi -f b-$(safename) # Many of the tests above leave interim layers behind. Clean them up. run_podman '?' image prune -f basic_teardown } @test "podman build --help defaults" { run_podman build --help assert "$output" =~ "--pull.*(default \"missing\")" "pull should default to missing" } # vim: filetype=sh