Skip to content

Commit

Permalink
Rework blast radius and risks progress display
Browse files Browse the repository at this point in the history
Fixes #304
  • Loading branch information
DavidS-ovm committed May 16, 2024
1 parent 4857010 commit 20b1fba
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 63 deletions.
31 changes: 20 additions & 11 deletions cmd/tea_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import (
"fmt"

tea "github.com/charmbracelet/bubbletea"
log "github.com/sirupsen/logrus"
)

type snapshotModel struct {
title string
taskModel
state string
items uint32
edges uint32
Expand All @@ -28,11 +27,18 @@ type finishSnapshotMsg struct {
edges uint32
}

func NewSnapShotModel(title string) snapshotModel {
return snapshotModel{
taskModel: NewTaskModel(title),
state: "pending",
}
}

func (m snapshotModel) Init() tea.Cmd {
return nil
return m.taskModel.Init()
}

func (m snapshotModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (m snapshotModel) Update(msg tea.Msg) (snapshotModel, tea.Cmd) {
switch msg := msg.(type) {
case startSnapshotMsg:
m.state = msg.newState
Expand All @@ -44,25 +50,28 @@ func (m snapshotModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.state = msg.newState
m.items = msg.items
m.edges = msg.edges
default:
var cmd tea.Cmd
m.taskModel, cmd = m.taskModel.Update(msg)
return m, cmd
}
log.Debugf("updated %+v => %v", msg, m)
return m, nil
}

func (m snapshotModel) View() string {
// TODO: add spinner and/or progressbar; complication: we do not have a
// expected number of items/edges to count towards for the progressbar
if m.items == 0 && m.edges == 0 {
return fmt.Sprintf("%s - %s", m.title, m.state)
return fmt.Sprintf("%v - %v", m.taskModel.View(), m.state)
} else if m.items == 1 && m.edges == 0 {
return fmt.Sprintf("%s - %s: 1 item", m.title, m.state)
return fmt.Sprintf("%v - %v: 1 item", m.taskModel.View(), m.state)
} else if m.items == 1 && m.edges == 1 {
return fmt.Sprintf("%s - %s: 1 item, 1 edge", m.title, m.state)
return fmt.Sprintf("%v - %v: 1 item, 1 edge", m.taskModel.View(), m.state)
} else if m.items > 1 && m.edges == 0 {
return fmt.Sprintf("%s - %s: %d items", m.title, m.state, m.items)
return fmt.Sprintf("%v - %v: %d items", m.taskModel.View(), m.state, m.items)
} else if m.items > 1 && m.edges == 1 {
return fmt.Sprintf("%s - %s: %d items, 1 edge", m.title, m.state, m.items)
return fmt.Sprintf("%v - %v: %d items, 1 edge", m.taskModel.View(), m.state, m.items)
} else {
return fmt.Sprintf("%s - %s: %d items, %d edges", m.title, m.state, m.items, m.edges)
return fmt.Sprintf("%v - %v: %d items, %d edges", m.taskModel.View(), m.state, m.items, m.edges)
}
}
4 changes: 0 additions & 4 deletions cmd/tea_taskmodel.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,6 @@ func (m taskModel) View() string {
label = lipgloss.NewStyle().Foreground(ColorPalette.LabelFaint).Render("+")
case taskStatusRunning:
label = m.spinner.View()
// all other lables are 7 cells wide
// for ansi.PrintableRuneWidth(label) <= 7 {
// label += " "
// }
case taskStatusDone:
label = lipgloss.NewStyle().Foreground(ColorPalette.BgSuccess).Render("✔︎")
case taskStatusError:
Expand Down
4 changes: 2 additions & 2 deletions cmd/terraform_apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ Applying changes with ` + "`" + `terraform %v` + "`\n"
processingHeader: processingHeader,

startingChange: make(chan tea.Msg, 10), // provide a small buffer for sending updates, so we don't block the processing
startingChangeSnapshot: snapshotModel{title: "Starting Change", state: "pending"},
startingChangeSnapshot: NewSnapShotModel("Starting Change"),
endingChange: make(chan tea.Msg, 10), // provide a small buffer for sending updates, so we don't block the processing
endingChangeSnapshot: snapshotModel{title: "Ending Change", state: "pending"},
endingChangeSnapshot: NewSnapShotModel("Ending Change"),
progress: []string{},
}
}
Expand Down
113 changes: 67 additions & 46 deletions cmd/terraform_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,20 +233,20 @@ type tfPlanModel struct {
ctx context.Context // note that this ctx is not initialized on NewTfPlanModel to instead get a modified context through the loadSourcesConfigMsg that has a timeout and cancelFunction configured
oi OvermindInstance

args []string
planTask taskModel
planHeader string
processingTask taskModel
processingHeader string
args []string
planTask taskModel
planHeader string

revlinkWarmupFinished bool

runTfPlan bool
tfPlanFinished bool
processing chan tea.Msg
processingModel snapshotModel
progress []string
changeUrl string
runTfPlan bool
tfPlanFinished bool
processing chan tea.Msg
blastRadiusModel snapshotModel
progress []string
changeUrl string

riskTask taskModel
riskMilestones []*sdp.RiskCalculationStatus_ProgressMilestone
riskMilestoneTasks []taskModel
risks []*sdp.Risk
Expand Down Expand Up @@ -277,26 +277,24 @@ func NewTfPlanModel(args []string) tea.Model {
planHeader := `Running ` + "`" + `terraform %v` + "`\n"
planHeader = fmt.Sprintf(planHeader, strings.Join(args, " "))

processingHeader := ` Processing plan from ` + "`" + `terraform %v` + "`\n"
processingHeader = fmt.Sprintf(processingHeader, strings.Join(args, " "))

return tfPlanModel{
args: args,
planTask: NewTaskModel("Planning Changes"),
planHeader: planHeader,
processingTask: NewTaskModel("Processing Planned Changes"),
processingHeader: processingHeader,

processing: make(chan tea.Msg, 10), // provide a small buffer for sending updates, so we don't block the processing
processingModel: snapshotModel{title: "Calculating Blast Radius", state: "pending"},
progress: []string{},
args: args,
planTask: NewTaskModel("Planning Changes"),
planHeader: planHeader,

processing: make(chan tea.Msg, 10), // provide a small buffer for sending updates, so we don't block the processing
blastRadiusModel: NewSnapShotModel("Calculating Blast Radius"),
progress: []string{},

riskTask: NewTaskModel("Calculating Risks"),
}
}

func (m tfPlanModel) Init() tea.Cmd {
return tea.Batch(
m.planTask.Init(),
m.processingTask.Init(),
m.blastRadiusModel.Init(),
m.riskTask.Init(),
)
}

Expand Down Expand Up @@ -324,7 +322,7 @@ func (m tfPlanModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
c.Env = append(c.Env, fmt.Sprintf("AWS_PROFILE=%v", aws_profile))
}

m.processingModel.state = "executing terraform plan"
m.blastRadiusModel.state = "executing terraform plan"

if viper.GetString("ovm-test-fake") != "" {
c = exec.CommandContext(m.ctx, "bash", "-c", "for i in $(seq 100); do echo fake terraform plan progress line $i of 100; done; sleep 1")
Expand Down Expand Up @@ -354,21 +352,22 @@ func (m tfPlanModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

case triggerPlanProcessingMsg:
m.processingTask.status = taskStatusRunning
m.processingModel.state = "executed terraform plan"
m.blastRadiusModel.status = taskStatusRunning
m.blastRadiusModel.state = "executed terraform plan"

cmds = append(cmds,
m.processPlanCmd,
m.processingTask.spinner.Tick,
m.blastRadiusModel.spinner.Tick,
m.waitForProcessingActivity,
)
case processingActivityMsg:
m.processingModel.state = "processing"
m.blastRadiusModel.state = "processing"
m.progress = append(m.progress, msg.text)
cmds = append(cmds, m.waitForProcessingActivity)
case processingFinishedActivityMsg:
m.processingModel.state = "finished"
m.processingTask.status = taskStatusDone
m.blastRadiusModel.status = taskStatusDone
m.blastRadiusModel.state = "finished"
m.riskTask.status = taskStatusDone
m.progress = append(m.progress, msg.text)
cmds = append(cmds, m.waitForProcessingActivity)
case changeUpdatedMsg:
Expand Down Expand Up @@ -398,20 +397,40 @@ func (m tfPlanModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
}
m.risks = msg.risks
m.processingModel.state = "Change updated"

if len(m.riskMilestones) > 0 {
m.riskTask.status = taskStatusRunning
cmds = append(cmds, m.riskTask.spinner.Tick)
} else if len(m.risks) > 0 {
m.riskTask.status = taskStatusDone
} else {
var allSkipped = true
for _, ms := range m.riskMilestoneTasks {
if ms.status != taskStatusSkipped {
allSkipped = false
break
}
}
if allSkipped {
m.riskTask.status = taskStatusSkipped
}
}

m.blastRadiusModel.status = taskStatusDone
m.blastRadiusModel.state = "Change updated"
cmds = append(cmds, m.waitForProcessingActivity)

case startSnapshotMsg:
mdl, cmd := m.processingModel.Update(msg)
m.processingModel = mdl.(snapshotModel)
var cmd tea.Cmd
m.blastRadiusModel, cmd = m.blastRadiusModel.Update(msg)
cmds = append(cmds, m.waitForProcessingActivity, cmd)
case progressSnapshotMsg:
mdl, cmd := m.processingModel.Update(msg)
m.processingModel = mdl.(snapshotModel)
var cmd tea.Cmd
m.blastRadiusModel, cmd = m.blastRadiusModel.Update(msg)
cmds = append(cmds, m.waitForProcessingActivity, cmd)
case finishSnapshotMsg:
mdl, cmd := m.processingModel.Update(msg)
m.processingModel = mdl.(snapshotModel)
var cmd tea.Cmd
m.blastRadiusModel, cmd = m.blastRadiusModel.Update(msg)
cmds = append(cmds, tea.Sequence(cmd, func() tea.Msg { return delayQuitMsg{} }))
case delayQuitMsg:
cmds = append(cmds, tea.Quit)
Expand All @@ -424,7 +443,10 @@ func (m tfPlanModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.planTask, cmd = m.planTask.Update(msg)
cmds = append(cmds, cmd)

m.processingTask, cmd = m.processingTask.Update(msg)
m.blastRadiusModel, cmd = m.blastRadiusModel.Update(msg)
cmds = append(cmds, cmd)

m.riskTask, cmd = m.riskTask.Update(msg)
cmds = append(cmds, cmd)

for i, ms := range m.riskMilestoneTasks {
Expand All @@ -447,16 +469,15 @@ func (m tfPlanModel) View() string {
bits = append(bits, markdownToString(m.planHeader))
}

if m.processingTask.status != taskStatusPending {
bits = append(bits, m.processingTask.View())
if m.blastRadiusModel.status != taskStatusPending {
bits = append(bits, m.blastRadiusModel.View())
}

if m.tfPlanFinished {
bits = append(bits, m.processingHeader)
bits = append(bits, fmt.Sprintf(" %v", m.processingModel.View()))
if m.riskTask.status != taskStatusPending {
bits = append(bits, m.riskTask.View())
}

if m.changeUrl != "" && len(m.risks) == 0 {
if m.changeUrl != "" {
for _, t := range m.riskMilestoneTasks {
bits = append(bits, fmt.Sprintf(" %v", t.View()))
}
Expand Down Expand Up @@ -517,7 +538,7 @@ func (m tfPlanModel) processPlanCmd() tea.Msg {
time.Sleep(time.Second)
m.processing <- progressSnapshotMsg{newState: "fake processing"}
time.Sleep(time.Second)
m.processing <- changeUpdatedMsg{url: "https://example.com"}
m.processing <- changeUpdatedMsg{url: "https://example.com/changes/abc"}
time.Sleep(time.Second)

m.processing <- processingActivityMsg{"Fake CalculateBlastRadiusResponse Status update: progress"}
Expand Down

0 comments on commit 20b1fba

Please sign in to comment.