github.com/containers/podman/v5@v5.1.0-rc1/test/system/build-testimage (about)

     1  #!/bin/bash
     2  #
     3  # build-testimage - script for producing a test image for podman CI
     4  #
     5  # The idea is to have a small multi-purpose image that can be pulled once
     6  # by system tests and used for as many tests as possible. This image
     7  # should live on quay.io, should be small in size, and should include
     8  # as many components as needed by system tests so they don't have to
     9  # pull other images.
    10  #
    11  # Unfortunately, "small" is incompatible with "systemd" so tests
    12  # still need a fedora image for that.
    13  #
    14  
    15  # Podman binary to use
    16  PODMAN=${PODMAN:-$(pwd)/bin/podman}
    17  
    18  # Tag for this new image
    19  YMD=$(date +%Y%m%d)
    20  
    21  # git-relative path to this script
    22  create_script=$(cd $(dirname $0) && git ls-files --full-name $(basename $0))
    23  if [ -z "$create_script" ]; then
    24      create_script=$0
    25  fi
    26  
    27  # Creation timestamp, Zulu time
    28  create_time_t=$(date +%s)
    29  create_time_z=$(env TZ=UTC date --date=@$create_time_t +'%Y-%m-%dT%H:%M:%SZ')
    30  
    31  set -ex
    32  
    33  # We'll need to create a Containerfile plus various other files to add in
    34  #
    35  # Please document the reason for all flags, apk's, and anything non-obvious
    36  tmpdir=$(mktemp -t -d $(basename $0).tmp.XXXXXXX)
    37  cd $tmpdir
    38  
    39  # 'image mount' test will confirm that this file exists and has our YMD tag
    40  echo $YMD >testimage-id
    41  
    42  # ...but set the timestamp on the file itself to a constant well-known
    43  # value, for use by the 'run --tz' test. Date value chosen for nerdiness
    44  # and because it's in the past. (Much as I'd love FFFFFFFF, we can't
    45  # use any future date because of unpredictable leap second adjustments).
    46  touch --date=@1600000000 testimage-id
    47  
    48  # 'pod' test will use this for --infra-command
    49  cat >pause <<EOF
    50  #!/bin/sh
    51  #
    52  # Trivial little pause script, used in one of the pod tests
    53  #
    54  trap 'exit 0' SIGTERM
    55  echo Confirmed: testimage pause invoked as \$0
    56  while :; do
    57      sleep 0.1
    58  done
    59  EOF
    60  chmod 755 pause
    61  
    62  # Add a health check
    63  cat >healthcheck <<EOF
    64  #!/bin/sh
    65  
    66  if test -e /uh-oh || test -e /uh-oh-only-once; then
    67      echo "Uh-oh on stdout!"
    68      echo "Uh-oh on stderr!" >&2
    69  
    70      # Special file causes us to fail healthcheck only once
    71      rm -f /uh-oh-only-once
    72  
    73      exit 1
    74  else
    75      echo "Life is Good on stdout"
    76      echo "Life is Good on stderr" >&2
    77      exit 0
    78  fi
    79  EOF
    80  chmod 755 healthcheck
    81  
    82  # alpine because it's small and light and reliable
    83  #    - check for updates @ https://hub.docker.com/_/alpine
    84  # busybox-extras provides httpd needed in 500-networking.bats
    85  # iproute2 provides JSON output (not in busybox) for 505-networking-pasta.bats
    86  # socat offers convenient UDP test termination in 505-networking-pasta.bats
    87  #
    88  # Two Containerfiles, because we have to do the image build in two parts,
    89  # which I think are easier to describe in reverse order:
    90  #    2) The second build has to be run with --timestamp=CONSTANT, otherwise
    91  #       the Created test in 110-history.bats may fail (#14456); but
    92  #    1) the timestamp of the testimage-id file must be preserved (see above),
    93  #       and 'build --timestamp' clobbers all file timestamps.
    94  #
    95  cat >Containerfile1 <<EOF
    96  ARG REPO=please-override-repo
    97  FROM docker.io/\${REPO}/alpine:3.19.0
    98  RUN apk add busybox-extras iproute2 socat
    99  ADD testimage-id healthcheck pause /home/podman/
   100  RUN rm -f /var/cache/apk/*
   101  EOF
   102  
   103  cat >Containerfile2 <<EOF
   104  FROM localhost/interim-image:latest
   105  LABEL created_by=$create_script
   106  LABEL created_at=$create_time_z
   107  WORKDIR /home/podman
   108  CMD ["/bin/echo", "This container is intended for podman CI testing"]
   109  EOF
   110  
   111  # Start from scratch
   112  testimg_base=quay.io/libpod/testimage
   113  testimg=${testimg_base}:$YMD
   114  $PODMAN rmi -f $testimg &> /dev/null || true
   115  
   116  # There should always be a testimage tagged ':0000000<X>' (eight digits,
   117  # zero-padded sequence ID) in the same location; this is used by tests
   118  # which need to pull a non-locally-cached image. This image will rarely
   119  # if ever need to change, nor in fact does it even have to be a copy of
   120  # this testimage since all we use it for is 'true'.
   121  # However, it does need to be multiarch :-(
   122  zerotag_latest=$(skopeo list-tags docker://${testimg_base} |\
   123                       jq -r '.Tags[]' |\
   124                       sort --version-sort |\
   125                       grep '^000' |\
   126                       tail -n 1)
   127  zerotag_next=$(printf "%08d" $((zerotag_latest + 1)))
   128  
   129  # We don't always need to push the :00xx image, but build it anyway.
   130  zeroimg=${testimg_base}:${zerotag_next}
   131  $PODMAN manifest create $zeroimg
   132  
   133  # Arch emulation on Fedora requires the qemu-user-static package.
   134  for arch in amd64 arm64 ppc64le s390x;do
   135      # docker.io repo is usually the same name as the desired arch; except
   136      # for arm64, where podman needs to have the arch be 'arm64' but the
   137      # image lives in 'arm64v8'.
   138      repo=$arch
   139      if [[ $repo = "arm64" ]]; then
   140          repo="${repo}v8"
   141      fi
   142  
   143      # First build defines REPO, but does not have --timestamp
   144      $PODMAN build \
   145              --arch=$arch \
   146              --build-arg REPO=$repo \
   147              --squash-all \
   148              --file Containerfile1 \
   149              -t interim-image \
   150              .
   151  
   152      # Second build forces --timestamp, and adds to manifest. Unfortunately
   153      # we can't use --squash-all with --timestamp: *all* timestamps get
   154      # clobbered. This is not fixable (#14536).
   155      $PODMAN build \
   156              --arch=$arch \
   157              --timestamp=$create_time_t \
   158              --manifest=$testimg \
   159              --squash \
   160              --file Containerfile2 \
   161              .
   162  
   163      # No longer need the interim image
   164      $PODMAN rmi interim-image
   165  
   166      # The zero-tag image
   167      $PODMAN pull --arch $arch     docker.io/$repo/busybox:1.34.1
   168      $PODMAN manifest add $zeroimg docker.io/$repo/busybox:1.34.1
   169  done
   170  
   171  # Clean up
   172  cd /tmp
   173  rm -rf $tmpdir
   174  
   175  # Tag image and push (all arches) to quay.
   176  cat <<EOF
   177  
   178  If you're happy with these images, run:
   179  
   180     podman manifest push --all  ${testimg} docker://${testimg}
   181     podman manifest push --all  ${zeroimg} docker://${zeroimg}
   182  
   183  (You do not always need to push the :0000 image)
   184  
   185  EOF