Skip to content

Commit

Permalink
Adds a button to the resources tab to initiate a retry for creating a…
Browse files Browse the repository at this point in the history
…ny missing or unsuccessfully created incident resource(s)
  • Loading branch information
metroid-samus committed Sep 19, 2023
1 parent e148554 commit 9d2bb76
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 24 deletions.
53 changes: 29 additions & 24 deletions src/dispatch/incident/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,8 @@ def inactivate_incident_participants(incident: Incident, db_session: Session):
)


def incident_create_resources(*, incident_id: int, db_session=None) -> Incident:
def incident_create_resources(*, incident: Incident, db_session=None) -> Incident:
"""Creates all resources required for incidents."""
# we get the incident
incident = incident_service.get(db_session=db_session, incident_id=incident_id)

# we get the incident
incident = incident_service.get(db_session=db_session, incident_id=incident_id)

# we create the incident ticket
if not incident.ticket:
ticket_flows.create_incident_ticket(incident=incident, db_session=db_session)
Expand All @@ -157,35 +151,29 @@ def incident_create_resources(*, incident_id: int, db_session=None) -> Incident:
tactical_participant_emails = [i.email for i, _ in individual_participants]

# we create the tactical group
tactical_group = (
incident.tactical_group
if incident.tactical_group
else group_flows.create_group(
if not incident.tactical_group:
group_flows.create_group(
subject=incident,
group_type=GroupType.tactical,
group_participants=tactical_participant_emails,
db_session=db_session,
)
)

# we create the notifications group
notification_participant_emails = [t.email for t in team_participants]
notifications_group = (
incident.notifications_group
if incident.notifications_group
else group_flows.create_group(
if not incident.notifications_group:
notification_participant_emails = [t.email for t in team_participants]
group_flows.create_group(
subject=incident,
group_type=GroupType.notifications,
group_participants=notification_participant_emails,
db_session=db_session,
)
)

# we create the storage folder
if not incident.storage:
storage_members = []
if tactical_group and notifications_group:
storage_members = [tactical_group.email, notifications_group.email]
if incident.tactical_group and incident.notifications_group:
storage_members = [incident.tactical_group.email, incident.notifications_group.email]
else:
storage_members = tactical_participant_emails

Expand All @@ -205,8 +193,11 @@ def incident_create_resources(*, incident_id: int, db_session=None) -> Incident:
# we create the conference room
if not incident.conference:
conference_participants = []
if tactical_group and notifications_group:
conference_participants = [tactical_group.email, notifications_group.email]
if incident.tactical_group and incident.notifications_group:
conference_participants = [
incident.tactical_group.email,
incident.notifications_group.email,
]
else:
conference_participants = tactical_participant_emails

Expand Down Expand Up @@ -280,16 +271,30 @@ def incident_create_resources(*, incident_id: int, db_session=None) -> Incident:
db_session=db_session,
)

return incident


@background_task
def incident_create_flow(*, organization_slug: str, incident_id: int, db_session=None) -> Incident:
def incident_create_resources_flow(
*, organization_slug: str, incident_id: int, db_session=None
) -> Incident:
"""Creates all resources required for new incidents and initiates incident response workflow."""
# we get the incident
incident = incident_service.get(db_session=db_session, incident_id=incident_id)

# we create the incident resources
incident_create_resources(incident_id=incident_id, db_session=db_session)
return incident_create_resources(incident=incident, db_session=db_session)


@background_task
def incident_create_flow(*, organization_slug: str, incident_id: int, db_session=None) -> Incident:
"""Creates all resources required for new incidents and initiates incident response workflow."""
# we get the incident
incident = incident_service.get(db_session=db_session, incident_id=incident_id)

# we create the incident resources
incident_create_resources(incident=incident, db_session=db_session)

event_service.log_incident_event(
db_session=db_session,
source="Dispatch Core App",
Expand Down
16 changes: 16 additions & 0 deletions src/dispatch/incident/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
incident_delete_flow,
incident_subscribe_participant_flow,
incident_update_flow,
incident_create_resources_flow,
)
from .metrics import create_incident_metric_query, make_forecast
from .models import (
Expand Down Expand Up @@ -139,6 +140,21 @@ def create_incident(
return incident


@router.post(
"/{incident_id}/resources",
response_model=IncidentUpdate,
summary="Creates resources for an existing incident.",
)
def create_incident_resources(
organization: OrganizationSlug,
incident_id: PrimaryKey,
current_incident: CurrentIncident,
):
"""Creates resources for an existing incident."""
incident_create_resources_flow(organization_slug=organization, incident_id=incident_id)
return current_incident


@router.put(
"/{incident_id}",
response_model=IncidentRead,
Expand Down
42 changes: 42 additions & 0 deletions src/dispatch/static/dispatch/src/incident/ResourcesTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,45 @@
</v-list-item>
<v-divider />
</span>
<span v-if="(!ticket && ticketPluginEnabled) ||
(!conference && conferencePluginEnabled) ||
(!conversation && conversationPluginEnabled) ||
(!storage && storagePluginEnabled) ||
(!documents && documentPluginEnabled)
">
<v-list-item @click="createAllResources()">
<v-list-item-content>
<v-list-item-title>Recreate Missing Resources</v-list-item-title>
<v-list-item-subtitle>Initiate a retry for creating any missing or unsuccesfully created
resource(s).</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-action>
<v-list-item-icon>
<v-icon>refresh</v-icon>
</v-list-item-icon>
</v-list-item-action>
</v-list-item>
</span>
</v-list>
</template>

<script>
import { mapActions } from "vuex"
import { mapFields } from "vuex-map-fields"
export default {
name: "IncidentResourcesTab",
data() {
return {
ticketPluginEnabled: false,
conferencePluginEnabled: false,
conversationPluginEnabled: false,
storagePluginEnabled: false,
documentPluginEnabled: false,
}
},
computed: {
...mapFields("incident", [
"selected.ticket",
Expand All @@ -80,5 +110,17 @@ export default {
"selected.conversation",
]),
},
async mounted() {
this.ticketPluginEnabled = await this.isPluginEnabled("ticket")
this.conferencePluginEnabled = await this.isPluginEnabled("conference")
this.conversationPluginEnabled = await this.isPluginEnabled("conversation")
this.storagePluginEnabled = await this.isPluginEnabled("storage")
this.documentPluginEnabled = await this.isPluginEnabled("document")
},
methods: {
...mapActions("incident", ["createAllResources", "isPluginEnabled"]),
},
}
</script>
4 changes: 4 additions & 0 deletions src/dispatch/static/dispatch/src/incident/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,8 @@ export default {
createReport(incidentId, type, payload) {
return API.post(`/${resource}/${incidentId}/report/${type}`, payload)
},

createAllResources(incidentId, payload) {
return API.post(`/${resource}/${incidentId}/resources`, payload)
},
}
54 changes: 54 additions & 0 deletions src/dispatch/static/dispatch/src/incident/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { debounce } from "lodash"

import SearchUtils from "@/search/utils"
import IncidentApi from "@/incident/api"
import PluginApi from "@/plugin/api"
import router from "@/router"

const getDefaultSelectedState = () => {
Expand Down Expand Up @@ -345,6 +346,28 @@ const actions = {
)
})
},
createAllResources({ commit, dispatch }) {
commit("SET_SELECTED_LOADING", true)
return IncidentApi.createAllResources(state.selected.id)
.then(function () {
dispatch("get")
commit(
"notification_backend/addBeNotification",
{ text: "Incident resource(s) created successfully.", type: "success" },
{ root: true }
)
})
.catch(() => {
commit(
"notification_backend/addBeNotification",
{ text: "No incident resources created.", type: "error" },
{ root: true }
)
})
.finally(() => {
commit("SET_SELECTED_LOADING", false)
})
},
resetSelected({ commit }) {
commit("RESET_SELECTED")
},
Expand All @@ -369,6 +392,37 @@ const actions = {
)
})
},
isPluginEnabled(_, type) {
if (!state.selected.project) {
return false
}
return PluginApi.getAllInstances({
filter: JSON.stringify({
and: [
{
model: "PluginInstance",
field: "enabled",
op: "==",
value: "true",
},
{
model: "Project",
field: "name",
op: "==",
value: state.selected.project.name,
},
{
model: "Plugin",
field: "type",
op: "==",
value: String(type),
},
],
}),
}).then((response) => {
return response.data.items.length > 0
})
},
}

const mutations = {
Expand Down

0 comments on commit 9d2bb76

Please sign in to comment.