diff --git a/.env b/.env new file mode 100644 index 000000000..10ab7dc6f --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +GITLAB_IMAGE=gitlab/gitlab-ce +GITLAB_TAG=13.3.5-ce.0 diff --git a/.renovaterc.json b/.renovaterc.json index be47e3af2..037a97e1a 100644 --- a/.renovaterc.json +++ b/.renovaterc.json @@ -4,8 +4,8 @@ ], "regexManagers": [ { - "fileMatch": ["^tools/build_test_env.sh$"], - "matchStrings": ["DEFAULT_GITLAB_TAG=(?.*?)\n"], + "fileMatch": ["^.env$"], + "matchStrings": ["GITLAB_TAG=(?.*?)\n"], "depNameTemplate": "gitlab/gitlab-ce", "datasourceTemplate": "docker", "versioningTemplate": "loose" diff --git a/README.rst b/README.rst index 2291242de..987338099 100644 --- a/README.rst +++ b/README.rst @@ -166,7 +166,7 @@ You need to install ``tox`` to run unit tests and documentation builds locally: Running integration tests ------------------------- -Two scripts run tests against a running gitlab instance, using a docker +Integration tests run against a running gitlab instance, using a docker container. You need to have docker installed on the test machine, and your user must have the correct permissions to talk to the docker daemon. @@ -180,9 +180,9 @@ To run these tests: # run the python API tests: tox -e py_func_v4 -By default, the tests run against the ``gitlab/gitlab-ce:latest`` image. You can -override both the image and tag with the ``-i`` and ``-t`` options, or by providing -either the ``GITLAB_IMAGE`` or ``GITLAB_TAG`` environment variables. +By default, the tests run against the latest version of the ``gitlab/gitlab-ce`` +image. You can override both the image and tag by providing either the +``GITLAB_IMAGE`` or ``GITLAB_TAG`` environment variables. This way you can run tests against different versions, such as ``nightly`` for features in an upcoming release, or an older release (e.g. ``12.8.0-ce.0``). @@ -191,20 +191,11 @@ The tag must match an exact tag on Docker Hub: .. code-block:: bash # run tests against `nightly` or specific tag - ./tools/py_functional_tests.sh -t nightly - ./tools/py_functional_tests.sh -t 12.8.0-ce.0 + GITLAB_TAG=nightly tox -e py_func_v4 + GITLAB_TAG=12.8.0-ce.0 tox -e py_func_v4 # run tests against the latest gitlab EE image - ./tools/py_functional_tests.sh -i gitlab/gitlab-ee - - # override tags with environment variables - GITLAB_TAG=nightly ./tools/py_functional_tests.sh - -You can also build a test environment using the following command: - -.. code-block:: bash - - ./tools/build_test_env.sh + GITLAB_IMAGE=gitlab/gitlab-ee tox -e py_func_v4 A freshly configured gitlab container will be available at http://localhost:8080 (login ``root`` / password ``5iveL!fe``). A configuration diff --git a/docker-requirements.txt b/docker-requirements.txt new file mode 100644 index 000000000..1bcd74b6e --- /dev/null +++ b/docker-requirements.txt @@ -0,0 +1,4 @@ +-r requirements.txt +-r test-requirements.txt +pytest-console-scripts +pytest-docker diff --git a/tools/build_test_env.sh b/tools/build_test_env.sh deleted file mode 100755 index a7b64b602..000000000 --- a/tools/build_test_env.sh +++ /dev/null @@ -1,158 +0,0 @@ -#!/bin/sh -# Copyright (C) 2016 Gauvain Pocentek -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . - -pecho() { printf %s\\n "$*"; } -log() { - [ "$#" -eq 0 ] || { pecho "$@"; return 0; } - while IFS= read -r log_line || [ -n "${log_line}" ]; do - log "${log_line}" - done -} -error() { log "ERROR: $@" >&2; } -fatal() { error "$@"; exit 1; } -try() { "$@" || fatal "'$@' failed"; } - -REUSE_CONTAINER= -NOVENV= -API_VER=4 -DEFAULT_GITLAB_IMAGE=gitlab/gitlab-ce -DEFAULT_GITLAB_TAG=13.3.6-ce.0 -GITLAB_IMAGE="${GITLAB_IMAGE:-$DEFAULT_GITLAB_IMAGE}" -GITLAB_TAG="${GITLAB_TAG:-$DEFAULT_GITLAB_TAG}" -VENV_CMD="python3 -m venv" -while getopts :knp:a:i:t: opt "$@"; do - case $opt in - k) REUSE_CONTAINER=1;; - n) NOVENV=1;; - a) API_VER=$OPTARG;; - i) GITLAB_IMAGE=$OPTARG;; - t) GITLAB_TAG=$OPTARG;; - :) fatal "Option -${OPTARG} requires a value";; - '?') fatal "Unknown option: -${OPTARG}";; - *) fatal "Internal error: opt=${opt}";; - esac -done - -case $API_VER in - 4) ;; - *) fatal "Wrong API version (4 only)";; -esac - -for req in \ - curl \ - docker \ - ; -do - command -v "${req}" >/dev/null 2>&1 || fatal "${req} is required" -done - -VENV=$(pwd)/.venv || exit 1 -CONFIG=/tmp/python-gitlab.cfg - -cleanup() { - rm -f "${CONFIG}" - log "Deactivating Python virtualenv..." - command -v deactivate >/dev/null 2>&1 && deactivate || true - log "Deleting python virtualenv..." - rm -rf "$VENV" - if [ -z "$REUSE_CONTAINER" ]; then - log "Stopping gitlab-test docker container..." - docker rm -f gitlab-test >/dev/null - fi - log "Done." -} -[ -z "${BUILD_TEST_ENV_AUTO_CLEANUP+set}" ] || { - trap cleanup EXIT - trap 'exit 1' HUP INT TERM -} - -if [ -z "$REUSE_CONTAINER" ] || ! docker top gitlab-test >/dev/null 2>&1; then - try docker pull "$GITLAB_IMAGE:$GITLAB_TAG" - GITLAB_OMNIBUS_CONFIG="external_url 'http://gitlab.test' -gitlab_rails['initial_root_password'] = '5iveL!fe' -gitlab_rails['initial_shared_runners_registration_token'] = 'sTPNtWLEuSrHzoHP8oCU' -registry['enable'] = false -nginx['redirect_http_to_https'] = false -nginx['listen_port'] = 80 -nginx['listen_https'] = false -pages_external_url 'http://pages.gitlab.lxd' -gitlab_pages['enable'] = true -gitlab_pages['inplace_chroot'] = true -prometheus['enable'] = false -alertmanager['enable'] = false -node_exporter['enable'] = false -redis_exporter['enable'] = false -postgres_exporter['enable'] = false -pgbouncer_exporter['enable'] = false -gitlab_exporter['enable'] = false -grafana['enable'] = false -letsencrypt['enable'] = false -" - try docker run --name gitlab-test --detach --publish 8080:80 \ - --publish 2222:22 --env "GITLAB_OMNIBUS_CONFIG=$GITLAB_OMNIBUS_CONFIG" \ - "$GITLAB_IMAGE:$GITLAB_TAG" >/dev/null -fi - -if [ -z "$NOVENV" ]; then - log "Creating Python virtualenv..." - try $VENV_CMD "$VENV" - . "$VENV"/bin/activate || fatal "failed to activate Python virtual environment" - - log "Installing dependencies into virtualenv..." - try pip install -r requirements.txt - - log "Installing into virtualenv..." - try pip install -e . - - # to run generate_token.py - pip install requests-html pytest-console-scripts -fi - -log "Waiting for gitlab to come online... " -I=0 -while :; do - sleep 1 - docker top gitlab-test >/dev/null 2>&1 || fatal "docker failed to start" - sleep 4 - docker logs gitlab-test 2>&1 | grep "gitlab Reconfigured!" \ - && break - I=$((I+5)) - log "Waiting for GitLab to reconfigure.. (${I}s)" - [ "$I" -lt 180 ] || fatal "timed out" -done - -# Get the token -TOKEN=$($(dirname $0)/generate_token.py) - -cat > $CONFIG << EOF -[global] -default = local -timeout = 30 - -[local] -url = http://localhost:8080 -private_token = $TOKEN -api_version = $API_VER -EOF - -log "Config file content ($CONFIG):" -log <$CONFIG - -if [ ! -z "$REUSE_CONTAINER" ]; then - echo reset gitlab - $(dirname $0)/reset_gitlab.py -fi -log "Test environment initialized." diff --git a/tools/functional/api/test_gitlab.py b/tools/functional/api/test_gitlab.py new file mode 100644 index 000000000..5cf3418d6 --- /dev/null +++ b/tools/functional/api/test_gitlab.py @@ -0,0 +1,8 @@ +""" +Temporary module to run legacy tests as a single pytest test case +as they're all plain asserts at module level. +""" + + +def test_api_v4(gl): + from tools.functional import python_test_v4 diff --git a/tools/functional/cli/conftest.py b/tools/functional/cli/conftest.py index 13c30962e..ba94dcbb8 100644 --- a/tools/functional/cli/conftest.py +++ b/tools/functional/cli/conftest.py @@ -2,7 +2,7 @@ @pytest.fixture -def gitlab_cli(script_runner, CONFIG): +def gitlab_cli(script_runner, gitlab_config): """Wrapper fixture to help make test cases less verbose.""" def _gitlab_cli(subcommands): @@ -10,7 +10,7 @@ def _gitlab_cli(subcommands): Return a script_runner.run method that takes a default gitlab command, and subcommands passed as arguments inside test cases. """ - command = ["gitlab", "--config-file", CONFIG] + command = ["gitlab", "--config-file", gitlab_config] for subcommand in subcommands: # ensure we get strings (e.g from IDs) diff --git a/tools/functional/conftest.py b/tools/functional/conftest.py index e60fa3915..9b80d2047 100644 --- a/tools/functional/conftest.py +++ b/tools/functional/conftest.py @@ -1,40 +1,128 @@ import tempfile +import time +import uuid from pathlib import Path from random import randint +from subprocess import check_output import pytest import gitlab -TEMP_DIR = tempfile.gettempdir() +def reset_gitlab(gl): + # previously tools/reset_gitlab.py + for project in gl.projects.list(): + project.delete() + for group in gl.groups.list(): + group.delete() + for variable in gl.variables.list(): + variable.delete() + for user in gl.users.list(): + if user.username != "root": + user.delete() + + +def set_token(container, rootdir): + set_token_rb = rootdir / "fixtures" / "set_token.rb" + + with open(set_token_rb, "r") as f: + set_token_command = f.read().strip() + + rails_command = [ + "docker", + "exec", + container, + "gitlab-rails", + "runner", + set_token_command, + ] + output = check_output(rails_command).decode().strip() + + return output + + +@pytest.fixture(scope="session") +def temp_dir(): + return Path(tempfile.gettempdir()) + + +@pytest.fixture(scope="session") +def test_dir(pytestconfig): + return pytestconfig.rootdir / "tools" / "functional" + + +@pytest.fixture(scope="session") +def docker_compose_file(test_dir): + return test_dir / "fixtures" / "docker-compose.yml" -def random_id(): +@pytest.fixture(scope="session") +def check_is_alive(request): """ - Helper to ensure new resource creation does not clash with - existing resources, for example when a previous test deleted a - resource but GitLab is still deleting it asynchronously in the - background. TODO: Expand to make it 100% safe. + Return a healthcheck function fixture for the GitLab container spinup. """ - return randint(9, 9999) + start = time.time() + + # Temporary manager to disable capsys in a session-scoped fixture + # so people know it takes a while for GitLab to spin up + # https://github.com/pytest-dev/pytest/issues/2704 + capmanager = request.config.pluginmanager.getplugin("capturemanager") + + def _check(container): + delay = int(time.time() - start) + + with capmanager.global_and_fixture_disabled(): + print(f"Waiting for GitLab to reconfigure.. (~{delay}s)") + + logs = ["docker", "logs", container] + output = check_output(logs).decode() + + return "gitlab Reconfigured!" in output + + return _check @pytest.fixture(scope="session") -def CONFIG(): - return Path(TEMP_DIR) / "python-gitlab.cfg" +def gitlab_config(check_is_alive, docker_ip, docker_services, temp_dir, test_dir): + config_file = temp_dir / "python-gitlab.cfg" + port = docker_services.port_for("gitlab", 80) + + docker_services.wait_until_responsive( + timeout=180, pause=5, check=lambda: check_is_alive("gitlab-test") + ) + + token = set_token("gitlab-test", rootdir=test_dir) + + config = f"""[global] +default = local +timeout = 60 + +[local] +url = http://{docker_ip}:{port} +private_token = {token} +api_version = 4""" + + with open(config_file, "w") as f: + f.write(config) + + return config_file @pytest.fixture(scope="session") -def gl(CONFIG): +def gl(gitlab_config): """Helper instance to make fixtures and asserts directly via the API.""" - return gitlab.Gitlab.from_config("local", [CONFIG]) + + instance = gitlab.Gitlab.from_config("local", [gitlab_config]) + reset_gitlab(instance) + + return instance @pytest.fixture(scope="module") def group(gl): """Group fixture for group API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex data = { "name": f"test-group-{_id}", "path": f"group-{_id}", @@ -52,7 +140,7 @@ def group(gl): @pytest.fixture(scope="module") def project(gl): """Project fixture for project API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex name = f"test-project-{_id}" project = gl.projects.create(name=name) @@ -68,7 +156,7 @@ def project(gl): @pytest.fixture(scope="module") def user(gl): """User fixture for user API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex email = f"user{_id}@email.com" username = f"user{_id}" name = f"User {_id}" @@ -87,7 +175,7 @@ def user(gl): @pytest.fixture(scope="module") def issue(project): """Issue fixture for issue API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex data = {"title": f"Issue {_id}", "description": f"Issue {_id} description"} return project.issues.create(data) @@ -96,7 +184,7 @@ def issue(project): @pytest.fixture(scope="module") def label(project): """Label fixture for project label API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex data = { "name": f"prjlabel{_id}", "description": f"prjlabel1 {_id} description", @@ -109,7 +197,7 @@ def label(project): @pytest.fixture(scope="module") def group_label(group): """Label fixture for group label API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex data = { "name": f"grplabel{_id}", "description": f"grplabel1 {_id} description", @@ -122,7 +210,7 @@ def group_label(group): @pytest.fixture(scope="module") def variable(project): """Variable fixture for project variable API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex data = {"key": f"var{_id}", "value": f"Variable {_id}"} return project.variables.create(data) @@ -131,7 +219,7 @@ def variable(project): @pytest.fixture(scope="module") def deploy_token(project): """Deploy token fixture for project deploy token API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex data = { "name": f"token-{_id}", "username": "root", @@ -145,7 +233,7 @@ def deploy_token(project): @pytest.fixture(scope="module") def group_deploy_token(group): """Deploy token fixture for group deploy token API resource tests.""" - _id = random_id() + _id = uuid.uuid4().hex data = { "name": f"group-token-{_id}", "username": "root", diff --git a/tools/ee-test.py b/tools/functional/ee-test.py similarity index 100% rename from tools/ee-test.py rename to tools/functional/ee-test.py diff --git a/tools/avatar.png b/tools/functional/fixtures/avatar.png similarity index 100% rename from tools/avatar.png rename to tools/functional/fixtures/avatar.png diff --git a/tools/functional/fixtures/docker-compose.yml b/tools/functional/fixtures/docker-compose.yml new file mode 100644 index 000000000..687eeaa8b --- /dev/null +++ b/tools/functional/fixtures/docker-compose.yml @@ -0,0 +1,31 @@ +version: '3' +services: + gitlab: + image: '${GITLAB_IMAGE}:${GITLAB_TAG}' + container_name: 'gitlab-test' + hostname: 'gitlab.test' + privileged: true # Just in case https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/1350 + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url 'http://gitlab.test' + gitlab_rails['initial_root_password'] = '5iveL!fe' + gitlab_rails['initial_shared_runners_registration_token'] = 'sTPNtWLEuSrHzoHP8oCU' + registry['enable'] = false + nginx['redirect_http_to_https'] = false + nginx['listen_port'] = 80 + nginx['listen_https'] = false + pages_external_url 'http://pages.gitlab.lxd' + gitlab_pages['enable'] = true + gitlab_pages['inplace_chroot'] = true + prometheus['enable'] = false + alertmanager['enable'] = false + node_exporter['enable'] = false + redis_exporter['enable'] = false + postgres_exporter['enable'] = false + pgbouncer_exporter['enable'] = false + gitlab_exporter['enable'] = false + grafana['enable'] = false + letsencrypt['enable'] = false + ports: + - '8080:80' + - '2222:22' diff --git a/tools/functional/fixtures/set_token.rb b/tools/functional/fixtures/set_token.rb new file mode 100644 index 000000000..735dcd55f --- /dev/null +++ b/tools/functional/fixtures/set_token.rb @@ -0,0 +1,9 @@ +# https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#programmatically-creating-a-personal-access-token + +user = User.find_by_username('root') + +token = user.personal_access_tokens.create(scopes: [:api, :sudo], name: 'default'); +token.set_token('python-gitlab-token'); +token.save! + +puts token.token diff --git a/tools/python_test_v4.py b/tools/functional/python_test_v4.py similarity index 98% rename from tools/python_test_v4.py rename to tools/functional/python_test_v4.py index 7ff97b67f..b29f9f3b5 100644 --- a/tools/python_test_v4.py +++ b/tools/functional/python_test_v4.py @@ -1,6 +1,7 @@ import base64 -import os +import tempfile import time +from pathlib import Path import requests @@ -56,11 +57,11 @@ qG2ZdhHHmSK2LaQLFiSprUkikStNU9BqSQ== =5OGa -----END PGP PUBLIC KEY BLOCK-----""" -AVATAR_PATH = os.path.join(os.path.dirname(__file__), "avatar.png") - +AVATAR_PATH = Path(__file__).parent / "fixtures" / "avatar.png" +TEMP_DIR = Path(tempfile.gettempdir()) # token authentication from config file -gl = gitlab.Gitlab.from_config(config_files=["/tmp/python-gitlab.cfg"]) +gl = gitlab.Gitlab.from_config(config_files=[TEMP_DIR / "python-gitlab.cfg"]) gl.auth() assert isinstance(gl.user, gitlab.v4.objects.CurrentUser) @@ -388,7 +389,7 @@ # We cannot check for export_status with group export API time.sleep(10) -import_archive = "/tmp/gitlab-group-export.tgz" +import_archive = TEMP_DIR / "gitlab-group-export.tgz" import_path = "imported_group" import_name = "Imported Group" @@ -1062,11 +1063,13 @@ count += 1 if count == 10: raise Exception("Project export taking too much time") -with open("/tmp/gitlab-export.tgz", "wb") as f: +with open(TEMP_DIR / "gitlab-export.tgz", "wb") as f: ex.download(streamed=True, action=f.write) output = gl.projects.import_project( - open("/tmp/gitlab-export.tgz", "rb"), "imported_project", name="Imported Project" + open(TEMP_DIR / "gitlab-export.tgz", "rb"), + "imported_project", + name="Imported Project", ) project_import = gl.projects.get(output["id"], lazy=True).imports.get() diff --git a/tools/functional_tests.sh b/tools/functional_tests.sh deleted file mode 100755 index 9b91f0f72..000000000 --- a/tools/functional_tests.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# Copyright (C) 2015 Gauvain Pocentek -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . - -setenv_script=$(dirname "$0")/build_test_env.sh || exit 1 -BUILD_TEST_ENV_AUTO_CLEANUP=true -. "$setenv_script" "$@" || exit 1 - -pytest --script-launch-mode=subprocess "$(dirname "$0")/functional/cli" diff --git a/tools/generate_token.py b/tools/generate_token.py deleted file mode 100755 index 89909bd90..000000000 --- a/tools/generate_token.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python - -from urllib.parse import urljoin -from requests_html import HTMLSession - -ENDPOINT = "http://localhost:8080" -LOGIN = "root" -PASSWORD = "5iveL!fe" - - -class GitlabSession(HTMLSession): - def __init__(self, endpoint, *args, **kwargs): - super().__init__(*args, **kwargs) - self.endpoint = endpoint - self.csrf = None - - def find_csrf_token(self, html): - param = html.find("meta[name=csrf-param]")[0].attrs["content"] - token = html.find("meta[name=csrf-token]")[0].attrs["content"] - self.csrf = {param: token} - - def obtain_csrf_token(self): - r = self.get(urljoin(self.endpoint, "/")) - self.find_csrf_token(r.html) - - def sign_in(self, login, password): - data = {"user[login]": login, "user[password]": password, **self.csrf} - r = self.post(urljoin(self.endpoint, "/users/sign_in"), data=data) - self.find_csrf_token(r.html) - - def obtain_personal_access_token(self, name): - data = { - "personal_access_token[name]": name, - "personal_access_token[scopes][]": ["api", "sudo"], - **self.csrf, - } - r = self.post( - urljoin(self.endpoint, "/profile/personal_access_tokens"), data=data - ) - return r.html.find("#created-personal-access-token")[0].attrs["value"] - - -def main(): - with GitlabSession(ENDPOINT) as s: - s.obtain_csrf_token() - s.sign_in(LOGIN, PASSWORD) - print(s.obtain_personal_access_token("default")) - - -if __name__ == "__main__": - main() diff --git a/tools/py_functional_tests.sh b/tools/py_functional_tests.sh deleted file mode 100755 index 1009cb981..000000000 --- a/tools/py_functional_tests.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# Copyright (C) 2015 Gauvain Pocentek -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . - -setenv_script=$(dirname "$0")/build_test_env.sh || exit 1 -BUILD_TEST_ENV_AUTO_CLEANUP=true -. "$setenv_script" "$@" || exit 1 - -try python "$(dirname "$0")"/python_test_v${API_VER}.py -pytest "$(dirname "$0")/functional/api" diff --git a/tools/reset_gitlab.py b/tools/reset_gitlab.py deleted file mode 100755 index 64668a974..000000000 --- a/tools/reset_gitlab.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -import sys - -from gitlab import Gitlab - - -def main(): - with Gitlab.from_config(config_files=["/tmp/python-gitlab.cfg"]) as gl: - for project in gl.projects.list(): - project.delete() - for group in gl.groups.list(): - group.delete() - for user in gl.users.list(): - if user.username != "root": - user.delete() - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tox.ini b/tox.ini index df7ca090f..92196e53e 100644 --- a/tox.ini +++ b/tox.ini @@ -55,7 +55,9 @@ commands = omit = *tests* [testenv:cli_func_v4] -commands = {toxinidir}/tools/functional_tests.sh -a 4 +deps = -r{toxinidir}/docker-requirements.txt +commands = pytest --script-launch-mode=subprocess tools/functional/cli {posargs} [testenv:py_func_v4] -commands = {toxinidir}/tools/py_functional_tests.sh -a 4 +deps = -r{toxinidir}/docker-requirements.txt +commands = pytest tools/functional/api {posargs}