Skip to content

Commit

Permalink
Merge branch 'slack_integration' of https://github.com/DrDroidLab/Pla…
Browse files Browse the repository at this point in the history
…yBooks into slack_integration
  • Loading branch information
jayeshsadhwani99 committed Apr 27, 2024
2 parents 541e819 + 16b904a commit 6001a61
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 2 deletions.
54 changes: 53 additions & 1 deletion executor/workflows/tasks.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import logging
from datetime import timedelta, datetime

import time

from celery import shared_task
from django.conf import settings

from accounts.models import Account
from executor.crud.playbook_execution_crud import create_playbook_execution, get_db_playbook_execution
from executor.crud.playbooks_crud import get_db_playbook_step, get_db_playbook_task_definitions
from executor.models import PlayBook
from executor.task_executor import execute_task
from executor.tasks import execute_playbook
from executor.workflows.action.action_executor import action_executor
from executor.workflows.crud.workflow_execution_crud import get_db_workflow_executions, \
Expand All @@ -21,7 +26,7 @@
from playbooks.utils.utils import current_datetime
from protos.base_pb2 import TimeRange
from protos.playbooks.intelligence_layer.interpreter_pb2 import InterpreterType, Interpretation as InterpretationProto
from protos.playbooks.playbook_pb2 import PlaybookExecution as PlaybookExecutionProto
from protos.playbooks.playbook_pb2 import PlaybookExecution as PlaybookExecutionProto, PlaybookExecutionLog, PlaybookTaskDefinition, PlaybookTaskExecutionResult
from protos.playbooks.workflow_pb2 import WorkflowExecutionStatusType, Workflow as WorkflowProto, \
WorkflowAction as WorkflowActionProto, WorkflowActionNotificationConfig, WorkflowActionSlackNotificationConfig
from utils.proto_utils import dict_to_proto, proto_to_dict
Expand Down Expand Up @@ -195,3 +200,50 @@ def workflow_action_execution(account_id, workflow_id, workflow_execution_id, pl
workflow_action_execution_prerun_notifier = publish_pre_run_task(workflow_action_execution)
workflow_action_execution_failure_notifier = publish_task_failure(workflow_action_execution)
workflow_action_execution_postrun_notifier = publish_post_run_task(workflow_action_execution)


# @shared_task()
def test_workflow_notification(account_id, workflow, message_type):
if message_type == WorkflowActionSlackNotificationConfig.MessageType.MESSAGE:
pe_logs = []
account = Account.objects.get(id=account_id)
time_range = { "time_lt": str(int(time.time())), "time_geq": str(int(time.time()) - 3600) }
tr: TimeRange = dict_to_proto(time_range, TimeRange)

playbook_id = workflow.playbooks[0].id.value
playbook = PlayBook.objects.get(id=playbook_id)
p_proto = playbook.proto

playbook_steps = get_db_playbook_step(account, playbook_id, is_active=True)
try:
all_step_executions = {}
for step in list(playbook_steps):
playbook_task_definitions = get_db_playbook_task_definitions(account, playbook_id, step.id, is_active=True)
playbook_task_definitions = playbook_task_definitions.order_by('created_at')
all_task_executions = []
for task in playbook_task_definitions:
task_proto = task.proto
task_result = execute_task(account_id, tr, task_proto)
all_task_executions.append({
'task': task,
'task_result': proto_to_dict(task_result),
'task_result_proto': task_result,
})
all_step_executions[step] = all_task_executions

for step, all_task_results in all_step_executions.items():
for result in all_task_results:
playbook_execution_log = PlaybookExecutionLog(
playbook=playbook,
playbook_step=step,
playbook_task_definition=result['task'].proto,
playbook_task_result=result['task_result_proto'],
)
pe_logs.append(playbook_execution_log)

except Exception as exc:
logger.error(f"Error occurred while running playbook: {exc}")

execution_output: [InterpretationProto] = playbook_execution_result_interpret(InterpreterType.BASIC_I, p_proto,
pe_logs)
action_executor(account, workflow.actions[0], execution_output)
3 changes: 3 additions & 0 deletions executor/workflows/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
path('create', workflow_views.workflows_create),
path('update', workflow_views.workflows_update),

# Test Notification
path('test_notification', workflow_views.test_workflows_notification),

# Workflow Execution APIs
path('execute', workflow_views.workflows_execute),
path('executions/get', workflow_views.workflows_execution_get),
Expand Down
29 changes: 28 additions & 1 deletion executor/workflows/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from executor.workflows.crud.workflow_execution_utils import create_workflow_execution_util
from executor.workflows.crud.workflows_crud import create_db_workflow
from executor.workflows.crud.workflows_update_processor import workflows_update_processor
from executor.workflows.tasks import test_workflow_notification
from playbooks.utils.decorators import web_api
from playbooks.utils.meta import get_meta
from playbooks.utils.queryset import filter_page
Expand All @@ -20,7 +21,7 @@
CreateWorkflowResponse, UpdateWorkflowRequest, UpdateWorkflowResponse, ExecuteWorkflowRequest, \
ExecuteWorkflowResponse, ExecutionWorkflowGetRequest, ExecutionWorkflowGetResponse, ExecutionsWorkflowsListResponse, \
ExecutionsWorkflowsListRequest
from protos.playbooks.workflow_pb2 import Workflow as WorkflowProto, WorkflowSchedule as WorkflowScheduleProto
from protos.playbooks.workflow_pb2 import Workflow as WorkflowProto, WorkflowActionSlackNotificationConfig, WorkflowSchedule as WorkflowScheduleProto
from utils.proto_utils import dict_to_proto

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -94,6 +95,32 @@ def workflows_update(request_message: UpdateWorkflowRequest) -> Union[UpdateWork
return UpdateWorkflowResponse(success=BoolValue(value=True))


@web_api(CreateWorkflowRequest)
def test_workflows_notification(request_message: CreateWorkflowRequest) -> Union[CreateWorkflowResponse, HttpResponse]:
account: Account = get_request_account()
user = get_request_user()
workflow: WorkflowProto = request_message.workflow

if not workflow.playbooks or workflow.playbooks == []:
return CreateWorkflowResponse(success=BoolValue(value=False),
message=Message(title="Invalid Request", description="Select a playbook"))

if not workflow.entry_points or workflow.entry_points == []:
return CreateWorkflowResponse(success=BoolValue(value=False),
message=Message(title="Invalid Request", description="Select the trigger type"))

if not workflow.entry_points[0].alert_config.slack_channel_alert_config.slack_channel_id:
return CreateWorkflowResponse(success=BoolValue(value=False),
message=Message(title="Invalid Request", description="Select a slack channel"))

if not workflow.actions or workflow.actions == []:
return CreateWorkflowResponse(success=BoolValue(value=False),
message=Message(title="Invalid Request", description="Select a notification type"))

test_workflow_notification(account.id, workflow, workflow.actions[0].notification_config.slack_config.message_type)
return CreateWorkflowResponse(success=BoolValue(value=True))


@web_api(ExecuteWorkflowRequest)
def workflows_execute(request_message: ExecuteWorkflowRequest) -> Union[ExecuteWorkflowResponse, HttpResponse]:
account: Account = get_request_account()
Expand Down
14 changes: 14 additions & 0 deletions web/src/components/Workflows/create/CreateWorkflow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { showSnackbar } from "../../../store/features/snackbar/snackbarSlice.ts"
import { useLazyGetWorkflowQuery } from "../../../store/features/workflow/api/getWorkflowApi.ts";
import Loading from "../../common/Loading/index.tsx";
import { useUpdateWorkflowMutation } from "../../../store/features/workflow/api/updateWorkflowApi.ts";
import { useLazyTestWorkflowNotificationQuery } from "../../../store/features/workflow/api/testWorkflowNotificationApi.ts";
import { stateToWorkflow } from "../../../utils/parser/workflow/stateToWorkflow.ts";
import { validate } from "./utils/validation.ts";

Expand All @@ -28,6 +29,8 @@ function CreateTrigger() {
useUpdateWorkflowMutation();
const [triggerGetWorkflow, { isLoading: workflowLoading }] =
useLazyGetWorkflowQuery();
const [triggerTestWorkflowNotification] =
useLazyTestWorkflowNotificationQuery();
const currentWorkflow = useSelector(currentWorkflowSelector);

const handleSave = async () => {
Expand All @@ -51,6 +54,11 @@ function CreateTrigger() {
}
};

const handleTestNotification = () => {
triggerTestWorkflowNotification();
dispatch(showSnackbar("Test Notification Sent"));
};

useEffect(() => {
return () => {
dispatch(resetWorkflowState());
Expand Down Expand Up @@ -89,6 +97,12 @@ function CreateTrigger() {
type="submit">
{workflowId ? "Update" : "Save"}
</button>
{/* <button
onClick={handleTestNotification}
className="text-sm bg-transparent hover:bg-violet-500 p-2 border-violet-500 border hover:text-white text-violet-500 rounded transition-all"
type="submit">
Test Run
</button> */}
{(isLoading || updateLoading) && <CircularProgress size={20} />}
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions web/src/constants/api/workflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

export const GET_WORKFLOWS = "/executor/workflows/get";
export const CREATE_WORKFLOW = "/executor/workflows/create";
export const TEST_WORKFLOW_NOTIFICATION = "/executor/workflows/test_notification";
export const UPDATE_WORKFLOW = "/executor/workflows/update";
export const DELETE_WORKFLOW = "/executor/workflows/update";
export const GET_WORKFLOW_EXECUTIONS = "/executor/workflows/executions/list";
Expand Down
1 change: 1 addition & 0 deletions web/src/store/features/workflow/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./getWorkflowsApi.ts";
export * from "./createWorkflowApi.ts";
export * from "./testWorkflowNotificationApi.ts";
17 changes: 17 additions & 0 deletions web/src/store/features/workflow/api/testWorkflowNotificationApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { TEST_WORKFLOW_NOTIFICATION } from "../../../../constants/index.ts";
import { stateToWorkflow } from "../../../../utils/parser/workflow/stateToWorkflow.ts";
import { apiSlice } from "../../../app/apiSlice.ts";

export const testWorkflowNotificationApi = apiSlice.injectEndpoints({
endpoints: (builder) => ({
testWorkflowNotification: builder.query<any, any>({
query: () => ({
url: TEST_WORKFLOW_NOTIFICATION,
body: stateToWorkflow(),
method: "POST",
})
}),
}),
});

export const { useLazyTestWorkflowNotificationQuery } = testWorkflowNotificationApi;

0 comments on commit 6001a61

Please sign in to comment.