Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
leg100 committed Sep 6, 2024
1 parent ebb75a3 commit 38ad4bc
Show file tree
Hide file tree
Showing 14 changed files with 89 additions and 159 deletions.
11 changes: 7 additions & 4 deletions internal/plan/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,15 @@ func (s *Service) ReloadAfterApply(sub <-chan resource.Event[*task.Task]) {
if !IsApplyTask(event.Payload) {
continue
}
ws := event.Payload.Workspace()
if _, err := s.states.CreateReloadTask(ws.GetID()); err != nil {
s.logger.Error("reloading state after apply", "error", err, "workspace", ws)
workspaceID := event.Payload.WorkspaceID
if workspaceID == nil {
continue
}
s.logger.Debug("reloading state after apply", "workspace", ws)
if _, err := s.states.CreateReloadTask(*workspaceID); err != nil {
s.logger.Error("reloading state after apply", "error", err, "workspace", *workspaceID)
continue
}
s.logger.Debug("reloading state after apply", "workspace", *workspaceID)
}
}
}
Expand Down
58 changes: 1 addition & 57 deletions internal/resource/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,64 +16,8 @@ func New(kind Kind, parent Resource) Common {
}
}

func (r Common) GetParent() Resource {
return r.Parent
}

func (r Common) HasAncestor(id ID) bool {
// Every entity is considered an ancestor of the nil ID (equivalent to the
// ID of the "global" entity).
if id == GlobalID {
return true
}
if r.Parent == nil {
// Parent has no parents, so go no further
return false
}
if r.Parent.GetID() == id {
return true
}
// Check parents of parent
return r.Parent.HasAncestor(id)
}

// Ancestors provides a list of successive parents, starting with the direct parents.
func (r Common) Ancestors() (ancestors []Resource) {
if r.Parent == nil {
return
}
ancestors = append(ancestors, r.Parent)
return append(ancestors, r.Parent.Ancestors()...)
}

func (r Common) getCurrentOrAncestorKind(k Kind) Resource {
if r.GetKind() == k {
return r
}
for _, parent := range r.Ancestors() {
if parent.GetKind() == k {
return parent
}
}
return nil
}

func (r Common) Module() Resource {
return r.getCurrentOrAncestorKind(Module)
}

func (r Common) Workspace() Resource {
return r.getCurrentOrAncestorKind(Workspace)
}

func (r Common) Dependencies() []ID {
// Direct dependencies
deps := r.dependencies
// Indirect dependencies
for _, parent := range r.Ancestors() {
deps = append(deps, parent.Dependencies()...)
}
return deps
return r.dependencies
}

