Current section

Files

Jump to
step_flow lib step_flow notification_hooks notification_hook_manager.ex
Raw

lib/step_flow/notification_hooks/notification_hook_manager.ex

defmodule StepFlow.NotificationHooks.NotificationHookManager do
@moduledoc """
Notification manager context.
"""
alias StepFlow.Jobs
alias StepFlow.Workflows
require Logger
def get_last_status(workflow_notification_data) do
if StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "status") == nil do
[]
else
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "status")
end
end
def notification_slack_from_job(job, channel, exposed_domain_name, description) do
send(
:step_flow_slack_bot,
{:message,
"Error for job #{job.name} ##{job.id} <#{exposed_domain_name}/workflows/#{job.workflow_id} |Open Workflow>\n```#{description}```",
channel}
)
end
def notification_teams_from_job(job, url, workflow, exposed_domain_name, description) do
headers = [{"content-type", "application/json"}]
body =
Poison.encode!(%{
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
potentialAction: [
%{
"@type": "OpenUri",
name: "View Workflow",
targets: [
%{
os: "default",
uri: "#{exposed_domain_name}/workflows/#{job.workflow_id}"
}
]
}
],
sections: [
%{
facts: [
%{
name: "Posted By:",
value: "#{exposed_domain_name}"
},
%{
name: "Workflow Reference:",
value: "#{workflow.reference}"
},
%{
name: "Workflow ID:",
value: "#{workflow.id}"
},
%{
name: "Workflow Identifier:",
value: "#{workflow.identifier}"
},
%{
name: "Job ID:",
value: "#{job.id}"
},
%{
name: "Job:",
value: "#{job.name}"
}
],
text: "```#{description}```"
}
],
summary: "MCAI Workflow Error Notification",
themeColor: "FF5733",
title: "MCAI Workflow Error Notification"
})
Logger.debug(
"#{__MODULE__}: POST #{url}, headers: #{inspect(headers)}, body: #{inspect(body)}"
)
{:ok, response} = HTTPoison.request("POST", url, body, headers)
if response.status_code == 200 do
{:ok, response.body}
else
Logger.error("Unable to notify: #{inspect(response)}")
end
end
def notification_from_job(job_id, description \\ nil) do
job = Jobs.get_job!(job_id)
topic = "update_workflow_" <> Integer.to_string(job.workflow_id)
channel = StepFlow.Configuration.get_slack_channel()
workflow = Workflows.get_workflow!(job.workflow_id)
exposed_domain_name = StepFlow.Configuration.get_exposed_domain_name()
if StepFlow.Configuration.get_slack_token() != nil and description != nil and channel != nil do
notification_slack_from_job(job, channel, exposed_domain_name, description)
end
url = StepFlow.Configuration.get_teams_url()
if url != nil and description != nil do
notification_teams_from_job(job, url, workflow, exposed_domain_name, description)
end
StepFlow.Notification.send(topic, %{workflow_id: job.workflow_id})
end
def notify_endpoint_with_workflow_status(
workflow_notification_url,
workflow,
exposed_domain_name,
status_wf,
workflow_endpoint_credentials
) do
headers =
if workflow_endpoint_credentials != nil do
[
{"content-type", "application/json"},
{"Authorization", "Basic #{workflow_endpoint_credentials}"}
]
else
[{"content-type", "application/json"}]
end
body =
if status_wf == "workflow_error" do
Poison.encode!(%{
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
potentialAction: [
%{
"@type": "OpenUri",
name: "View Workflow",
targets: [
%{
os: "default",
uri: "#{exposed_domain_name}/workflows/#{workflow.id}"
}
]
}
],
sections: [
%{
facts: [
%{
name: "Posted By",
value: "#{exposed_domain_name}"
},
%{
name: "Workflow Reference",
value: "#{workflow.reference}"
},
%{
name: "Workflow ID",
value: "#{workflow.id}"
},
%{
name: "Workflow Identifier",
value: "#{workflow.identifier}"
},
%{
name: "Workflow Status",
value: "#{status_wf}"
}
]
}
],
summary: "MCAI Workflow Error Notification",
themeColor: "FF5733",
title: "MCAI Workflow Error Notification"
})
else
Poison.encode!(%{
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
potentialAction: [
%{
"@type": "OpenUri",
name: "View Workflow",
targets: [
%{
os: "default",
uri: "#{exposed_domain_name}/workflows/#{workflow.id}"
}
]
}
],
sections: [
%{
facts: [
%{
name: "Posted By",
value: "#{exposed_domain_name}"
},
%{
name: "Workflow Reference",
value: "#{workflow.reference}"
},
%{
name: "Workflow ID",
value: "#{workflow.id}"
},
%{
name: "Workflow Identifier",
value: "#{workflow.identifier}"
},
%{
name: "Workflow Status",
value: "#{status_wf}"
}
]
}
],
summary: "MCAI Workflow Success Notification",
themeColor: "339933",
title: "MCAI Workflow Success Notification"
})
end
Logger.debug(
"#{__MODULE__}: POST #{workflow_notification_url}, headers: #{inspect(headers)}, body: #{inspect(body)}"
)
{_, response} = HTTPoison.request("POST", workflow_notification_url, body, headers)
%{
"condition" => status_wf,
"timestamp" =>
NaiveDateTime.utc_now()
|> NaiveDateTime.to_string()
|> NaiveDateTime.from_iso8601!()
|> NaiveDateTime.truncate(:second),
"response" => response.status_code
}
end
def notify_endpoint_with_job_status(
workflow_notification_url,
job,
workflow,
exposed_domain_name,
status_job,
workflow_endpoint_credentials
) do
headers =
if workflow_endpoint_credentials != nil do
[
{"content-type", "application/json"},
{"Authorization", "Basic #{workflow_endpoint_credentials}"}
]
else
[{"content-type", "application/json"}]
end
body =
if status_job == "job_error" do
Poison.encode!(%{
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
potentialAction: [
%{
"@type": "OpenUri",
name: "View Workflow",
targets: [
%{
os: "default",
uri: "#{exposed_domain_name}/workflows/#{workflow.id}"
}
]
}
],
sections: [
%{
facts: [
%{
name: "Posted By",
value: "#{exposed_domain_name}"
},
%{
name: "Workflow Reference",
value: "#{workflow.reference}"
},
%{
name: "Workflow ID",
value: "#{workflow.id}"
},
%{
name: "Job Id",
value: "#{job.id}"
},
%{
name: "Job Status",
value: "#{status_job}"
}
]
}
],
summary: "MCAI Job Error Notification",
themeColor: "FF5733",
title: "MCAI Job Error Notification"
})
else
Poison.encode!(%{
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
potentialAction: [
%{
"@type": "OpenUri",
name: "View Workflow",
targets: [
%{
os: "default",
uri: "#{exposed_domain_name}/workflows/#{workflow.id}"
}
]
}
],
sections: [
%{
facts: [
%{
name: "Posted By",
value: "#{exposed_domain_name}"
},
%{
name: "Workflow Reference",
value: "#{workflow.reference}"
},
%{
name: "Workflow ID",
value: "#{workflow.id}"
},
%{
name: "Job Id",
value: "#{job.id}"
},
%{
name: "Job Status",
value: "#{status_job}"
}
]
}
],
summary: "MCAI Job Success Notification",
themeColor: "339933",
title: "MCAI Job Success Notification"
})
end
Logger.debug(
"#{__MODULE__}: POST #{workflow_notification_url}, headers: #{inspect(headers)}, body: #{inspect(body)}"
)
{_, response} = HTTPoison.request("POST", workflow_notification_url, body, headers)
%{
"condition" => status_job <> "_" <> Integer.to_string(job.id),
"timestamp" =>
NaiveDateTime.utc_now()
|> NaiveDateTime.to_string()
|> NaiveDateTime.from_iso8601!()
|> NaiveDateTime.truncate(:second),
"response" => response.status_code
}
end
def retrieve_status(
conditions,
job_status,
"job",
workflow_notification_data,
job,
workflow,
exposed_domain_name
) do
cond do
Enum.member?(
conditions,
"job_completed"
) and job_status == "completed" ->
notify_endpoint_with_job_status(
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "endpoint"),
job,
workflow,
exposed_domain_name,
"job_completed",
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "credentials")
)
Enum.member?(
conditions,
"job_error"
) and job_status == "error" ->
notify_endpoint_with_job_status(
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "endpoint"),
job,
workflow,
exposed_domain_name,
"job_error",
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "credentials")
)
true ->
nil
end
end
def retrieve_status(
conditions,
workflow_status,
"workflow",
workflow_notification_data,
workflow,
exposed_domain_name
) do
cond do
Enum.member?(
conditions,
"workflow_completed"
) and workflow_status == "completed" ->
notify_endpoint_with_workflow_status(
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "endpoint"),
workflow,
exposed_domain_name,
"workflow_completed",
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "credentials")
)
Enum.member?(
conditions,
"workflow_error"
) and workflow_status == "error" ->
notify_endpoint_with_workflow_status(
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "endpoint"),
workflow,
exposed_domain_name,
"workflow_error",
StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "credentials")
)
true ->
nil
end
end
def manage_notification_status(job_id, "job", job_status) do
job = Jobs.get_job!(job_id)
workflow = Workflows.get_workflow!(job.workflow_id)
exposed_domain_name = StepFlow.Configuration.get_exposed_domain_name()
workflow_notifications_with_status =
for workflow_notification_data <- workflow.notification_hooks do
conditions = StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "conditions")
last_status = get_last_status(workflow_notification_data)
new_status =
retrieve_status(
conditions,
job_status,
"job",
workflow_notification_data,
job,
workflow,
exposed_domain_name
)
if new_status != nil do
Map.put(workflow_notification_data, "status", last_status ++ [new_status])
else
workflow_notification_data
end
end
{_, workflow} =
Workflows.update_workflow(workflow, %{
notification_hooks: workflow_notifications_with_status
})
workflow
end
def manage_notification_status(workflow_id, "workflow", workflow_status) do
workflow = Workflows.get_workflow!(workflow_id)
exposed_domain_name = StepFlow.Configuration.get_exposed_domain_name()
workflow_notifications_with_status =
for workflow_notification_data <- workflow.notification_hooks do
conditions = StepFlow.Map.get_by_key_or_atom(workflow_notification_data, "conditions")
last_status = get_last_status(workflow_notification_data)
new_status =
retrieve_status(
conditions,
workflow_status,
"workflow",
workflow_notification_data,
workflow,
exposed_domain_name
)
if new_status != nil do
Map.put(workflow_notification_data, "status", last_status ++ [new_status])
else
workflow_notification_data
end
end
{_, workflow} =
Workflows.update_workflow(workflow, %{
notification_hooks: workflow_notifications_with_status
})
workflow
end
end