Skip to content

Commit

Permalink
Adds signal env (#3756)
Browse files Browse the repository at this point in the history
* Adds signal env
  • Loading branch information
kevgliss authored Sep 7, 2023
1 parent 84a9cc2 commit e77bfb2
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Adds an environment variable for spliting up test and prod signals.
Revision ID: 1dd78f49e303
Revises: 4e57f5b1f3f3
Create Date: 2023-09-05 09:57:18.160124
"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = "1dd78f49e303"
down_revision = "4e57f5b1f3f3"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("signal", sa.Column("environment", sa.String(), nullable=True, default="prod"))
op.execute("UPDATE signal SET environment = 'prod'")
op.alter_column("signal", "environment", nullable=False)

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("signal", "environment")
# ### end Alembic commands ###
8 changes: 7 additions & 1 deletion src/dispatch/signal/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
from dispatch.signal import flows as signal_flows
from dispatch.signal import service as signal_service
from dispatch.signal.enums import SignalEngagementStatus
from dispatch.signal.models import SignalFilterAction, SignalInstance, SignalInstanceCreate
from dispatch.signal.models import (
SignalFilterAction,
SignalInstance,
SignalInstanceCreate,
SignalEnvironment,
)
from dispatch.workflow import flows as workflow_flows
from dispatch.entity_type.models import EntityScopeEnum

Expand Down Expand Up @@ -167,6 +172,7 @@ def create_signal_instance(
signal = signal_service.get_by_variant_or_external_id(
db_session=db_session,
project_id=project.id,
environment=signal_instance_data.get("environment", SignalEnvironment.PROD),
external_id=signal_instance_data.get("id"),
variant=signal_instance_data["variant"],
)
Expand Down
9 changes: 9 additions & 0 deletions src/dispatch/signal/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ class SignalFilterAction(DispatchEnum):
none = "none"


class SignalEnvironment(DispatchEnum):
PROD = "prod"
TEST = "test"


class Signal(Base, TimeStampMixin, ProjectMixin):
id = Column(Integer, primary_key=True)
name = Column(String)
Expand All @@ -141,6 +146,7 @@ class Signal(Base, TimeStampMixin, ProjectMixin):
variant = Column(String)
loopin_signal_identity = Column(Boolean, default=False)
enabled = Column(Boolean, default=False)
environment = Column(String, default=SignalEnvironment.PROD)
case_type_id = Column(Integer, ForeignKey(CaseType.id))
case_type = relationship("CaseType", backref="signals")
case_priority_id = Column(Integer, ForeignKey(CasePriority.id))
Expand Down Expand Up @@ -304,6 +310,7 @@ class SignalBase(DispatchBase):
enabled: Optional[bool] = False
external_url: Optional[str]
create_case: Optional[bool] = True
environment: Optional[SignalEnvironment] = SignalEnvironment.PROD
oncall_service: Optional[Service]
source: Optional[SourceBase]
created_at: Optional[datetime] = None
Expand All @@ -330,6 +337,7 @@ class SignalUpdate(SignalBase):
class SignalRead(SignalBase):
id: PrimaryKey
engagements: Optional[List[SignalEngagementRead]] = []
environment: Optional[SignalEnvironment] = SignalEnvironment.PROD
entity_types: Optional[List[EntityTypeRead]] = []
filters: Optional[List[SignalFilterRead]] = []
workflows: Optional[List[WorkflowRead]] = []
Expand All @@ -344,6 +352,7 @@ class SignalReadMinimal(DispatchBase):
description: Optional[str]
variant: Optional[str]
external_id: str
environment: Optional[SignalEnvironment] = SignalEnvironment.PROD
enabled: Optional[bool] = False
external_url: Optional[str]
create_case: Optional[bool] = True
Expand Down
19 changes: 16 additions & 3 deletions src/dispatch/signal/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,18 +225,31 @@ def get_by_primary_or_external_id(


def get_by_variant_or_external_id(
*, db_session: Session, project_id: int, external_id: str = None, variant: str = None
*,
db_session: Session,
project_id: int,
environment: str,
external_id: str = None,
variant: str = None,
) -> Optional[Signal]:
"""Gets a signal it's external id (and variant if supplied)."""
if variant:
return (
db_session.query(Signal)
.filter(Signal.project_id == project_id, Signal.variant == variant)
.filter(
Signal.project_id == project_id,
Signal.environment == environment,
Signal.variant == variant,
)
.one_or_none()
)
return (
db_session.query(Signal)
.filter(Signal.project_id == project_id, Signal.external_id == external_id)
.filter(
Signal.project_id == project_id,
Signal.environment == environment,
Signal.external_id == external_id,
)
.one_or_none()
)

Expand Down
10 changes: 6 additions & 4 deletions src/dispatch/signal/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import logging
from typing import Union

from fastapi import APIRouter, BackgroundTasks, HTTPException, Request, Response, status, Depends
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request, Response, status
from pydantic.error_wrappers import ErrorWrapper, ValidationError
from sqlalchemy.exc import IntegrityError

from dispatch.auth.permissions import SensitiveProjectActionPermission, PermissionsDependency
from dispatch.auth.permissions import PermissionsDependency, SensitiveProjectActionPermission
from dispatch.auth.service import CurrentUser
from dispatch.database.core import DbSession
from dispatch.database.service import CommonParameters, search_filter_sort_paginate
Expand All @@ -15,11 +15,13 @@
from dispatch.rate_limiter import limiter
from dispatch.signal import service as signal_service

from .flows import signal_instance_update_flow
from .models import (
SignalCreate,
SignalEngagementCreate,
SignalEngagementPagination,
SignalEngagementRead,
SignalEnvironment,
SignalFilterCreate,
SignalFilterPagination,
SignalFilterRead,
Expand All @@ -44,8 +46,6 @@
update_signal_filter,
)

from .flows import signal_instance_update_flow

router = APIRouter()

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -75,12 +75,14 @@ def create_signal_instance(
if not signal_instance_in.signal:
external_id = signal_instance_in.raw.get("externalId")
variant = signal_instance_in.raw.get("variant")
environment = signal_instance_in.raw.get("environment", SignalEnvironment.PROD)

if external_id or variant:
signal = signal_service.get_by_variant_or_external_id(
db_session=db_session,
project_id=project.id,
external_id=external_id,
environment=environment,
variant=variant,
)

Expand Down
1 change: 1 addition & 0 deletions tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ class SignalFactory(BaseFactory):
description = "Test Description"
external_url = "https://test.com"
external_id = "1234"
environment = "test"
variant = "Test Variant"
enabled = True
loopin_signal_identity = False
Expand Down
23 changes: 21 additions & 2 deletions tests/signal/test_signal_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def test_create_signal_instance(session, signal, case_severity, case_priority, u
case_severity.default = True
case_severity.project_id = signal.project_id

instance_data = {"variant": signal.variant}
instance_data = {"variant": signal.variant, "environment": "test"}

assert create_signal_instance(
db_session=session,
Expand All @@ -31,6 +31,25 @@ def test_create_signal_instance_no_variant(session, signal, case_severity, case_
case_severity.default = True
case_severity.project_id = signal.project_id

instance_data = {"variant": "unknown", "environment": "test"}
with pytest.raises(DispatchException):
create_signal_instance(
db_session=session,
project=signal.project,
signal_instance_data=instance_data,
current_user=user,
)


def test_create_signal_instance_no_environment(session, signal, case_severity, case_priority, user):
from dispatch.signal.flows import create_signal_instance

case_priority.default = True
case_priority.project_id = signal.project_id

case_severity.default = True
case_severity.project_id = signal.project_id

instance_data = {"variant": "unknown"}
with pytest.raises(DispatchException):
create_signal_instance(
Expand All @@ -51,7 +70,7 @@ def test_create_signal_instance_not_enabled(session, signal, case_severity, case
case_severity.project_id = signal.project_id

signal.enabled = False
instance_data = {"variant": signal.variant}
instance_data = {"variant": signal.variant, "environment": "test"}
with pytest.raises(DispatchException):
create_signal_instance(
db_session=session,
Expand Down

0 comments on commit e77bfb2

Please sign in to comment.