diff --git a/plugins/splunk-on-call/README.md b/plugins/splunk-on-call/README.md index 5276d6d2df..78313d3329 100644 --- a/plugins/splunk-on-call/README.md +++ b/plugins/splunk-on-call/README.md @@ -48,22 +48,18 @@ import { ## Client configuration -In order to be able to perform certain action (create-acknowledge-resolve an action), you need to provide the username of the user making the action. -The user supplied must be a valid Splunk On-Call user and a member of your organization. +In order to be able to perform certain action (create-acknowledge-resolve an action), you need to provide a REST Endpoint. -In addition, you also need to enable the REST Endpoint integration on https://portal.victorops.com/ by going to Integrations > 3rd Party Integrations > REST – Generic. +To enable the REST Endpoint integration you can go on https://portal.victorops.com/ inside Integrations > 3rd Party Integrations > REST – Generic. You can now copy the URL to notify: `/$routing_key` In `app-config.yaml`: ```yaml splunkOnCall: - username: eventsRestEndpoint: ``` -The user supplied must be a valid Splunk On-Call user and a member of your organization. - In order to make the API calls, you need to provide a new proxy config which will redirect to the Splunk On-Call API endpoint and add authentication information in the headers: ```yaml diff --git a/plugins/splunk-on-call/src/api/client.ts b/plugins/splunk-on-call/src/api/client.ts index 616ebb7023..045ea04d63 100644 --- a/plugins/splunk-on-call/src/api/client.ts +++ b/plugins/splunk-on-call/src/api/client.ts @@ -42,12 +42,9 @@ export const splunkOnCallApiRef = createApiRef({ export class SplunkOnCallClient implements SplunkOnCallApi { static fromConfig(configApi: ConfigApi, discoveryApi: DiscoveryApi) { - const usernameFromConfig: string | null = - configApi.getOptionalString('splunkOnCall.username') || null; const eventsRestEndpoint: string | null = configApi.getOptionalString('splunkOnCall.eventsRestEndpoint') || null; return new SplunkOnCallClient({ - username: usernameFromConfig, eventsRestEndpoint, discoveryApi, }); diff --git a/plugins/splunk-on-call/src/api/types.ts b/plugins/splunk-on-call/src/api/types.ts index b4007a9051..b42ab6a287 100644 --- a/plugins/splunk-on-call/src/api/types.ts +++ b/plugins/splunk-on-call/src/api/types.ts @@ -89,7 +89,6 @@ export type OnCallsResponse = { }; export type ClientApiConfig = { - username: string | null; eventsRestEndpoint: string | null; discoveryApi: DiscoveryApi; }; diff --git a/plugins/splunk-on-call/src/components/Escalation/EscalationPolicy.tsx b/plugins/splunk-on-call/src/components/Escalation/EscalationPolicy.tsx index 9538a0e73b..4234ba1621 100644 --- a/plugins/splunk-on-call/src/components/Escalation/EscalationPolicy.tsx +++ b/plugins/splunk-on-call/src/components/Escalation/EscalationPolicy.tsx @@ -15,7 +15,13 @@ */ import React from 'react'; -import { List, ListSubheader } from '@material-ui/core'; +import { + createStyles, + List, + ListSubheader, + makeStyles, + Theme, +} from '@material-ui/core'; import { EscalationUsersEmptyState } from './EscalationUsersEmptyState'; import { EscalationUser } from './EscalationUser'; import { useAsync } from 'react-use'; @@ -24,12 +30,28 @@ import { useApi, Progress } from '@backstage/core'; import { Alert } from '@material-ui/lab'; import { User } from '../types'; +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + maxHeight: '400px', + overflow: 'auto', + }, + subheader: { + backgroundColor: 'white', + }, + progress: { + margin: `0 ${theme.spacing(2)}px`, + }, + }), +); + type Props = { users: { [key: string]: User }; team: string; }; export const EscalationPolicy = ({ users, team }: Props) => { + const classes = useStyles(); const api = useApi(splunkOnCallApiRef); const { value: userNames, loading, error } = useAsync(async () => { @@ -54,24 +76,30 @@ export const EscalationPolicy = ({ users, team }: Props) => { ); } - if (loading) { - return ; - } - - if (!userNames?.length) { + if (!loading && !userNames?.length) { return ; } return ( - ON CALL}> - {userNames && + ON CALL + } + > + {loading ? ( + + ) : ( + userNames && userNames.map( (userName, index) => userName && userName in users && ( ), - )} + ) + )} ); }; diff --git a/plugins/splunk-on-call/src/components/Incident/Incidents.tsx b/plugins/splunk-on-call/src/components/Incident/Incidents.tsx index 507020f0a5..189367542d 100644 --- a/plugins/splunk-on-call/src/components/Incident/Incidents.tsx +++ b/plugins/splunk-on-call/src/components/Incident/Incidents.tsx @@ -15,7 +15,13 @@ */ import React, { useEffect } from 'react'; -import { List, ListSubheader } from '@material-ui/core'; +import { + createStyles, + List, + ListSubheader, + makeStyles, + Theme, +} from '@material-ui/core'; import { IncidentListItem } from './IncidentListItem'; import { IncidentsEmptyState } from './IncidentEmptyState'; import { useAsyncFn } from 'react-use'; @@ -23,12 +29,28 @@ import { splunkOnCallApiRef } from '../../api'; import { useApi, Progress } from '@backstage/core'; import { Alert } from '@material-ui/lab'; +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + maxHeight: '400px', + overflow: 'auto', + }, + subheader: { + backgroundColor: 'white', + }, + progress: { + margin: `0 ${theme.spacing(2)}px`, + }, + }), +); + type Props = { refreshIncidents: boolean; team: string; }; export const Incidents = ({ refreshIncidents, team }: Props) => { + const classes = useStyles(); const api = useApi(splunkOnCallApiRef); const [{ value: incidents, loading, error }, getIncidents] = useAsyncFn( @@ -61,24 +83,32 @@ export const Incidents = ({ refreshIncidents, team }: Props) => { ); } - if (loading) { - return ; - } - - if (!incidents?.length) { + if (!loading && !incidents?.length) { return ; } return ( - INCIDENTS}> - {incidents!.map((incident, index) => ( - getIncidents()} - key={index} - team={team} - incident={incident} - /> - ))} + + CRITICAL INCIDENTS + + } + > + {loading ? ( + + ) : ( + incidents!.map((incident, index) => ( + getIncidents()} + key={index} + team={team} + incident={incident} + /> + )) + )} ); }; diff --git a/plugins/splunk-on-call/src/components/SplunkOnCallCard.tsx b/plugins/splunk-on-call/src/components/SplunkOnCallCard.tsx index e2cc642c6a..8a7364fea9 100644 --- a/plugins/splunk-on-call/src/components/SplunkOnCallCard.tsx +++ b/plugins/splunk-on-call/src/components/SplunkOnCallCard.tsx @@ -34,6 +34,7 @@ import { } from '@material-ui/core'; import { Incidents } from './Incident'; import { EscalationPolicy } from './Escalation'; +import WebIcon from '@material-ui/icons/Web'; import { useAsync } from 'react-use'; import { Alert } from '@material-ui/lab'; import { splunkOnCallApiRef, UnauthorizedError } from '../api'; @@ -64,16 +65,6 @@ export const MissingTeamAnnotation = () => ( ); -export const MissingUsername = () => ( - - - -); - export const MissingEventsRestEndpoint = () => ( { const [refreshIncidents, setRefreshIncidents] = useState(false); const team = entity.metadata.annotations![SPLUNK_ON_CALL_TEAM]; - const username = config.getOptionalString('splunkOnCall.username') || null; - const eventsRestEndpoint = config.getOptionalString('splunkOnCall.eventsRestEndpoint') || null; @@ -126,9 +115,6 @@ export const SplunkOnCallCard = ({ entity }: Props) => { return { usersHashMap, userList: allUsers }; }); - const incidentCreator = - username && users?.userList.find(user => user.username === username); - if (error instanceof UnauthorizedError) { return ; } @@ -149,9 +135,6 @@ export const SplunkOnCallCard = ({ entity }: Props) => { if (!team) { return ; } - if (!username || !incidentCreator) { - return ; - } if (!eventsRestEndpoint) { return ; @@ -163,15 +146,12 @@ export const SplunkOnCallCard = ({ entity }: Props) => { {users?.usersHashMap && team && ( )} - {incidentCreator && ( - - )} + ); }; @@ -191,15 +171,22 @@ export const SplunkOnCallCard = ({ entity }: Props) => { icon: , }; + const serviceLink = { + label: 'Portal', + href: 'https://portal.victorops.com/', + icon: , + }; + return ( Team: {team}, - username && ( - - ), + , ]} /> diff --git a/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.tsx b/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.tsx index a43dc548dd..2872c80ba0 100644 --- a/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.tsx +++ b/plugins/splunk-on-call/src/components/TriggerDialog/TriggerDialog.tsx @@ -36,12 +36,10 @@ import { useApi, alertApiRef } from '@backstage/core'; import { useAsyncFn } from 'react-use'; import { splunkOnCallApiRef } from '../../api'; import { Alert } from '@material-ui/lab'; -import { User } from '../types'; import { TriggerAlarmRequest } from '../../api/types'; type Props = { team: string; - incidentCreator: User; showDialog: boolean; handleDialog: () => void; onIncidentCreated: () => void; @@ -58,8 +56,17 @@ const useStyles = makeStyles((theme: Theme) => }, formControl: { margin: theme.spacing(1), + display: 'flex', + flexDirection: 'row', + alignItems: 'center', minWidth: `calc(100% - ${theme.spacing(2)}px)`, }, + formHeader: { + width: '50%', + }, + incidentType: { + width: '90%', + }, targets: { display: 'flex', flexDirection: 'column', @@ -70,7 +77,6 @@ const useStyles = makeStyles((theme: Theme) => export const TriggerDialog = ({ team, - incidentCreator, showDialog, handleDialog, onIncidentCreated: onIncidentCreated, @@ -142,10 +148,7 @@ export const TriggerDialog = ({ This action will trigger an incident - Created by:{' '} - - {incidentCreator?.firstName} {incidentCreator?.lastName} - + Created by: {`{ REST } Endpoint`} @@ -163,22 +166,35 @@ export const TriggerDialog = ({ align="justify" > Please describe the problem you want to report. Be as descriptive as - possible. Your signed in user and a reference to the current page will - automatically be amended to the alarm so that the receiver can reach - out to you if necessary. + possible.
+ Note that only the Incident type, Incident display name{' '} + and the Incident message fields are required.
- Incident type - +
+ Incident type + +
+
-