Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/csv/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

type Input struct {
RefreshInfos state.ResourceInfos
ApplyInfos state.ResourceInfos
RefreshInfos state.ResourceOperationInfos
ApplyInfos state.ResourceOperationInfos
}

func ToCsv(input Input) []byte {
Expand Down
36 changes: 18 additions & 18 deletions internal/plainui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ type UIModel struct {
reader reader.Reader
writer io.Writer

refreshInfos state.ResourceInfos
applyInfos state.ResourceInfos
refreshInfos state.ResourceOperationInfos
applyInfos state.ResourceOperationInfos

totalCnt int
doneCnt int
Expand Down Expand Up @@ -117,28 +117,28 @@ func (m *UIModel) Run() error {
case views.HookMsg:
switch hook := msg.Hook.(type) {
case json.RefreshStart:
res := &state.ResourceInfo{
res := &state.ResourceOperationInfo{
Idx: len(m.refreshInfos) + 1,
RawResourceAddr: hook.Resource,
Loc: state.ResourceInfoLocator{
Loc: state.ResourceOperationInfoLocator{
Module: hook.Resource.Module,
ResourceAddr: hook.Resource.Addr,
Action: "refresh",
},
Status: state.ResourceStatusStart,
Status: state.ResourceOperationStatusStart,
StartTime: msg.TimeStamp,
}
m.refreshInfos = append(m.refreshInfos, res)
msgstr = msg.Message

case json.RefreshComplete:
loc := state.ResourceInfoLocator{
loc := state.ResourceOperationInfoLocator{
Module: hook.Resource.Module,
ResourceAddr: hook.Resource.Addr,
Action: "refresh",
}
status := state.ResourceStatusComplete
update := state.ResourceInfoUpdate{
status := state.ResourceOperationStatusComplete
update := state.ResourceOperationInfoUpdate{
Status: &status,
Endtime: &msg.TimeStamp,
}
Expand All @@ -149,15 +149,15 @@ func (m *UIModel) Run() error {
msgstr = msg.Message

case json.OperationStart:
info := &state.ResourceInfo{
info := &state.ResourceOperationInfo{
Idx: len(m.applyInfos) + 1,
RawResourceAddr: hook.Resource,
Loc: state.ResourceInfoLocator{
Loc: state.ResourceOperationInfoLocator{
Module: hook.Resource.Module,
ResourceAddr: hook.Resource.Addr,
Action: string(hook.Action),
},
Status: state.ResourceStatusStart,
Status: state.ResourceOperationStatusStart,
StartTime: msg.TimeStamp,
}
m.applyInfos = append(m.applyInfos, info)
Expand All @@ -166,7 +166,7 @@ func (m *UIModel) Run() error {
msgstr = fmt.Sprintf("[%*d/%*d] %s", w, info.Idx, w, m.totalCnt, msg.Message)

case json.OperationProgress:
loc := state.ResourceInfoLocator{
loc := state.ResourceOperationInfoLocator{
Module: hook.Resource.Module,
ResourceAddr: hook.Resource.Addr,
Action: string(hook.Action),
Expand All @@ -181,13 +181,13 @@ func (m *UIModel) Run() error {
msgstr = fmt.Sprintf("[%*d/%*d] %s", w, info.Idx, w, m.totalCnt, msg.Message)

case json.OperationComplete:
loc := state.ResourceInfoLocator{
loc := state.ResourceOperationInfoLocator{
Module: hook.Resource.Module,
ResourceAddr: hook.Resource.Addr,
Action: string(hook.Action),
}
status := state.ResourceStatusComplete
update := state.ResourceInfoUpdate{
status := state.ResourceOperationStatusComplete
update := state.ResourceOperationInfoUpdate{
Status: &status,
Endtime: &msg.TimeStamp,
}
Expand All @@ -201,13 +201,13 @@ func (m *UIModel) Run() error {
msgstr = fmt.Sprintf("[%*d/%*d] %s", w, info.Idx, w, m.totalCnt, msg.Message)

case json.OperationErrored:
loc := state.ResourceInfoLocator{
loc := state.ResourceOperationInfoLocator{
Module: hook.Resource.Module,
ResourceAddr: hook.Resource.Addr,
Action: string(hook.Action),
}
status := state.ResourceStatusErrored
update := state.ResourceInfoUpdate{
status := state.ResourceOperationStatusErrored
update := state.ResourceOperationInfoUpdate{
Status: &status,
Endtime: &msg.TimeStamp,
}
Expand Down
67 changes: 67 additions & 0 deletions internal/state/plan_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package state

import (
"fmt"
"strconv"

"github.com/charmbracelet/bubbles/table"
"github.com/magodo/pipeform/internal/terraform/views/json"
)

type PlanInfo struct {
Resource json.ResourceAddr
Action json.ChangeAction

PrevResource *json.ResourceAddr
Reason json.ChangeReason
}

type PlanInfos []*PlanInfo

func (infos PlanInfos) ToRows() []table.Row {
var rows []table.Row
for i, info := range infos {
var comment string
switch info.Action {
case json.ActionDelete, json.ActionReplace:
comment = string(info.Reason)
case json.ActionMove:
if info.PrevResource != nil {
source := info.PrevResource.Addr
if info.PrevResource.Module != "" {
source = fmt.Sprintf("%s (%s)", source, info.PrevResource.Module)
}
comment = fmt.Sprintf("Moved from %s", source)
}
}
row := []string{
strconv.Itoa(i + 1),
info.Resource.Module,
info.Resource.Addr,
string(info.Action),
comment,
}
rows = append(rows, row)
}
return rows
}

func (infos PlanInfos) ToColumns(width int) []table.Column {
const indexWidth = 6
const actionWidth = 8

dynamicWidth := width - indexWidth - actionWidth

commentWidth := dynamicWidth / 3
moduleWidth := dynamicWidth / 3
resourceWidth := dynamicWidth / 3

return []table.Column{
{Title: "Index", Width: indexWidth},
{Title: "Module", Width: moduleWidth},
{Title: "Resource", Width: resourceWidth},
{Title: "Action", Width: actionWidth},
// Comment is a combination of "reason" (for delete/replace) and a modified version of "previous_resource" (for move)
{Title: "Comment", Width: commentWidth},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,57 @@ import (
"github.com/magodo/pipeform/internal/terraform/views/json"
)

type ResourceStatus string
type ResourceOperationStatus string

const (
// Once received one OperationStart hook message
ResourceStatusStart ResourceStatus = "start"
ResourceOperationStatusStart ResourceOperationStatus = "start"
// Once received one OperationComplete hook message
ResourceStatusComplete ResourceStatus = "complete"
ResourceOperationStatusComplete ResourceOperationStatus = "complete"
// Once received one OperationErrored hook message
ResourceStatusErrored ResourceStatus = "error"
ResourceOperationStatusErrored ResourceOperationStatus = "error"

// TODO: Support refresh? (refresh is an independent lifecycle than the resource apply lifecycle)
// TODO: Support provision? (provision is a intermidiate stage in the resource apply lifecycle)
)

func resourceStatusEmoji(status ResourceStatus) string {
func resourceOperationStatusEmoji(status ResourceOperationStatus) string {
switch status {
case ResourceStatusStart:
case ResourceOperationStatusStart:
return "🕛"
case ResourceStatusComplete:
case ResourceOperationStatusComplete:
return "✅"
case ResourceStatusErrored:
case ResourceOperationStatusErrored:
return "❌"
default:
return "❓"
}
}

type ResourceInfoLocator struct {
type ResourceOperationInfoLocator struct {
Module string
ResourceAddr string
Action string
}

type ResourceInfo struct {
type ResourceOperationInfo struct {
Idx int
RawResourceAddr json.ResourceAddr
Loc ResourceInfoLocator
Status ResourceStatus
Loc ResourceOperationInfoLocator
Status ResourceOperationStatus
StartTime time.Time
EndTime time.Time
}

type ResourceInfoUpdate struct {
Status *ResourceStatus
type ResourceOperationInfoUpdate struct {
Status *ResourceOperationStatus
Endtime *time.Time
}

// ResourceInfos records the operation information for each resource's action.
type ResourceInfos []*ResourceInfo
// ResourceOperationInfos records the operation information for each resource's action.
type ResourceOperationInfos []*ResourceOperationInfo

func (infos ResourceInfos) Find(loc ResourceInfoLocator) *ResourceInfo {
func (infos ResourceOperationInfos) Find(loc ResourceOperationInfoLocator) *ResourceOperationInfo {
for _, info := range infos {
if info.Loc == loc {
return info
Expand All @@ -69,7 +69,7 @@ func (infos ResourceInfos) Find(loc ResourceInfoLocator) *ResourceInfo {
return nil
}

func (infos ResourceInfos) Update(loc ResourceInfoLocator, update ResourceInfoUpdate) *ResourceInfo {
func (infos ResourceOperationInfos) Update(loc ResourceOperationInfoLocator, update ResourceOperationInfoUpdate) *ResourceOperationInfo {
info := infos.Find(loc)
if info == nil {
return nil
Expand All @@ -85,7 +85,7 @@ func (infos ResourceInfos) Update(loc ResourceInfoLocator, update ResourceInfoUp

// ToRows turns the ResourceInfos into table rows.
// The total is used to decorate the index as a fraction, if total > 0.
func (infos ResourceInfos) ToRows(total int) []table.Row {
func (infos ResourceOperationInfos) ToRows(total int) []table.Row {
now := time.Now()
var rows []table.Row
for _, info := range infos {
Expand All @@ -103,7 +103,7 @@ func (infos ResourceInfos) ToRows(total int) []table.Row {

row := []string{
idx,
resourceStatusEmoji(info.Status),
resourceOperationStatusEmoji(info.Status),
string(info.Loc.Action),
module,
info.Loc.ResourceAddr,
Expand All @@ -114,7 +114,7 @@ func (infos ResourceInfos) ToRows(total int) []table.Row {
return rows
}

func (infos ResourceInfos) ToColumns(width int) []table.Column {
func (infos ResourceOperationInfos) ToColumns(width int) []table.Column {
const statusWidth = 6
const actionWidth = 8
const timeWidth = 24
Expand All @@ -135,7 +135,7 @@ func (infos ResourceInfos) ToColumns(width int) []table.Column {
}
}

func (infos ResourceInfos) ToCsv(stage string) []string {
func (infos ResourceOperationInfos) ToCsv(stage string) []string {
var out []string
now := time.Now()
for _, info := range infos {
Expand All @@ -157,7 +157,7 @@ func (infos ResourceInfos) ToCsv(stage string) []string {
return out
}

func (info ResourceInfo) Duration(now time.Time) time.Duration {
func (info ResourceOperationInfo) Duration(now time.Time) time.Duration {
var dur time.Duration
if info.EndTime.Equal(time.Time{}) {
dur = now.Sub(info.StartTime).Truncate(time.Second)
Expand Down
Loading
Loading