Skip to content

Commit

Permalink
Load data and verify (#1983)
Browse files Browse the repository at this point in the history
* add load data and verify stages to check data integrity after upgrade or restore
No-Issue
  • Loading branch information
chr-stian authored Nov 20, 2023
1 parent eb6bc81 commit 87de28d
Show file tree
Hide file tree
Showing 7 changed files with 465 additions and 0 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ exclude docs_requirements.txt
exclude .readthedocs.yaml
include django-automated-logging-LICENSE.txt
include galaxy_ng/automated_logging/templates/dal/admin/view.html
include galaxy_ng/tests/integration/load_data.yaml
recursive-include galaxy_ng *.py
163 changes: 163 additions & 0 deletions galaxy_ng/tests/integration/api/test_load_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import logging
import json
import pytest

from galaxy_ng.tests.integration.conftest import is_hub_4_7_or_higher
from galaxy_ng.tests.integration.utils.iqe_utils import sign_collection_on_demand
from galaxy_ng.tests.integration.utils.repo_management_utils import create_repo_and_dist, \
upload_new_artifact
from galaxykit.collections import deprecate_collection, \
move_or_copy_collection
from galaxykit.containers import create_container, delete_container
from galaxykit.namespaces import add_group
from galaxykit.registries import create_registry, delete_registry
from galaxykit.remotes import create_remote, update_remote
from galaxykit.roles import put_update_role
from galaxykit.users import update_user
from galaxykit.utils import GalaxyClientError, wait_for_task

logger = logging.getLogger(__name__)


class TestLoadData:

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.load_data
def test_load_data(self, galaxy_client, data, ansible_config):
"""
Test loading data that will be verified at a later stage
after the AAP upgrade or backup/restore
"""
gc = galaxy_client("admin")

for group in data["groups"]:
# creates a group, nothing happens if it already exists
logger.debug(f"Creating group {group['name']}")
gc.create_group(group["name"])

for user in data["users"]:
# creates a user, nothing happens if it already exists
logger.debug(f"Creating user {user['username']}")
_user = gc.get_or_create_user(user["username"], user["password"], group=None)
update_body = {
"id": _user[1]["id"],
"username": user["username"],
"email": user["email"],
"password": user["password"],
"is_superuser": user["is_superuser"],
}
# if it exists, we should update it
update_user(gc, update_body)
if user["group"]:
group = gc.get_group(user["group"])
gc.add_user_to_group(user["username"], group["id"])

for ns in data["namespaces"]:
logger.debug(f"Creating namespace {ns['name']}")
gc.create_namespace(ns["name"], ns["group"],
object_roles=["galaxy.collection_namespace_owner"])
add_group(gc, ns["name"], ns["group"],
object_roles=["galaxy.collection_namespace_owner"])

if is_hub_4_7_or_higher(ansible_config):
for repo in data["repositories"]:
try:
logger.debug(f"Creating repository and distribution {repo['name']}")
create_repo_and_dist(gc, repo["name"])
except GalaxyClientError as e:
if "This field must be unique" in e.response.text:
logger.debug(
f"Repository {repo['name']} already exists. Not a problem.")
else:
raise e

for remote in data["remotes"]:
try:
logger.debug(f"Creating remote {remote['name']}")
create_remote(gc, remote["name"], remote["url"], remote["signed_only"],
remote["tls_validation"])
except GalaxyClientError as e:
if "This field must be unique" in e.response.text:
logger.debug(f"Remote {remote['name']} already exists. Updating it.")
# let's update it, maybe the yaml file wants to change the details
update_remote(gc, remote["name"], remote["url"],
{"signed_only": remote["signed_only"],
"tls_validation": remote["tls_validation"]})
else:
raise e

for collection in data["collections"]:
if (collection["repository"] != "published"
and not is_hub_4_7_or_higher(ansible_config)):
continue

try:
artifact = upload_new_artifact(
gc, collection["namespace"], collection["repository"],
collection["version"], collection["name"])
move_or_copy_collection(gc, artifact.namespace, artifact.name,
artifact.version, "staging",
destination=collection["repository"])
if collection["signed"]:
logger.debug("Signing collection")
sign_collection_on_demand(
gc, "ansible-default", collection["repository"],
artifact.namespace, artifact.name, artifact.version)
if collection["deprecated"]:
logger.debug("Deprecating collection")
deprecate_collection(gc, collection["namespace"], artifact.name,
repository=collection["repository"])
except GalaxyClientError as e:
if "already exists" in e.response.text:
logger.debug(f"Collection collection_dep_a_{collection['name']} "
f"already exists. Not doing anything")
else:
raise e

for role in data["roles"]:
name = role["name"]
description = role["description"]
permissions = role["permissions"]
try:
logger.debug(f"Creating role {role['name']}")
gc.create_role(name, description, permissions)
except GalaxyClientError as e:
if "This field must be unique" in e.response.text:
logger.debug(f"Role {role['name']} already exists. Updating it")
updated_body = {
"name": role["name"],
"description": description,
"permissions": permissions,
}
put_update_role(gc, name, updated_body)
else:
raise e

for remote_registry in data["remote_registries"]:
try:
logger.debug(f"Creating remote registry {remote_registry['name']}")
create_registry(gc, remote_registry["name"], remote_registry["url"])
except GalaxyClientError as e:
if "This field must be unique" in e.response.text:
logger.debug(f"Remote registry {remote_registry['name']} already exists. "
f"Updating it")
delete_registry(gc, remote_registry['name'])
create_registry(gc, remote_registry["name"], remote_registry["url"])
else:
raise e

for ee in data["execution_environments"]:
try:
logger.debug(f"Creating execution environment {ee['name']}")
create_container(gc, ee["name"], ee["upstream_name"], ee["remote_registry"])
except GalaxyClientError as e:
if "This field must be unique" in e.response.text:
logger.debug(f"Execution environment {ee['name']} already exists. "
f"Updating it")
delete_resp = delete_container(gc, ee["name"])
resp = json.loads(delete_resp.content.decode('utf-8'))
wait_for_task(gc, resp)
create_container(gc, ee["name"], ee["upstream_name"],
ee["remote_registry"])
else:
raise e
166 changes: 166 additions & 0 deletions galaxy_ng/tests/integration/api/test_verify_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import logging
import pytest

from galaxy_ng.tests.integration.conftest import is_hub_4_7_or_higher
from galaxy_ng.tests.integration.utils.iqe_utils import is_upgrade_from_aap23_hub46, \
galaxy_auto_sign_collections
from galaxy_ng.tests.integration.utils.repo_management_utils import search_collection_endpoint
from galaxykit.collections import collection_info
from galaxykit.groups import get_group_id
from galaxykit.namespaces import get_namespace
from galaxykit.registries import get_registry_pk
from galaxykit.remotes import view_remotes
from galaxykit.repositories import get_repository_href
from galaxykit.roles import get_role
from galaxykit.users import get_user

logger = logging.getLogger(__name__)

SKIP_MESSAGE = "Load data stage was run on AAP 2.3, without repository management"


class TestVerifyData:

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.verify_data
def test_verify_data_users(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for expected_user in data["users"]:
actual_user = get_user(gc, expected_user["username"])
assert expected_user["username"] == actual_user["username"]
assert expected_user["email"] == actual_user["email"]
assert expected_user["is_superuser"] == actual_user["is_superuser"]
assert expected_user["group"] in str(actual_user["groups"])

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.verify_data
def test_verify_data_ns(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for expected_ns in data["namespaces"]:
actual_ns = get_namespace(gc, expected_ns["name"])
assert expected_ns["name"] == actual_ns["name"]
assert expected_ns["group"] in str(actual_ns["groups"])

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.verify_data
def test_verify_data_collections(self, galaxy_client, data, ansible_config):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for expected_col in data["collections"]:
if (expected_col["repository"]
!= "published" and not is_hub_4_7_or_higher(
ansible_config)) or is_upgrade_from_aap23_hub46():
continue

expected_name = f"collection_dep_a_{expected_col['name']}"
actual_col = collection_info(gc, expected_col["repository"],
expected_col["namespace"], expected_name,
expected_col["version"])
assert actual_col["version"] == expected_col["version"]
assert actual_col["name"] == expected_name
assert actual_col["namespace"]["name"] == expected_col["namespace"]
if not galaxy_auto_sign_collections():
if expected_col["signed"]:
assert len(actual_col["signatures"]) > 0
else:
assert len(actual_col["signatures"]) == 0
else:
assert len(actual_col["signatures"]) > 0
if is_hub_4_7_or_higher(ansible_config):
_, actual_col = search_collection_endpoint(gc, name=expected_name)
assert actual_col[0]["is_deprecated"] == expected_col["deprecated"]
if galaxy_auto_sign_collections():
assert actual_col[0]["is_signed"] is True
else:
assert actual_col[0]["is_signed"] == expected_col["signed"]
assert actual_col[0]["cv_name"] == expected_name
assert actual_col[0]["cv_version"] == expected_col["version"]
assert actual_col[0]["repo_name"] == expected_col["repository"]

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.verify_data
def test_verify_data_groups(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for expected_group in data["groups"]:
get_group_id(gc, expected_group["name"])

@pytest.mark.min_hub_version("4.7dev")
@pytest.mark.skipif(is_upgrade_from_aap23_hub46(), reason=SKIP_MESSAGE)
@pytest.mark.verify_data
def test_verify_data_repos(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for expected_repo in data["repositories"]:
get_repository_href(gc, expected_repo["name"])

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.verify_data
def test_verify_data_rbac_roles(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for expected_rbac_role in data["roles"]:
role_info_1 = get_role(gc, expected_rbac_role["name"])
assert role_info_1["name"] == expected_rbac_role["name"]
assert role_info_1["description"] == expected_rbac_role["description"]
assert sorted(role_info_1["permissions"]) == sorted(
expected_rbac_role["permissions"])

@pytest.mark.min_hub_version("4.7dev")
@pytest.mark.verify_data
def test_verify_data_ee(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for ee in data["execution_environments"]:
# this needs to be moved to galaxykit
actual_ee = gc.get(f"v3/plugin/execution-environments/repositories/{ee['name']}/")
assert actual_ee["name"] == ee["name"]
assert (actual_ee["pulp"]["repository"]["remote"]["upstream_name"]
== ee["upstream_name"])
actual_registry = actual_ee["pulp"]["repository"]["remote"]["registry"]
expected_registry = get_registry_pk(gc, ee["remote_registry"])
assert expected_registry == actual_registry

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.verify_data
def test_verify_data_remote_registries(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for remote_registry in data["remote_registries"]:
# this needs to be moved to galaxykit
actual_rr = gc.get(f"_ui/v1/execution-environments/registries/"
f"?name={remote_registry['name']}")
assert actual_rr["data"][0]["name"] == remote_registry["name"]
assert actual_rr["data"][0]["url"] == remote_registry["url"]

@pytest.mark.min_hub_version("4.6dev")
@pytest.mark.verify_data
def test_verify_data_remotes(self, galaxy_client, data):
"""
Test that verifies the data previously loaded by test_load_data
"""
gc = galaxy_client("admin")
for remote in data["remotes"]:
actual_remote = view_remotes(gc, remote["name"])
assert actual_remote["results"][0]["url"] == remote["url"]
assert actual_remote["results"][0]["name"] == remote["name"]
assert actual_remote["results"][0]["signed_only"] == remote["signed_only"]
assert actual_remote["results"][0]["tls_validation"] == remote["tls_validation"]
16 changes: 16 additions & 0 deletions galaxy_ng/tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import os
import shutil
import yaml

import pytest
from orionutils.utils import increment_version
Expand Down Expand Up @@ -81,6 +82,8 @@
all: tests that are unmarked and should pass in all deployment modes
galaxy_stage_ansible: tests that run against galaxy-stage.ansible.com
installer_smoke_test: smoke tests to validate AAP installation (VM)
load_data: tests that load data that will be verified after upgrade or backup/restore
verify_data: tests that verify the data previously loaded by load_data test
"""

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -546,6 +549,14 @@ def keep_generated_test_artifact(ansible_config):
)


@pytest.fixture(scope="session")
def data():
path = 'galaxy_ng/tests/integration/load_data.yaml'
with open(path, 'r') as yaml_file:
data = yaml.safe_load(yaml_file)
return data


def min_hub_version(ansible_config, spec):
version = get_hub_version(ansible_config)
return Requirement.parse(f"galaxy_ng<{spec}").specifier.contains(version)
Expand All @@ -561,6 +572,11 @@ def is_hub_4_5(ansible_config):
return parse_version(hub_version) < parse_version('4.6')


def is_hub_4_7_or_higher(ansible_config):
hub_version = get_hub_version(ansible_config)
return parse_version(hub_version) >= parse_version('4.7')


# add the "all" label to any unmarked tests
def pytest_collection_modifyitems(items, config):
for item in items:
Expand Down
Loading

0 comments on commit 87de28d

Please sign in to comment.