summaryrefslogtreecommitdiff
path: root/contrib/cirrus/lib.sh
diff options
context:
space:
mode:
authorBrent Baude <bbaude@redhat.com>2020-10-05 08:42:15 -0500
committerGitHub <noreply@github.com>2020-10-05 08:42:15 -0500
commitcaace52d54c846c948c88a62f973f4d11808532e (patch)
tree41ef903d08193a4f6ff0edba9727f54a1e0583d5 /contrib/cirrus/lib.sh
parent436dda23852a367807d86e98b7a59f09a82c1802 (diff)
parent2c9084e2245834094e14e9105e64b6062d70a0f1 (diff)
downloadpodman-caace52d54c846c948c88a62f973f4d11808532e.tar.gz
podman-caace52d54c846c948c88a62f973f4d11808532e.tar.bz2
podman-caace52d54c846c948c88a62f973f4d11808532e.zip
Merge pull request #6784 from cevich/new_ci_cd
Cirrus: Make efficient and performant
Diffstat (limited to 'contrib/cirrus/lib.sh')
-rw-r--r--contrib/cirrus/lib.sh379
1 files changed, 133 insertions, 246 deletions
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index 0dbb57ab3..b57aee1af 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -3,243 +3,161 @@
# Library of common, shared utility functions. This file is intended
# to be sourced by other scripts, not called directly.
-# Global details persist here
-source /etc/environment # not always loaded under all circumstances
-
-# Automation environment doesn't automatically load for Ubuntu 18
-if [[ -r '/usr/share/automation/environment' ]]; then
- source '/usr/share/automation/environment'
+# BEGIN Global export of all variables
+set -a
+
+# Due to differences across platforms and runtime execution environments,
+# handling of the (otherwise) default shell setup is non-uniform. Rather
+# than attempt to workaround differences, simply force-load/set required
+# items every time this library is utilized.
+source /etc/profile
+source /etc/environment
+USER="$(whoami)"
+HOME="$(getent passwd $USER | cut -d : -f 6)"
+# Some platforms set and make this read-only
+[[ -n "$UID" ]] || \
+ UID=$(getent passwd $USER | cut -d : -f 3)
+GID=$(getent passwd $USER | cut -d : -f 4)
+
+# During VM Image build, the 'containers/automation' installation
+# was performed. The final step of that installation sets the
+# installation location in $AUTOMATION_LIB_PATH in /etc/environment
+# or in the default shell profile.
+# shellcheck disable=SC2154
+if [[ -n "$AUTOMATION_LIB_PATH" ]]; then
+ for libname in defaults anchors console_output utils; do
+ # There's no way shellcheck can process this location
+ # shellcheck disable=SC1090
+ source $AUTOMATION_LIB_PATH/${libname}.sh
+ done
+else
+ (
+ echo "WARNING: It does not appear that containers/automation was installed."
+ echo " Functionality of most of this library will be negatively impacted"
+ echo " This ${BASH_SOURCE[0]} was loaded by ${BASH_SOURCE[1]}"
+ ) > /dev/stderr
fi
-# Under some contexts these values are not set, make sure they are.
-export USER="$(whoami)"
-export HOME="$(getent passwd $USER | cut -d : -f 6)"
-[[ -n "$UID" ]] || export UID=$(getent passwd $USER | cut -d : -f 3)
-export GID=$(getent passwd $USER | cut -d : -f 4)
+OS_RELEASE_ID="$(source /etc/os-release; echo $ID)"
+# GCE image-name compatible string representation of distribution _major_ version
+OS_RELEASE_VER="$(source /etc/os-release; echo $VERSION_ID | cut -d '.' -f 1)"
+# Combined to ease soe usage
+OS_REL_VER="${OS_RELEASE_ID}-${OS_RELEASE_VER}"
# Essential default paths, many are overridden when executing under Cirrus-CI
-export GOPATH="${GOPATH:-/var/tmp/go}"
+GOPATH="${GOPATH:-/var/tmp/go}"
if type -P go &> /dev/null
then
- # required for go 1.12+
- export GOCACHE="${GOCACHE:-$HOME/.cache/go-build}"
+ # Cirrus-CI caches $GOPATH contents
+ export GOCACHE="${GOCACHE:-$GOPATH/cache/go-build}"
# called processes like `make` and other tools need these vars.
eval "export $(go env)"
# Ensure compiled tooling is reachable
- export PATH="$PATH:$GOPATH/bin"
+ PATH="$PATH:$GOPATH/bin:$HOME/.local/bin"
fi
-CIRRUS_WORKING_DIR="${CIRRUS_WORKING_DIR:-$GOPATH/src/github.com/containers/podman}"
-export GOSRC="${GOSRC:-$CIRRUS_WORKING_DIR}"
-export PATH="$HOME/bin:$GOPATH/bin:/usr/local/bin:$PATH"
-export LD_LIBRARY_PATH="/usr/local/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
+CIRRUS_WORKING_DIR="${CIRRUS_WORKING_DIR:-$(realpath $(dirname ${BASH_SOURCE[0]})/../../)}"
+GOSRC="${GOSRC:-$CIRRUS_WORKING_DIR}"
+PATH="$HOME/bin:/usr/local/bin:$PATH"
+LD_LIBRARY_PATH="/usr/local/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
+
# Saves typing / in case location ever moves
SCRIPT_BASE=${SCRIPT_BASE:-./contrib/cirrus}
-# Important filepaths
-SETUP_MARKER_FILEPATH="${SETUP_MARKER_FILEPATH:-/var/tmp/.setup_environment_sh_complete}"
+
# Downloaded, but not installed packages.
PACKAGE_DOWNLOAD_DIR=/var/cache/download
# Log remote-client system test varlink output here
-export VARLINK_LOG=/var/tmp/varlink.log
-
-cd $GOSRC
-if type -P git &> /dev/null && [[ -d "$GOSRC/.git" ]]
-then
- CIRRUS_CHANGE_IN_REPO=${CIRRUS_CHANGE_IN_REPO:-$(git show-ref --hash=8 HEAD || date +%s)}
-else # pick something unique and obviously not from Cirrus
- CIRRUS_CHANGE_IN_REPO=${CIRRUS_CHANGE_IN_REPO:-unknown_$(date +%s)}
-fi
+PODMAN_SERVER_LOG=$CIRRUS_WORKING_DIR/varlink.log
# Defaults when not running under CI
export CI="${CI:-false}"
CIRRUS_CI="${CIRRUS_CI:-false}"
DEST_BRANCH="${DEST_BRANCH:-master}"
CONTINUOUS_INTEGRATION="${CONTINUOUS_INTEGRATION:-false}"
-CIRRUS_REPO_NAME=${CIRRUS_REPO_NAME:-libpod}
+CIRRUS_REPO_NAME=${CIRRUS_REPO_NAME:-podman}
CIRRUS_BASE_SHA=${CIRRUS_BASE_SHA:-unknown$(date +%s)} # difficult to reliably discover
CIRRUS_BUILD_ID=${CIRRUS_BUILD_ID:-$RANDOM$(date +%s)} # must be short and unique
-OS_RELEASE_ID="$(source /etc/os-release; echo $ID)"
-# GCE image-name compatible string representation of distribution _major_ version
-OS_RELEASE_VER="$(source /etc/os-release; echo $VERSION_ID | cut -d '.' -f 1)"
-# Combined to ease soe usage
-OS_REL_VER="${OS_RELEASE_ID}-${OS_RELEASE_VER}"
+# Needed for linting and code validation
+EPOCH_TEST_COMMIT=${CIRRUS_BASE_SHA:-$CIRRUS_LAST_GREEN_CHANGE}
-# IN_PODMAN container image
-IN_PODMAN_IMAGE="quay.io/libpod/${OS_RELEASE_ID}_podman:$_BUILT_IMAGE_SUFFIX"
-# Image for uploading releases
-UPLDREL_IMAGE="quay.io/libpod/upldrel:master"
-
-# This is needed under some environments/contexts
-SUDO=''
-[[ "$UID" -eq 0 ]] || \
- SUDO='sudo -E'
-
-# Avoid getting stuck waiting for user input
-export DEBIAN_FRONTEND="noninteractive"
-SUDOAPTGET="$SUDO apt-get -qq --yes"
-SUDOAPTADD="$SUDO add-apt-repository --yes"
-# Regex that finds enabled periodic apt configuration items
-PERIODIC_APT_RE='^(APT::Periodic::.+")1"\;'
-# Short-cuts for retrying/timeout calls
-LILTO="timeout_attempt_delay_command 120s 5 30s"
-BIGTO="timeout_attempt_delay_command 300s 5 60s"
-
-# Safe env. vars. to transfer from root -> $ROOTLESS_USER (go env handled separately)
-ROOTLESS_ENV_RE='(CIRRUS_.+)|(ROOTLESS_.+)|(.+_IMAGE.*)|(.+_BASE)|(.*DIRPATH)|(.*FILEPATH)|(SOURCE.*)|(DEPEND.*)|(.+_DEPS_.+)|(OS_REL.*)|(.+_ENV_RE)|(TRAVIS)|(CI.+)|(REMOTE.*)'
+# Regex of env. vars. to explicitly pass when executing tests
+# inside a container or as a rootless user
+PASSTHROUGH_ENV_RE='(^CI.*)|(^CIRRUS)|(^DISTRO_NV)|(^GOPATH)|(^GOCACHE)|(^GOSRC)|(^SCRIPT_BASE)|(CGROUP_MANAGER)|(OCI_RUNTIME)|(^TEST.*)|(^PODBIN_NAME)|(^PRIV_NAME)|(^ALT_NAME)|(^ROOTLESS_USER)|(SKIP_USERNS)|(.*_NAME)|(.*_FQIN)'
# Unsafe env. vars for display
-SECRET_ENV_RE='(ACCOUNT)|(GC[EP]..+)|(SSH)'
+SECRET_ENV_RE='(ACCOUNT)|(GC[EP]..+)|(SSH)|(PASSWORD)|(TOKEN)'
-SPECIALMODE="${SPECIALMODE:-none}"
-RCLI="${RCLI:-false}"
-export CONTAINER_RUNTIME=${CONTAINER_RUNTIME:-podman}
-
-# When running as root, this may be empty or not, as a user, it MUST be set.
-if [[ "$USER" == "root" ]]
-then
- ROOTLESS_USER="${ROOTLESS_USER:-}"
-else
- ROOTLESS_USER="${ROOTLESS_USER:-$USER}"
-fi
# Type of filesystem used for cgroups
CG_FS_TYPE="$(stat -f -c %T /sys/fs/cgroup)"
-# Pass in a list of one or more envariable names; exit non-zero with
-# helpful error message if any value is empty
-req_env_var() {
- # Provide context. If invoked from function use its name; else script name
- local caller=${FUNCNAME[1]}
- if [[ -n "$caller" ]]; then
- # Indicate that it's a function name
- caller="$caller()"
- else
- # Not called from a function: use script name
- caller=$(basename $0)
- fi
-
- # Usage check
- [[ -n "$1" ]] || die 1 "FATAL: req_env_var: invoked without arguments"
-
- # Each input arg is an envariable name, e.g. HOME PATH etc. Expand each.
- # If any is empty, bail out and explain why.
- for i; do
- if [[ -z "${!i}" ]]; then
- die 9 "FATAL: $caller requires \$$i to be non-empty"
- fi
+# Set to 1 in all podman container images
+CONTAINER="${CONTAINER:-0}"
+
+# END Global export of all variables
+set +a
+
+lilto() { err_retry 8 1000 "" "$@"; } # just over 4 minutes max
+bigto() { err_retry 7 5670 "" "$@"; } # 12 minutes max
+
+# Print shell-escaped variable=value pairs, one per line, based on
+# variable name matching a regex. This is intended to support
+# passthrough of CI variables from host -> container or from root -> user.
+# For all other vars. we rely on tooling to load this library from inside
+# the container or as rootless user to pickup the remainder.
+passthrough_envars(){
+ local xchars
+ local envname
+ local envval
+ # Avoid values containing entirely punctuation|control|whitespace
+ xchars='[:punct:][:cntrl:][:space:]'
+ warn "Will pass env. vars. matching the following regex:
+ $PASSTHROUGH_ENV_RE"
+ for envname in $(awk 'BEGIN{for(v in ENVIRON) print v}' | \
+ grep -Ev "SETUP_ENVIRONMENT" | \
+ grep -Ev "$SECRET_ENV_RE" | \
+ grep -E "$PASSTHROUGH_ENV_RE"); do
+
+ envval="${!envname}"
+ [[ -n $(tr -d "$xchars" <<<"$envval") ]] || continue
+
+ # Properly escape values to prevent injection
+ printf -- "$envname=%q\n" "$envval"
done
}
-item_test() {
- ITEM="$1"
- shift
- TEST_ARGS="$@"
- req_env_var ITEM TEST_ARGS
-
- if ERR=$(test "$@" 2>&1)
- then
- echo "ok $ITEM"
- return 0
- else
- RET=$?
- echo -n "not ok $ITEM: $TEST_ARGS"
- if [[ -z "$ERR" ]]
- then
- echo ""
- else # test command itself failed
- echo -n ":" # space follows :'s in $ERR
- echo "$ERR" | cut -d : -f 4- # omit filename, line number, and command
- fi
- return $RET
- fi
-}
-
-show_env_vars() {
- echo "Showing selection of environment variable definitions:"
- _ENV_VAR_NAMES=$(awk 'BEGIN{for(v in ENVIRON) print v}' | \
- egrep -v "(^PATH$)|(^BASH_FUNC)|(^[[:punct:][:space:]]+)|$SECRET_ENV_RE" | \
- sort -u)
- for _env_var_name in $_ENV_VAR_NAMES
- do
- # Supports older BASH versions
- printf " ${_env_var_name}=%q\n" "$(printenv $_env_var_name)"
- done
-}
-
-die() {
- echo "************************************************"
- echo ">>>>> ${2:-FATAL ERROR (but no message given!) in ${FUNCNAME[1]}()}"
- echo "************************************************"
- exit ${1:-1}
-}
-
-warn() {
- echo ">>>>> ${1:-WARNING (but no message given!) in ${FUNCNAME[1]}()}" > /dev/stderr
-}
-
-bad_os_id_ver() {
- echo "Unknown/Unsupported distro. $OS_RELEASE_ID and/or version $OS_RELEASE_VER for $(basename $0)"
- exit 42
-}
-
-stub() {
- echo "STUB: Pretending to do $1"
-}
-
-timeout_attempt_delay_command() {
- TIMEOUT=$1
- ATTEMPTS=$2
- DELAY=$3
- shift 3
- STDOUTERR=$(mktemp -p '' $(basename $0)_XXXXX)
- req_env_var ATTEMPTS DELAY
- echo "Retrying $ATTEMPTS times with a $DELAY delay, and $TIMEOUT timeout for command: $@"
- for (( COUNT=1 ; COUNT <= $ATTEMPTS ; COUNT++ ))
- do
- echo "##### (attempt #$COUNT)" &>> "$STDOUTERR"
- if timeout --foreground $TIMEOUT "$@" &>> "$STDOUTERR"
- then
- echo "##### (success after #$COUNT attempts)" &>> "$STDOUTERR"
- break
- else
- echo "##### (failed with exit: $?)" &>> "$STDOUTERR"
- sleep $DELAY
- fi
- done
- cat "$STDOUTERR"
- rm -f "$STDOUTERR"
- if (( COUNT > $ATTEMPTS ))
- then
- echo "##### (exceeded $ATTEMPTS attempts)"
- exit 125
- fi
-}
-
setup_rootless() {
- req_env_var ROOTLESS_USER GOPATH GOSRC SECRET_ENV_RE ROOTLESS_ENV_RE
+ req_env_vars ROOTLESS_USER GOPATH GOSRC SECRET_ENV_RE
+
+ local rootless_uid
+ local rootless_gid
+ local env_var_val
- # Only do this once
+ # Only do this once; established by setup_environment.sh
+ # shellcheck disable=SC2154
if passwd --status $ROOTLESS_USER
then
- echo "Updating $ROOTLESS_USER user permissions on possibly changed libpod code"
+ msg "Updating $ROOTLESS_USER user permissions on possibly changed libpod code"
chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC"
return 0
fi
-
- cd $GOSRC
+ msg "************************************************************"
+ msg "Setting up rootless user '$ROOTLESS_USER'"
+ msg "************************************************************"
+ cd $GOSRC || exit 1
# Guarantee independence from specific values
- ROOTLESS_UID=$[RANDOM+1000]
- ROOTLESS_GID=$[RANDOM+1000]
- echo "creating $ROOTLESS_UID:$ROOTLESS_GID $ROOTLESS_USER user"
- groupadd -g $ROOTLESS_GID $ROOTLESS_USER
- useradd -g $ROOTLESS_GID -u $ROOTLESS_UID --no-user-group --create-home $ROOTLESS_USER
+ rootless_uid=$[RANDOM+1000]
+ rootless_gid=$[RANDOM+1000]
+ msg "creating $rootless_uid:$rootless_gid $ROOTLESS_USER user"
+ groupadd -g $rootless_gid $ROOTLESS_USER
+ useradd -g $rootless_gid -u $rootless_uid --no-user-group --create-home $ROOTLESS_USER
chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOPATH" "$GOSRC"
- echo "creating ssh key pair for $USER"
+ msg "creating ssh key pair for $USER"
[[ -r "$HOME/.ssh/id_rsa" ]] || \
ssh-keygen -P "" -f "$HOME/.ssh/id_rsa"
- echo "Allowing ssh key for $ROOTLESS_USER"
+ msg "Allowing ssh key for $ROOTLESS_USER"
(umask 077 && mkdir "/home/$ROOTLESS_USER/.ssh")
chown -R $ROOTLESS_USER:$ROOTLESS_USER "/home/$ROOTLESS_USER/.ssh"
install -o $ROOTLESS_USER -g $ROOTLESS_USER -m 0600 \
@@ -247,49 +165,38 @@ setup_rootless() {
# Makes debugging easier
cat /root/.ssh/authorized_keys >> "/home/$ROOTLESS_USER/.ssh/authorized_keys"
- echo "Configuring subuid and subgid"
+ msg "Configuring subuid and subgid"
grep -q "${ROOTLESS_USER}" /etc/subuid || \
- echo "${ROOTLESS_USER}:$[ROOTLESS_UID * 100]:65536" | \
+ echo "${ROOTLESS_USER}:$[rootless_uid * 100]:65536" | \
tee -a /etc/subuid >> /etc/subgid
# Env. vars set by Cirrus and setup_environment.sh must be explicitly
# transferred to the test-user.
- echo "Configuring rootless user's environment variables:"
- echo "# Added by $GOSRC/$SCRIPT_PATH/lib.sh setup_rootless()"
- _ENV_VAR_NAMES=$(awk 'BEGIN{for(v in ENVIRON) print v}' | \
- egrep -v "(^PATH$)|(^BASH_FUNC)|(^[[:punct:][:space:]]+)|$SECRET_ENV_RE" | \
- egrep "$ROOTLESS_ENV_RE" | \
- sort -u)
- for _env_var_name in $_ENV_VAR_NAMES
- do
- # Works with older versions of bash
- printf "${_env_var_name}=%q\n" "$(printenv $_env_var_name)" >> "/home/$ROOTLESS_USER/.bashrc"
- done
+ msg "Configuring rootless user's environment variables:"
+
+ (
+ echo "# Added by ${BASH_SOURCE[0]} ${FUNCNAME[0]}()"
+ echo "export SETUP_ENVIRONMENT=1"
+ ) >> "/home/$ROOTLESS_USER/.bashrc"
- echo "Ensure the systems ssh process is up and running within 5 minutes"
+ while read -r env_var_val; do
+ echo "export $env_var_val" >> "/home/$ROOTLESS_USER/.bashrc"
+ done <<<"$(passthrough_envars)"
+ chown $ROOTLESS_USER:$ROOTLESS_USER "/home/$ROOTLESS_USER/.bashrc"
+ cat "/home/$ROOTLESS_USER/.bashrc" | indent 2
+
+ msg "Ensure the systems ssh process is up and running within 5 minutes"
systemctl start sshd
- NOW=$(date +%s)
- TIMEOUT=$(date --date '+5 minutes' +%s)
- while [[ "$(date +%s)" -lt "$TIMEOUT" ]]
- do
- if timeout --foreground -k 1s 1s \
- ssh $ROOTLESS_USER@localhost \
- -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no \
- true
- then
- break
- else
- sleep 2s
- fi
- done
- [[ "$(date +%s)" -lt "$TIMEOUT" ]] || \
- die 11 "Timeout exceeded waiting for localhost ssh capability"
+ lilto ssh $ROOTLESS_USER@localhost \
+ -o UserKnownHostsFile=/dev/null \
+ -o StrictHostKeyChecking=no \
+ -o CheckHostIP=no true
}
install_test_configs() {
echo "Installing cni config, policy and registry config"
- req_env_var GOSRC SCRIPT_BASE
- cd $GOSRC
+ req_env_vars GOSRC SCRIPT_BASE
+ cd $GOSRC || exit 1
install -v -D -m 644 ./cni/87-podman-bridge.conflist /etc/cni/net.d/
# This config must always sort last in the list of networks (podman picks first one
# as the default). This config prevents allocation of network address space used
@@ -306,7 +213,7 @@ install_test_configs() {
# can only run the compiled source version.
remove_packaged_podman_files() {
echo "Removing packaged podman files to prevent conflicts with source build and testing."
- req_env_var OS_RELEASE_ID
+ req_env_vars OS_RELEASE_ID
# If any binaries are resident they could cause unexpected pollution
for unit in io.podman.service io.podman.socket
@@ -324,9 +231,9 @@ remove_packaged_podman_files() {
if [[ "$OS_RELEASE_ID" =~ "ubuntu" ]]
then
- LISTING_CMD="$SUDO dpkg-query -L podman"
+ LISTING_CMD="dpkg-query -L podman"
else
- LISTING_CMD="$SUDO rpm -ql podman"
+ LISTING_CMD="rpm -ql podman"
fi
# yum/dnf/dpkg may list system directories, only remove files
@@ -334,29 +241,9 @@ remove_packaged_podman_files() {
do
# Sub-directories may contain unrelated/valuable stuff
if [[ -d "$fullpath" ]]; then continue; fi
- ooe.sh $SUDO rm -vf "$fullpath"
+ ooe.sh rm -vf "$fullpath"
done
# Be super extra sure and careful vs performant and completely safe
- sync && echo 3 > /proc/sys/vm/drop_caches
-}
-
-# The version of CRI-O and Kubernetes must always match
-get_kubernetes_version(){
- # TODO: Look up the kube RPM/DEB version installed, or in $PACKAGE_DOWNLOAD_DIR
- # and retrieve the major-minor version directly.
- local KUBERNETES_VERSION="1.15"
- echo "$KUBERNETES_VERSION"
-}
-
-canonicalize_image_names() {
- req_env_var IMGNAMES
- echo "Adding all current base images to \$IMGNAMES for timestamp update"
- export IMGNAMES="\
-$IMGNAMES
-$UBUNTU_BASE_IMAGE
-$PRIOR_UBUNTU_BASE_IMAGE
-$FEDORA_BASE_IMAGE
-$PRIOR_FEDORA_BASE_IMAGE
-"
+ sync && echo 3 > /proc/sys/vm/drop_caches || true
}