summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorNejc Habjan <nejc.habjan@siemens.com>2020-09-05 00:15:04 +0200
committerNejc Habjan <nejc.habjan@siemens.com>2020-09-15 22:05:48 +0200
commit79489c775141c4ddd1f7aecae90dae8061d541fe (patch)
tree7c8f45e232049e0cad13af57e05b7ccbd8c6bb82 /tools
parent0d89a6e61bd4ae244c1545463272ef830d72dda9 (diff)
downloadgitlab-79489c775141c4ddd1f7aecae90dae8061d541fe.tar.gz
test(env): replace custom scripts with pytest and docker-compose
Diffstat (limited to 'tools')
-rwxr-xr-xtools/build_test_env.sh158
-rw-r--r--tools/functional/api/test_gitlab.py8
-rw-r--r--tools/functional/cli/conftest.py4
-rw-r--r--tools/functional/conftest.py99
-rwxr-xr-xtools/functional/ee-test.py (renamed from tools/ee-test.py)0
-rw-r--r--tools/functional/fixtures/avatar.png (renamed from tools/avatar.png)bin592 -> 592 bytes
-rw-r--r--tools/functional/fixtures/docker-compose.yml31
-rw-r--r--tools/functional/fixtures/set_token.rb9
-rw-r--r--tools/functional/python_test_v4.py (renamed from tools/python_test_v4.py)17
-rwxr-xr-xtools/functional_tests.sh21
-rwxr-xr-xtools/generate_token.py51
-rwxr-xr-xtools/py_functional_tests.sh22
-rwxr-xr-xtools/reset_gitlab.py20
13 files changed, 155 insertions, 285 deletions
diff --git a/tools/build_test_env.sh b/tools/build_test_env.sh
deleted file mode 100755
index a7b64b6..0000000
--- a/tools/build_test_env.sh
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/bin/sh
-# Copyright (C) 2016 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# 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 <http://www.gnu.org/licenses/>.
-
-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 0000000..5cf3418
--- /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 13c3096..ba94dcb 100644
--- a/tools/functional/cli/conftest.py
+++ b/tools/functional/cli/conftest.py
@@ -2,7 +2,7 @@ import pytest
@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(script_runner, CONFIG):
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 e60fa39..ec0d08b 100644
--- a/tools/functional/conftest.py
+++ b/tools/functional/conftest.py
@@ -1,6 +1,8 @@
+import time
import tempfile
from pathlib import Path
from random import randint
+from subprocess import check_output
import pytest
@@ -8,6 +10,7 @@ import gitlab
TEMP_DIR = tempfile.gettempdir()
+TEST_DIR = Path(__file__).resolve().parent
def random_id():
@@ -20,15 +23,103 @@ def random_id():
return randint(9, 9999)
+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):
+ set_token_rb = TEST_DIR / "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 CONFIG():
- return Path(TEMP_DIR) / "python-gitlab.cfg"
+def docker_compose_file():
+ return TEST_DIR / "fixtures" / "docker-compose.yml"
@pytest.fixture(scope="session")
-def gl(CONFIG):
+def check_is_alive(request):
+ """
+ Return a healthcheck function fixture for the GitLab container spinup.
+ """
+ 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 gitlab_config(check_is_alive, docker_ip, docker_services):
+ config_file = Path(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")
+
+ 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(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")
diff --git a/tools/ee-test.py b/tools/functional/ee-test.py
index 3f75655..3f75655 100755
--- a/tools/ee-test.py
+++ b/tools/functional/ee-test.py
diff --git a/tools/avatar.png b/tools/functional/fixtures/avatar.png
index a3a767c..a3a767c 100644
--- a/tools/avatar.png
+++ b/tools/functional/fixtures/avatar.png
Binary files differ
diff --git a/tools/functional/fixtures/docker-compose.yml b/tools/functional/fixtures/docker-compose.yml
new file mode 100644
index 0000000..5dd9d90
--- /dev/null
+++ b/tools/functional/fixtures/docker-compose.yml
@@ -0,0 +1,31 @@
+version: '3'
+services:
+ gitlab:
+ image: 'gitlab/gitlab-ce:latest'
+ 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 0000000..735dcd5
--- /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
index 7ff97b6..6c90fe6 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 @@ nxs4TLO3kZjUTgWKdhpgRNF5hwaz51ZjpebaRf/ZqRuNyX4lIRolDxzOn/+O1o8L
qG2ZdhHHmSK2LaQLFiSprUkikStNU9BqSQ==
=5OGa
-----END PGP PUBLIC KEY BLOCK-----"""
-AVATAR_PATH = os.path.join(os.path.dirname(__file__), "avatar.png")
-
+AVATAR_PATH = Path(__file__).resolve().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 @@ assert export.message == "202 Accepted"
# 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 @@ while ex.export_status != "finished":
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 9b91f0f..0000000
--- a/tools/functional_tests.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-# Copyright (C) 2015 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# 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 <http://www.gnu.org/licenses/>.
-
-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 89909bd..0000000
--- 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 1009cb9..0000000
--- a/tools/py_functional_tests.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-# Copyright (C) 2015 Gauvain Pocentek <gauvain@pocentek.net>
-#
-# 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 <http://www.gnu.org/licenses/>.
-
-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 64668a9..0000000
--- 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())