From d1e146f5775e9e9d8b7ce42725d5d182da086de0 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Wed, 18 Sep 2019 16:39:41 -0400 Subject: [PATCH 1/8] Add create_user task --- ...f9caba7_add_environment_role_csp_fields.py | 30 +++++++++++++++++++ atst/domain/csp/cloud.py | 2 +- atst/domain/environment_roles.py | 23 ++++++++++++++ atst/jobs.py | 30 +++++++++++++++++++ atst/models/environment_role.py | 5 +++- tests/test_jobs.py | 23 ++++++++++---- 6 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 alembic/versions/e3d93f9caba7_add_environment_role_csp_fields.py diff --git a/alembic/versions/e3d93f9caba7_add_environment_role_csp_fields.py b/alembic/versions/e3d93f9caba7_add_environment_role_csp_fields.py new file mode 100644 index 00000000..481a865a --- /dev/null +++ b/alembic/versions/e3d93f9caba7_add_environment_role_csp_fields.py @@ -0,0 +1,30 @@ +"""add environment_role csp fields + +Revision ID: e3d93f9caba7 +Revises: 691b04ecd85e +Create Date: 2019-09-18 16:35:47.554060 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'e3d93f9caba7' # pragma: allowlist secret +down_revision = '691b04ecd85e' # pragma: allowlist secret +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('environment_roles', sa.Column('claimed_until', sa.TIMESTAMP(timezone=True), nullable=True)) + op.add_column('environment_roles', sa.Column('csp_user_id', sa.String(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('environment_roles', 'csp_user_id') + op.drop_column('environment_roles', 'claimed_until') + # ### end Alembic commands ### diff --git a/atst/domain/csp/cloud.py b/atst/domain/csp/cloud.py index 5f8689c1..4a6961e5 100644 --- a/atst/domain/csp/cloud.py +++ b/atst/domain/csp/cloud.py @@ -194,7 +194,7 @@ class MockCloudProvider(CloudProviderInterface): GeneralCSPException("Could not create user."), ) - return {"id": self._id()} + return self._id() def suspend_user(self, auth_credentials, csp_user_id): self._maybe_raise(self.NETWORK_FAILURE_PCT, self.NETWORK_EXCEPTION) diff --git a/atst/domain/environment_roles.py b/atst/domain/environment_roles.py index b28e94b2..00ac730f 100644 --- a/atst/domain/environment_roles.py +++ b/atst/domain/environment_roles.py @@ -1,5 +1,10 @@ +from sqlalchemy.orm.exc import NoResultFound + from atst.database import db from atst.models import EnvironmentRole, ApplicationRole +from atst.domain.exceptions import NotFoundError +from uuid import UUID +from typing import List class EnvironmentRoles(object): @@ -22,6 +27,15 @@ class EnvironmentRoles(object): ) return existing_env_role + @classmethod + def get_by_id(cls, id_) -> EnvironmentRole: + try: + return ( + db.session.query(EnvironmentRole).filter(EnvironmentRole.id == id_) + ).one() + except NoResultFound: + raise NotFoundError(cls.resource_name) + @classmethod def get_by_user_and_environment(cls, user_id, environment_id): existing_env_role = ( @@ -54,3 +68,12 @@ class EnvironmentRoles(object): .filter(EnvironmentRole.deleted != True) .all() ) + + @classmethod + def get_environment_roles_pending_creation(cls) -> List[UUID]: + results = ( + db.session.query(EnvironmentRole.id) + # TODO + .filter(EnvironmentRole.status == "PENDING").all() + ) + return [id_ for id_, in results] diff --git a/atst/jobs.py b/atst/jobs.py index 46717192..f702f13f 100644 --- a/atst/jobs.py +++ b/atst/jobs.py @@ -6,6 +6,7 @@ from atst.queue import celery from atst.models import EnvironmentJobFailure, EnvironmentRoleJobFailure from atst.domain.csp.cloud import CloudProviderInterface, GeneralCSPException from atst.domain.environments import Environments +from atst.domain.environment_roles import EnvironmentRoles from atst.models.utils import claim_for_update @@ -101,6 +102,20 @@ def do_create_environment_baseline(csp: CloudProviderInterface, environment_id=N db.session.commit() +def do_create_user(csp: CloudProviderInterface, environment_role_id=None): + environment_role = EnvironmentRoles.get_by_id(environment_role_id) + + with claim_for_update(environment_role) as environment_role: + credentials = environment_role.environment.root_user_info["credentials"] + + csp_user_id = csp.create_or_update_user( + credentials, environment_role, "role_id" + ) + environment_role.csp_user_id = csp_user_id + db.session.add(environment_role) + db.session.commit() + + def do_work(fn, task, csp, **kwargs): try: fn(csp, **kwargs) @@ -130,6 +145,13 @@ def create_environment_baseline(self, environment_id=None): ) +@celery.task(bind=True) +def create_user(self, environment_role_id=None): + do_work( + do_create_user, self, app.csp.cloud, environment_role_id=environment_role_id + ) + + @celery.task(bind=True) def dispatch_create_environment(self): for environment_id in Environments.get_environments_pending_creation( @@ -152,3 +174,11 @@ def dispatch_create_environment_baseline(self): pendulum.now() ): create_environment_baseline.delay(environment_id=environment_id) + + +@celery.task(bind=True) +def dispatch_provision_user(self): + for ( + environment_role_id + ) in EnvironmentRoles.get_environment_roles_pending_creation(): + create_user.delay(environment_role_id=environment_role_id) diff --git a/atst/models/environment_role.py b/atst/models/environment_role.py index 9f6754f8..9b23c300 100644 --- a/atst/models/environment_role.py +++ b/atst/models/environment_role.py @@ -1,5 +1,5 @@ from enum import Enum -from sqlalchemy import Index, ForeignKey, Column, String +from sqlalchemy import Index, ForeignKey, Column, String, TIMESTAMP from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship @@ -33,6 +33,9 @@ class EnvironmentRole( job_failures = relationship("EnvironmentRoleJobFailure") + csp_user_id = Column(String()) + claimed_until = Column(TIMESTAMP(timezone=True)) + def __repr__(self): return "".format( self.role, self.application_role.user_name, self.environment.name, self.id diff --git a/tests/test_jobs.py b/tests/test_jobs.py index cef271bf..89ff9be5 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -16,12 +16,18 @@ from atst.jobs import ( dispatch_create_atat_admin_user, dispatch_create_environment_baseline, create_environment, + do_create_user, ) from atst.models.utils import claim_for_update from atst.domain.exceptions import ClaimFailedException from tests.factories import EnvironmentFactory, EnvironmentRoleFactory, PortfolioFactory +@pytest.fixture(autouse=True, scope="function") +def csp(): + return Mock(wraps=MockCloudProvider({}, with_delay=False, with_failure=False)) + + def test_environment_job_failure(celery_app, celery_worker): @celery_app.task(bind=True, base=RecordEnvironmentFailure) def _fail_hard(self, environment_id=None): @@ -63,11 +69,6 @@ yesterday = now.subtract(days=1) tomorrow = now.add(days=1) -@pytest.fixture(autouse=True, scope="function") -def csp(): - return Mock(wraps=MockCloudProvider({}, with_delay=False, with_failure=False)) - - def test_create_environment_job(session, csp): environment = EnvironmentFactory.create() do_create_environment(csp, environment.id) @@ -291,3 +292,15 @@ def test_claim_for_update(session): # The claim is released assert environment.claimed_until is None + + +def test_create_user(csp, session): + environment = EnvironmentFactory.create( + root_user_info={"credentials": MockCloudProvider({})._auth_credentials} + ) + environment_role = EnvironmentRoleFactory.create(environment=environment) + do_create_user(csp, environment_role_id=environment_role.id) + + session.refresh(environment_role) + + assert environment_role.csp_user_id From d9e52c7741d9c7c23d40e38b4a1db578ab01f832 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Fri, 20 Sep 2019 10:12:23 -0400 Subject: [PATCH 2/8] Fix test_create_or_update_user --- tests/domain/test_mock_csp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/domain/test_mock_csp.py b/tests/domain/test_mock_csp.py index 27495f4c..941479b7 100644 --- a/tests/domain/test_mock_csp.py +++ b/tests/domain/test_mock_csp.py @@ -27,8 +27,8 @@ def test_create_environment_baseline(mock_csp: MockCloudProvider): def test_create_or_update_user(mock_csp: MockCloudProvider): - user_dict = mock_csp.create_or_update_user(CREDENTIALS, {}, "csp_role_id") - assert isinstance(user_dict["id"], str) + csp_user_id = mock_csp.create_or_update_user(CREDENTIALS, {}, "csp_role_id") + assert isinstance(csp_user_id, str) def test_suspend_user(mock_csp: MockCloudProvider): From 1ef4e437d7cced441bd5683080e32bd04f0aeb6b Mon Sep 17 00:00:00 2001 From: richard-dds Date: Fri, 20 Sep 2019 11:00:52 -0400 Subject: [PATCH 3/8] Schedule beat task for dispatch_create_user --- atst/queue.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/atst/queue.py b/atst/queue.py index 5fc12a3f..c7d117c6 100644 --- a/atst/queue.py +++ b/atst/queue.py @@ -18,6 +18,10 @@ def update_celery(celery, app): "task": "atst.jobs.dispatch_create_environment_baseline", "schedule": 60, }, + "beat-dispatch_provision_user": { + "task": "atst.jobs.dispatch_provision_user", + "schedule": 60, + }, } class ContextTask(celery.Task): From 2fca542100f034c79fcccd21079c4e24b12ad40e Mon Sep 17 00:00:00 2001 From: richard-dds Date: Fri, 20 Sep 2019 11:37:18 -0400 Subject: [PATCH 4/8] Implement dispatch query for provision_user --- ...477b211a07c_add_environment_role_status.py | 28 +++++++++++++++ atst/domain/environment_roles.py | 9 +++-- atst/jobs.py | 12 +++---- atst/models/environment.py | 8 +++++ atst/models/environment_role.py | 9 ++++- tests/test_jobs.py | 34 ++++++++++++++----- 6 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 alembic/versions/4477b211a07c_add_environment_role_status.py diff --git a/alembic/versions/4477b211a07c_add_environment_role_status.py b/alembic/versions/4477b211a07c_add_environment_role_status.py new file mode 100644 index 00000000..e659eb2b --- /dev/null +++ b/alembic/versions/4477b211a07c_add_environment_role_status.py @@ -0,0 +1,28 @@ +"""add environment_role status + +Revision ID: 4477b211a07c +Revises: e3d93f9caba7 +Create Date: 2019-09-20 11:04:10.961311 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '4477b211a07c' # pragma: allowlist secret +down_revision = 'e3d93f9caba7' # pragma: allowlist secret +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('environment_roles', sa.Column('status', sa.Enum('PENDING', 'COMPLETED', 'PENDING_DELETE', name='status', native_enum=False), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('environment_roles', 'status') + # ### end Alembic commands ### diff --git a/atst/domain/environment_roles.py b/atst/domain/environment_roles.py index 00ac730f..d8475f0e 100644 --- a/atst/domain/environment_roles.py +++ b/atst/domain/environment_roles.py @@ -1,7 +1,7 @@ from sqlalchemy.orm.exc import NoResultFound from atst.database import db -from atst.models import EnvironmentRole, ApplicationRole +from atst.models import EnvironmentRole, ApplicationRole, Environment from atst.domain.exceptions import NotFoundError from uuid import UUID from typing import List @@ -73,7 +73,10 @@ class EnvironmentRoles(object): def get_environment_roles_pending_creation(cls) -> List[UUID]: results = ( db.session.query(EnvironmentRole.id) - # TODO - .filter(EnvironmentRole.status == "PENDING").all() + .join(Environment) + .filter(Environment.deleted == False) + .filter(Environment.baseline_info != None) + .filter(EnvironmentRole.status == EnvironmentRole.Status.PENDING) + .all() ) return [id_ for id_, in results] diff --git a/atst/jobs.py b/atst/jobs.py index f702f13f..e861d8b5 100644 --- a/atst/jobs.py +++ b/atst/jobs.py @@ -102,14 +102,14 @@ def do_create_environment_baseline(csp: CloudProviderInterface, environment_id=N db.session.commit() -def do_create_user(csp: CloudProviderInterface, environment_role_id=None): +def do_provision_user(csp: CloudProviderInterface, environment_role_id=None): environment_role = EnvironmentRoles.get_by_id(environment_role_id) with claim_for_update(environment_role) as environment_role: - credentials = environment_role.environment.root_user_info["credentials"] + credentials = environment_role.environment.csp_credentials csp_user_id = csp.create_or_update_user( - credentials, environment_role, "role_id" + credentials, environment_role, environment_role.role ) environment_role.csp_user_id = csp_user_id db.session.add(environment_role) @@ -146,9 +146,9 @@ def create_environment_baseline(self, environment_id=None): @celery.task(bind=True) -def create_user(self, environment_role_id=None): +def provision_user(self, environment_role_id=None): do_work( - do_create_user, self, app.csp.cloud, environment_role_id=environment_role_id + do_provision_user, self, app.csp.cloud, environment_role_id=environment_role_id ) @@ -181,4 +181,4 @@ def dispatch_provision_user(self): for ( environment_role_id ) in EnvironmentRoles.get_environment_roles_pending_creation(): - create_user.delay(environment_role_id=environment_role_id) + provision_user.delay(environment_role_id=environment_role_id) diff --git a/atst/models/environment.py b/atst/models/environment.py index f3d85502..b8129fe5 100644 --- a/atst/models/environment.py +++ b/atst/models/environment.py @@ -84,3 +84,11 @@ class Environment( @property def history(self): return self.get_changes() + + @property + def csp_credentials(self): + return ( + self.root_user_info.get("credentials") + if self.root_user_info is not None + else None + ) diff --git a/atst/models/environment_role.py b/atst/models/environment_role.py index 9b23c300..988d19ab 100644 --- a/atst/models/environment_role.py +++ b/atst/models/environment_role.py @@ -1,5 +1,5 @@ from enum import Enum -from sqlalchemy import Index, ForeignKey, Column, String, TIMESTAMP +from sqlalchemy import Index, ForeignKey, Column, String, TIMESTAMP, Enum as SQLAEnum from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship @@ -36,6 +36,13 @@ class EnvironmentRole( csp_user_id = Column(String()) claimed_until = Column(TIMESTAMP(timezone=True)) + class Status(Enum): + PENDING = "pending" + COMPLETED = "completed" + PENDING_DELETE = "pending_delete" + + status = Column(SQLAEnum(Status, native_enum=False), default=Status.PENDING) + def __repr__(self): return "".format( self.role, self.application_role.user_name, self.environment.name, self.id diff --git a/tests/test_jobs.py b/tests/test_jobs.py index 89ff9be5..d8ffd319 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -16,11 +16,12 @@ from atst.jobs import ( dispatch_create_atat_admin_user, dispatch_create_environment_baseline, create_environment, - do_create_user, + dispatch_provision_user, ) from atst.models.utils import claim_for_update from atst.domain.exceptions import ClaimFailedException from tests.factories import EnvironmentFactory, EnvironmentRoleFactory, PortfolioFactory +from atst.models import EnvironmentRole @pytest.fixture(autouse=True, scope="function") @@ -294,13 +295,30 @@ def test_claim_for_update(session): assert environment.claimed_until is None -def test_create_user(csp, session): - environment = EnvironmentFactory.create( - root_user_info={"credentials": MockCloudProvider({})._auth_credentials} +def test_dispatch_provision_user(csp, session, celery_app, celery_worker, monkeypatch): + # Given that I have three environment roles: + # (A) one of which has a completed status + # (B) one of which has an environment that has not been provisioned + # (C) one of which is pending and has a provisioned environment + provisioned_environment = EnvironmentFactory.create( + cloud_id="cloud_id", root_user_info={}, baseline_info={} + ) + unprovisioned_environment = EnvironmentFactory.create() + _er_a = EnvironmentRoleFactory.create( + environment=provisioned_environment, status=EnvironmentRole.Status.COMPLETED + ) + _er_b = EnvironmentRoleFactory.create( + environment=unprovisioned_environment, status=EnvironmentRole.Status.PENDING + ) + er_c = EnvironmentRoleFactory.create( + environment=provisioned_environment, status=EnvironmentRole.Status.PENDING ) - environment_role = EnvironmentRoleFactory.create(environment=environment) - do_create_user(csp, environment_role_id=environment_role.id) - session.refresh(environment_role) + mock = Mock() + monkeypatch.setattr("atst.jobs.provision_user", mock) - assert environment_role.csp_user_id + # When I dispatch the user provisioning task + dispatch_provision_user.run() + + # I expect it to dispatch only one call, to EnvironmentRole C + mock.delay.assert_called_once_with(environment_role_id=er_c.id) From 4eee06ba44b98745a0bba6e466fdda871bcfaf29 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Fri, 20 Sep 2019 11:43:19 -0400 Subject: [PATCH 5/8] Add test for do_provision_user --- tests/test_jobs.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/test_jobs.py b/tests/test_jobs.py index d8ffd319..e5d4b0b4 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -17,6 +17,7 @@ from atst.jobs import ( dispatch_create_environment_baseline, create_environment, dispatch_provision_user, + do_provision_user, ) from atst.models.utils import claim_for_update from atst.domain.exceptions import ClaimFailedException @@ -322,3 +323,29 @@ def test_dispatch_provision_user(csp, session, celery_app, celery_worker, monkey # I expect it to dispatch only one call, to EnvironmentRole C mock.delay.assert_called_once_with(environment_role_id=er_c.id) + + +def test_do_provision_user(csp, session): + # Given that I have an EnvironmentRole with a provisioned environment + credentials = MockCloudProvider(())._auth_credentials + provisioned_environment = EnvironmentFactory.create( + cloud_id="cloud_id", + root_user_info={"credentials": credentials}, + baseline_info={}, + ) + environment_role = EnvironmentRoleFactory.create( + environment=provisioned_environment, + status=EnvironmentRole.Status.PENDING, + role="my_role", + ) + + # When I call the user provisoning task + do_provision_user(csp=csp, environment_role_id=environment_role.id) + + session.refresh(environment_role) + # I expect that the CSP create_or_update_user method will be called + csp.create_or_update_user.assert_called_once_with( + credentials, environment_role, "my_role" + ) + # I expect that the EnvironmentRole now has a csp_user_id + assert environment_role.csp_user_id From f523db4d2d44a9ccc4a9f0f363bab221204b7cec Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Sep 2019 10:44:37 -0400 Subject: [PATCH 6/8] Squash migrations related to env role provisioning --- ...477b211a07c_add_environment_role_status.py | 28 ------------------- ...d_environment_role_provisioning_fields.py} | 4 ++- 2 files changed, 3 insertions(+), 29 deletions(-) delete mode 100644 alembic/versions/4477b211a07c_add_environment_role_status.py rename alembic/versions/{e3d93f9caba7_add_environment_role_csp_fields.py => e3d93f9caba7_add_environment_role_provisioning_fields.py} (77%) diff --git a/alembic/versions/4477b211a07c_add_environment_role_status.py b/alembic/versions/4477b211a07c_add_environment_role_status.py deleted file mode 100644 index e659eb2b..00000000 --- a/alembic/versions/4477b211a07c_add_environment_role_status.py +++ /dev/null @@ -1,28 +0,0 @@ -"""add environment_role status - -Revision ID: 4477b211a07c -Revises: e3d93f9caba7 -Create Date: 2019-09-20 11:04:10.961311 - -""" -from alembic import op -import sqlalchemy as sa -from sqlalchemy.dialects import postgresql - -# revision identifiers, used by Alembic. -revision = '4477b211a07c' # pragma: allowlist secret -down_revision = 'e3d93f9caba7' # pragma: allowlist secret -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('environment_roles', sa.Column('status', sa.Enum('PENDING', 'COMPLETED', 'PENDING_DELETE', name='status', native_enum=False), nullable=True)) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('environment_roles', 'status') - # ### end Alembic commands ### diff --git a/alembic/versions/e3d93f9caba7_add_environment_role_csp_fields.py b/alembic/versions/e3d93f9caba7_add_environment_role_provisioning_fields.py similarity index 77% rename from alembic/versions/e3d93f9caba7_add_environment_role_csp_fields.py rename to alembic/versions/e3d93f9caba7_add_environment_role_provisioning_fields.py index 481a865a..98257583 100644 --- a/alembic/versions/e3d93f9caba7_add_environment_role_csp_fields.py +++ b/alembic/versions/e3d93f9caba7_add_environment_role_provisioning_fields.py @@ -1,4 +1,4 @@ -"""add environment_role csp fields +"""add environment_role provisioning fields Revision ID: e3d93f9caba7 Revises: 691b04ecd85e @@ -20,6 +20,7 @@ def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column('environment_roles', sa.Column('claimed_until', sa.TIMESTAMP(timezone=True), nullable=True)) op.add_column('environment_roles', sa.Column('csp_user_id', sa.String(), nullable=True)) + op.add_column('environment_roles', sa.Column('status', sa.Enum('PENDING', 'COMPLETED', 'PENDING_DELETE', name='status', native_enum=False), nullable=True)) # ### end Alembic commands ### @@ -27,4 +28,5 @@ def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_column('environment_roles', 'csp_user_id') op.drop_column('environment_roles', 'claimed_until') + op.drop_column('environment_roles', 'status') # ### end Alembic commands ### From 399cf74ed6e83b951c309be6d9f18c6a1039f27a Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Sep 2019 11:30:06 -0400 Subject: [PATCH 7/8] Only provision EnvironmentRoles with active ApplicationRoles --- atst/domain/environment_roles.py | 10 +++++++++- tests/test_jobs.py | 27 ++++++++++++++++++++------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/atst/domain/environment_roles.py b/atst/domain/environment_roles.py index d8475f0e..c3c89169 100644 --- a/atst/domain/environment_roles.py +++ b/atst/domain/environment_roles.py @@ -1,7 +1,13 @@ from sqlalchemy.orm.exc import NoResultFound from atst.database import db -from atst.models import EnvironmentRole, ApplicationRole, Environment +from atst.models import ( + EnvironmentRole, + ApplicationRole, + Environment, + ApplicationInvitation, + ApplicationRoleStatus, +) from atst.domain.exceptions import NotFoundError from uuid import UUID from typing import List @@ -74,9 +80,11 @@ class EnvironmentRoles(object): results = ( db.session.query(EnvironmentRole.id) .join(Environment) + .join(ApplicationRole) .filter(Environment.deleted == False) .filter(Environment.baseline_info != None) .filter(EnvironmentRole.status == EnvironmentRole.Status.PENDING) + .filter(ApplicationRole.status == ApplicationRoleStatus.ACTIVE) .all() ) return [id_ for id_, in results] diff --git a/tests/test_jobs.py b/tests/test_jobs.py index e5d4b0b4..212e8515 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -21,8 +21,13 @@ from atst.jobs import ( ) from atst.models.utils import claim_for_update from atst.domain.exceptions import ClaimFailedException -from tests.factories import EnvironmentFactory, EnvironmentRoleFactory, PortfolioFactory -from atst.models import EnvironmentRole +from tests.factories import ( + EnvironmentFactory, + EnvironmentRoleFactory, + PortfolioFactory, + ApplicationRoleFactory, +) +from atst.models import EnvironmentRole, ApplicationRoleStatus @pytest.fixture(autouse=True, scope="function") @@ -300,7 +305,8 @@ def test_dispatch_provision_user(csp, session, celery_app, celery_worker, monkey # Given that I have three environment roles: # (A) one of which has a completed status # (B) one of which has an environment that has not been provisioned - # (C) one of which is pending and has a provisioned environment + # (C) one of which is pending, has a provisioned environment but an inactive application role + # (D) one of which is pending, has a provisioned environment and has an active application role provisioned_environment = EnvironmentFactory.create( cloud_id="cloud_id", root_user_info={}, baseline_info={} ) @@ -311,8 +317,15 @@ def test_dispatch_provision_user(csp, session, celery_app, celery_worker, monkey _er_b = EnvironmentRoleFactory.create( environment=unprovisioned_environment, status=EnvironmentRole.Status.PENDING ) - er_c = EnvironmentRoleFactory.create( - environment=provisioned_environment, status=EnvironmentRole.Status.PENDING + _er_c = EnvironmentRoleFactory.create( + environment=unprovisioned_environment, + status=EnvironmentRole.Status.PENDING, + application_role=ApplicationRoleFactory(status=ApplicationRoleStatus.PENDING), + ) + er_d = EnvironmentRoleFactory.create( + environment=provisioned_environment, + status=EnvironmentRole.Status.PENDING, + application_role=ApplicationRoleFactory(status=ApplicationRoleStatus.ACTIVE), ) mock = Mock() @@ -321,8 +334,8 @@ def test_dispatch_provision_user(csp, session, celery_app, celery_worker, monkey # When I dispatch the user provisioning task dispatch_provision_user.run() - # I expect it to dispatch only one call, to EnvironmentRole C - mock.delay.assert_called_once_with(environment_role_id=er_c.id) + # I expect it to dispatch only one call, to EnvironmentRole D + mock.delay.assert_called_once_with(environment_role_id=er_d.id) def test_do_provision_user(csp, session): From 23319e0c39cce22c085819b320cea87a110db990 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 23 Sep 2019 11:45:33 -0400 Subject: [PATCH 8/8] Remove unused import --- atst/domain/environment_roles.py | 1 - 1 file changed, 1 deletion(-) diff --git a/atst/domain/environment_roles.py b/atst/domain/environment_roles.py index c3c89169..9dd59365 100644 --- a/atst/domain/environment_roles.py +++ b/atst/domain/environment_roles.py @@ -5,7 +5,6 @@ from atst.models import ( EnvironmentRole, ApplicationRole, Environment, - ApplicationInvitation, ApplicationRoleStatus, ) from atst.domain.exceptions import NotFoundError