diff --git a/src/aap_eda/core/management/commands/create_initial_data.py b/src/aap_eda/core/management/commands/create_initial_data.py index 21ac944f8..382680563 100644 --- a/src/aap_eda/core/management/commands/create_initial_data.py +++ b/src/aap_eda/core/management/commands/create_initial_data.py @@ -1072,6 +1072,8 @@ def _copy_registry_credentials(self): if not credentials: return + default_organization = models.utils.get_default_organization() + cred_type = models.CredentialType.objects.filter( name=enums.DefaultCredentialType.REGISTRY ).first() @@ -1099,6 +1101,7 @@ def _copy_registry_credentials(self): "managed": False, "credential_type": cred_type, "inputs": inputs_to_store(inputs), + "organization": default_organization, }, ) if created: @@ -1126,6 +1129,8 @@ def _copy_scm_credentials(self): if not credentials: return + default_organization = models.utils.get_default_organization() + cred_type = models.CredentialType.objects.filter( name=enums.DefaultCredentialType.SOURCE_CONTROL ).first() @@ -1141,6 +1146,7 @@ def _copy_scm_credentials(self): "managed": False, "credential_type": cred_type, "inputs": inputs_to_store(inputs), + "organization": default_organization, }, ) if created: diff --git a/src/aap_eda/core/migrations/0051_alter_activation_organization_and_more.py b/src/aap_eda/core/migrations/0051_alter_activation_organization_and_more.py new file mode 100644 index 000000000..1b37ba2c4 --- /dev/null +++ b/src/aap_eda/core/migrations/0051_alter_activation_organization_and_more.py @@ -0,0 +1,77 @@ +# Generated by Django 4.2.7 on 2024-10-21 22:14 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0050_update_credential_type_help_text"), + ] + + operations = [ + migrations.AlterField( + model_name="activation", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="auditrule", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="decisionenvironment", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="edacredential", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="eventstream", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="project", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="rulebook", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + migrations.AlterField( + model_name="rulebookprocess", + name="organization", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="core.organization", + ), + ), + ] diff --git a/src/aap_eda/core/models/base.py b/src/aap_eda/core/models/base.py index a5428be62..3ed0ed9f4 100644 --- a/src/aap_eda/core/models/base.py +++ b/src/aap_eda/core/models/base.py @@ -14,8 +14,6 @@ from django.db import models -from .utils import get_default_organization_id - __all__ = ("BaseOrgModel", "UniqueNamedModel") @@ -28,7 +26,6 @@ class Meta: on_delete=models.CASCADE, blank=False, null=False, - default=get_default_organization_id, ) diff --git a/src/aap_eda/core/models/utils.py b/src/aap_eda/core/models/utils.py index b98fb22c6..60b98fdf4 100644 --- a/src/aap_eda/core/models/utils.py +++ b/src/aap_eda/core/models/utils.py @@ -17,5 +17,9 @@ from .organization import Organization +def get_default_organization(): + return Organization.objects.get(name=settings.DEFAULT_ORGANIZATION_NAME) + + def get_default_organization_id(): - return Organization.objects.get(name=settings.DEFAULT_ORGANIZATION_NAME).id + return get_default_organization().id diff --git a/tests/conftest.py b/tests/conftest.py index 733b762f5..37a44edac 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,7 +15,9 @@ import logging import pytest +from django.conf import settings +from aap_eda.core import models from aap_eda.settings import default @@ -32,6 +34,18 @@ def _factory(logger): return _factory +################################################################# +# Organization +################################################################# +@pytest.fixture +def default_organization() -> models.Organization: + "Corresponds to migration add_default_organization" + return models.Organization.objects.get_or_create( + name=settings.DEFAULT_ORGANIZATION_NAME, + description="The default organization", + )[0] + + ################################################################# # Redis ################################################################# diff --git a/tests/integration/api/test_activation_with_credential.py b/tests/integration/api/test_activation_with_credential.py index 01157d8da..579a70fe9 100644 --- a/tests/integration/api/test_activation_with_credential.py +++ b/tests/integration/api/test_activation_with_credential.py @@ -403,11 +403,13 @@ def test_create_activation_with_conflict_credentials( name="credential-1", inputs={"sasl_username": "adam", "sasl_password": "secret"}, credential_type_id=user_credential_type.id, + organization_id=default_organization.id, ), models.EdaCredential( name="credential-2", inputs={"sasl_username": "bearny", "sasl_password": "demo"}, credential_type_id=user_credential_type.id, + organization_id=default_organization.id, ), ] ) diff --git a/tests/integration/api/test_credential_type.py b/tests/integration/api/test_credential_type.py index b2f4d9028..a3c0301d7 100644 --- a/tests/integration/api/test_credential_type.py +++ b/tests/integration/api/test_credential_type.py @@ -297,7 +297,9 @@ def test_delete_credential_type(superuser_client: APIClient): @pytest.mark.django_db def test_delete_credential_type_with_credentials( - superuser_client: APIClient, preseed_credential_types + superuser_client: APIClient, + default_organization: models.Organization, + preseed_credential_types, ): credential_type = models.CredentialType.objects.create( name="user_type", @@ -310,6 +312,7 @@ def test_delete_credential_type_with_credentials( name="credential-1", inputs={"username": "adam"}, credential_type=credential_type, + organization=default_organization, ) response = superuser_client.delete( @@ -491,6 +494,7 @@ def test_update_managed_credential_type( ) def test_update_credential_type_with_created_credentials( superuser_client: APIClient, + default_organization: models.Organization, preseed_credential_types, data, status_code, @@ -507,6 +511,7 @@ def test_update_credential_type_with_created_credentials( name="test-eda-credential", inputs={"username": "adam"}, credential_type_id=user_type.id, + organization=default_organization, ) response = superuser_client.patch( diff --git a/tests/integration/api/test_decision_environment.py b/tests/integration/api/test_decision_environment.py index 73b49d7f1..3192fc31f 100644 --- a/tests/integration/api/test_decision_environment.py +++ b/tests/integration/api/test_decision_environment.py @@ -66,6 +66,7 @@ def test_create_decision_environment( name="eda-credential", description="Default Credential", credential_type=credential_type, + organization=default_organization, inputs=inputs_to_store( { "username": "dummy-user", @@ -144,6 +145,7 @@ def test_create_decision_environment_with_empty_credential( description="Default Credential", credential_type=credential_type, inputs=inputs_to_store(credential_inputs), + organization=default_organization, ) data_in = { "name": "de1", @@ -237,6 +239,7 @@ def test_retrieve_decision_environment_not_exist(admin_client: APIClient): def test_partial_update_decision_environment( default_decision_environment: models.DecisionEnvironment, admin_client: APIClient, + default_organization: models.Organization, preseed_credential_types, credential_type, status_code, @@ -247,6 +250,7 @@ def test_partial_update_decision_environment( name="eda-credential", description="Default Credential", credential_type=credential_type, + organization=default_organization, inputs=inputs_to_store( { "username": "dummy-user", @@ -292,6 +296,7 @@ def test_partial_update_decision_environment( @pytest.mark.django_db def test_partial_update_decision_environment_with_image_url_and_host( default_decision_environment: models.DecisionEnvironment, + default_organization: models.Organization, admin_client: APIClient, preseed_credential_types, inputs, @@ -306,6 +311,7 @@ def test_partial_update_decision_environment_with_image_url_and_host( description="Default Credential", credential_type=credential_type, inputs=inputs_to_store(inputs), + organization=default_organization, ) data = {"eda_credential_id": credential.id, "image_url": "quay.io"} response = admin_client.patch( diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 89e18b974..e16aa81b2 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -316,7 +316,9 @@ def default_rulebook( @pytest.fixture def bad_rulebook( - default_project: models.Project, bad_rulesets: str + default_project: models.Project, + default_organization: models.Organization, + bad_rulesets: str, ) -> models.Rulebook: """Return a bad Rulebook.""" return models.Rulebook.objects.create( @@ -324,12 +326,15 @@ def bad_rulebook( rulesets=bad_rulesets, description="test bad rulebook", project=default_project, + organization=default_organization, ) @pytest.fixture def default_rulebook_with_run_job_template( - default_project: models.Project, default_run_job_template_rulesets: str + default_project: models.Project, + default_organization: models.Organization, + default_run_job_template_rulesets: str, ) -> models.Rulebook: """Return a default Rulebook with run_job_template action""" return models.Rulebook.objects.create( @@ -337,6 +342,7 @@ def default_rulebook_with_run_job_template( rulesets=default_run_job_template_rulesets, description="test rulebook", project=default_project, + organization=default_organization, ) @@ -360,13 +366,16 @@ def ruleset_with_job_template() -> str: @pytest.fixture def rulebook_with_job_template( - default_project: models.Project, ruleset_with_job_template: str + default_project: models.Project, + default_organization: models.Organization, + ruleset_with_job_template: str, ) -> models.Rulebook: rulebook = models.Rulebook.objects.create( name="job-template.yml", description="rulebook with job template", rulesets=ruleset_with_job_template, project=default_project, + organization=default_organization, ) return rulebook @@ -430,7 +439,9 @@ def default_rule(ruleset_1: models.Ruleset) -> models.Rule: ################################################################# @pytest.fixture def default_activation_instance( - default_activation: models.Activation, default_project: models.Project + default_activation: models.Activation, + default_project: models.Project, + default_organization: models.Organization, ) -> models.RulebookProcess: """Return a list of Activation Instances""" instance = models.RulebookProcess.objects.create( @@ -441,6 +452,7 @@ def default_activation_instance( status_message=enums.ACTIVATION_STATUS_MESSAGE_MAP[ enums.ActivationStatus.COMPLETED ], + organization=default_organization, ) models.RulebookProcessQueue.objects.create( @@ -454,6 +466,7 @@ def default_activation_instance( @pytest.fixture def default_audit_rule( default_activation_instance: models.RulebookProcess, + default_organization: models.Organization, ) -> models.AuditRule: return models.AuditRule.objects.create( name="default audit rule", @@ -462,12 +475,14 @@ def default_audit_rule( ruleset_uuid=DUMMY_UUID, ruleset_name="test-audit-ruleset-name-1", activation_instance=default_activation_instance, + organization=default_organization, ) @pytest.fixture def audit_rule_1( default_activation_instances: List[models.RulebookProcess], + default_organization: models.Organization, ) -> models.AuditRule: return models.AuditRule.objects.create( name="rule with 1 action", @@ -476,12 +491,14 @@ def audit_rule_1( ruleset_uuid=DUMMY_UUID, ruleset_name="test-audit-ruleset-name-1", activation_instance=default_activation_instances[0], + organization=default_organization, ) @pytest.fixture def audit_rule_2( new_activation_instance: models.RulebookProcess, + default_organization: models.Organization, ) -> models.AuditRule: return models.AuditRule.objects.create( name="rule with 2 actions/events", @@ -490,6 +507,7 @@ def audit_rule_2( ruleset_uuid=DUMMY_UUID, ruleset_name="test-audit-ruleset-name-2", activation_instance=new_activation_instance, + organization=default_organization, ) @@ -684,7 +702,9 @@ def new_activation( @pytest.fixture def default_activation_instances( - default_activation: models.Activation, default_project: models.Project + default_activation: models.Activation, + default_project: models.Project, + default_organization: models.Organization, ) -> models.RulebookProcess: """Return a list of Activation Instances""" instances = models.RulebookProcess.objects.bulk_create( @@ -697,6 +717,7 @@ def default_activation_instances( status_message=enums.ACTIVATION_STATUS_MESSAGE_MAP[ enums.ActivationStatus.COMPLETED ], + organization=default_organization, ), models.RulebookProcess( name="default-activation-instance-2", @@ -706,6 +727,7 @@ def default_activation_instances( status_message=enums.ACTIVATION_STATUS_MESSAGE_MAP[ enums.ActivationStatus.FAILED ], + organization=default_organization, ), ] ) @@ -721,7 +743,9 @@ def default_activation_instances( @pytest.fixture def new_activation_instance( - new_activation: models.Activation, default_project: models.Project + new_activation: models.Activation, + default_project: models.Project, + default_organization: models.Organization, ) -> models.RulebookProcess: """Return an Activation Instance for new_activation fixture""" return models.RulebookProcess.objects.create( @@ -732,6 +756,7 @@ def new_activation_instance( status_message=enums.ACTIVATION_STATUS_MESSAGE_MAP[ enums.ActivationStatus.COMPLETED ], + organization=default_organization, ) @@ -1040,15 +1065,6 @@ def default_gpg_credential( ################################################################# # Organizations and Teams ################################################################# -@pytest.fixture -def default_organization() -> models.Organization: - "Corresponds to migration add_default_organization" - return models.Organization.objects.get_or_create( - name=settings.DEFAULT_ORGANIZATION_NAME, - description="The default organization", - )[0] - - @pytest.fixture def new_organization() -> models.Organization: "Return a new organization" diff --git a/tests/integration/core/conftest.py b/tests/integration/core/conftest.py index 04bb11307..8e2ed0b08 100644 --- a/tests/integration/core/conftest.py +++ b/tests/integration/core/conftest.py @@ -17,16 +17,18 @@ @pytest.fixture() -def new_activation(new_user): +def new_activation(new_user, default_organization): return models.Activation.objects.create( name="activation", user=new_user, + organization=default_organization, ) @pytest.fixture() -def new_rulebook_process_with_activation(new_activation): +def new_rulebook_process_with_activation(new_activation, default_organization): return models.RulebookProcess.objects.create( name="test-instance", activation=new_activation, + organization=default_organization, ) diff --git a/tests/integration/core/test_create_initial_data.py b/tests/integration/core/test_create_initial_data.py index 59f6b9351..a115d6574 100644 --- a/tests/integration/core/test_create_initial_data.py +++ b/tests/integration/core/test_create_initial_data.py @@ -92,7 +92,7 @@ def test_remove_extra_permission(): ################################################################# # Credentials ################################################################# -def create_old_registry_credential(): +def create_old_registry_credential(default_organization: models.Organization): credential = models.Credential.objects.create( name="registry cred", credential_type=enums.CredentialType.REGISTRY, @@ -103,11 +103,12 @@ def create_old_registry_credential(): name="my DE", image_url="private-reg.com/fred/de", credential=credential, + organization=default_organization, ) return credential, de -def create_old_git_credential(): +def create_old_git_credential(default_organization: models.Organization): credential = models.Credential.objects.create( name="git cred", credential_type=enums.CredentialType.GITHUB, @@ -118,13 +119,16 @@ def create_old_git_credential(): name="my project", url="github.com/fred/projects", credential=credential, + organization=default_organization, ) return credential, project @pytest.mark.django_db -def test_copy_registry_credentials(caplog): - credential, de = create_old_registry_credential() +def test_copy_registry_credentials( + default_organization: models.Organization, caplog +): + credential, de = create_old_registry_credential(default_organization) Command().handle() assert not models.Credential.objects.filter(id=credential.id).exists() @@ -143,8 +147,10 @@ def test_copy_registry_credentials(caplog): @pytest.mark.django_db -def test_copy_project_credentials(caplog): - credential, project = create_old_git_credential() +def test_copy_project_credentials( + default_organization: models.Organization, caplog +): + credential, project = create_old_git_credential(default_organization) Command().handle() assert not models.Credential.objects.filter(id=credential.id).exists() diff --git a/tests/integration/core/test_process_parent.py b/tests/integration/core/test_process_parent.py index 61052889b..483ed3628 100644 --- a/tests/integration/core/test_process_parent.py +++ b/tests/integration/core/test_process_parent.py @@ -30,13 +30,16 @@ ], ) @pytest.mark.django_db -def test_latest_instance_field(instance): +def test_latest_instance_field( + default_organization: models.Organization, instance +): """Test latest_instance field is updated when a new instance is created.""" assert instance.latest_instance is None kwargs = { "name": "test-instance", "status": ActivationStatus.PENDING, + "organization": default_organization, } if isinstance(instance, models.Activation): diff --git a/tests/integration/core/test_rulebook_process.py b/tests/integration/core/test_rulebook_process.py index 2a07ee2d0..bf8a9ff80 100644 --- a/tests/integration/core/test_rulebook_process.py +++ b/tests/integration/core/test_rulebook_process.py @@ -25,7 +25,7 @@ @pytest.fixture() -def init_data(): +def init_data(default_organization: models.Organization): user = models.User.objects.create( username="tester", password="secret", @@ -36,10 +36,12 @@ def init_data(): activation = models.Activation.objects.create( name="activation", user=user, + organization=default_organization, ) return models.RulebookProcess.objects.create( name="test-instance", activation=activation, + organization=default_organization, ) diff --git a/tests/integration/services/activation/conftest.py b/tests/integration/services/activation/conftest.py index 6ea3921ca..ac5b46879 100644 --- a/tests/integration/services/activation/conftest.py +++ b/tests/integration/services/activation/conftest.py @@ -19,16 +19,21 @@ @pytest.fixture -def default_decision_environment() -> models.DecisionEnvironment: +def default_decision_environment( + default_organization, +) -> models.DecisionEnvironment: """Return a default decision environment.""" return models.DecisionEnvironment.objects.create( name="test-decision-environment", image_url="localhost:14000/test-image-url", + organization=default_organization, ) @pytest.fixture -def default_rulebook() -> models.Rulebook: +def default_rulebook( + default_organization: models.Organization, +) -> models.Rulebook: """Return a default rulebook.""" rulesets = """ --- @@ -48,6 +53,7 @@ def default_rulebook() -> models.Rulebook: return models.Rulebook.objects.create( name="test-rulebook", rulesets=rulesets, + organization=default_organization, ) diff --git a/tests/integration/services/activation/engine/conftest.py b/tests/integration/services/activation/engine/conftest.py new file mode 100644 index 000000000..7b7525813 --- /dev/null +++ b/tests/integration/services/activation/engine/conftest.py @@ -0,0 +1,65 @@ +# Copyright 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Common Attributes for Engine Tests.""" + +import pytest +from dateutil import parser + +from aap_eda.core import models + +from .utils import InitData + + +def _common_data( + default_organization: models.Organization, + k8s_service_name: str = None, +) -> InitData: + user = models.User.objects.create( + username="tester", + password="secret", + first_name="Adam", + last_name="Tester", + email="adam@example.com", + ) + activation = models.Activation.objects.create( + name="activation", + k8s_service_name=k8s_service_name, + user=user, + organization=default_organization, + ) + activation_instance = models.RulebookProcess.objects.create( + name="test-instance", + log_read_at=parser.parse("2023-10-30T19:18:48.362883381Z"), + activation=activation, + organization=default_organization, + ) + + return InitData( + activation=activation, + activation_instance=activation_instance, + ) + + +@pytest.fixture() +def init_kubernetes_data( + default_organization: models.Organization, +) -> InitData: + return _common_data(default_organization, "test_k8s_service") + + +@pytest.fixture() +def init_podman_data( + default_organization: models.Organization, +) -> InitData: + return _common_data(default_organization) diff --git a/tests/integration/services/activation/engine/test_kubernetes.py b/tests/integration/services/activation/engine/test_kubernetes.py index 05ad3e47a..90f7bb1f5 100644 --- a/tests/integration/services/activation/engine/test_kubernetes.py +++ b/tests/integration/services/activation/engine/test_kubernetes.py @@ -12,11 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from dataclasses import dataclass from unittest import mock import pytest -from dateutil import parser from kubernetes import client as k8sclient from kubernetes.client.rest import ApiException from kubernetes.config.config_exception import ConfigException @@ -24,11 +22,6 @@ from aap_eda.core import models from aap_eda.core.enums import ActivationStatus, ProcessParentType from aap_eda.services.activation.db_log_handler import DBLogger -from aap_eda.services.activation.engine.common import ( - AnsibleRulebookCmdLine, - ContainerRequest, - Credential, -) from aap_eda.services.activation.engine.exceptions import ( ContainerCleanupError, ContainerEngineError, @@ -46,68 +39,7 @@ get_k8s_client, ) - -@dataclass -class InitData: - activation: models.Activation - activation_instance: models.RulebookProcess - - -@pytest.fixture() -def init_data(): - user = models.User.objects.create( - username="tester", - password="secret", - first_name="Adam", - last_name="Tester", - email="adam@example.com", - ) - activation = models.Activation.objects.create( - name="activation", - k8s_service_name="test_k8s_service", - user=user, - ) - activation_instance = models.RulebookProcess.objects.create( - name="test-instance", - log_read_at=parser.parse("2023-10-30T19:18:48.362883381Z"), - activation=activation, - ) - - return InitData( - activation=activation, - activation_instance=activation_instance, - ) - - -def get_ansible_rulebook_cmdline(data: InitData): - return AnsibleRulebookCmdLine( - ws_url="ws://localhost:8000/api/eda/ws/ansible-rulebook", - ws_ssl_verify="no", - ws_token_url="http://localhost:8000/api/eda/v1/auth/token/refresh", - ws_access_token="access", - ws_refresh_token="refresh", - id=data.activation.id, - log_level="-v", - heartbeat=5, - ) - - -def get_request(data: InitData): - return ContainerRequest( - name="test-request", - image_url="quay.io/ansible/ansible-rulebook:main", - rulebook_process_id=data.activation_instance.id, - process_parent_id=data.activation.id, - cmdline=get_ansible_rulebook_cmdline(data), - credential=Credential( - username="admin", secret="secret", ssl_verify=True - ), - ports=[("localhost", 8080)], - mem_limit="8G", - env_vars={"a": 1}, - extra_args={"b": 2}, - k8s_service_name=data.activation.k8s_service_name, - ) +from .utils import get_request def get_container_state(phase: str): @@ -266,8 +198,8 @@ def get_pod_statuses_with_exit_code(exit_code: int): @pytest.fixture -def kubernetes_engine(init_data): - activation_id = init_data.activation.id +def kubernetes_engine(init_kubernetes_data): + activation_id = init_kubernetes_data.activation.id with mock.patch("builtins.open", mock.mock_open(read_data="aap-eda")): engine = Engine( activation_id=str(activation_id), @@ -285,8 +217,8 @@ def kubernetes_engine(init_data): ], ) @pytest.mark.django_db -def test_engine_init(init_data, resource_prefixes): - activation_id = init_data.activation.id +def test_engine_init(init_kubernetes_data, resource_prefixes): + activation_id = init_kubernetes_data.activation.id with mock.patch("builtins.open", mock.mock_open(read_data="aap-eda")): for prefix in resource_prefixes: engine = Engine( @@ -303,8 +235,8 @@ def test_engine_init(init_data, resource_prefixes): @pytest.mark.django_db -def test_engine_init_with_exception(init_data): - activation_id = init_data.activation.id +def test_engine_init_with_exception(init_kubernetes_data): + activation_id = init_kubernetes_data.activation.id with pytest.raises( ContainerEngineInitError, match=( @@ -342,10 +274,19 @@ def raise_config_exception(*args, **kwargs): @pytest.mark.django_db -def test_engine_start(init_data, kubernetes_engine): +def test_engine_start( + init_kubernetes_data, + kubernetes_engine, + default_organization: models.Organization, +): engine = kubernetes_engine - request = get_request(init_data) - log_handler = DBLogger(init_data.activation_instance.id) + request = get_request( + init_kubernetes_data, + "admin", + default_organization, + k8s_service_name=init_kubernetes_data.activation.k8s_service_name, + ) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) with mock.patch("aap_eda.services.activation.engine.kubernetes.watch"): with mock.patch.object(engine.client, "core_api") as core_api_mock: @@ -353,12 +294,12 @@ def test_engine_start(init_data, kubernetes_engine): engine.start(request, log_handler) assert engine.job_name == ( - f"activation-job-{init_data.activation.id}-" - f"{init_data.activation_instance.id}" + f"activation-job-{init_kubernetes_data.activation.id}-" + f"{init_kubernetes_data.activation_instance.id}" ) assert engine.pod_name == ( - f"activation-pod-{init_data.activation.id}-" - f"{init_data.activation_instance.id}" + f"activation-pod-{init_kubernetes_data.activation.id}-" + f"{init_kubernetes_data.activation_instance.id}" ) assert models.RulebookProcessLog.objects.count() == 5 @@ -368,10 +309,19 @@ def test_engine_start(init_data, kubernetes_engine): @pytest.mark.django_db -def test_engine_start_with_create_job_exception(init_data, kubernetes_engine): +def test_engine_start_with_create_job_exception( + init_kubernetes_data, + kubernetes_engine, + default_organization: models.Organization, +): engine = kubernetes_engine - request = get_request(init_data) - log_handler = DBLogger(init_data.activation_instance.id) + request = get_request( + init_kubernetes_data, + "admin", + default_organization, + k8s_service_name=init_kubernetes_data.activation.k8s_service_name, + ) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) def raise_api_error(*args, **kwargs): raise ApiException("Job create error") @@ -385,10 +335,19 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_start_with_pod_status(init_data, kubernetes_engine): +def test_engine_start_with_pod_status( + init_kubernetes_data, + kubernetes_engine, + default_organization: models.Organization, +): engine = kubernetes_engine - request = get_request(init_data) - log_handler = DBLogger(init_data.activation_instance.id) + request = get_request( + init_kubernetes_data, + "admin", + default_organization, + k8s_service_name=init_kubernetes_data.activation.k8s_service_name, + ) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) with mock.patch.object(engine.client, "core_api") as core_api_mock: core_api_mock.list_namespaced_service.return_value.items = None @@ -422,11 +381,19 @@ def test_engine_start_with_pod_status(init_data, kubernetes_engine): ) @pytest.mark.django_db def test_engine_start_with_invalid_image_exception( - init_data, kubernetes_engine, image_reasons + init_kubernetes_data, + kubernetes_engine, + image_reasons, + default_organization: models.Organization, ): engine = kubernetes_engine - request = get_request(init_data) - log_handler = DBLogger(init_data.activation_instance.id) + request = get_request( + init_kubernetes_data, + "admin", + default_organization, + k8s_service_name=init_kubernetes_data.activation.k8s_service_name, + ) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) with mock.patch( "aap_eda.services.activation.engine.kubernetes.watch" @@ -492,9 +459,9 @@ def test_get_status_with_exit_codes(kubernetes_engine, exit_codes): @pytest.mark.django_db -def test_delete_secret(init_data, kubernetes_engine): +def test_delete_secret(init_kubernetes_data, kubernetes_engine): engine = kubernetes_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) status_mock = mock.Mock() with mock.patch.object(engine.client, "core_api") as core_api_mock: @@ -527,10 +494,10 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db -def test_delete_service(init_data, kubernetes_engine): +def test_delete_service(init_kubernetes_data, kubernetes_engine): engine = kubernetes_engine engine.job_name = "activation-job" - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) service_name = "eda-service" service_mock = mock.Mock() service_mock.metadata.name = service_name @@ -562,11 +529,11 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db -def test_delete_job(init_data, kubernetes_engine): +def test_delete_job(init_kubernetes_data, kubernetes_engine): engine = kubernetes_engine job_name = "eda-job" engine.job_name = job_name - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) job_mock = mock.Mock() job_mock.metadata.name = job_name @@ -587,11 +554,11 @@ def test_delete_job(init_data, kubernetes_engine): @pytest.mark.django_db -def test_delete_job_with_exception(init_data, kubernetes_engine): +def test_delete_job_with_exception(init_kubernetes_data, kubernetes_engine): engine = kubernetes_engine job_name = "eda-job" engine.job_name = job_name - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) job_mock = mock.Mock() job_mock.metadata.name = job_name @@ -614,9 +581,9 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db -def test_cleanup(init_data, kubernetes_engine): +def test_cleanup(init_kubernetes_data, kubernetes_engine): engine = kubernetes_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) job_name = "eda-job" with mock.patch.object(engine, "_delete_secret") as secret_mock: @@ -633,10 +600,10 @@ def test_cleanup(init_data, kubernetes_engine): @pytest.mark.django_db -def test_update_logs(init_data, kubernetes_engine): +def test_update_logs(init_kubernetes_data, kubernetes_engine): engine = kubernetes_engine - log_handler = DBLogger(init_data.activation_instance.id) - init_log_read_at = init_data.activation_instance.log_read_at + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) + init_log_read_at = init_kubernetes_data.activation_instance.log_read_at job_name = "eda-job" pod_mock = mock.Mock() @@ -666,8 +633,11 @@ def test_update_logs(init_data, kubernetes_engine): engine.update_logs(job_name, log_handler) assert models.RulebookProcessLog.objects.last().log == f"{message}" - init_data.activation_instance.refresh_from_db() - assert init_data.activation_instance.log_read_at > init_log_read_at + init_kubernetes_data.activation_instance.refresh_from_db() + assert ( + init_kubernetes_data.activation_instance.log_read_at + > init_log_read_at + ) def raise_api_error(*args, **kwargs): raise ApiException("Container not found") @@ -690,7 +660,7 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db -def test_get_job_pod(init_data, kubernetes_engine): +def test_get_job_pod(init_kubernetes_data, kubernetes_engine): engine = kubernetes_engine pods_mock = mock.Mock() pod = get_pod("running") @@ -722,10 +692,19 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db -def test_create_service(init_data, kubernetes_engine): +def test_create_service( + init_kubernetes_data, + kubernetes_engine, + default_organization: models.Organization, +): engine = kubernetes_engine engine.job_name = "eda-job" - request = get_request(init_data) + request = get_request( + init_kubernetes_data, + "admin", + default_organization, + k8s_service_name=init_kubernetes_data.activation.k8s_service_name, + ) with mock.patch.object(engine.client, "core_api") as core_api_mock: core_api_mock.list_namespaced_service.return_value.items = None @@ -744,11 +723,20 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db -def test_create_secret(init_data, kubernetes_engine): +def test_create_secret( + init_kubernetes_data, + kubernetes_engine, + default_organization: models.Organization, +): engine = kubernetes_engine engine.job_name = "eda-job" - request = get_request(init_data) - log_handler = DBLogger(init_data.activation_instance.id) + request = get_request( + init_kubernetes_data, + "admin", + default_organization, + k8s_service_name=init_kubernetes_data.activation.k8s_service_name, + ) + log_handler = DBLogger(init_kubernetes_data.activation_instance.id) def raise_api_error(*args, **kwargs): raise ApiException("Secret create error") diff --git a/tests/integration/services/activation/engine/test_podman.py b/tests/integration/services/activation/engine/test_podman.py index 3ae5dcc7b..c26f0a29a 100644 --- a/tests/integration/services/activation/engine/test_podman.py +++ b/tests/integration/services/activation/engine/test_podman.py @@ -13,12 +13,10 @@ # limitations under the License. import os -from dataclasses import dataclass from pathlib import Path from unittest import mock import pytest -from dateutil import parser from podman import PodmanClient from podman.errors import ContainerError, ImageNotFound from podman.errors.exceptions import APIError, NotFound @@ -29,7 +27,6 @@ from aap_eda.services.activation.db_log_handler import DBLogger from aap_eda.services.activation.engine import messages from aap_eda.services.activation.engine.common import ( - AnsibleRulebookCmdLine, ContainerRequest, Credential, ) @@ -44,70 +41,15 @@ ) from aap_eda.services.activation.engine.podman import Engine, get_podman_client -DATA_DIR = Path(__file__).parent / "data" - - -@dataclass -class InitData: - activation: models.Activation - activation_instance: models.RulebookProcess - - -@pytest.fixture() -def init_data(): - user = models.User.objects.create( - username="tester", - password="secret", - first_name="Adam", - last_name="Tester", - email="adam@example.com", - ) - activation = models.Activation.objects.create( - name="activation", - user=user, - ) - activation_instance = models.RulebookProcess.objects.create( - name="test-instance", - log_read_at=parser.parse("2023-10-30T19:18:48.362883381Z"), - activation=activation, - ) - - return InitData( - activation=activation, - activation_instance=activation_instance, - ) - - -def get_ansible_rulebook_cmdline(data: InitData): - return AnsibleRulebookCmdLine( - ws_url="ws://localhost:8000/api/eda/ws/ansible-rulebook", - ws_ssl_verify="no", - ws_token_url="http://localhost:8000/api/eda/v1/auth/token/refresh", - ws_access_token="access", - ws_refresh_token="refresh", - id=data.activation.id, - log_level="-v", - heartbeat=5, - ) +from .utils import InitData, get_ansible_rulebook_cmdline, get_request - -def get_request(data: InitData): - return ContainerRequest( - name="test-request", - image_url="quay.io/ansible/ansible-rulebook:main", - rulebook_process_id=data.activation_instance.id, - process_parent_id=data.activation.id, - cmdline=get_ansible_rulebook_cmdline(data), - ports=[("localhost", 8080)], - mem_limit="8G", - mounts=[{"/dev": "/opt"}], - env_vars={"a": 1}, - extra_args={"b": 2}, - credential=Credential(username="me", secret="secret", ssl_verify=True), - ) +DATA_DIR = Path(__file__).parent / "data" -def get_request_with_never_pull_policy(data: InitData): +def get_request_with_never_pull_policy( + data: InitData, + default_organization: models.Organization, +): return ContainerRequest( name="test-request", image_url="quay.io/ansible/ansible-rulebook:main", @@ -115,18 +57,31 @@ def get_request_with_never_pull_policy(data: InitData): process_parent_id=data.activation.id, cmdline=get_ansible_rulebook_cmdline(data), pull_policy="Never", - credential=Credential(username="me", secret="secret", ssl_verify=True), + credential=Credential( + username="me", + secret="secret", + ssl_verify=True, + organization=default_organization, + ), ) -def get_request_with_credential(data: InitData): +def get_request_with_credential( + default_organization: models.Organization, + data: InitData, +): return ContainerRequest( name="test-request", image_url="quay.io/ansible/ansible-rulebook:main", rulebook_process_id=data.activation_instance.id, process_parent_id=data.activation.id, cmdline=get_ansible_rulebook_cmdline(data), - credential=Credential(username="me", secret="secret", ssl_verify=True), + credential=Credential( + username="me", + secret="secret", + ssl_verify=True, + organization=default_organization, + ), ) @@ -136,8 +91,8 @@ def use_dummy_socket_url(settings): @pytest.fixture -def podman_engine(init_data): - activation_id = init_data.activation.id +def podman_engine(init_podman_data): + activation_id = init_podman_data.activation.id with mock.patch( "aap_eda.services.activation.engine.podman.PodmanClient" ) as client_mock: @@ -183,16 +138,16 @@ def raise_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_init(init_data): - activation_id = init_data.activation.id +def test_engine_init(init_podman_data): + activation_id = init_podman_data.activation.id with mock.patch("aap_eda.services.activation.engine.podman.PodmanClient"): engine = Engine(_activation_id=str(activation_id)) engine.client.version.assert_called_once() @pytest.mark.django_db -def test_engine_init_with_exception(init_data): - activation_id = init_data.activation.id +def test_engine_init_with_exception(init_podman_data): + activation_id = init_podman_data.activation.id with pytest.raises( ContainerEngineInitError, match=r"http://socket_url/", @@ -201,10 +156,19 @@ def test_engine_init_with_exception(init_data): @pytest.mark.django_db -def test_engine_start(init_data, podman_engine): +def test_engine_start( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - request = get_request(init_data) - log_handler = DBLogger(init_data.activation_instance.id) + request = get_request( + init_podman_data, + "me", + default_organization, + mounts=[{"/dev": "/opt"}], + ) + log_handler = DBLogger(init_podman_data.activation_instance.id) engine.start(request, log_handler) @@ -214,10 +178,16 @@ def test_engine_start(init_data, podman_engine): @pytest.mark.django_db -def test_engine_start_with_none_image_url(init_data, podman_engine): +def test_engine_start_with_none_image_url( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - request = get_request(init_data) + log_handler = DBLogger(init_podman_data.activation_instance.id) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) request.image_url = None with pytest.raises(ContainerStartError): @@ -225,11 +195,22 @@ def test_engine_start_with_none_image_url(init_data, podman_engine): @pytest.mark.django_db -def test_engine_start_with_credential(init_data, podman_engine): +def test_engine_start_with_credential( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - request = get_request(init_data) - credential = Credential(username="me", secret="secret", ssl_verify=True) + log_handler = DBLogger(init_podman_data.activation_instance.id) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) + credential = Credential( + username="me", + secret="secret", + ssl_verify=True, + organization=default_organization, + ) request.credential = credential engine.start(request, log_handler) @@ -259,10 +240,21 @@ def test_engine_start_with_credential(init_data, podman_engine): @pytest.mark.django_db -def test_engine_start_with_login_api_exception(init_data, podman_engine): - credential = Credential(username="me", secret="sec1", ssl_verify=True) +def test_engine_start_with_login_api_exception( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): + credential = Credential( + username="me", + secret="sec1", + ssl_verify=True, + organization=default_organization, + ) engine = podman_engine - request = get_request(init_data) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) request.credential = credential def raise_error(*args, **kwargs): @@ -275,10 +267,16 @@ def raise_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_start_with_image_not_found_exception(init_data, podman_engine): +def test_engine_start_with_image_not_found_exception( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - request = get_request(init_data) + log_handler = DBLogger(init_podman_data.activation_instance.id) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) def raise_not_found_error(*args, **kwargs): raise ImageNotFound("Image not found") @@ -296,10 +294,16 @@ def raise_not_found_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_start_with_image_api_exception(init_data, podman_engine): +def test_engine_start_with_image_api_exception( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - request = get_request(init_data) + log_handler = DBLogger(init_podman_data.activation_instance.id) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) def raise_api_error(*args, **kwargs): raise APIError("Image not found") @@ -312,11 +316,15 @@ def raise_api_error(*args, **kwargs): @pytest.mark.django_db def test_engine_start_with_image_pull_timeout_exception( - init_data, podman_engine + init_podman_data, + podman_engine, + default_organization: models.Organization, ): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - request = get_request(init_data) + log_handler = DBLogger(init_podman_data.activation_instance.id) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) error = "Task exceeded maximum timeout value 120 seconds" def raise_timeout_error(*args, **kwargs): @@ -329,10 +337,16 @@ def raise_timeout_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_start_with_image_pull_exception(init_data, podman_engine): +def test_engine_start_with_image_pull_exception( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - request = get_request(init_data) + log_handler = DBLogger(init_podman_data.activation_instance.id) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) image_mock = mock.Mock() image_mock.pull.return_value.id = None @@ -349,10 +363,16 @@ def test_engine_start_with_image_pull_exception(init_data, podman_engine): @pytest.mark.django_db -def test_engine_start_with_containers_run_exception(init_data, podman_engine): +def test_engine_start_with_containers_run_exception( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - request = get_request(init_data) + log_handler = DBLogger(init_podman_data.activation_instance.id) + request = get_request( + init_podman_data, "me", default_organization, mounts=[{"/dev": "/opt"}] + ) def raise_error(*args, **kwargs): raise ContainerError( @@ -374,10 +394,16 @@ def raise_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_start_with_never_pull_policy_request(init_data, podman_engine): +def test_engine_start_with_never_pull_policy_request( + init_podman_data, + podman_engine, + default_organization: models.Organization, +): engine = podman_engine - request = get_request_with_never_pull_policy(init_data) - log_handler = DBLogger(init_data.activation_instance.id) + request = get_request_with_never_pull_policy( + init_podman_data, default_organization + ) + log_handler = DBLogger(init_podman_data.activation_instance.id) engine.start(request, log_handler) @@ -455,9 +481,9 @@ def test_engine_get_status_with_exception(podman_engine): @pytest.mark.django_db -def test_engine_cleanup(init_data, podman_engine): +def test_engine_cleanup(init_podman_data, podman_engine): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_podman_data.activation_instance.id) engine.cleanup("100", log_handler) @@ -467,9 +493,11 @@ def test_engine_cleanup(init_data, podman_engine): @pytest.mark.django_db -def test_engine_cleanup_with_not_found_exception(init_data, podman_engine): +def test_engine_cleanup_with_not_found_exception( + init_podman_data, podman_engine +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_podman_data.activation_instance.id) def raise_error(*args, **kwargs): raise NotFound("Not found") @@ -486,9 +514,9 @@ def raise_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_cleanup_with_remove_exception(init_data, podman_engine): +def test_engine_cleanup_with_remove_exception(init_podman_data, podman_engine): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_podman_data.activation_instance.id) err_msg = "Not found" @@ -505,9 +533,9 @@ def raise_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_cleanup_with_get_exception(init_data, podman_engine): +def test_engine_cleanup_with_get_exception(init_podman_data, podman_engine): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_podman_data.activation_instance.id) err_msg = "Not found" @@ -521,10 +549,10 @@ def raise_error(*args, **kwargs): @pytest.mark.django_db -def test_engine_update_logs(init_data, podman_engine): +def test_engine_update_logs(init_podman_data, podman_engine): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) - init_log_read_at = init_data.activation_instance.log_read_at + log_handler = DBLogger(init_podman_data.activation_instance.id) + init_log_read_at = init_podman_data.activation_instance.log_read_at message = ( "2023-10-31 15:28:01,318 - ansible_rulebook.engine - INFO - " "Calling main in ansible.eda.range" @@ -559,14 +587,16 @@ def test_engine_update_logs(init_data, podman_engine): ) assert models.RulebookProcessLog.objects.last().log == f"{message}" - init_data.activation_instance.refresh_from_db() - assert init_data.activation_instance.log_read_at > init_log_read_at + init_podman_data.activation_instance.refresh_from_db() + assert init_podman_data.activation_instance.log_read_at > init_log_read_at @pytest.mark.django_db -def test_engine_update_logs_with_container_not_found(init_data, podman_engine): +def test_engine_update_logs_with_container_not_found( + init_podman_data, podman_engine +): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_podman_data.activation_instance.id) engine.client.containers.exists.return_value = None engine.update_logs("100", log_handler) @@ -577,9 +607,9 @@ def test_engine_update_logs_with_container_not_found(init_data, podman_engine): @pytest.mark.django_db -def test_engine_update_logs_with_exception(init_data, podman_engine): +def test_engine_update_logs_with_exception(init_podman_data, podman_engine): engine = podman_engine - log_handler = DBLogger(init_data.activation_instance.id) + log_handler = DBLogger(init_podman_data.activation_instance.id) def raise_error(*args, **kwargs): raise APIError("Not found") diff --git a/tests/integration/services/activation/engine/utils.py b/tests/integration/services/activation/engine/utils.py new file mode 100644 index 000000000..a45c77b7b --- /dev/null +++ b/tests/integration/services/activation/engine/utils.py @@ -0,0 +1,68 @@ +# Copyright 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Common Utilities for Engine Tests.""" + +from dataclasses import dataclass + +from aap_eda.core import models +from aap_eda.services.activation.engine.common import ( + AnsibleRulebookCmdLine, + ContainerRequest, + Credential, +) + + +@dataclass +class InitData: + activation: models.Activation + activation_instance: models.RulebookProcess + + +def get_ansible_rulebook_cmdline(data: InitData): + return AnsibleRulebookCmdLine( + ws_url="ws://localhost:8000/api/eda/ws/ansible-rulebook", + ws_ssl_verify="no", + ws_token_url="http://localhost:8000/api/eda/v1/auth/token/refresh", + ws_access_token="access", + ws_refresh_token="refresh", + id=data.activation.id, + log_level="-v", + heartbeat=5, + ) + + +def get_request( + data: InitData, + username: str, + default_organization: models.Organization, + **kwargs, +): + return ContainerRequest( + name="test-request", + image_url="quay.io/ansible/ansible-rulebook:main", + rulebook_process_id=data.activation_instance.id, + process_parent_id=data.activation.id, + cmdline=get_ansible_rulebook_cmdline(data), + credential=Credential( + username=username, + secret="secret", + ssl_verify=True, + organization=default_organization, + ), + ports=[("localhost", 8080)], + mem_limit="8G", + env_vars={"a": 1}, + extra_args={"b": 2}, + **kwargs, + ) diff --git a/tests/integration/services/activation/test_activation.py b/tests/integration/services/activation/test_activation.py index 08c6c5379..9ea5224f3 100644 --- a/tests/integration/services/activation/test_activation.py +++ b/tests/integration/services/activation/test_activation.py @@ -30,6 +30,7 @@ def activation_no_instance( default_user: models.User, default_decision_environment: models.DecisionEnvironment, default_rulebook: models.Rulebook, + default_organization: models.Organization, ) -> models.Activation: """Return an activation with outassociated RulebookProcess.""" return models.Activation.objects.create( @@ -39,16 +40,21 @@ def activation_no_instance( rulebook=default_rulebook, # rulebook_rulesets is populated by the serializer rulebook_rulesets=default_rulebook.rulesets, + organization=default_organization, ) @pytest.fixture -def activation(activation_no_instance) -> models.Activation: +def activation( + default_organization: models.Organization, + activation_no_instance, +) -> models.Activation: """Return an activation with associated RulebookProcess.""" models.RulebookProcess.objects.create( name="activation-instance-1", activation=activation_no_instance, git_hash=PROJECT_GIT_HASH, + organization=default_organization, ) return activation_no_instance diff --git a/tests/integration/services/activation/test_manager.py b/tests/integration/services/activation/test_manager.py index 015090ed0..a06b66466 100644 --- a/tests/integration/services/activation/test_manager.py +++ b/tests/integration/services/activation/test_manager.py @@ -43,7 +43,9 @@ def apply_settings(settings: SettingsWrapper, **kwargs): @pytest.fixture -def rulebook_with_job_template() -> models.Rulebook: +def rulebook_with_job_template( + default_organization: models.Organization, +) -> models.Rulebook: """Return a default rulebook.""" rulesets = """ --- @@ -63,6 +65,7 @@ def rulebook_with_job_template() -> models.Rulebook: return models.Rulebook.objects.create( name="test-rulebook", rulesets=rulesets, + organization=default_organization, ) @@ -74,10 +77,14 @@ def eda_caplog(caplog_factory) -> LogCaptureFixture: @pytest.fixture def activation_with_instance( + default_organization: models.Organization, basic_activation: models.Activation, ) -> models.Activation: """Return an activation with an instance.""" - models.RulebookProcess.objects.create(activation=basic_activation) + models.RulebookProcess.objects.create( + activation=basic_activation, + organization=default_organization, + ) return basic_activation @@ -100,6 +107,7 @@ def basic_activation( default_user: models.User, default_decision_environment: models.DecisionEnvironment, default_rulebook: models.Rulebook, + default_organization: models.Organization, ) -> models.Activation: """Return the minimal activation.""" return models.Activation.objects.create( @@ -110,6 +118,7 @@ def basic_activation( # rulebook_rulesets is populated by the serializer rulebook_rulesets=default_rulebook.rulesets, log_level=enums.RulebookProcessLogLevel.INFO, + organization=default_organization, ) @@ -118,6 +127,7 @@ def new_activation_with_instance( default_user: models.User, default_decision_environment: models.DecisionEnvironment, default_rulebook: models.Rulebook, + default_organization: models.Organization, ) -> models.Activation: """Return an activation with an instance.""" activation = models.Activation.objects.create( @@ -127,10 +137,12 @@ def new_activation_with_instance( rulebook=default_rulebook, # rulebook_rulesets is populated by the serializer rulebook_rulesets=default_rulebook.rulesets, + organization=default_organization, ) models.RulebookProcess.objects.create( activation=activation, status=enums.ActivationStatus.RUNNING, + organization=default_organization, ) models.RulebookProcessQueue.objects.create( process=activation.latest_instance, diff --git a/tests/integration/services/test_project_import.py b/tests/integration/services/test_project_import.py index 5dea07760..534c7634c 100644 --- a/tests/integration/services/test_project_import.py +++ b/tests/integration/services/test_project_import.py @@ -65,7 +65,11 @@ def storage_save_patch(): @pytest.mark.django_db -def test_project_import(storage_save_patch, service_tempdir_patch): +def test_project_import( + default_organization: models.Organization, + storage_save_patch, + service_tempdir_patch, +): def clone_project(_url, path, *_args, **_kwargs): src = DATA_DIR / "project-01" shutil.copytree(src, path, symlinks=False) @@ -85,6 +89,7 @@ def clone_project(_url, path, *_args, **_kwargs): url="https://git.example.com/repo01.git", scm_branch="my_branch", scm_refspec="the_ref", + organization=default_organization, ), models.Project( name="test-project-02", @@ -92,6 +97,7 @@ def clone_project(_url, path, *_args, **_kwargs): verify_ssl=False, scm_branch="tag2", scm_refspec="", + organization=default_organization, ), ] ) @@ -128,7 +134,9 @@ def clone_project(_url, path, *_args, **_kwargs): @pytest.mark.django_db def test_project_import_with_new_layout( - storage_save_patch, service_tempdir_patch + default_organization: models.Organization, + storage_save_patch, + service_tempdir_patch, ): def clone_project(_url, path, *_args, **_kwargs): src = DATA_DIR / "project-02" @@ -144,7 +152,9 @@ def clone_project(_url, path, *_args, **_kwargs): git_mock.clone.side_effect = clone_project project = models.Project.objects.create( - name="test-project-01", url="https://git.example.com/repo.git" + name="test-project-01", + url="https://git.example.com/repo.git", + organization=default_organization, ) service = ProjectImportService(scm_cls=git_mock) @@ -157,7 +167,9 @@ def clone_project(_url, path, *_args, **_kwargs): @pytest.mark.django_db def test_project_import_rulebook_directory_missing( - storage_save_patch, service_tempdir_patch + default_organization: models.Organization, + storage_save_patch, + service_tempdir_patch, ): repo_mock = mock.Mock(name="ScmRepository()") repo_mock.rev_parse.return_value = ( @@ -167,7 +179,9 @@ def test_project_import_rulebook_directory_missing( git_mock.clone.return_value = repo_mock project = models.Project.objects.create( - name="test-project-01", url="https://git.example.com/repo.git" + name="test-project-01", + url="https://git.example.com/repo.git", + organization=default_organization, ) message_expected = ( "The 'extensions/eda/rulebooks' or 'rulebooks'" @@ -188,7 +202,9 @@ def test_project_import_rulebook_directory_missing( @pytest.mark.django_db def test_project_import_with_vaulted_data( - storage_save_patch, service_tempdir_patch + default_organization: models.Organization, + storage_save_patch, + service_tempdir_patch, ): def clone_project(_url, path, *_args, **_kwargs): src = DATA_DIR / "project-04" @@ -204,7 +220,9 @@ def clone_project(_url, path, *_args, **_kwargs): git_mock.clone.side_effect = clone_project project = models.Project.objects.create( - name="test-project-04", url="https://git.example.com/repo.git" + name="test-project-04", + url="https://git.example.com/repo.git", + organization=default_organization, ) service = ProjectImportService(scm_cls=git_mock) @@ -215,7 +233,7 @@ def clone_project(_url, path, *_args, **_kwargs): assert project.import_state == models.Project.ImportState.COMPLETED -def _setup_project_sync(): +def _setup_project_sync(default_organization: models.Organization): def clone_project(_url, path, *_args, **_kwargs): src = DATA_DIR / "project-02" shutil.copytree(src, path, symlinks=False) @@ -228,7 +246,9 @@ def clone_project(_url, path, *_args, **_kwargs): git_mock.clone.side_effect = clone_project project = models.Project.objects.create( - name="test-project-01", url="https://git.example.com/repo.git" + name="test-project-01", + url="https://git.example.com/repo.git", + organization=default_organization, ) service = ProjectImportService(scm_cls=git_mock) @@ -245,10 +265,14 @@ def clone_project(_url, path, *_args, **_kwargs): @pytest.mark.django_db -def test_project_sync(storage_save_patch, service_tempdir_patch): +def test_project_sync( + default_organization: models.Organization, + storage_save_patch, + service_tempdir_patch, +): # TODO(cutwater): Create activations and verify that rulebook content # is updated - project = _setup_project_sync() + project = _setup_project_sync(default_organization) storage_save_patch.reset_mock() def clone_project(_url, path, *_args, **_kwargs): @@ -280,8 +304,12 @@ def clone_project(_url, path, *_args, **_kwargs): @pytest.mark.django_db -def test_project_sync_same_hash(storage_save_patch, service_tempdir_patch): - project = _setup_project_sync() +def test_project_sync_same_hash( + default_organization: models.Organization, + storage_save_patch, + service_tempdir_patch, +): + project = _setup_project_sync(default_organization) storage_save_patch.reset_mock() def clone_project(_url, path, *_args, **_kwargs): @@ -314,7 +342,10 @@ def clone_project(_url, path, *_args, **_kwargs): @pytest.mark.django_db def test_project_import_with_invalid_rulebooks( - storage_save_patch, service_tempdir_patch, caplog + default_organization: models.Organization, + storage_save_patch, + service_tempdir_patch, + caplog, ): def clone_project(_url, path, *_args, **_kwargs): src = DATA_DIR / "project-05" @@ -330,7 +361,9 @@ def clone_project(_url, path, *_args, **_kwargs): git_mock.clone.side_effect = clone_project project = models.Project.objects.create( - name="test-project-04", url="https://git.example.com/repo.git" + name="test-project-04", + url="https://git.example.com/repo.git", + organization=default_organization, ) logger = logging.getLogger("aap_eda") diff --git a/tests/integration/services/test_restart_helper.py b/tests/integration/services/test_restart_helper.py index 104028e02..38aa283fb 100644 --- a/tests/integration/services/test_restart_helper.py +++ b/tests/integration/services/test_restart_helper.py @@ -29,7 +29,7 @@ @pytest.fixture() -def activation(): +def activation(default_organization: models.Organization): user = models.User.objects.create_user( username="luke.skywalker", first_name="Luke", @@ -40,6 +40,7 @@ def activation(): return models.Activation.objects.create( name="test1", user=user, + organization=default_organization, ) diff --git a/tests/integration/tasks/test_activation_request_queue.py b/tests/integration/tasks/test_activation_request_queue.py index 3d3bbd56d..c874daca8 100644 --- a/tests/integration/tasks/test_activation_request_queue.py +++ b/tests/integration/tasks/test_activation_request_queue.py @@ -22,7 +22,7 @@ @pytest.fixture() -def activations(): +def activations(default_organization: models.Organization): user = models.User.objects.create_user( username="luke.skywalker", first_name="Luke", @@ -33,11 +33,13 @@ def activations(): activation1 = models.Activation.objects.create( name="test1", user=user, + organization=default_organization, ) activation2 = models.Activation.objects.create( name="test2", user=user, + organization=default_organization, ) return [activation1, activation2] diff --git a/tests/integration/tasks/test_orchestrator.py b/tests/integration/tasks/test_orchestrator.py index e60aecb44..52cdaa0e9 100644 --- a/tests/integration/tasks/test_orchestrator.py +++ b/tests/integration/tasks/test_orchestrator.py @@ -28,7 +28,9 @@ @pytest.fixture -def default_rulebook() -> models.Rulebook: +def default_rulebook( + default_organization: models.Organization, +) -> models.Rulebook: """Return a default rulebook.""" rulesets = """ --- @@ -48,11 +50,12 @@ def default_rulebook() -> models.Rulebook: return models.Rulebook.objects.create( name="test-rulebook", rulesets=rulesets, + organization=default_organization, ) @pytest.fixture() -def activation(default_rulebook): +def activation(default_rulebook, default_organization): user = models.User.objects.create_user( username="luke.skywalker", first_name="Luke", @@ -63,6 +66,7 @@ def activation(default_rulebook): decision_environment = models.DecisionEnvironment.objects.create( name="test-decision-environment", image_url="localhost:14000/test-image-url", + organization=default_organization, ) return models.Activation.objects.create( name="test1", @@ -70,11 +74,12 @@ def activation(default_rulebook): decision_environment=decision_environment, rulebook=default_rulebook, rulebook_rulesets=default_rulebook.rulesets, + organization=default_organization, ) @pytest.fixture() -def max_running_processes(): +def max_running_processes(default_organization: models.Organization): user = models.User.objects.create_user( username="luke.skywalker2", first_name="Luke", @@ -87,6 +92,7 @@ def max_running_processes(): activation = models.Activation.objects.create( name=f"test_max_running{i}", user=user, + organization=default_organization, ) status = ( ActivationStatus.STARTING if i == 0 else ActivationStatus.RUNNING @@ -95,6 +101,7 @@ def max_running_processes(): name=f"running{i}", activation=activation, status=status, + organization=default_organization, ) processes.append(process) models.RulebookProcessQueue.objects.create( @@ -271,6 +278,7 @@ def test_max_running_activation_after_start_job( activation, max_running_processes, container_engine_mock, + default_organization: models.Organization, ): """Check if the max running processes error is handled correctly when the limit is reached after the request is started.""" @@ -282,6 +290,7 @@ def side_effect(*args, **kwargs): name="running", activation=max_running_processes[0].activation, status=ActivationStatus.RUNNING, + organization=default_organization, ) original_start_method(instance, *args[1:], **kwargs) diff --git a/tests/integration/tasks/test_projects.py b/tests/integration/tasks/test_projects.py index 14ff29ad5..49d5ed0b4 100644 --- a/tests/integration/tasks/test_projects.py +++ b/tests/integration/tasks/test_projects.py @@ -29,6 +29,7 @@ def fake_job(): @mock.patch("aap_eda.tasks.project.import_project") def test_monitor_project_tasks_import( import_task_mock: mock.Mock, + default_organization: models.Organization, default_queue: Queue, ): """Test monitor_project_tasks rq task. @@ -44,6 +45,7 @@ def test_monitor_project_tasks_import( name="test_monitor_project_tasks", url="https://git.example.com/acme/project-01", import_state=models.Project.ImportState.PENDING, + organization=default_organization, ) default_queue.enqueue(monitor_project_tasks, default_queue.name) @@ -59,6 +61,7 @@ def test_monitor_project_tasks_import( @mock.patch("aap_eda.tasks.project.sync_project") def test_monitor_project_tasks_sync( sync_task_mock: mock.Mock, + default_organization: models.Organization, default_queue: Queue, ): """Test monitor_project_tasks rq task. @@ -75,6 +78,7 @@ def test_monitor_project_tasks_sync( url="https://git.example.com/acme/project-01", import_state=models.Project.ImportState.PENDING, git_hash="dummy-hash", + organization=default_organization, ) default_queue.enqueue(monitor_project_tasks, default_queue.name) @@ -90,6 +94,7 @@ def test_monitor_project_tasks_sync( @mock.patch("aap_eda.tasks.project.sync_project") def test_monitor_project_tasks_with_job( sync_task_mock: mock.Mock, + default_organization: models.Organization, default_queue: Queue, ): """Test monitor_project_tasks rq task. @@ -108,6 +113,7 @@ def test_monitor_project_tasks_with_job( import_state=models.Project.ImportState.PENDING, git_hash="dummy-hash", import_task_id=expected_job_id, + organization=default_organization, ) default_queue.enqueue(fake_job, job_id=expected_job_id) default_queue.enqueue(monitor_project_tasks, default_queue.name) diff --git a/tests/integration/wsapi/test_consumer.py b/tests/integration/wsapi/test_consumer.py index 4b14de4ab..59228aa3d 100644 --- a/tests/integration/wsapi/test_consumer.py +++ b/tests/integration/wsapi/test_consumer.py @@ -52,8 +52,11 @@ @pytest.mark.django_db(transaction=True) async def test_handle_workers_without_credentials( ws_communicator: WebsocketCommunicator, + default_organization: models.Organization, ): - rulebook_process_with_extra_var = await _prepare_db_data() + rulebook_process_with_extra_var = await _prepare_db_data( + default_organization + ) rulebook_process_without_extra_var = ( await _prepare_activation_instance_without_extra_var() ) @@ -110,9 +113,12 @@ async def test_handle_workers_without_credentials( async def test_handle_workers_with_eda_system_vault_credential( ws_communicator: WebsocketCommunicator, preseed_credential_types, + default_organization: models.Organization, ): rulebook_process_id = ( - await _prepare_activation_instance_with_eda_system_vault_credential() + await _prepare_activation_instance_with_eda_system_vault_credential( + default_organization, + ) ) payload = { @@ -138,9 +144,13 @@ async def test_handle_workers_with_eda_system_vault_credential( @pytest.mark.django_db(transaction=True) async def test_handle_workers_with_controller_info( - ws_communicator: WebsocketCommunicator, preseed_credential_types + ws_communicator: WebsocketCommunicator, + preseed_credential_types, + default_organization: models.Organization, ): - rulebook_process_id = await _prepare_activation_with_controller_info() + rulebook_process_id = await _prepare_activation_with_controller_info( + default_organization, + ) payload = { "type": "Worker", @@ -173,7 +183,7 @@ async def test_handle_workers_with_validation_errors( connected, _ = await communicator.connect(timeout=3) assert connected - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) payload = { "type": "Worker", @@ -190,7 +200,7 @@ async def test_handle_jobs( ws_communicator: WebsocketCommunicator, default_organization: models.Organization, ): - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) assert (await get_job_instance_count()) == 0 assert (await get_activation_instance_job_instance_count()) == 0 @@ -238,7 +248,7 @@ async def test_handle_actions_multiple_firing( ws_communicator: WebsocketCommunicator, default_organization: models.Organization, ): - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) job_instance = await _prepare_job_instance() assert (await get_audit_rule_count()) == 0 @@ -272,7 +282,7 @@ async def test_handle_actions_with_empty_job_uuid( ws_communicator: WebsocketCommunicator, default_organization: models.Organization, ): - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) assert (await get_audit_rule_count()) == 0 # job uuid is empty string @@ -297,7 +307,7 @@ async def test_handle_actions( ws_communicator: WebsocketCommunicator, default_organization: models.Organization, ): - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) job_instance = await _prepare_job_instance() assert (await get_audit_rule_count()) == 0 @@ -340,7 +350,7 @@ async def test_rule_status_with_multiple_failed_actions( ws_communicator: WebsocketCommunicator, default_organization: models.Organization, ): - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) job_instance = await _prepare_job_instance() action1 = create_action_payload( @@ -376,7 +386,7 @@ async def test_handle_heartbeat( ws_communicator: WebsocketCommunicator, default_organization: models.Organization, ): - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) rulebook_process = await get_rulebook_process(rulebook_process_id) activation = await get_activation_by_rulebook_process(rulebook_process_id) assert activation.ruleset_stats == {} @@ -446,7 +456,7 @@ async def test_multiple_rules_for_one_event( ws_communicator: WebsocketCommunicator, default_organization: models.Organization, ): - rulebook_process_id = await _prepare_db_data() + rulebook_process_id = await _prepare_db_data(default_organization) job_instance = await _prepare_job_instance() matching_events = _matching_events() @@ -560,6 +570,7 @@ async def test_controller_job_url( api_url, old_url, new_url, + default_organization: models.Organization, ): my_aap_inputs = { "host": api_url, @@ -569,7 +580,7 @@ async def test_controller_job_url( "oauth_token": "", } rulebook_process_id = await _prepare_activation_with_controller_info( - my_aap_inputs + default_organization, my_aap_inputs ) job_instance = await _prepare_job_instance() @@ -663,23 +674,28 @@ def get_job_instance_event_count(): @database_sync_to_async -def _prepare_activation_instance_with_eda_system_vault_credential(): +def _prepare_activation_instance_with_eda_system_vault_credential( + default_organization: models.Organization, +): project, _ = models.Project.objects.get_or_create( name="test-project", url="https://github.com/test/project", git_hash="92156b2b76c6adb9afbd5688550a621bcc2e5782,", + organization=default_organization, ) rulebook, _ = models.Rulebook.objects.get_or_create( name="test-rulebook", rulesets=TEST_RULESETS, project=project, + organization=default_organization, ) decision_environment = models.DecisionEnvironment.objects.create( name="de_test_name_1", image_url="de_test_image_url", description="de_test_description", + organization=default_organization, ) user = models.User.objects.create_user( @@ -698,6 +714,7 @@ def _prepare_activation_instance_with_eda_system_vault_credential(): inputs={"vault_id": "adam", "vault_password": "secret"}, managed=False, credential_type=vault_credential_type, + organization=default_organization, ) activation, _ = models.Activation.objects.get_or_create( @@ -707,34 +724,42 @@ def _prepare_activation_instance_with_eda_system_vault_credential(): project=project, user=user, decision_environment=decision_environment, + organization=default_organization, ) activation.eda_credentials.add(credential) rulebook_process, _ = models.RulebookProcess.objects.get_or_create( activation=activation, + organization=default_organization, ) return rulebook_process.id @database_sync_to_async -def _prepare_activation_with_controller_info(inputs=AAP_INPUTS): +def _prepare_activation_with_controller_info( + default_organization: models.Organization, + inputs=AAP_INPUTS, +): project, _ = models.Project.objects.get_or_create( name="test-project", url="https://github.com/test/project", git_hash="92156b2b76c6adb9afbd5688550a621bcc2e5782,", + organization=default_organization, ) rulebook, _ = models.Rulebook.objects.get_or_create( name="test-rulebook", rulesets=TEST_RULESETS, project=project, + organization=default_organization, ) decision_environment = models.DecisionEnvironment.objects.create( name="de_test_name_1", image_url="de_test_image_url", description="de_test_description", + organization=default_organization, ) user = models.User.objects.create_user( @@ -753,6 +778,7 @@ def _prepare_activation_with_controller_info(inputs=AAP_INPUTS): inputs=inputs, managed=False, credential_type=aap_credential_type, + organization=default_organization, ) activation, _ = models.Activation.objects.get_or_create( @@ -762,28 +788,32 @@ def _prepare_activation_with_controller_info(inputs=AAP_INPUTS): project=project, user=user, decision_environment=decision_environment, + organization=default_organization, ) activation.eda_credentials.add(credential) rulebook_process, _ = models.RulebookProcess.objects.get_or_create( activation=activation, + organization=default_organization, ) return rulebook_process.id @database_sync_to_async -def _prepare_db_data(): +def _prepare_db_data(default_organization: models.Organization): project, _ = models.Project.objects.get_or_create( name="test-project", url="https://github.com/test/project", git_hash="92156b2b76c6adb9afbd5688550a621bcc2e5782,", + organization=default_organization, ) rulebook, _ = models.Rulebook.objects.get_or_create( name="test-rulebook", rulesets=TEST_RULESETS, project=project, + organization=default_organization, ) user = models.User.objects.create_user( @@ -801,6 +831,7 @@ def _prepare_db_data(): name="de_test_name_1", image_url="de_test_image_url", description="de_test_description", + organization=default_organization, ) activation, _ = models.Activation.objects.get_or_create( @@ -812,10 +843,12 @@ def _prepare_db_data(): user=user, decision_environment=decision_environment, awx_token=token[0], + organization=default_organization, ) rulebook_process, _ = models.RulebookProcess.objects.get_or_create( activation=activation, + organization=default_organization, ) ruleset, _ = models.Ruleset.objects.get_or_create( @@ -841,17 +874,21 @@ def _prepare_db_data(): @database_sync_to_async -def _prepare_activation_instance_without_extra_var(): +def _prepare_activation_instance_without_extra_var( + default_organization: models.Organization, +): project = models.Project.objects.create( name="test-project-no-extra_var", url="https://github.com/test/project", git_hash="92156b2b76c6adb9afbd5688550a621bcc2e5782,", + organization=default_organization, ) rulebook = models.Rulebook.objects.create( name="test-rulebook", rulesets=TEST_RULESETS, project=project, + organization=default_organization, ) user = models.User.objects.create_user( @@ -869,6 +906,7 @@ def _prepare_activation_instance_without_extra_var(): name="de_test_name_2", image_url="de_test_image_url", description="de_test_description", + organization=default_organization, ) activation = models.Activation.objects.create( @@ -879,27 +917,33 @@ def _prepare_activation_instance_without_extra_var(): user=user, decision_environment=decision_environment, awx_token=token[0], + organization=default_organization, ) rulebook_process = models.RulebookProcess.objects.create( activation=activation, + organization=default_organization, ) return rulebook_process.id @database_sync_to_async -def _prepare_activation_instance_no_token(): +def _prepare_activation_instance_no_token( + default_organization: models.Organization, +): project = models.Project.objects.create( name="test-project-no-token", url="https://github.com/test/project", git_hash="92156b2b76c6adb9afbd5688550a621bcc2e5782,", + organization=default_organization, ) rulebook = models.Rulebook.objects.create( name="test-rulebook", rulesets=TEST_RULESETS, project=project, + organization=default_organization, ) user = models.User.objects.create_user( @@ -914,6 +958,7 @@ def _prepare_activation_instance_no_token(): name="de_no_token", image_url="de_test_image_url", description="de_test_description", + organization=default_organization, ) activation = models.Activation.objects.create( @@ -923,10 +968,12 @@ def _prepare_activation_instance_no_token(): project=project, user=user, decision_environment=decision_environment, + organization=default_organization, ) rulebook_process = models.RulebookProcess.objects.create( activation=activation, + organization=default_organization, ) return rulebook_process.id diff --git a/tests/unit/test_scm.py b/tests/unit/test_scm.py index b580e8ced..40a051e39 100644 --- a/tests/unit/test_scm.py +++ b/tests/unit/test_scm.py @@ -16,22 +16,25 @@ import pytest -from aap_eda.core.models import EdaCredential +from aap_eda.core import models from aap_eda.services.project.scm import ScmError, ScmRepository @pytest.fixture -def credential() -> EdaCredential: - credential = EdaCredential.objects.create( +def credential( + default_organization: models.Organization, +) -> models.EdaCredential: + credential = models.EdaCredential.objects.create( name="test-eda-credential", inputs={"username": "adam", "password": "secret"}, + organization=default_organization, ) credential.refresh_from_db() return credential @pytest.mark.django_db -def test_git_clone(credential: EdaCredential): +def test_git_clone(credential: models.EdaCredential): executor = mock.MagicMock() with tempfile.TemporaryDirectory() as dest_path: repository = ScmRepository.clone( @@ -65,7 +68,7 @@ def test_git_clone(credential: EdaCredential): @pytest.mark.django_db def test_git_clone_leak_password( - credential: EdaCredential, + credential: models.EdaCredential, ): executor = mock.MagicMock() @@ -110,7 +113,7 @@ def test_git_clone_without_ssl_verification(): @pytest.mark.django_db def test_git_clone_empty_project( - credential: EdaCredential, + credential: models.EdaCredential, ): executor = mock.MagicMock()