Skip to content

Commit

Permalink
Initial work
Browse files Browse the repository at this point in the history
  • Loading branch information
kevgliss committed Sep 23, 2020
1 parent 2df5f50 commit 4edcdb3
Show file tree
Hide file tree
Showing 30 changed files with 1,073 additions and 81 deletions.
1 change: 0 additions & 1 deletion requirements-base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,3 @@ statsmodels
tabulate
tenacity
uvicorn
metaflow
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,6 @@ def run(self):
"slack_conversation = dispatch.plugins.dispatch_slack.plugin:SlackConversationPlugin",
"zoom_conference = dispatch.plugins.dispatch_zoom.plugin:ZoomConferencePlugin",
"opsgenie_oncall = dispatch.plugins.dispatch_opsgenie.plugin:OpsGenieOncallPlugin",
"metaflow_external_workflow = dispatch.plugins.dispatch_metaflow.plugin:MetaflowExternalWorkflowPlugin",
],
},
)
2 changes: 1 addition & 1 deletion src/dispatch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os.path
from subprocess import check_output


try:
VERSION = __import__("pkg_resources").get_distribution("dispatch").version
except Exception:
Expand Down Expand Up @@ -36,6 +35,7 @@
from dispatch.term.models import Term # noqa lgtm[py/unused-import]
from dispatch.ticket.models import Ticket # noqa lgtm[py/unused-import]
from dispatch.plugin.models import Plugin # noqa lgtm[py/unused-import]
from dispatch.workflow.models import Workflow, WorkflowInstance # noqa lgtm[py/unused-import]
except Exception:
pass

Expand Down
41 changes: 41 additions & 0 deletions src/dispatch/alembic/versions/466823f3046e_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Adds artifact association table.
Revision ID: 466823f3046e
Revises: 7351fa734e2a
Create Date: 2020-09-23 12:42:38.268434
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "466823f3046e"
down_revision = "7351fa734e2a"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"workflow_instance_artifacts",
sa.Column("document_id", sa.Integer(), nullable=False),
sa.Column("workflow_instance_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["document_id"],
["document.id"],
),
sa.ForeignKeyConstraint(
["workflow_instance_id"],
["workflow_instance.id"],
),
sa.PrimaryKeyConstraint("document_id", "workflow_instance_id"),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("workflow_instance_artifacts")
# ### end Alembic commands ###
77 changes: 77 additions & 0 deletions src/dispatch/alembic/versions/7351fa734e2a_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""Adds workflow table.
Revision ID: 7351fa734e2a
Revises: ecdb4e7566f2
Create Date: 2020-09-23 11:42:36.889418
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils


