Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/workflows #583

Merged
merged 26 commits into from
Oct 6, 2020
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e553c09
Initial work
kevgliss Sep 16, 2020
0651d24
Initial work completed
kevgliss Sep 18, 2020
e3fdfef
wrong metaflow
kevgliss Sep 21, 2020
5901137
fixing unused imports
kevgliss Sep 21, 2020
ec2aa35
Allow multiple apps
kevgliss Sep 21, 2020
502a4f6
Initial work
kevgliss Sep 23, 2020
a095feb
Adds basic UI
kevgliss Sep 24, 2020
566490c
More work on workflow syncing.
kevgliss Sep 25, 2020
fb5300e
Adding completion messages and artifact display.
kevgliss Sep 29, 2020
c773336
Adds created notification
kevgliss Sep 29, 2020
d1e81a4
Improves syncing and adds 'list-workflows' command
kevgliss Sep 30, 2020
f88593d
Fixing artifact links and skipping completed workflows
kevgliss Sep 30, 2020
e905295
Avoid duplicate documents on update
kevgliss Sep 30, 2020
32e589e
Merge branch 'master' into feature/workflows
kevgliss Oct 1, 2020
a042659
adding reason and incident details tab
kevgliss Oct 1, 2020
4c0061c
Merge branch 'feature/workflows' of github.com:Netflix/dispatch into …
kevgliss Oct 1, 2020
bd90414
Remove unused import
kevgliss Oct 2, 2020
2c55635
Update src/dispatch/workflow/views.py
kevgliss Oct 2, 2020
6ec5dc3
Update src/dispatch/workflow/views.py
kevgliss Oct 2, 2020
4efc340
Update src/dispatch/workflow/views.py
kevgliss Oct 2, 2020
06dae11
Update src/dispatch/workflow/views.py
kevgliss Oct 2, 2020
e7e3e37
Update src/dispatch/workflow/service.py
kevgliss Oct 2, 2020
1c3981e
Update src/dispatch/plugins/dispatch_slack/modals.py
kevgliss Oct 2, 2020
8dc9979
Adding suggestions
kevgliss Oct 2, 2020
7f8424c
Merge branch 'feature/workflows' of github.com:Netflix/dispatch into …
kevgliss Oct 2, 2020
605b519
Merge branch 'master' into feature/workflows
kevgliss Oct 2, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 # noqa lgtm[py/unused-import]
except Exception:
pass

Expand Down
28 changes: 28 additions & 0 deletions src/dispatch/alembic/versions/189759c2b5bf_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Adding a run reason.