func (r Common) WithDependencies(deps ...ID) Common {
Expand Down
14 changes: 0 additions & 14 deletions internal/resource/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,9 @@ type Resource interface {
GetID() ID
// GetKind retrieves the kind of resource.
GetKind() Kind
// GetParent retrieves the resource's parent, the resource from which the
// resource was spawned.
GetParent() Resource
// HasAncestor determines whether the resource has an ancestor with the
// given ID.
HasAncestor(ID) bool
// Ancestors retrieves a list of the resource's ancestors, nearest first.
Ancestors() []Resource
// String is a human-readable identifier for the resource. Not necessarily
// unique across pug.
String() string
// Module retrieves the resource's module. Returns nil if the resource does
// not have a module ancestor.
Module() Resource
// Workspace retrieves the resource's workspcae. Returns nil if the resource does
// not have a workspace ancestor.
Workspace() Resource
// Dependencies returns both direct dependencies and indirect dependencies that
// ancestor resources have.
Dependencies() []ID
Expand Down
23 changes: 0 additions & 23 deletions internal/resource/resource_test.go

This file was deleted.

2 changes: 1 addition & 1 deletion internal/state/reloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (r *reloader) Reload(workspaceID resource.ID) (task.Spec, error) {
Command: []string{"state", "pull"},
JSON: true,
BeforeExited: func(t *task.Task) (task.Summary, error) {
state, err := newState(t.Workspace(), t.NewReader(false))
state, err := newState(workspaceID, t.NewReader(false))
if err != nil {
return nil, fmt.Errorf("constructing pug state: %w", err)
}
Expand Down
14 changes: 8 additions & 6 deletions internal/state/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@ import (
type Resource struct {
resource.Common

Address ResourceAddress
Attributes map[string]any
Tainted bool
WorkspaceID resource.ID
Address ResourceAddress
Attributes map[string]any
Tainted bool
}

func (r *Resource) String() string {
return string(r.Address)
}

func newResource(state resource.Resource, addr ResourceAddress, attrs json.RawMessage) (*Resource, error) {
func newResource(workspaceID resource.ID, addr ResourceAddress, attrs json.RawMessage) (*Resource, error) {
res := &Resource{
Common: resource.New(resource.StateResource, state),
Address: addr,
Common: resource.New(resource.StateResource, resource.GlobalResource),
WorkspaceID: workspaceID,
Address: addr,
}
if err := json.Unmarshal(attrs, &res.Attributes); err != nil {
return nil, err
Expand Down
8 changes: 4 additions & 4 deletions internal/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ type State struct {
Lineage string
}

func newState(ws resource.Resource, r io.Reader) (*State, error) {
func newState(workspaceID resource.ID, r io.Reader) (*State, error) {
// Default to a serial of -1 to indicate that there is no state yet.
state := &State{
Common: resource.New(resource.State, ws),
WorkspaceID: ws.GetID(),
Common: resource.New(resource.State, resource.GlobalResource),
WorkspaceID: workspaceID,
Serial: -1,
}

Expand Down Expand Up @@ -74,7 +74,7 @@ func newState(ws resource.Resource, r io.Reader) (*State, error) {

addr := ResourceAddress(b.String())
var err error
m[addr], err = newResource(state, addr, instance.Attributes)
m[addr], err = newResource(workspaceID, addr, instance.Attributes)
if err != nil {
return nil, fmt.Errorf("decoding resource %s: %w", addr, err)
}
Expand Down
74 changes: 39 additions & 35 deletions internal/tui/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ type Helpers struct {
Logger logging.Interface
}

func (h *Helpers) WorkspaceName(res resource.Resource) string {
if ws := res.Workspace(); ws != nil {
return ws.String()
}
return ""
}

func (h *Helpers) ModuleCurrentWorkspace(mod *module.Module) *workspace.Workspace {
if mod.CurrentWorkspaceID == nil {
return nil
Expand All @@ -52,18 +45,6 @@ func (h *Helpers) ModuleCurrentWorkspace(mod *module.Module) *workspace.Workspac
return ws
}

func (h *Helpers) Module(res resource.Resource) *module.Module {
if res.Module() == nil {
return nil
}
mod, ok := res.Module().(*module.Module)
if !ok {
h.Logger.Error("unable to unwrap module from resource interface", "resource", res)
return nil
}
return mod
}

func (h *Helpers) CurrentWorkspaceName(workspaceID *resource.ID) string {
if workspaceID == nil {
return "-"
Expand Down Expand Up @@ -149,29 +130,42 @@ func (h *Helpers) TaskModulePath(t *task.Task) string {
return ""
}

// TaskWorkspace retrieves either the task's workspace if it belongs to a
// workspace, or if it belongs to a module, then it retrieves the module's
// current workspace
func (h *Helpers) TaskWorkspace(t *task.Task) (resource.Resource, bool) {
if ws := t.Workspace(); ws != nil {
return ws, true
// TaskWorkspace retrieves the task's workspace if it belongs to one.
func (h *Helpers) TaskWorkspace(t *task.Task) *workspace.Workspace {
workspaceID := t.WorkspaceID
if workspaceID == nil {
return nil
}
if mod := h.TaskModule(t); mod != nil {
if ws := h.ModuleCurrentWorkspace(mod); ws != nil {
return ws, true
}
return nil, false
ws, err := h.Workspaces.Get(*workspaceID)
if err != nil {
return nil
}
return nil, false
return ws
}

func (h *Helpers) TaskWorkspaceName(t *task.Task) string {
if ws := h.TaskWorkspace(t); ws != nil {
return ws.Path
return ws.Name
}
return ""
}

// TaskWorkspaceOrCurrentWorkspace retrieves either the task's workspace if it belongs to a
// workspace, or if it belongs to a module, then it retrieves the module's
// current workspace
func (h *Helpers) TaskWorkspaceOrCurrentWorkspace(t *task.Task) *workspace.Workspace {
if ws := h.TaskWorkspace(t); ws != nil {
return ws
}
if mod := h.TaskModule(t); mod != nil {
if ws := h.ModuleCurrentWorkspace(mod); ws != nil {
return ws
}
return nil
}
return nil
}

// TaskStatus provides a rendered colored task status.
func (h *Helpers) TaskStatus(t *task.Task, background bool) string {
var color lipgloss.Color
Expand Down Expand Up @@ -387,14 +381,24 @@ func (h *Helpers) Breadcrumbs(title string, res resource.Resource, crumbs ...str
return h.Breadcrumbs(title, resource.GlobalResource, cmd)
case *state.Resource:
addr := TitleAddress.Render(res.String())
return h.Breadcrumbs(title, res.GetParent().GetParent(), addr)
ws, err := h.Workspaces.Get(res.WorkspaceID)
if err != nil {
h.Logger.Error("rendering breadcrumbs", "error", err)
return ""
}
return h.Breadcrumbs(title, ws, addr)
case *task.Group:
cmd := TitleCommand.Render(res.String())
id := TitleID.Render(res.GetID().String())
return h.Breadcrumbs(title, res.GetParent(), cmd, id)
return h.Breadcrumbs(title, resource.GlobalResource, cmd, id)
case *workspace.Workspace:
name := TitleWorkspace.Render(res.String())
return h.Breadcrumbs(title, res.GetParent(), append(crumbs, name)...)
mod, err := h.Modules.Get(res.ModuleID)
if err != nil {
h.Logger.Error("rendering breadcrumbs", "error", err)
return ""
}
return h.Breadcrumbs(title, mod, append(crumbs, name)...)
case *module.Module:
crumbs = append(crumbs, TitlePath.Render(res.String()))
}
Expand Down
9 changes: 7 additions & 2 deletions internal/tui/module/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,13 @@ func (m list) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case resource.Event[*task.Task]:
// Re-render module whenever a task event is received belonging to the
// module.
if mod := msg.Payload.Module(); mod != nil {
m.table.AddItems(mod.(*module.Module))
if moduleID := msg.Payload.ModuleID; moduleID != nil {
mod, err := m.Modules.Get(*moduleID)
if err != nil {
m.Logger.Error("re-rendering module upon receiving task event", "error", err, "task", msg.Payload)
return m, nil
}
m.table.AddItems(mod)
}
case tea.KeyMsg:
switch {
Expand Down
4 changes: 2 additions & 2 deletions internal/tui/task/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (mm *ListMaker) Make(_ resource.ID, width, height int) (tea.Model, error) {
return table.RenderedRow{
taskIDColumn.Key: t.ID.String(),
table.ModuleColumn.Key: mm.Helpers.TaskModulePath(t),
table.WorkspaceColumn.Key: mm.Helpers.WorkspaceName(t),
table.WorkspaceColumn.Key: mm.Helpers.TaskWorkspaceName(t),
commandColumn.Key: t.String(),
ageColumn.Key: tui.Ago(time.Now(), t.Updated),
statusColumn.Key: mm.Helpers.TaskStatus(t, false),
Expand Down Expand Up @@ -147,7 +147,7 @@ func (m List) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
)
case key.Matches(msg, keys.Common.State):
if row, ok := m.Table.CurrentRow(); ok {
if ws, ok := m.TaskWorkspace(row.Value); ok {
if ws := m.TaskWorkspaceOrCurrentWorkspace(row.Value); ws != nil {
return m, tui.NavigateTo(tui.ResourceListKind, tui.WithParent(ws.GetID()))
} else {
return m, tui.ReportError(errors.New("task not associated with a workspace"))
Expand Down
6 changes: 3 additions & 3 deletions internal/tui/task/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.CreateTasksWithSpecs(spec),
)
case key.Matches(msg, keys.Common.State):
if ws, ok := m.TaskWorkspace(m.task); ok {
if ws := m.TaskWorkspaceOrCurrentWorkspace(m.task); ws != nil {
return m, tui.NavigateTo(tui.ResourceListKind, tui.WithParent(ws.GetID()))
} else {
return m, tui.ReportError(errors.New("task not associated with a workspace"))
Expand Down Expand Up @@ -306,10 +306,10 @@ func (m model) HelpBindings() []key.Binding {
keys.Common.Retry,
localKeys.ToggleInfo,
}
if mod := m.task.Module(); mod != nil {
if moduleID := m.task.ModuleID; moduleID != nil {
bindings = append(bindings, keys.Common.Module)
}
if ws := m.task.Workspace(); ws != nil {
if workspaceID := m.task.WorkspaceID; workspaceID != nil {
bindings = append(bindings, keys.Common.Workspace)
}
if plan.IsApplyTask(m.task) {
Expand Down
9 changes: 7 additions & 2 deletions internal/tui/workspace/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,13 @@ func (m list) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case resource.Event[*task.Task]:
// Re-render workspace whenever a task event is received belonging to the
// workspace.
if ws := msg.Payload.Workspace(); ws != nil {
m.table.AddItems(ws.(*workspace.Workspace))
if workspaceID := msg.Payload.WorkspaceID; workspaceID != nil {
ws, err := m.Workspaces.Get(*workspaceID)
if err != nil {
m.Logger.Error("re-rendering workspace upon receiving task event", "error", err, "task", msg.Payload)
return m, nil
}
m.table.AddItems(ws)
}
case tea.KeyMsg:
switch {
Expand Down
Loading

0 comments on commit 38ad4bc

Please sign in to comment.