Update schema and create/update Environments domain methods to enforce environment name uniqueness within an application context.

This commit is contained in:
leigh-mil
2019-12-16 11:02:18 -05:00
parent a227044ccf
commit 812caf5d7d
4 changed files with 61 additions and 4 deletions

View File

@@ -0,0 +1,28 @@
"""add uniqueness contraint to environment within an application
Revision ID: 08f2a640e9c2
Revises: c487d91f1a26
Create Date: 2019-12-16 10:43:12.331095
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '08f2a640e9c2' # pragma: allowlist secret
down_revision = 'c487d91f1a26' # pragma: allowlist secret
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_unique_constraint('environments_name_application_id_key', 'environments', ['name', 'application_id'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('environments_name_application_id_key', 'environments', type_='unique')
# ### end Alembic commands ###

View File

@@ -12,6 +12,7 @@ from atst.models import (
CLIN, CLIN,
) )
from atst.domain.environment_roles import EnvironmentRoles from atst.domain.environment_roles import EnvironmentRoles
from atst.utils import update_or_raise_already_exists_error
from .exceptions import NotFoundError, DisabledError from .exceptions import NotFoundError, DisabledError
@@ -21,7 +22,7 @@ class Environments(object):
def create(cls, user, application, name): def create(cls, user, application, name):
environment = Environment(application=application, name=name, creator=user) environment = Environment(application=application, name=name, creator=user)
db.session.add(environment) db.session.add(environment)
db.session.commit() update_or_raise_already_exists_error(message="environment")
return environment return environment
@classmethod @classmethod
@@ -39,7 +40,8 @@ class Environments(object):
if name is not None: if name is not None:
environment.name = name environment.name = name
db.session.add(environment) db.session.add(environment)
db.session.commit() update_or_raise_already_exists_error(message="environment")
return environment
@classmethod @classmethod
def get(cls, environment_id): def get(cls, environment_id):

View File

@@ -1,4 +1,4 @@
from sqlalchemy import Column, ForeignKey, String, TIMESTAMP from sqlalchemy import Column, ForeignKey, String, TIMESTAMP, UniqueConstraint
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.dialects.postgresql import JSONB
from enum import Enum from enum import Enum
@@ -38,6 +38,12 @@ class Environment(
primaryjoin="and_(EnvironmentRole.environment_id == Environment.id, EnvironmentRole.deleted == False)", primaryjoin="and_(EnvironmentRole.environment_id == Environment.id, EnvironmentRole.deleted == False)",
) )
__table_args__ = (
UniqueConstraint(
"name", "application_id", name="environments_name_application_id_key"
),
)
class ProvisioningStatus(Enum): class ProvisioningStatus(Enum):
PENDING = "pending" PENDING = "pending"
COMPLETED = "completed" COMPLETED = "completed"

View File

@@ -4,7 +4,7 @@ from uuid import uuid4
from atst.domain.environments import Environments from atst.domain.environments import Environments
from atst.domain.environment_roles import EnvironmentRoles from atst.domain.environment_roles import EnvironmentRoles
from atst.domain.exceptions import NotFoundError, DisabledError from atst.domain.exceptions import AlreadyExistsError, DisabledError, NotFoundError
from atst.models.environment_role import CSPRole, EnvironmentRole from atst.models.environment_role import CSPRole, EnvironmentRole
from tests.factories import ( from tests.factories import (
@@ -100,6 +100,27 @@ def test_update_environment():
assert environment.name == "name 2" assert environment.name == "name 2"
def test_create_does_not_duplicate_names_within_application():
application = ApplicationFactory.create()
name = "Your Environment"
user = application.portfolio.owner
assert Environments.create(user, application, name)
with pytest.raises(AlreadyExistsError):
Environments.create(user, application, name)
def test_update_does_not_duplicate_names_within_application():
application = ApplicationFactory.create()
name = "Your Environment"
environment = EnvironmentFactory.create(application=application, name=name)
dupe_env = EnvironmentFactory.create(application=application)
user = application.portfolio.owner
with pytest.raises(AlreadyExistsError):
Environments.update(dupe_env, name)
class EnvQueryTest: class EnvQueryTest:
@property @property
def NOW(self): def NOW(self):