Skip to content

Commit

Permalink
Merge pull request #56 from supreeth7/oncall-tui-port
Browse files Browse the repository at this point in the history
OSD-8797: ported oncall features to TUI
  • Loading branch information
openshift-merge-robot authored Oct 27, 2021
2 parents c30bbc2 + 081dede commit 9e564b8
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 76 deletions.
4 changes: 2 additions & 2 deletions cmd/pdcli/alerts/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
pdApi "github.com/PagerDuty/go-pagerduty"
"github.com/openshift/pagerduty-short-circuiter/pkg/client"
"github.com/openshift/pagerduty-short-circuiter/pkg/constants"
"github.com/openshift/pagerduty-short-circuiter/pkg/pdcli"
pdcli "github.com/openshift/pagerduty-short-circuiter/pkg/pdcli/alerts"
"github.com/openshift/pagerduty-short-circuiter/pkg/ui"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -232,7 +232,7 @@ func initAlertsUI(tui *ui.TUI, alerts []pdcli.Alert, title string) {
// It adds the returned table as a new TUI page view.
func initIncidentsUI(tui *ui.TUI, c client.PagerDutyClient) {
incidentHeaders := []string{"INCIDENT ID", "NAME", "SEVERITY", "STATUS", "SERVICE"}
tui.IncidentsTable = tui.InitTable(incidentHeaders, tui.Incidents, true, true, "Incidents")
tui.IncidentsTable = tui.InitTable(incidentHeaders, tui.Incidents, true, true, ui.IncidentsTableTitle)
tui.SetIncidentsTableEvents()

tui.Pages.AddPage(ui.AckIncidentsPageTitle, tui.IncidentsTable, true, false)
Expand Down
104 changes: 75 additions & 29 deletions cmd/pdcli/oncall/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ limitations under the License.
package oncall

import (
"strings"

"github.com/PagerDuty/go-pagerduty"
"github.com/openshift/pagerduty-short-circuiter/pkg/client"
"github.com/openshift/pagerduty-short-circuiter/pkg/output"
"github.com/openshift/pagerduty-short-circuiter/pkg/pdcli"
pdcli "github.com/openshift/pagerduty-short-circuiter/pkg/pdcli/oncall"
"github.com/openshift/pagerduty-short-circuiter/pkg/ui"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -57,6 +60,8 @@ func init() {
func oncallHandler(cmd *cobra.Command, args []string) (err error) {

var onCallUsers []pdcli.OncallUser
var allTeamsOncall []pdcli.OncallUser
var nextOncall []pdcli.OncallUser

// Establish a secure connection with the PagerDuty API
client, err := client.NewClient().Connect()
Expand All @@ -65,45 +70,88 @@ func oncallHandler(cmd *cobra.Command, args []string) (err error) {
return err
}

switch {
case options.allTeams:
// Fetch oncall data from all teams
onCallUsers, err = pdcli.AllTeamsOncall(client)
user, err := client.GetCurrentUser(pagerduty.GetCurrentUserOptions{})

if err != nil {
return err
}
if err != nil {
return err
}

printOncalls(onCallUsers)
// UI
var tui ui.TUI

case options.nextOncall:
onCallUsers, err = pdcli.UserNextOncallSchedule(client)
tui.Username = user.Name

if err != nil {
return err
}
// Initialize TUI
tui.Init()

printOncalls(onCallUsers)
// Fetch oncall data from Platform-SRE team
onCallUsers, err = pdcli.TeamSREOnCall(client)

default:
// Fetch oncall data from Platform-SRE team
onCallUsers, err = pdcli.TeamSREOnCall(client)
if err != nil {
return err
}

if err != nil {
return err
for _, v := range onCallUsers {
if strings.Contains(v.OncallRole, "Primary") {
tui.Primary = v.Name
}

printOncalls(onCallUsers)
if strings.Contains(v.OncallRole, "Secondary") {
tui.Secondary = v.Name
}
}

// Fetch oncall data from all teams
allTeamsOncall, err = pdcli.AllTeamsOncall(client)

if err != nil {
return err
}

// Fetch the current user's oncall schedule
nextOncall, err = pdcli.UserNextOncallSchedule(client, user.ID)

if err != nil {
return err
}

initOncallUI(&tui, onCallUsers)
initAllTeamsOncallUI(&tui, allTeamsOncall)
initNextOncallUI(&tui, nextOncall)

tui.SetOncallSecondaryData()

err = tui.StartApp()

if err != nil {
return err
}

return nil
}

func initOncallUI(tui *ui.TUI, onCallData []pdcli.OncallUser) {
headers, data := getOncallTableData(onCallData)
tui.Table = tui.InitTable(headers, data, false, false, ui.OncallTableTitle)
tui.Pages.AddPage(ui.OncallPageTitle, tui.Table, true, true)
}

func initNextOncallUI(tui *ui.TUI, onCallData []pdcli.OncallUser) {
headers, data := getOncallTableData(onCallData)
tui.NextOncallTable = tui.InitTable(headers, data, false, false, ui.NextOncallTableTitle)
tui.Pages.AddPage(ui.NextOncallPageTitle, tui.NextOncallTable, true, false)
}

func initAllTeamsOncallUI(tui *ui.TUI, onCallData []pdcli.OncallUser) {
headers, data := getOncallTableData(onCallData)
tui.AllTeamsOncallTable = tui.InitTable(headers, data, false, false, ui.AllTeamsOncallTableTitle)
tui.Pages.AddPage(ui.AllTeamsOncallPageTitle, tui.AllTeamsOncallTable, true, false)
}

//printOncalls prints data in a tabular form.
func printOncalls(oncallData []pdcli.OncallUser) {
func getOncallTableData(oncallData []pdcli.OncallUser) ([]string, [][]string) {

// Initialize table writer
table := output.NewTable(false)
var tableData [][]string

for _, v := range oncallData {

Expand Down Expand Up @@ -139,12 +187,10 @@ func printOncalls(oncallData []pdcli.OncallUser) {
data = append(data, "N/A")
}

table.AddRow(data)
tableData = append(tableData, data)
}

headers := []string{"Escalation Policy", "Name", "Oncall Role", "From", "To"}

table.SetHeaders(headers)
table.SetData()
table.Print()
return headers, tableData
}
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
Expand Down Expand Up @@ -508,7 +507,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
Expand Down
File renamed without changes.
10 changes: 2 additions & 8 deletions pkg/pdcli/oncallHandlers.go → pkg/pdcli/oncall/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,13 @@ func AllTeamsOncall(c client.PagerDutyClient) ([]OncallUser, error) {

// UserNextOncallSchedule displays the current user's
// next oncall schedule.
func UserNextOncallSchedule(c client.PagerDutyClient) ([]OncallUser, error) {
func UserNextOncallSchedule(c client.PagerDutyClient, userID string) ([]OncallUser, error) {
var callOpts pagerduty.ListOnCallOptions
var nextOncallData []OncallUser

callOpts.Until = time.Now().AddDate(0, 3, 0).String()

user, err := c.GetCurrentUser(pagerduty.GetCurrentUserOptions{})

if err != nil {
return nil, err
}

callOpts.UserIDs = append(callOpts.UserIDs, user.ID)
callOpts.UserIDs = append(callOpts.UserIDs, userID)

// Fetch the oncall data from pagerduty API
onCallOncallUser, err := c.ListOnCalls(callOpts)
Expand Down
2 changes: 1 addition & 1 deletion pkg/ui/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package ui

import (
"github.com/gdamore/tcell/v2"
"github.com/openshift/pagerduty-short-circuiter/pkg/pdcli"
pdcli "github.com/openshift/pagerduty-short-circuiter/pkg/pdcli/alerts"
)

// SetAlertsTableEvents is the event handler for the alerts table.
Expand Down
38 changes: 22 additions & 16 deletions pkg/ui/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package ui

import (
"github.com/gdamore/tcell/v2"
"github.com/openshift/pagerduty-short-circuiter/pkg/pdcli"
pdcli "github.com/openshift/pagerduty-short-circuiter/pkg/pdcli/alerts"
)

// initKeyboard initializes the keyboard event handlers for all the TUI components.
Expand All @@ -21,17 +21,18 @@ func (tui *TUI) initKeyboard() {
tui.showDefaultSecondaryView()
}

if tui.Pages.HasPage(OncallPageTitle) {
tui.Pages.SwitchToPage(OncallPageTitle)
tui.Footer.SetText(FooterTextOncall)
}

return nil
}

if event.Rune() == 'q' || event.Rune() == 'Q' {
tui.App.Stop()
}

if event.Rune() == 'm' || event.Rune() == 'M' {
tui.toggleMouse()
}

return event
})

Expand All @@ -51,6 +52,22 @@ func (tui *TUI) initKeyboard() {
tui.Footer.SetText(FooterText)
}

if tui.NextOncallTable != nil {
if event.Rune() == 'N' || event.Rune() == 'n' {
tui.Pages.SwitchToPage(NextOncallPageTitle)

if len(tui.AckIncidents) == 0 {
tui.showSecondaryView("You are not scheduled for any oncall duties for the next 3 months. Cheer up!")
}
}
}

if tui.AllTeamsOncallTable != nil {
if event.Rune() == 'A' || event.Rune() == 'a' {
tui.Pages.SwitchToPage(AllTeamsOncallPageTitle)
}
}

return event
})

Expand Down Expand Up @@ -97,14 +114,3 @@ func (tui *TUI) initKeyboard() {
})

}

// toggleMouse enables & disables mouse events in TUI.
func (tui *TUI) toggleMouse() {
if tui.isMouseEnabled {
tui.App.EnableMouse(false)
} else {
tui.App.EnableMouse(true)
}

tui.isMouseEnabled = !tui.isMouseEnabled
}
7 changes: 7 additions & 0 deletions pkg/ui/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ func (tui *TUI) SetAlertsSecondaryData() {
"Viewing alerts assigned to: " + tui.AssginedTo + "\n" +
"Number of alerts fetched: " + tui.FetchedAlerts
}

// SetAlertsSecondaryData initializes the text data for the secondary textview component of the UI.
func (tui *TUI) SetOncallSecondaryData() {
tui.secondaryText = "Logged in user: " + tui.Username + "\n" +
"Current Oncall Primary: " + tui.Primary + "\n" +
"Current Oncall Secondary: " + tui.Secondary
}
46 changes: 30 additions & 16 deletions pkg/ui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ import (
type TUI struct {

// Main UI elements
App *tview.Application
AlertMetadata *tview.TextView
Table *tview.Table
IncidentsTable *tview.Table
Pages *tview.Pages
Info *tview.TextView
Layout *tview.Flex
Footer *tview.TextView
App *tview.Application
AlertMetadata *tview.TextView
Table *tview.Table
IncidentsTable *tview.Table
NextOncallTable *tview.Table
AllTeamsOncallTable *tview.Table
Pages *tview.Pages
Info *tview.TextView
Layout *tview.Flex
Footer *tview.TextView

// Misc. UI elements
isMouseEnabled bool
secondaryText string
secondaryText string

// Internals
Username string
Expand All @@ -34,25 +35,35 @@ type TUI struct {
AckIncidents []string
ClusterID string
Client client.PagerDutyClient
Primary string
Secondary string
}

const (
// Table Titles
AlertsTableTitle = "[ Alerts ]"
AlertMetadataViewTitle = "[ Alert Data ]"
AlertsTableTitle = "[ ALERTS ]"
AlertMetadataViewTitle = "[ ALERT DATA ]"
IncidentsTableTitle = "[ INCIDENTS ]"
OncallTableTitle = "[ ONCALL ]"
NextOncallTableTitle = "[ NEXT ONCALL ]"
AllTeamsOncallTableTitle = "[ ALL TEAMS ONCALL ]"

// Page Titles
AlertsPageTitle = "Alerts"
AlertDataPageTitle = "Metadata"
AckIncidentsPageTitle = "Incidents"
AlertsPageTitle = "Alerts"
AlertDataPageTitle = "Metadata"
AckIncidentsPageTitle = "Incidents"
OncallPageTitle = "Oncall"
NextOncallPageTitle = "Next Oncall"
AllTeamsOncallPageTitle = "All Teams Oncall"

// Text Format
TitleFmt = " [lightcyan::b]%s "

// Footer
FooterText = "[Q] Quit | [Esc] Go Back | [M] Enable/Disable Mouse"
FooterText = "[Q] Quit | [Esc] Go Back"
FooterTextAlerts = FooterText + " | [A] Ack Mode"
FooterTextAck = FooterText + " | [ENTER] Select Incident | [CTRL+A] Acknowledge Incidents"
FooterTextOncall = FooterText + " | [N] View Your Next Oncall Schedule | [A] View All Teams Oncall"

// Colors
TableTitleColor = tcell.ColorLightCyan
Expand Down Expand Up @@ -149,6 +160,9 @@ func (t *TUI) initFooter() {
case AlertsPageTitle:
t.Footer.SetText(FooterTextAlerts)

case OncallPageTitle:
t.Footer.SetText(FooterTextOncall)

default:
t.Footer.SetText(FooterText)

Expand Down
2 changes: 1 addition & 1 deletion tests/alerts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
. "github.com/onsi/gomega"

mockpd "github.com/openshift/pagerduty-short-circuiter/pkg/client/mock"
"github.com/openshift/pagerduty-short-circuiter/pkg/pdcli"
pdcli "github.com/openshift/pagerduty-short-circuiter/pkg/pdcli/alerts"
)

// incident retuns a pagerduty incident object with pre-configured data.
Expand Down
2 changes: 1 addition & 1 deletion tests/oncall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
mockpd "github.com/openshift/pagerduty-short-circuiter/pkg/client/mock"
"github.com/openshift/pagerduty-short-circuiter/pkg/pdcli"
pdcli "github.com/openshift/pagerduty-short-circuiter/pkg/pdcli/oncall"
)

var _ = Describe("pdcli oncall", func() {
Expand Down

0 comments on commit 9e564b8

Please sign in to comment.