github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/contrib/cirrus/lib.sh (about)

     1  
     2  
     3  # Library of common, shared utility functions.  This file is intended
     4  # to be sourced by other scripts, not called directly.
     5  
     6  # Global details persist here
     7  source /etc/environment  # not always loaded under all circumstances
     8  
     9  # Under some contexts these values are not set, make sure they are.
    10  export USER="$(whoami)"
    11  export HOME="$(getent passwd $USER | cut -d : -f 6)"
    12  [[ -n "$UID" ]] || export UID=$(getent passwd $USER | cut -d : -f 3)
    13  export GID=$(getent passwd $USER | cut -d : -f 4)
    14  
    15  # Essential default paths, many are overridden when executing under Cirrus-CI
    16  export GOPATH="${GOPATH:-/var/tmp/go}"
    17  if type -P go &> /dev/null
    18  then
    19      # required for go 1.12+
    20      export GOCACHE="${GOCACHE:-$HOME/.cache/go-build}"
    21      # called processes like `make` and other tools need these vars.
    22      eval "export $(go env)"
    23  
    24      # Ensure compiled tooling is reachable
    25      export PATH="$PATH:$GOPATH/bin"
    26  fi
    27  CIRRUS_WORKING_DIR="${CIRRUS_WORKING_DIR:-$GOPATH/src/github.com/containers/libpod}"
    28  export GOSRC="${GOSRC:-$CIRRUS_WORKING_DIR}"
    29  export PATH="$HOME/bin:$GOPATH/bin:/usr/local/bin:$PATH"
    30  export LD_LIBRARY_PATH="/usr/local/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
    31  # Saves typing / in case location ever moves
    32  SCRIPT_BASE=${SCRIPT_BASE:-./contrib/cirrus}
    33  PACKER_BASE=${PACKER_BASE:-./contrib/cirrus/packer}
    34  # Important filepaths
    35  SETUP_MARKER_FILEPATH="${SETUP_MARKER_FILEPATH:-/var/tmp/.setup_environment_sh_complete}"
    36  AUTHOR_NICKS_FILEPATH="${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/git_authors_to_irc_nicks.csv"
    37  BUILDAH_PACKAGES_FILEPATH="./contrib/cirrus/packages.sh"  # in buildah repo.
    38  
    39  # Log remote-client system test varlink output here
    40  export VARLINK_LOG=/var/tmp/varlink.log
    41  
    42  cd $GOSRC
    43  if type -P git &> /dev/null && [[ -d "$GOSRC/.git" ]]
    44  then
    45      CIRRUS_CHANGE_IN_REPO=${CIRRUS_CHANGE_IN_REPO:-$(git show-ref --hash=8 HEAD || date +%s)}
    46  else # pick something unique and obviously not from Cirrus
    47      CIRRUS_CHANGE_IN_REPO=${CIRRUS_CHANGE_IN_REPO:-unknown_$(date +%s)}
    48  fi
    49  
    50  # Defaults when not running under CI
    51  export CI="${CI:-false}"
    52  CIRRUS_CI="${CIRRUS_CI:-false}"
    53  DEST_BRANCH="${DEST_BRANCH:-v1.9}"
    54  CONTINUOUS_INTEGRATION="${CONTINUOUS_INTEGRATION:-false}"
    55  CIRRUS_REPO_NAME=${CIRRUS_REPO_NAME:-libpod}
    56  CIRRUS_BASE_SHA=${CIRRUS_BASE_SHA:-unknown$(date +%s)}  # difficult to reliably discover
    57  CIRRUS_BUILD_ID=${CIRRUS_BUILD_ID:-$RANDOM$(date +%s)}  # must be short and unique
    58  # Vars. for image-building
    59  PACKER_VER="1.4.2"
    60  # CSV of cache-image names to build (see $PACKER_BASE/libpod_images.json)
    61  
    62  # Base-images rarely change, define them here so they're out of the way.
    63  export PACKER_BUILDS="${PACKER_BUILDS:-ubuntu-18,ubuntu-19,fedora-31,fedora-30}"
    64  # Manually produced base-image names (see $SCRIPT_BASE/README.md)
    65  export UBUNTU_BASE_IMAGE="ubuntu-1910-eoan-v20200211"
    66  export PRIOR_UBUNTU_BASE_IMAGE="ubuntu-1804-bionic-v20200218"
    67  # Manually produced base-image names (see $SCRIPT_BASE/README.md)
    68  export FEDORA_BASE_IMAGE="fedora-cloud-base-31-1-9-1578586410"
    69  export PRIOR_FEDORA_BASE_IMAGE="fedora-cloud-base-30-1-2-1578586410"
    70  export BUILT_IMAGE_SUFFIX="${BUILT_IMAGE_SUFFIX:--$CIRRUS_REPO_NAME-${CIRRUS_BUILD_ID}}"
    71  # IN_PODMAN container image
    72  IN_PODMAN_IMAGE="quay.io/libpod/in_podman:$DEST_BRANCH"
    73  # Image for uploading releases
    74  UPLDREL_IMAGE="quay.io/libpod/upldrel:v1.9"
    75  
    76  # Avoid getting stuck waiting for user input
    77  export DEBIAN_FRONTEND="noninteractive"
    78  SUDOAPTGET="ooe.sh sudo -E apt-get -qq --yes"
    79  SUDOAPTADD="ooe.sh sudo -E add-apt-repository --yes"
    80  # Regex that finds enabled periodic apt configuration items
    81  PERIODIC_APT_RE='^(APT::Periodic::.+")1"\;'
    82  # Short-cuts for retrying/timeout calls
    83  LILTO="timeout_attempt_delay_command 120s 5 30s"
    84  BIGTO="timeout_attempt_delay_command 300s 5 60s"
    85  
    86  # Safe env. vars. to transfer from root -> $ROOTLESS_USER  (go env handled separately)
    87  ROOTLESS_ENV_RE='(CIRRUS_.+)|(ROOTLESS_.+)|(.+_IMAGE.*)|(.+_BASE)|(.*DIRPATH)|(.*FILEPATH)|(SOURCE.*)|(DEPEND.*)|(.+_DEPS_.+)|(OS_REL.*)|(.+_ENV_RE)|(TRAVIS)|(CI.+)|(TEST_REMOTE.*)'
    88  # Unsafe env. vars for display
    89  SECRET_ENV_RE='(IRCID)|(ACCOUNT)|(GC[EP]..+)|(SSH)'
    90  
    91  SPECIALMODE="${SPECIALMODE:-none}"
    92  MOD_LIBPOD_CONF="${MOD_LIBPOD_CONF:false}"
    93  TEST_REMOTE_CLIENT="${TEST_REMOTE_CLIENT:-false}"
    94  export CONTAINER_RUNTIME=${CONTAINER_RUNTIME:-podman}
    95  
    96  # When running as root, this may be empty or not, as a user, it MUST be set.
    97  if [[ "$USER" == "root" ]]
    98  then
    99      ROOTLESS_USER="${ROOTLESS_USER:-}"
   100  else
   101      ROOTLESS_USER="${ROOTLESS_USER:-$USER}"
   102  fi
   103  
   104  # GCE image-name compatible string representation of distribution name
   105  OS_RELEASE_ID="$(source /etc/os-release; echo $ID)"
   106  # GCE image-name compatible string representation of distribution _major_ version
   107  OS_RELEASE_VER="$(source /etc/os-release; echo $VERSION_ID | cut -d '.' -f 1)"
   108  # Combined to ease soe usage
   109  OS_REL_VER="${OS_RELEASE_ID}-${OS_RELEASE_VER}"
   110  # Type of filesystem used for cgroups
   111  CG_FS_TYPE="$(stat -f -c %T /sys/fs/cgroup)"
   112  
   113  # Installed into cache-images, supports overrides
   114  # by user-data in case of breakage or for debugging.
   115  CUSTOM_CLOUD_CONFIG_DEFAULTS="$GOSRC/$PACKER_BASE/cloud-init/$OS_RELEASE_ID/cloud.cfg.d"
   116  # Pass in a list of one or more envariable names; exit non-zero with
   117  # helpful error message if any value is empty
   118  req_env_var() {
   119      # Provide context. If invoked from function use its name; else script name
   120      local caller=${FUNCNAME[1]}
   121      if [[ -n "$caller" ]]; then
   122          # Indicate that it's a function name
   123          caller="$caller()"
   124      else
   125          # Not called from a function: use script name
   126          caller=$(basename $0)
   127      fi
   128  
   129      # Usage check
   130      [[ -n "$1" ]] || die 1 "FATAL: req_env_var: invoked without arguments"
   131  
   132      # Each input arg is an envariable name, e.g. HOME PATH etc. Expand each.
   133      # If any is empty, bail out and explain why.
   134      for i; do
   135          if [[ -z "${!i}" ]]; then
   136              die 9 "FATAL: $caller requires \$$i to be non-empty"
   137          fi
   138      done
   139  }
   140  
   141  item_test() {
   142      ITEM="$1"
   143      shift
   144      TEST_ARGS="$@"
   145      req_env_var ITEM TEST_ARGS
   146  
   147      if ERR=$(test "$@" 2>&1)
   148      then
   149          echo "ok $ITEM"
   150          return 0
   151      else
   152          RET=$?
   153          echo -n "not ok $ITEM: $TEST_ARGS"
   154          if [[ -z "$ERR" ]]
   155          then
   156              echo ""
   157          else  # test command itself failed
   158              echo -n ":"  # space follows :'s in $ERR
   159              echo "$ERR" | cut -d : -f 4-  # omit filename, line number, and command
   160          fi
   161          return $RET
   162      fi
   163  }
   164  
   165  show_env_vars() {
   166      echo "Showing selection of environment variable definitions:"
   167      _ENV_VAR_NAMES=$(awk 'BEGIN{for(v in ENVIRON) print v}' | \
   168          egrep -v "(^PATH$)|(^BASH_FUNC)|(^[[:punct:][:space:]]+)|$SECRET_ENV_RE" | \
   169          sort -u)
   170      for _env_var_name in $_ENV_VAR_NAMES
   171      do
   172          # Supports older BASH versions
   173          printf "    ${_env_var_name}=%q\n" "$(printenv $_env_var_name)"
   174      done
   175  }
   176  
   177  die() {
   178      echo "************************************************"
   179      echo ">>>>> ${2:-FATAL ERROR (but no message given!) in ${FUNCNAME[1]}()}"
   180      echo "************************************************"
   181      exit ${1:-1}
   182  }
   183  
   184  warn() {
   185      echo ">>>>> ${1:-WARNING (but no message given!) in ${FUNCNAME[1]}()}" > /dev/stderr
   186  }
   187  
   188  bad_os_id_ver() {
   189      echo "Unknown/Unsupported distro. $OS_RELEASE_ID and/or version $OS_RELEASE_VER for $(basename $0)"
   190      exit 42
   191  }
   192  
   193  stub() {
   194      echo "STUB: Pretending to do $1"
   195  }
   196  
   197  timeout_attempt_delay_command() {
   198      TIMEOUT=$1
   199      ATTEMPTS=$2
   200      DELAY=$3
   201      shift 3
   202      STDOUTERR=$(mktemp -p '' $(basename $0)_XXXXX)
   203      req_env_var ATTEMPTS DELAY
   204      echo "Retrying $ATTEMPTS times with a $DELAY delay, and $TIMEOUT timeout for command: $@"
   205      for (( COUNT=1 ; COUNT <= $ATTEMPTS ; COUNT++ ))
   206      do
   207          echo "##### (attempt #$COUNT)" &>> "$STDOUTERR"
   208          if timeout --foreground $TIMEOUT "$@" &>> "$STDOUTERR"
   209          then
   210              echo "##### (success after #$COUNT attempts)" &>> "$STDOUTERR"
   211              break
   212          else
   213              echo "##### (failed with exit: $?)" &>> "$STDOUTERR"
   214              sleep $DELAY
   215          fi
   216      done
   217      cat "$STDOUTERR"
   218      rm -f "$STDOUTERR"
   219      if (( COUNT > $ATTEMPTS ))
   220      then
   221          echo "##### (exceeded $ATTEMPTS attempts)"
   222          exit 125
   223      fi
   224  }
   225  
   226  ircmsg() {
   227      req_env_var CIRRUS_TASK_ID IRCID
   228      [[ -n "$*" ]] || die 9 "ircmsg() invoked without message text argument"
   229      # Sometimes setup_environment.sh didn't run
   230      SCRIPT="$(dirname $0)/podbot.py"
   231      NICK="podbot_$CIRRUS_TASK_ID"
   232      NICK="${NICK:0:15}"  # Any longer will break things
   233      set +e
   234      $SCRIPT $NICK $@
   235      echo "Ignoring exit($?)"
   236      set -e
   237  }
   238  
   239  # This covers all possible human & CI workflow parallel & serial combinations
   240  # where at least one caller must definitively discover if within a commit range
   241  # there is at least one release tag not having any '-' characters (return 0)
   242  # or otherwise (return non-0).
   243  is_release() {
   244      unset RELVER
   245      local ret
   246      req_env_var CIRRUS_CHANGE_IN_REPO
   247      if [[ -n "$CIRRUS_TAG" ]]; then
   248          RELVER="$CIRRUS_TAG"
   249      elif [[ ! "$CIRRUS_BASE_SHA" =~ "unknown" ]]
   250      then
   251          # Normally not possible for this to be empty, except when unittesting.
   252          req_env_var CIRRUS_BASE_SHA
   253          local range="${CIRRUS_BASE_SHA}..${CIRRUS_CHANGE_IN_REPO}"
   254          if echo "${range}$CIRRUS_TAG" | grep -iq 'unknown'; then
   255              die 11 "is_release() unusable range ${range} or tag $CIRRUS_TAG"
   256          fi
   257  
   258          if type -P git &> /dev/null
   259          then
   260              git fetch --all --tags &> /dev/null|| \
   261                  die 12 "is_release() failed to fetch tags"
   262              RELVER=$(git log --pretty='format:%d' $range | \
   263                       grep '(tag:' | sed -r -e 's/\s+[(]tag:\s+(v[0-9].*)[)]/\1/' | \
   264                       sort -uV | tail -1)
   265              ret=$?
   266          else
   267              warn -1 "Git command not found while checking for release"
   268              ret="-1"
   269          fi
   270          [[ "$ret" -eq "0" ]] || \
   271              die 13 "is_release() failed to parse tags"
   272      else  # Not testing a PR, but neither CIRRUS_BASE_SHA or CIRRUS_TAG are set
   273          return 1
   274      fi
   275      if [[ -n "$RELVER" ]]; then
   276          echo "Found \$RELVER $RELVER"
   277          if echo "$RELVER" | grep -q '-'; then
   278              return 2  # development tag
   279          else
   280              return 0
   281          fi
   282      else
   283          return 1  # not a release
   284      fi
   285  }
   286  
   287  setup_rootless() {
   288      req_env_var ROOTLESS_USER GOSRC SECRET_ENV_RE ROOTLESS_ENV_RE
   289  
   290      # Only do this once
   291      if passwd --status $ROOTLESS_USER
   292      then
   293          echo "Updating $ROOTLESS_USER user permissions on possibly changed libpod code"
   294          chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOSRC"
   295          return 0
   296      fi
   297  
   298      cd $GOSRC
   299      # Guarantee independence from specific values
   300      ROOTLESS_UID=$[RANDOM+1000]
   301      ROOTLESS_GID=$[RANDOM+1000]
   302      echo "creating $ROOTLESS_UID:$ROOTLESS_GID $ROOTLESS_USER user"
   303      groupadd -g $ROOTLESS_GID $ROOTLESS_USER
   304      useradd -g $ROOTLESS_GID -u $ROOTLESS_UID --no-user-group --create-home $ROOTLESS_USER
   305      chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOSRC"
   306  
   307      echo "creating ssh keypair for $USER"
   308      [[ -r "$HOME/.ssh/id_rsa" ]] || \
   309          ssh-keygen -P "" -f "$HOME/.ssh/id_rsa"
   310  
   311      echo "Allowing ssh key for $ROOTLESS_USER"
   312      (umask 077 && mkdir "/home/$ROOTLESS_USER/.ssh")
   313      chown -R $ROOTLESS_USER:$ROOTLESS_USER "/home/$ROOTLESS_USER/.ssh"
   314      install -o $ROOTLESS_USER -g $ROOTLESS_USER -m 0600 \
   315          "$HOME/.ssh/id_rsa.pub" "/home/$ROOTLESS_USER/.ssh/authorized_keys"
   316      # Makes debugging easier
   317      cat /root/.ssh/authorized_keys >> "/home/$ROOTLESS_USER/.ssh/authorized_keys"
   318  
   319      echo "Configuring subuid and subgid"
   320      grep -q "${ROOTLESS_USER}" /etc/subuid || \
   321          echo "${ROOTLESS_USER}:$[ROOTLESS_UID * 100]:65536" | \
   322              tee -a /etc/subuid >> /etc/subgid
   323  
   324      # Env. vars set by Cirrus and setup_environment.sh must be explicitly
   325      # transferred to the test-user.
   326      echo "Configuring rootless user's environment variables:"
   327      echo "# Added by $GOSRC/$SCRIPT_PATH/lib.sh setup_rootless()"
   328      _ENV_VAR_NAMES=$(awk 'BEGIN{for(v in ENVIRON) print v}' | \
   329          egrep -v "(^PATH$)|(^BASH_FUNC)|(^[[:punct:][:space:]]+)|$SECRET_ENV_RE" | \
   330          egrep "$ROOTLESS_ENV_RE" | \
   331          sort -u)
   332      for _env_var_name in $_ENV_VAR_NAMES
   333      do
   334          # Works with older versions of bash
   335          printf "${_env_var_name}=%q\n" "$(printenv $_env_var_name)" >> "/home/$ROOTLESS_USER/.bashrc"
   336      done
   337  
   338      echo "Ensure the systems ssh process is up and running within 5 minutes"
   339      systemctl start sshd
   340      NOW=$(date +%s)
   341      TIMEOUT=$(date --date '+5 minutes' +%s)
   342      while [[ "$(date +%s)" -lt "$TIMEOUT" ]]
   343      do
   344          if timeout --foreground -k 1s 1s \
   345              ssh $ROOTLESS_USER@localhost \
   346              -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no \
   347              true
   348          then
   349              break
   350          else
   351              sleep 2s
   352          fi
   353      done
   354      [[ "$(date +%s)" -lt "$TIMEOUT" ]] || \
   355          die 11 "Timeout exceeded waiting for localhost ssh capability"
   356  }
   357  
   358  # Helper/wrapper script to only show stderr/stdout on non-zero exit
   359  install_ooe() {
   360      req_env_var SCRIPT_BASE
   361      echo "Installing script to mask stdout/stderr unless non-zero exit."
   362      sudo install -D -m 755 "$GOSRC/$SCRIPT_BASE/ooe.sh" /usr/local/bin/ooe.sh
   363  }
   364  
   365  # Grab a newer version of git from software collections
   366  # https://www.softwarecollections.org/en/
   367  # and use it with a wrapper
   368  install_scl_git() {
   369      echo "Installing SoftwareCollections updated 'git' version."
   370      ooe.sh sudo yum -y install rh-git29
   371      cat << "EOF" | sudo tee /usr/bin/git
   372  #!/bin/bash
   373  
   374  scl enable rh-git29 -- git $@
   375  EOF
   376      sudo chmod 755 /usr/bin/git
   377  }
   378  
   379  install_test_configs() {
   380      echo "Installing cni config, policy and registry config"
   381      req_env_var GOSRC SCRIPT_BASE
   382      cd $GOSRC
   383      install -v -D -m 644 ./cni/87-podman-bridge.conflist /etc/cni/net.d/
   384      # This config must always sort last in the list of networks (podman picks first one
   385      # as the default).  This config prevents allocation of network address space used
   386      # by default in google cloud.  https://cloud.google.com/vpc/docs/vpc#ip-ranges
   387      install -v -D -m 644 $SCRIPT_BASE/99-do-not-use-google-subnets.conflist /etc/cni/net.d/
   388      install -v -D -m 644 ./test/policy.json /etc/containers/
   389      install -v -D -m 644 ./test/registries.conf /etc/containers/
   390  }
   391  
   392  # Remove all files (except conmon, for now) provided by the distro version of podman.
   393  # Except conmon, for now as it's expected to eventually be  packaged separately.
   394  # All VM cache-images used for testing include the distro podman because (1) it's
   395  # required for podman-in-podman testing and (2) it somewhat simplifies the task
   396  # of pulling in necessary prerequisites packages as the set can change over time.
   397  # For general CI testing however, calling this function makes sure the system
   398  # can only run the compiled source version.
   399  remove_packaged_podman_files() {
   400      echo "Removing packaged podman files to prevent conflicts with source build and testing."
   401      req_env_var OS_RELEASE_ID
   402  
   403      # If any binaries are resident they could cause unexpected pollution
   404      for unit in io.podman.service io.podman.socket
   405      do
   406          for state in enabled active
   407          do
   408              if systemctl --quiet is-$state $unit
   409              then
   410                  echo "Warning: $unit found $state prior to packaged-file removal"
   411                  systemctl --quiet disable $unit || true
   412                  systemctl --quiet stop $unit || true
   413              fi
   414          done
   415      done
   416  
   417      if [[ "$OS_RELEASE_ID" =~ "ubuntu" ]]
   418      then
   419          LISTING_CMD="sudo -E dpkg-query -L podman"
   420      else
   421          LISTING_CMD='sudo rpm -ql podman'
   422      fi
   423  
   424      # yum/dnf/dpkg may list system directories, only remove files
   425      $LISTING_CMD | while read fullpath
   426      do
   427          # Sub-directories may contain unrelated/valuable stuff
   428          if [[ -d "$fullpath" ]]; then continue; fi
   429          ooe.sh sudo rm -vf "$fullpath"
   430      done
   431  
   432      # Be super extra sure and careful vs performant and completely safe
   433      sync && echo 3 > /proc/sys/vm/drop_caches
   434  }
   435  
   436  canonicalize_image_names() {
   437      req_env_var IMGNAMES
   438      echo "Adding all current base images to \$IMGNAMES for timestamp update"
   439      export IMGNAMES="\
   440  $IMGNAMES
   441  $UBUNTU_BASE_IMAGE
   442  $PRIOR_UBUNTU_BASE_IMAGE
   443  $FEDORA_BASE_IMAGE
   444  $PRIOR_FEDORA_BASE_IMAGE
   445  "
   446  }
   447  
   448  systemd_banish() {
   449      $GOSRC/$PACKER_BASE/systemd_banish.sh
   450  }
   451  
   452  install_buildah_packages() {
   453      git clone https://github.com/containers/buildah.git /tmp/buildah
   454      if [[ -r "$BUILDAH_PACKAGES_FILEPATH" ]]; then
   455          source "$BUILDAH_PACKAGES_FILEPATH"
   456          req_env_var UBUNTU_BUILDAH_PACKAGES FEDORA_BUILDAH_PACKAGES OS_RELEASE_ID
   457          case "$OS_RELEASE_ID" in
   458              fedora)
   459                  $BIGTO ooe.sh sudo dnf install -y ${FEDORA_BUILDAH_PACKAGES[@]}
   460                  ;;
   461              ubuntu)
   462                  $LILTO $SUDOAPTGET update
   463                  $BIGTO $SUDOAPTGET install ${UBUNTU_BUILDAH_PACKAGES[@]}
   464                  ;;
   465              *) bad_os_id_ver ;;
   466          esac
   467      else
   468          warn "Could not find $BUILDAH_PACKAGES_FILEPATH in buildah repository root."
   469      fi
   470  }
   471  
   472  _finalize() {
   473      set +e  # Don't fail at the very end
   474      if [[ -d "$CUSTOM_CLOUD_CONFIG_DEFAULTS" ]]
   475      then
   476          echo "Installing custom cloud-init defaults"
   477          sudo cp -v "$CUSTOM_CLOUD_CONFIG_DEFAULTS"/* /etc/cloud/cloud.cfg.d/
   478      else
   479          echo "Could not find any files in $CUSTOM_CLOUD_CONFIG_DEFAULTS"
   480      fi
   481      echo "Re-initializing so next boot does 'first-boot' setup again."
   482      cd /
   483      sudo rm -rf /var/lib/cloud/instanc*
   484      sudo rm -rf /root/.ssh/*
   485      sudo rm -rf /etc/ssh/*key*
   486      sudo rm -rf /etc/ssh/moduli
   487      sudo rm -rf /home/*
   488      sudo rm -rf /tmp/*
   489      sudo rm -rf /tmp/.??*
   490      sudo sync
   491      sudo fstrim -av
   492  }
   493  
   494  rh_finalize() {
   495      set +e  # Don't fail at the very end
   496      echo "Resetting to fresh-state for usage as cloud-image."
   497      PKG=$(type -P dnf || type -P yum || echo "")
   498      sudo $PKG clean all
   499      sudo rm -rf /var/cache/{yum,dnf}
   500      sudo rm -f /etc/udev/rules.d/*-persistent-*.rules
   501      sudo touch /.unconfigured  # force firstboot to run
   502      _finalize
   503  }
   504  
   505  ubuntu_finalize() {
   506      set +e  # Don't fail at the very end
   507      echo "Resetting to fresh-state for usage as cloud-image."
   508      $LILTO $SUDOAPTGET autoremove
   509      sudo rm -rf /var/cache/apt
   510      _finalize
   511  }