Revision ID: 189759c2b5bf
Revises: 99f3dec93615
Create Date: 2020-10-01 14:53:31.791427

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "189759c2b5bf"
down_revision = "99f3dec93615"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("workflow_instance", sa.Column("run_reason", sa.String(), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("workflow_instance", "run_reason")
# ### end Alembic commands ###
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 ###
32 changes: 32 additions & 0 deletions src/dispatch/alembic/versions/72c7fa0ce0a3_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Adds workflow plugins.

Revision ID: 72c7fa0ce0a3
Revises: 466823f3046e
Create Date: 2020-09-24 10:00:34.338853

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '72c7fa0ce0a3'
down_revision = '466823f3046e'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('workflow', sa.Column('plugin_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'workflow', 'plugin', ['plugin_id'], ['id'])
op.drop_column('workflow', 'plugin_slug')
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('workflow', sa.Column('plugin_slug', sa.VARCHAR(), autoincrement=False, nullable=True))
op.drop_constraint(None, 'workflow', type_='foreignkey')
op.drop_column('workflow', 'plugin_id')
# ### 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 ###
32 changes: 32 additions & 0 deletions src/dispatch/alembic/versions/995a59897e01_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Allows plugins to be disable.

Revision ID: 995a59897e01
Revises: 72c7fa0ce0a3
Create Date: 2020-09-24 10:08:07.729599

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "995a59897e01"
down_revision = "72c7fa0ce0a3"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("workflow", sa.Column("enabled", sa.Boolean(), nullable=True))
op.drop_column("workflow", "is_active")
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"workflow", sa.Column("is_active", sa.BOOLEAN(), autoincrement=False, nullable=True)
)
op.drop_column("workflow", "enabled")
# ### end Alembic commands ###
66 changes: 66 additions & 0 deletions src/dispatch/alembic/versions/99f3dec93615_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Adds priorities, terms, types, and artifact relationships and tables.

Revision ID: 99f3dec93615
Revises: 9f927a8e4679
Create Date: 2020-09-28 15:47:08.865362

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '99f3dec93615'
down_revision = '9f927a8e4679'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('workflow_incident_priority',
sa.Column('incident_priority_id', sa.Integer(), nullable=False),
sa.Column('workflow_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['incident_priority_id'], ['incident_priority.id'], ),
sa.ForeignKeyConstraint(['workflow_id'], ['workflow.id'], ),
sa.PrimaryKeyConstraint('incident_priority_id', 'workflow_id')
)
op.create_table('workflow_incident_type',
sa.Column('incident_type_id', sa.Integer(), nullable=False),
sa.Column('workflow_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['incident_type_id'], ['incident_type.id'], ),
sa.ForeignKeyConstraint(['workflow_id'], ['workflow.id'], ),
sa.PrimaryKeyConstraint('incident_type_id', 'workflow_id')
)
op.create_table('workflow_term',
sa.Column('term_id', sa.Integer(), nullable=False),
sa.Column('workflow_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['term_id'], ['term.id'], ),
sa.ForeignKeyConstraint(['workflow_id'], ['workflow.id'], ),
sa.PrimaryKeyConstraint('term_id', 'workflow_id')
)
op.create_table('workflow_instance_artifact',
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')
)
op.drop_table('workflow_instance_artifacts')
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('workflow_instance_artifacts',
sa.Column('document_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('workflow_instance_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['document_id'], ['document.id'], name='workflow_instance_artifacts_document_id_fkey'),
sa.ForeignKeyConstraint(['workflow_instance_id'], ['workflow_instance.id'], name='workflow_instance_artifacts_workflow_instance_id_fkey'),
sa.PrimaryKeyConstraint('document_id', 'workflow_instance_id', name='workflow_instance_artifacts_pkey')
)
op.drop_table('workflow_instance_artifact')
op.drop_table('workflow_term')
op.drop_table('workflow_incident_type')
op.drop_table('workflow_incident_priority')
# ### end Alembic commands ###
28 changes: 28 additions & 0 deletions src/dispatch/alembic/versions/9f927a8e4679_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Adds instance parameters.

Revision ID: 9f927a8e4679
Revises: 995a59897e01
Create Date: 2020-09-25 12:48:21.180604

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '9f927a8e4679'
down_revision = '995a59897e01'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('workflow_instance', sa.Column('parameters', sa.JSON(), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('workflow_instance', 'parameters')
# ### 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
2 changes: 2 additions & 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 Expand Up @@ -418,6 +419,7 @@ def dispatch_scheduler():
from .tag.scheduled import sync_tags # noqa
from .task.scheduled import sync_tasks, create_task_reminders # noqa
from .term.scheduled import sync_terms # noqa
from .workflow.scheduled import sync_workflows, sync_active_stable_workflows # noqa


@dispatch_scheduler.command("list")
Expand Down
2 changes: 2 additions & 0 deletions src/dispatch/common/utils/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ def install_plugins():
logger.error(
"Something went wrong with creating plugin rows, is the database setup correctly?"
)
except KeyError as e:
logger.warning(f"failed to load plugin {ep.name}. Reason: {e}")
except Exception:
logger.error(f"Failed to load plugin {ep.name}:{traceback.format_exc()}")
else:
Expand Down
13 changes: 13 additions & 0 deletions src/dispatch/document/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ def create(*, db_session, document_in: DocumentCreate) -> Document:
return document


def get_or_create(*, db_session, document_in) -> Document:
kevgliss marked this conversation as resolved.
Show resolved Hide resolved
if hasattr(document_in, "resource_id"):
q = db_session.query(Document).filter(Document.resource_id == document_in.resource_id)
else:
q = db_session.query(Document).filter_by(**document_in.dict())

instance = q.first()
if instance:
return instance

return create(db_session=db_session, document_in=document_in)


def update(*, db_session, document: Document, document_in: DocumentUpdate) -> Document:
"""Updates a document."""
document_data = jsonable_encoder(document)
Expand Down