diff options
Diffstat (limited to 'contrib/cirrus')
-rw-r--r-- | contrib/cirrus/README.md | 31 | ||||
-rwxr-xr-x | contrib/cirrus/integration_test.sh | 2 | ||||
-rw-r--r-- | contrib/cirrus/lib.sh | 95 | ||||
-rwxr-xr-x | contrib/cirrus/notice_master_failure.sh | 19 | ||||
-rw-r--r-- | contrib/cirrus/packer/centos_setup.sh | 1 | ||||
-rw-r--r-- | contrib/cirrus/packer/fedora_setup.sh | 1 | ||||
-rw-r--r-- | contrib/cirrus/packer/rhel_setup.sh | 1 | ||||
-rw-r--r-- | contrib/cirrus/packer/ubuntu_setup.sh | 1 | ||||
-rwxr-xr-x | contrib/cirrus/rootless_test.sh | 39 | ||||
-rwxr-xr-x | contrib/cirrus/setup_environment.sh | 21 | ||||
-rwxr-xr-x | contrib/cirrus/test/test_dot_cirrus_yaml.py | 78 |
11 files changed, 256 insertions, 33 deletions
diff --git a/contrib/cirrus/README.md b/contrib/cirrus/README.md index 0d91301c6..0dabf5df6 100644 --- a/contrib/cirrus/README.md +++ b/contrib/cirrus/README.md @@ -33,6 +33,17 @@ task (pass or fail) is set based on the exit status of the last script to execut the vendor.conf, the code and the vendored packages in ./vendor are in sync at all times. +### ``meta`` Task + +***N/B: Steps below are performed by automation*** + +1. Launch a container built from definition in ``./contrib/imgts``. + +2. Update VM Image metadata to help track usage across all automation. + +4. Always exits successfully unless there's a major problem. + + ### ``testing`` Task ***N/B: Steps below are performed by automation*** @@ -52,6 +63,26 @@ task (pass or fail) is set based on the exit status of the last script to execut Total execution time is capped at 2-hours (includes all the above) but this script normally completes in less than an hour. +### ``rootless_testing`` Task + +***N/B: Steps below are performed by automation*** + +1. After `gating` passes, spin up one VM per + `matrix: image_name` item. Once accessible, ``ssh`` + into each VM as the `root` user. + +2. ``setup_environment.sh``: Configure root's `.bash_profile` + the same as for other tasks. However, also add a regular + user account, chown all the source code to them. Set up + fresh ssh pub/priv. keys for the root user, adding the + public part to the user's `authorized_keys` file. + +3. As root, call ssh to connect to localhost as the user, + and run the ``rootless_test.sh`` script from the source + tree. This is needed so the user has a clean process tree + and environment - i.e. without `sudo`, `su`, `runuser`, + etc. in the mix. From here, all testing as the user may + be performed. ### ``optional_testing`` Task diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh index 0fd86dfdc..58c8af289 100755 --- a/contrib/cirrus/integration_test.sh +++ b/contrib/cirrus/integration_test.sh @@ -19,7 +19,7 @@ case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in ubuntu-18) make install PREFIX=/usr ETCDIR=/etc make test-binaries - SKIP_USERNS=1 make localintegration GINKGOTIMEOUT=90m + SKIP_USERNS=1 make localintegration ;; fedora-29) ;& # Continue to the next item fedora-28) ;& diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 8be696933..e941610e2 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -53,6 +53,7 @@ show_env_vars() { echo " BUILDTAGS $BUILDTAGS BUILT_IMAGE_SUFFIX $BUILT_IMAGE_SUFFIX +ROOTLESS_USER $ROOTLESS_USER CI $CI CIRRUS_CI $CIRRUS_CI CI_NODE_INDEX $CI_NODE_INDEX @@ -100,6 +101,15 @@ clean_env() { unset -v UNSET_ENV_VARS $UNSET_ENV_VARS || true # don't fail on read-only } +die() { + req_env_var " + 1 $1 + 2 $2 + " + echo "$2" + exit $1 +} + # Return a GCE image-name compatible string representation of distribution name os_release_id() { eval "$(egrep -m 1 '^ID=' /etc/os-release | tr -d \' | tr -d \")" @@ -117,6 +127,15 @@ bad_os_id_ver() { exit 42 } +run_rootless() { + if [[ -z "$ROOTLESS_USER" ]] + then + return 1 + else + return 0 + fi +} + stub() { echo "STUB: Pretending to do $1" } @@ -124,14 +143,14 @@ stub() { ircmsg() { req_env_var " CIRRUS_TASK_ID $CIRRUS_TASK_ID - 1 $1 + @ $@ " # Sometimes setup_environment.sh didn't run SCRIPT="$(dirname $0)/podbot.py" NICK="podbot_$CIRRUS_TASK_ID" NICK="${NICK:0:15}" # Any longer will break things set +e - $SCRIPT $NICK $1 + $SCRIPT $NICK $@ echo "Ignoring exit($?)" set -e } @@ -146,12 +165,57 @@ record_timestamp() { echo -e "BLEEEEEEEEEEP!\n." } -# Run sudo in directory with GOPATH set -cdsudo() { - DIR="$1" - shift - CMD="cd $DIR && $@" - sudo --preserve-env=GOPATH --non-interactive bash -c "$CMD" +setup_rootless() { + req_env_var " + ROOTLESS_USER $ROOTLESS_USER + GOSRC $GOSRC + ENVLIB $ENVLIB + " + + if passwd --status $ROOTLESS_USER + then + echo "Updating $ROOTLESS_USER user permissions on possibly changed libpod code" + chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOSRC" + return 0 + fi + + # 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 + chown -R $ROOTLESS_USER:$ROOTLESS_USER "$GOSRC" + + echo "creating ssh keypair for $USER" + ssh-keygen -P "" -f $HOME/.ssh/id_rsa + + echo "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 \ + "$HOME/.ssh/id_rsa.pub" "/home/$ROOTLESS_USER/.ssh/authorized_keys" + # Makes debugging easier + cat /root/.ssh/authorized_keys >> "/home/$ROOTLESS_USER/.ssh/authorized_keys" + + echo "Configuring subuid and subgid" + grep -q "${ROOTLESS_USER}" /etc/subuid || \ + echo "${ROOTLESS_USER}:$[ROOTLESS_UID * 100]:65536" | \ + tee -a /etc/subuid >> /etc/subgid + + echo "Setting permissions on automation files" + chmod 666 "$TIMESTAMPS_FILEPATH" + + echo "Copying $HOME/$ENVLIB" + install -o $ROOTLESS_USER -g $ROOTLESS_USER -m 0700 \ + "$HOME/$ENVLIB" "/home/$ROOTLESS_USER/$ENVLIB" + + echo "Configuring user's go environment variables" + su --login --command 'go env' $ROOTLESS_USER | \ + while read envline + do + X=$(echo "export $envline" | tee -a "/home/$ROOTLESS_USER/$ENVLIB") && echo "$X" + done } # Helper/wrapper script to only show stderr/stdout on non-zero exit @@ -300,21 +364,6 @@ EOF fi } -# Runs in testing VM, not image building -install_testing_dependencies() { - echo "Installing ginkgo, gomega, and easyjson into \$GOPATH=$GOPATH" - req_env_var " - GOPATH $GOPATH - GOSRC $GOSRC - " - cd "$GOSRC" - ooe.sh go get -u github.com/onsi/ginkgo/ginkgo - ooe.sh install -D -m 755 "$GOPATH"/bin/ginkgo /usr/bin/ - ooe.sh go get github.com/onsi/gomega/... - ooe.sh go get -u github.com/mailru/easyjson/... - sudo install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/ -} - install_packer_copied_files(){ # Install cni config, policy and registry config sudo install -D -m 755 /tmp/libpod/cni/87-podman-bridge.conflist \ diff --git a/contrib/cirrus/notice_master_failure.sh b/contrib/cirrus/notice_master_failure.sh new file mode 100755 index 000000000..4b09331d3 --- /dev/null +++ b/contrib/cirrus/notice_master_failure.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +source $(dirname $0)/lib.sh + +# mIRC "escape" codes are the most standard, for a non-standard client-side interpretation. +ETX="$(echo -n -e '\x03')" +RED="${ETX}4" +NOR="$(echo -n -e '\x0f')" + +if [[ "$CIRRUS_BRANCH" =~ "master" ]] +then + BURL="https://cirrus-ci.com/build/$CIRRUS_BUILD_ID" + ircmsg "${RED}[Action Recommended]: ${NOR}Post-merge testing ${RED}$CIRRUS_BRANCH failed${NOR} in $CIRRUS_TASK_NAME on $(os_release_id)-$(os_release_ver): $BURL. Please investigate, and re-run if appropriate." +fi + +# This script assumed to be executed on failure +die 1 "Testing Failed" diff --git a/contrib/cirrus/packer/centos_setup.sh b/contrib/cirrus/packer/centos_setup.sh index 923f2563b..d947a1d7f 100644 --- a/contrib/cirrus/packer/centos_setup.sh +++ b/contrib/cirrus/packer/centos_setup.sh @@ -27,6 +27,7 @@ ooe.sh sudo yum -y install centos-release-scl epel-release ooe.sh sudo yum -y install \ PyYAML \ atomic-registries \ + bats \ btrfs-progs-devel \ bzip2 \ device-mapper-devel \ diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh index de7ad4506..84aee7667 100644 --- a/contrib/cirrus/packer/fedora_setup.sh +++ b/contrib/cirrus/packer/fedora_setup.sh @@ -26,6 +26,7 @@ ooe.sh sudo dnf update -y ooe.sh sudo dnf install -y \ atomic-registries \ + bats \ btrfs-progs-devel \ bzip2 \ device-mapper-devel \ diff --git a/contrib/cirrus/packer/rhel_setup.sh b/contrib/cirrus/packer/rhel_setup.sh index ac6866a57..20be97f9b 100644 --- a/contrib/cirrus/packer/rhel_setup.sh +++ b/contrib/cirrus/packer/rhel_setup.sh @@ -33,6 +33,7 @@ ooe.sh sudo yum -y update ooe.sh sudo yum -y install \ PyYAML \ atomic-registries \ + bats \ btrfs-progs-devel \ bzip2 \ device-mapper-devel \ diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh index 5b7e1d714..24f1cce21 100644 --- a/contrib/cirrus/packer/ubuntu_setup.sh +++ b/contrib/cirrus/packer/ubuntu_setup.sh @@ -38,6 +38,7 @@ ooe.sh sudo -E apt-get -qq install \ apparmor \ autoconf \ automake \ + bats \ bison \ btrfs-tools \ build-essential \ diff --git a/contrib/cirrus/rootless_test.sh b/contrib/cirrus/rootless_test.sh new file mode 100755 index 000000000..d0e2ceb95 --- /dev/null +++ b/contrib/cirrus/rootless_test.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e +source $HOME/.bash_profile + +cd $GOSRC +source $(dirname $0)/lib.sh + +req_env_var " +GOSRC $GOSRC +OS_RELEASE_ID $OS_RELEASE_ID +OS_RELEASE_VER $OS_RELEASE_VER +" + +if ! run_rootless +then + echo "Error: Expected rootless env. vars not set or empty" + exit 1 +fi + +echo "." +echo "Hello, my name is $USER and I live in $PWD can I be your friend?" + +record_timestamp "rootless test start" + +cd "$GOSRC" +case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in + ubuntu-18) ;& # Continue to the next item + fedora-29) ;& + fedora-28) + make + make varlink_generate + make test-binaries + make ginkgo + ;; + *) bad_os_id_ver ;; +esac + +record_timestamp "rootless test end" diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 77c20d9bd..96d0e1b55 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -43,6 +43,7 @@ then "export OS_RELEASE_ID=\"$(os_release_id)\"" \ "export OS_RELEASE_VER=\"$(os_release_ver)\"" \ "export OS_REL_VER=\"$(os_release_id)-$(os_release_ver)\"" \ + "export ROOTLESS_USER=$ROOTLESS_USER" \ "export BUILT_IMAGE_SUFFIX=\"-$CIRRUS_REPO_NAME-${CIRRUS_CHANGE_IN_REPO:0:8}\"" \ "export GOPATH=\"/var/tmp/go\"" \ 'export PATH="$HOME/bin:$GOPATH/bin:/usr/local/bin:$PATH"' \ @@ -70,18 +71,20 @@ then *) bad_os_id_ver ;; esac - # Do the same for golang env. vars - go env | while read envline - do - X=$(echo "export $envline" | tee -a "$HOME/$ENVLIB") && eval "$X" && echo "$X" - done - cd "${GOSRC}/" + # Reload to incorporate any changes from above source "$SCRIPT_BASE/lib.sh" - # Only testing-VMs need deps installed, not image-builder VM - echo "$CIRRUS_TASK_NAME" | grep -q 'image' || \ - install_testing_dependencies # must exist in $GOPATH + if run_rootless + then + setup_rootless + make install.catatonit + go get github.com/onsi/ginkgo/ginkgo + go get github.com/onsi/gomega/... + dnf -y update runc + fi fi +show_env_vars + record_timestamp "env. setup end" diff --git a/contrib/cirrus/test/test_dot_cirrus_yaml.py b/contrib/cirrus/test/test_dot_cirrus_yaml.py new file mode 100755 index 000000000..2894bc45e --- /dev/null +++ b/contrib/cirrus/test/test_dot_cirrus_yaml.py @@ -0,0 +1,78 @@ +#!/bin/env python3 + +import sys +import os +import os.path +import unittest +import warnings +import yaml + +class TestCaseBase(unittest.TestCase): + + SCRIPT_PATH = os.path.realpath((os.path.dirname(sys.argv[0]))) + CIRRUS_WORKING_DIR = os.environ.get('CIRRUS_WORKING_DIR', + '{0}/../../../'.format(SCRIPT_PATH)) + + def setUp(self): + os.chdir(self.CIRRUS_WORKING_DIR) + + +class TestCirrusYAML(TestCaseBase): + + IMAGE_NAME_SUFFIX = '_CACHE_IMAGE_NAME' + ACTIVE_IMAGES_NAME = 'ACTIVE_CACHE_IMAGE_NAMES' + + def setUp(self): + TestCirrusYAML._cirrus = None + super().setUp() + + @property + def cirrus(self): + if TestCirrusYAML._cirrus is None: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore",category=DeprecationWarning) + with open('.cirrus.yml', "r") as dot_cirrus_dot_yaml: + TestCirrusYAML._cirrus = yaml.load(dot_cirrus_dot_yaml) + return TestCirrusYAML._cirrus + + def _assert_get_cache_image_names(self, env): + inames = set([key for key in env.keys() + if key.endswith(self.IMAGE_NAME_SUFFIX)]) + self.assertNotEqual(inames, set()) + + ivalues = set([value for key, value in env.items() + if key in inames]) + self.assertNotEqual(ivalues, set()) + return ivalues + + def _assert_get_subdct(self, key, dct): + self.assertIn(key, dct) + return dct[key] + + def test_parse_yaml(self): + self.assertIsInstance(self.cirrus, dict) + + def test_active_cache_image_names(self): + env = self._assert_get_subdct('env', self.cirrus) + acin = self._assert_get_subdct(self.ACTIVE_IMAGES_NAME, env) + + for ivalue in self._assert_get_cache_image_names(env): + self.assertIn(ivalue, acin, + "The '{}' sub-key of 'env' should contain this among" + " its space-separated values." + "".format(self.ACTIVE_IMAGES_NAME)) + + + def test_cache_image_names_active(self): + env = self._assert_get_subdct('env', self.cirrus) + ivalues = self._assert_get_cache_image_names(env) + + for avalue in set(self._assert_get_subdct(self.ACTIVE_IMAGES_NAME, env).split()): + self.assertIn(avalue, ivalues, + "All space-separated values in the '{}' sub-key" + " of 'env' must also be used in a key with a '{}' suffix." + "".format(self.ACTIVE_IMAGES_NAME, self.IMAGE_NAME_SUFFIX)) + + +if __name__ == '__main__': + unittest.main(failfast=True, catchbreak=True, verbosity=0) |