From 3859981095a7942d6e682be1e4c55912392efee4 Mon Sep 17 00:00:00 2001 From: Steven Kalt Date: Sun, 31 May 2020 15:35:27 -0400 Subject: [PATCH 1/5] fix(tests): got ./ci-integration/virtualization/Dockerfile to build Notes from investigating `The command 'bash -c pip install -e . --user' returned a non-zero code: 1`: ./ci-integration/virtualization/Dockerfile was running off of debian 10, aka buster. Buster is possibly the last debian to have python as python2.7 rather than 3.x. Thus, `pip` runs as python 2.7 and fails to work with ./setup.py, which is written to work in python 3.x. That raised a new error: ``` Exception: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/pip/_internal/req/req_install.py", line 339, in check_if_exists self.satisfied_by = pkg_resources.get_distribution(str(no_marker)) File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 481, in get_distribution dist = get_provider(dist) File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 357, in get_provider return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 900, in require needed = self.resolve(parse_requirements(requirements)) File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 791, in resolve raise VersionConflict(dist, req).with_context(dependent_req) pkg_resources.ContextualVersionConflict: (wheel 0.32.3 (/usr/lib/python3/dist-packages), Requirement.parse('wheel==0.30'), {'volttron'}) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/pip/_internal/cli/base_command.py", line 143, in main status = self.run(options, args) File "/usr/lib/python3/dist-packages/pip/_internal/commands/install.py", line 338, in run resolver.resolve(requirement_set) File "/usr/lib/python3/dist-packages/pip/_internal/resolve.py", line 102, in resolve self._resolve_one(requirement_set, req) File "/usr/lib/python3/dist-packages/pip/_internal/resolve.py", line 256, in _resolve_one abstract_dist = self._get_abstract_dist_for(req_to_install) File "/usr/lib/python3/dist-packages/pip/_internal/resolve.py", line 193, in _get_abstract_dist_for req, self.require_hashes, self.use_user_site, self.finder, File "/usr/lib/python3/dist-packages/pip/_internal/operations/prepare.py", line 329, in prepare_editable_requirement req.check_if_exists(use_user_site) File "/usr/lib/python3/dist-packages/pip/_internal/req/req_install.py", line 350, in check_if_exists self.req.name File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 481, in get_distribution dist = get_provider(dist) File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 357, in get_provider return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 900, in require needed = self.resolve(parse_requirements(requirements)) File "/usr/share/python-wheels/pkg_resources-0.0.0-py2.py3-none-any.whl/pkg_resources/__init__.py", line 791, in resolve raise VersionConflict(dist, req).with_context(dependent_req) pkg_resources.ContextualVersionConflict: (wheel 0.32.3 (/usr/lib/python3/dist-packages), Requirement.parse('wheel==0.30'), {'volttron'}) ``` I fixed this by loosening the version requirements on the `wheel` package. --- bootstrap.py | 2 +- ci-integration/virtualization/Dockerfile | 13 ++++++------- ci-integration/virtualization/Dockerfile.testing | 5 +---- requirements.py | 2 +- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/bootstrap.py b/bootstrap.py index 04e30a2249..76bd693e11 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -132,7 +132,7 @@ def update(operation, verbose=None, upgrade=False, offline=False, optional_requi # We must install wheel first to eliminate a bunch of scary looking # errors at first install. # TODO Look towards fixing the packaging so that it works with 0.31 - pip('install', ['wheel==0.30'], verbose, True, offline=offline) + pip('install', ['wheel~=0.32'], verbose, True, offline=offline) # Build option_requirements separately to pass install options build_option = '--build-option' if wheeling else '--install-option' diff --git a/ci-integration/virtualization/Dockerfile b/ci-integration/virtualization/Dockerfile index ef64201d57..b0fd7b9662 100644 --- a/ci-integration/virtualization/Dockerfile +++ b/ci-integration/virtualization/Dockerfile @@ -3,21 +3,20 @@ ARG image_repo=volttron-docker ARG image_tag=deps-master-amd64 FROM ${image_user}/${image_repo}:${image_tag} as volttron_deps - +USER root +RUN mkdir -p /var/lib/apt/lists/partial \ + && apt-get update \ + && apt-get install -y python3-pip; # Note I couldn't get variable expansion on the chown argument to work here # so must hard code the user. Note this is a feature request for docker # https://github.com/moby/moby/issues/35018 +# Now resolved: https://github.com/moby/moby/issues/35018#event-2301021020 COPY --chown=volttron:volttron . ${VOLTTRON_ROOT} USER $VOLTTRON_USER -# The following lines ar no longer necesary because of the copy command above. -#WORKDIR /code -#RUN git clone https://github.com/VOLTTRON/volttron -b ${VOLTTRON_GIT_BRANCH} - WORKDIR /code/volttron -#RUN pip install --user -r requirements.txt -RUN pip install -e . --user +RUN python3 -m pip install -e . --user ############################################ # RABBITMQ SPECIFIC INSTALLATION diff --git a/ci-integration/virtualization/Dockerfile.testing b/ci-integration/virtualization/Dockerfile.testing index 9b89e33067..c1e87390ef 100644 --- a/ci-integration/virtualization/Dockerfile.testing +++ b/ci-integration/virtualization/Dockerfile.testing @@ -1,11 +1,9 @@ FROM volttron_test_base as test_core WORKDIR ${VOLTTRON_ROOT} -#COPY ./ci-integration/virtualization/requirements_test.txt ./requirements_test.txt USER $VOLTTRON_USER RUN pwd -#RUN ls -a -RUN pip install --user -r ./ci-integration/virtualization/requirements_test.txt +RUN python3 -m pip install --user -r ./ci-integration/virtualization/requirements_test.txt RUN echo "export VOLTTRON_ROOT=${VOLTTRON_ROOT}" > /home/volttron/.bashrc && \ echo "export VOLTTRON_USER_HOME=${VOLTTRON_USER_HOME}" >> /home/volttron/.bashrc && \ @@ -14,4 +12,3 @@ RUN echo "export VOLTTRON_ROOT=${VOLTTRON_ROOT}" > /home/volttron/.bashrc && \ USER root WORKDIR ${VOLTTRON_ROOT} ENTRYPOINT ["/startup/entrypoint.sh"] -#CMD ["/startup/bootstart.sh"] diff --git a/requirements.py b/requirements.py index 6cf46fe215..a0de80bb1c 100644 --- a/requirements.py +++ b/requirements.py @@ -61,7 +61,7 @@ # Cross platform way of handling changes in file/directories. # https://github.com/Bogdanp/watchdog_gevent 'watchdog-gevent', - 'wheel==0.30' + 'wheel~=0.32' ] extras_require = { From a19143c71decc4bc16778e5ee19bc8aee6fa3679 Mon Sep 17 00:00:00 2001 From: Steven Kalt Date: Sun, 31 May 2020 16:16:14 -0400 Subject: [PATCH 2/5] fix(tests): configure CI to report errors I've also fixed some of the warnings that `shellcheck` reports. --- ci-integration/run-test-docker.sh | 48 +++++++++++++++++-------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/ci-integration/run-test-docker.sh b/ci-integration/run-test-docker.sh index 94c4114373..705c946372 100755 --- a/ci-integration/run-test-docker.sh +++ b/ci-integration/run-test-docker.sh @@ -1,4 +1,6 @@ #!/bin/bash +set -x # log all shell commands for debugging. +set -e # fail if any command errors without being caught with an || or an 'if'. # The following script builds a volttron test image and then # runs each of the test modules inside a docker container based @@ -42,10 +44,12 @@ ignoredirs=(services/core/DNP3Agent services/core/IEEE2030_5Agent services/core/ # failed. HAS_FAILED=0 +set +e # allow this script to handle errors. + # method to push a test module into the queue push_test(){ testpath="$1" - testqueue+=($testpath) + testqueue+=("$testpath") } # method to get a test module out of the queue @@ -60,15 +64,15 @@ pop_test(){ # global state arrays. run_test(){ # bash /home/osboxes/repos/volttron-rabbitmq/ci-integration/sleep_ten.sh & - local filename=$1; + local filename="$1" echo "Running test module $filename" - base_filename=`basename $filename` + base_filename="$(basename "$filename")" # Start the docker run module. - docker run -e "IGNORE_ENV_CHECK=1" --name $base_filename \ - -t volttron_test_image pytest $filename > "$base_filename.result.txt" 2>&1 & + docker run -e "IGNORE_ENV_CHECK=1" --name "$base_filename" \ + -t volttron_test_image pytest "$filename" > "$base_filename.result.txt" 2>&1 & runningprocs+=($!) outputfiles+=("$base_filename.result.txt") - containernames+=($base_filename) + containernames+=("$base_filename") sleep 0.5 } @@ -77,9 +81,9 @@ run_test(){ # and failed tests are found. exit_cleanly(){ echo "Cleaning up test containers before exiting!" - for container in ${containernames[@]}; do - docker stop $container - docker container rm $container + for container in "${containernames[@]}"; do + docker stop "$container" + docker container rm "$container" done docker system prune --force exit 1 @@ -94,7 +98,7 @@ process_pid(){ # is still executing. If it is not then we need to see what the # exit code was of the container. if [[ ! -e "/proc/${pid}" ]]; then - exitcode=$(docker inspect ${containernames[$index]} --format='{{.State.ExitCode}}') + exitcode=$(docker inspect "${containernames[$index]}" --format='{{.State.ExitCode}}') #echo "Exit code is ${exitcode}" # Exit code 5 is if there are no tests within the file so we filter that out @@ -106,7 +110,7 @@ process_pid(){ HAS_FAILED=1 #echo "FAST_FAIL is ${FAST_FAIL} if its 0 should start clean exit procedure." if [[ ${FAST_FAIL} -eq 0 && -n ${CI} ]]; then - docker logs ${containernames[$index]} + docker logs "${containernames[$index]}" fi if [[ ${FAST_FAIL} -eq 0 ]]; then echo "Exiting cleanly now!" @@ -116,36 +120,36 @@ process_pid(){ else # process passed so cleanup the result file. echo "module ${containernames[$index]} PASSED removing: ${outputfiles[$index]}" - rm ${outputfiles[$index]} + rm "${outputfiles[$index]}" fi # Clean up the test container now that this process is done. - docker container rm ${containernames[$index]} &>/dev/null + docker container rm "${containernames[$index]}" &>/dev/null # Remove pid from the array of running procs. - runningprocs=( ${runningprocs[@]:0:$index} ${runningprocs[@]:$((index + 1))} ) - outputfiles=( ${outputfiles[@]:0:$index} ${outputfiles[@]:$((index + 1))} ) - containernames=( ${containernames[@]:0:$index} ${containernames[@]:$((index + 1))} ) + runningprocs=( "${runningprocs[@]:0:$index}" "${runningprocs[@]:$((index + 1))}" ) + outputfiles=( "${outputfiles[@]:0:$index}" "${outputfiles[@]:$((index + 1))}" ) + containernames=( "${containernames[@]:0:$index}" "${containernames[@]:$((index + 1))}" ) fi i=$(( i+1 )) } #LOOP through set of directories and run bunch of test files in parallel -for dir in ${testdirs[@]} +for dir in "${testdirs[@]}" do for file in $( find $dir -type f -name "test*.py" -o -name "*test.py" ! -name "*conftest.py" ) do - echo $file; + echo "$file"; ignore=0 - for pattern in ${ignoredirs[@]}; do + for pattern in "${ignoredirs[@]}"; do if [[ $file == *"$pattern"* ]]; then - echo $file "IGNORED" + echo "$file IGNORED" ignore=1 break fi done if [[ $ignore == 0 ]]; then - push_test $file; + push_test "$file"; fi done done @@ -159,7 +163,7 @@ while [[ ${#testqueue[@]} -gt 0 ]]; do while [[ ${#runningprocs[@]} -lt ${NUM_PROCESSES} && ${#testqueue[@]} -gt 0 ]]; do # pop the front of the queue into the next_test variable pop_test - run_test ${next_test} + run_test "${next_test}" done i=0 From a268daaeb1c05f605848caf71e1b2db2ed75eab7 Mon Sep 17 00:00:00 2001 From: Craig <3979063+craig8@users.noreply.github.com> Date: Fri, 5 Jun 2020 19:37:30 -0700 Subject: [PATCH 3/5] keep wheel @ 0.30 --- requirements.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.py b/requirements.py index a0de80bb1c..6cf46fe215 100644 --- a/requirements.py +++ b/requirements.py @@ -61,7 +61,7 @@ # Cross platform way of handling changes in file/directories. # https://github.com/Bogdanp/watchdog_gevent 'watchdog-gevent', - 'wheel~=0.32' + 'wheel==0.30' ] extras_require = { From 39ec04cb6b0a74c11f79a5679b055d5648d100d6 Mon Sep 17 00:00:00 2001 From: Steven Kalt Date: Wed, 10 Jun 2020 16:46:27 -0400 Subject: [PATCH 4/5] fix: Revert wheel package to 0.30 Wheel >= 0.31 appears to include breaking changes. As requested in PR#2363, I've reverted to 0.30. Special thanks to @craig8, from whom I copied most of these changes. --- bootstrap.py | 2 +- ci-integration/run-test-docker.sh | 1 + ci-integration/virtualization/Dockerfile | 13 +++++-------- ci-integration/virtualization/core/bootstart.sh | 2 ++ requirements.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bootstrap.py b/bootstrap.py index 76bd693e11..5141013021 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -132,7 +132,7 @@ def update(operation, verbose=None, upgrade=False, offline=False, optional_requi # We must install wheel first to eliminate a bunch of scary looking # errors at first install. # TODO Look towards fixing the packaging so that it works with 0.31 - pip('install', ['wheel~=0.32'], verbose, True, offline=offline) + pip('install', ['wheel~=0.30'], verbose, True, offline=offline) # Build option_requirements separately to pass install options build_option = '--build-option' if wheeling else '--install-option' diff --git a/ci-integration/run-test-docker.sh b/ci-integration/run-test-docker.sh index 705c946372..54aca9dd70 100755 --- a/ci-integration/run-test-docker.sh +++ b/ci-integration/run-test-docker.sh @@ -19,6 +19,7 @@ fi export FAST_FAIL=${FAST_FAIL:-true} +pip list echo "RUNNING $NUM_PROCESSES PARALLEL PROCESSESS AT A TIME" echo "FAST_FAIL IS $FAST_FAIL" diff --git a/ci-integration/virtualization/Dockerfile b/ci-integration/virtualization/Dockerfile index b0fd7b9662..7cc7e7c594 100644 --- a/ci-integration/virtualization/Dockerfile +++ b/ci-integration/virtualization/Dockerfile @@ -1,12 +1,10 @@ ARG image_user=laroque ARG image_repo=volttron-docker -ARG image_tag=deps-master-amd64 - +ARG image_tag=deps-feature_python3-amd64 + +# Note: the image should include python3 and volttron's dependencies. FROM ${image_user}/${image_repo}:${image_tag} as volttron_deps -USER root -RUN mkdir -p /var/lib/apt/lists/partial \ - && apt-get update \ - && apt-get install -y python3-pip; + # Note I couldn't get variable expansion on the chown argument to work here # so must hard code the user. Note this is a feature request for docker # https://github.com/moby/moby/issues/35018 @@ -16,7 +14,6 @@ COPY --chown=volttron:volttron . ${VOLTTRON_ROOT} USER $VOLTTRON_USER WORKDIR /code/volttron -RUN python3 -m pip install -e . --user ############################################ # RABBITMQ SPECIFIC INSTALLATION @@ -37,7 +34,7 @@ RUN set -eux \ && wget -P $VOLTTRON_USER_HOME https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.7/rabbitmq-server-generic-unix-3.7.7.tar.xz \ && tar -xf $VOLTTRON_USER_HOME/rabbitmq-server-generic-unix-3.7.7.tar.xz --directory $RMQ_ROOT \ && $RMQ_HOME/sbin/rabbitmq-plugins enable rabbitmq_management rabbitmq_federation rabbitmq_federation_management rabbitmq_shovel rabbitmq_shovel_management rabbitmq_auth_mechanism_ssl rabbitmq_trust_store -RUN pip install gevent-pika --user +RUN python3 -m pip install gevent-pika --user ############################################ diff --git a/ci-integration/virtualization/core/bootstart.sh b/ci-integration/virtualization/core/bootstart.sh index 9d256aadf7..7c7e975adc 100644 --- a/ci-integration/virtualization/core/bootstart.sh +++ b/ci-integration/virtualization/core/bootstart.sh @@ -9,6 +9,8 @@ echo "Right before setup-platform.py is called I am calling printenv" printenv +pip list +pip install --user wheel==0.30 #python /startup/setup-platform.py PID=$? echo "PID WAS $PID" diff --git a/requirements.py b/requirements.py index a0de80bb1c..810e8d01f4 100644 --- a/requirements.py +++ b/requirements.py @@ -61,7 +61,7 @@ # Cross platform way of handling changes in file/directories. # https://github.com/Bogdanp/watchdog_gevent 'watchdog-gevent', - 'wheel~=0.32' + 'wheel~=0.30' ] extras_require = { From f17b30ce3e1deb859ea71ac66dd69d2a49301875 Mon Sep 17 00:00:00 2001 From: Steven Kalt Date: Wed, 10 Jun 2020 16:55:32 -0400 Subject: [PATCH 5/5] chore(tests): comment ultra-verbose bash logging --- ci-integration/run-test-docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-integration/run-test-docker.sh b/ci-integration/run-test-docker.sh index 54aca9dd70..8c9bfc41d1 100755 --- a/ci-integration/run-test-docker.sh +++ b/ci-integration/run-test-docker.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -x # log all shell commands for debugging. +# set -x # log all shell commands for debugging. set -e # fail if any command errors without being caught with an || or an 'if'. # The following script builds a volttron test image and then