Implement dispatch query for provision_user

This commit is contained in:
richard-dds 2019-09-20 11:37:18 -04:00
parent 1ef4e437d7
commit 2fca542100
6 changed files with 82 additions and 18 deletions

View File

@ -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 ###

View File

@ -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]

View File

@ -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)

View File

@ -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
)

View File

@ -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 "<EnvironmentRole(role='{}', user='{}', environment='{}', id='{}')>".format(
self.role, self.application_role.user_name, self.environment.name, self.id

View File

@ -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)