# revision identifiers, used by Alembic.
revision = "7351fa734e2a"
down_revision = "ecdb4e7566f2"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"workflow",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(), nullable=True),
sa.Column("description", sa.String(), nullable=True),
sa.Column("is_active", sa.Boolean(), nullable=True),
sa.Column("parameters", sa.JSON(), nullable=True),
sa.Column("resource_id", sa.String(), nullable=True),
sa.Column("plugin_slug", sa.String(), nullable=True),
sa.Column("search_vector", sqlalchemy_utils.types.ts_vector.TSVectorType(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("updated_at", sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(
"ix_workflow_search_vector",
"workflow",
["search_vector"],
unique=False,
postgresql_using="gin",
)
op.create_table(
"workflow_instance",
sa.Column("resource_type", sa.String(), nullable=True),
sa.Column("resource_id", sa.String(), nullable=True),
sa.Column("weblink", sa.String(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("workflow_id", sa.Integer(), nullable=True),
sa.Column("creator_id", sa.Integer(), nullable=True),
sa.Column("status", sa.String(), nullable=True),
sa.Column("incident_id", sa.Integer(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("updated_at", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(
["creator_id"],
["participant.id"],
),
sa.ForeignKeyConstraint(
["incident_id"],
["incident.id"],
),
sa.ForeignKeyConstraint(
["workflow_id"],
["workflow.id"],
),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("workflow_instance")
op.drop_index("ix_workflow_search_vector", table_name="workflow")
op.drop_table("workflow")
# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions src/dispatch/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from dispatch.task.views import router as task_router
from dispatch.plugin.views import router as plugin_router
from dispatch.auth.views import user_router, auth_router
from dispatch.workflow.views import router as workflow_router

from .config import DISPATCH_AUTHENTICATION_PROVIDER_SLUG

Expand Down Expand Up @@ -57,6 +58,7 @@
authenticated_api_router.include_router(
incident_priority_router, prefix="/incident_priorities", tags=["incident_priorities"]
)
authenticated_api_router.include_router(workflow_router, prefix="/workflows", tags=["workflows"])
authenticated_api_router.include_router(plugin_router, prefix="/plugins", tags=["plugins"])

doc_router = APIRouter()
Expand Down
1 change: 1 addition & 0 deletions src/dispatch/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ def sync_triggers():
sync_trigger(engine, "team_contact", "search_vector", ["name", "company", "notes"])
sync_trigger(engine, "term", "search_vector", ["text"])
sync_trigger(engine, "dispatch_user", "search_vector", ["email"])
sync_trigger(engine, "workflow", "search_vector", ["name", "description"])


@dispatch_cli.group("database")
Expand Down
4 changes: 2 additions & 2 deletions src/dispatch/common/utils/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ def install_plugins():
"""

for ep in pkg_resources.iter_entry_points("dispatch.plugins"):
logger.debug(f"Attempting to load plugin: {ep.name}")
logger.info(f"Attempting to load plugin: {ep.name}")
try:
plugin = ep.load()
register(plugin)
logger.error(f"Successfully loaded plugin: {ep.name}")
logger.info(f"Successfully loaded plugin: {ep.name}")
except SQLAlchemyError:
logger.error(
"Something went wrong with creating plugin rows, is the database setup correctly?"
Expand Down
2 changes: 1 addition & 1 deletion src/dispatch/plugins/bases/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
from .task import TaskPlugin # noqa
from .term import TermPlugin # noqa
from .ticket import TicketPlugin # noqa
from .external_workflow import ExternalWorkflowPlugin # noqa
from .workflow import WorkflowPlugin # noqa
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
.. module: dispatch.plugins.bases.external_workflow
.. module: dispatch.plugins.bases.workflow
:platform: Unix
:copyright: (c) 2019 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
Expand All @@ -9,12 +9,12 @@
from dispatch.models import PluginOptionModel


class ExternalWorkflowPlugin(Plugin):
type = "external-workflow"
class WorkflowPlugin(Plugin):
type = "workflow"
_schema = PluginOptionModel

def list(self, **kwargs):
def get_instance(self, workflow_id: str, instance_id: str, **kwargs):
raise NotImplementedError

def run(self, **kwargs):
def run(self, workflow_id: str, params: dict, **kwargs):
raise NotImplementedError
1 change: 0 additions & 1 deletion src/dispatch/plugins/dispatch_metaflow/__init__.py

This file was deleted.

1 change: 0 additions & 1 deletion src/dispatch/plugins/dispatch_metaflow/_version.py

This file was deleted.

11 changes: 0 additions & 11 deletions src/dispatch/plugins/dispatch_metaflow/config.py

This file was deleted.

53 changes: 0 additions & 53 deletions src/dispatch/plugins/dispatch_metaflow/plugin.py

This file was deleted.

10 changes: 9 additions & 1 deletion src/dispatch/plugins/dispatch_slack/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
SLACK_COMMAND_UPDATE_INCIDENT_SLUG,
SLACK_COMMAND_UPDATE_NOTIFICATIONS_GROUP_SLUG,
SLACK_COMMAND_UPDATE_PARTICIPANT_SLUG,
SLACK_COMMAND_RUN_EXTERNAL_WORKFLOW_SLUG,
)


Expand All @@ -39,6 +40,10 @@
INCIDENT_CONVERSATION_TACTICAL_REPORT_SUGGESTION = f"Consider providing a tactical report using the `{SLACK_COMMAND_REPORT_TACTICAL_SLUG}` command."

INCIDENT_CONVERSATION_COMMAND_MESSAGE = {
SLACK_COMMAND_RUN_EXTERNAL_WORKFLOW_SLUG: {
"response_type": "ephemeral",
"text": "Opening a modal to run an external workflow...",
},
SLACK_COMMAND_REPORT_TACTICAL_SLUG: {
"response_type": "ephemeral",
"text": "Opening a dialog to write a tactical report...",
Expand Down Expand Up @@ -169,7 +174,10 @@ def get_template(message_type: MessageType):
default_notification,
INCIDENT_TASK_REMINDER_DESCRIPTION,
),
MessageType.incident_status_reminder: (default_notification, None,),
MessageType.incident_status_reminder: (
default_notification,
None,
),
MessageType.incident_task_list: (default_notification, INCIDENT_TASK_LIST_DESCRIPTION),
}

Expand Down
27 changes: 25 additions & 2 deletions src/dispatch/plugins/dispatch_slack/modals.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,11 @@ def report_incident_from_submitted_form(action: dict, db_session: Session = None
user_id = action["user"]["id"]
channel_id = submitted_form.get("private_metadata")["channel_id"]
dispatch_slack_service.send_ephemeral_message(
client=slack_client, conversation_id=channel_id, user_id=user_id, text="", blocks=blocks,
client=slack_client,
conversation_id=channel_id,
user_id=user_id,
text="",
blocks=blocks,
)

# Create the incident
Expand Down Expand Up @@ -849,4 +853,23 @@ def run_external_workflow_submitted_form(action: dict, db_session=None):
incident = incident_service.get(db_session=db_session, incident_id=incident_id)
params.update({"incident_id": incident.id, "incident_name": incident.name})
plugin = plugin_service.get_active(plugin_type="external-workflow", db_session=db_session)
plugin.instance.run(workflow_id, params)

workflow_resource = plugin.instance.run(workflow_id, params)

blocks = [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Workflow has been started.",
},
}
]

dispatch_slack_service.send_ephemeral_message(
slack_client,
incident.conversation.channel_id,
command["user_id"],
"No external workflow plugin.",
blocks=blocks,
)
7 changes: 7 additions & 0 deletions src/dispatch/static/dispatch/src/api/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ const Menu = [
icon: "playlist_add_check",
href: "/tasks"
},
{
title: "Workflows",
group: "workflows",
component: "Workflows",
icon: "work",
href: "/workflows"
},
/*{ header: "Routing" },
{
title: "Route",
Expand Down
14 changes: 13 additions & 1 deletion src/dispatch/static/dispatch/src/router/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,24 @@ export const protectedRoute = [
meta: { title: "Documents", icon: "view_compact", group: "knowledge", requiresAuth: true },
children: [
{
path: "/Documents",
path: "/documents",
name: "DocumentTable",
component: () => import(/* webpackChunkName: "definition-table" */ "@/document/Table.vue")
}
]
},
{
path: "/workflows",
component: DefaultLayout,
meta: { title: "Workflows", icon: "view_compac", group: "knowledge", requiresAuth: true },
children: [
{
path: "/workflows",
name: "WorkflowTable",
component: () => import(/* webpackChunkName: "definition-table" */ "@/workflow/Table.vue")
}
]
},
{
path: "/definitions",
component: DefaultLayout,
Expand Down

0 comments on commit 4edcdb3

Please sign in to comment.