Skip to content

Commit bec1686

Browse files
committed
feat(add docker context object)
1 parent f771d1b commit bec1686

11 files changed

Lines changed: 271 additions & 8 deletions

File tree

internal/dao/docker.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"log"
1010
"net/http"
1111
"os"
12+
"os/exec"
1213
"strings"
1314
"sync"
1415
"time"
@@ -591,6 +592,40 @@ func (d *DockerClient) StackPS(name string) (string, error) {
591592
return d.Stack.PS(name)
592593
}
593594

595+
func (d *DockerClient) InspectContext(name string) (string, error) {
596+
cmd := exec.Command("docker", "context", "inspect", name)
597+
output, err := cmd.CombinedOutput()
598+
if err != nil {
599+
return "", fmt.Errorf("error inspecting context: %v, output: %s", err, string(output))
600+
}
601+
return string(output), nil
602+
}
603+
604+
func (d *DockerClient) RemoveContext(name string) error {
605+
cmd := exec.Command("docker", "context", "rm", name)
606+
output, err := cmd.CombinedOutput()
607+
if err != nil {
608+
return fmt.Errorf("error removing context: %v, output: %s", err, string(output))
609+
}
610+
return nil
611+
}
612+
613+
func (d *DockerClient) CreateContext(name, description, host string) error {
614+
args := []string{"context", "create", name}
615+
if description != "" {
616+
args = append(args, "--description", description)
617+
}
618+
if host != "" {
619+
args = append(args, "--docker", fmt.Sprintf("host=%s", host))
620+
}
621+
cmd := exec.Command("docker", args...)
622+
output, err := cmd.CombinedOutput()
623+
if err != nil {
624+
return fmt.Errorf("error creating context: %v, output: %s", err, string(output))
625+
}
626+
return nil
627+
}
628+
594629
func (d *DockerClient) ListTasks() ([]common.Resource, error) {
595630
return d.Task.List()
596631
}

internal/ui/app.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/jr-k/d4s/internal/ui/views/nodes"
2828
"github.com/jr-k/d4s/internal/ui/views/configs"
2929
"github.com/jr-k/d4s/internal/ui/views/secrets"
30+
"github.com/jr-k/d4s/internal/ui/views/contexts"
3031
"github.com/jr-k/d4s/internal/ui/views/stacks"
3132
"github.com/jr-k/d4s/internal/ui/views/tasks"
3233
"github.com/jr-k/d4s/internal/ui/views/services"
@@ -377,6 +378,18 @@ func (a *App) initUI() {
377378
}
378379
a.Views[styles.TitleConfigs] = vConfigs
379380

381+
// Contexts
382+
vContexts := view.NewResourceView(a, styles.TitleContexts)
383+
vContexts.ShortcutsFunc = contexts.GetShortcuts
384+
vContexts.FetchFunc = contexts.Fetch
385+
vContexts.InspectFunc = contexts.Inspect
386+
vContexts.RemoveFunc = contexts.Remove
387+
vContexts.Headers = contexts.Headers
388+
vContexts.InputHandler = func(event *tcell.EventKey) *tcell.EventKey {
389+
return contexts.InputHandler(vContexts, event)
390+
}
391+
a.Views[styles.TitleContexts] = vContexts
392+
380393
for title, view := range a.Views {
381394
a.Pages.AddPage(title, view.Table, true, false)
382395
}
@@ -426,9 +439,10 @@ func (a *App) initUI() {
426439
return a.ActiveInspector.InputHandler(event)
427440
}
428441

429-
// Don't intercept global keys if an input modal is open
442+
// Don't intercept global keys if a modal/dialog is open
430443
frontPage, _ := a.Pages.GetFrontPage()
431-
if frontPage == "input" || frontPage == "confirm" {
444+
switch frontPage {
445+
case "input", "confirm", "form", "picker", "env_editor", "textview", "result":
432446
return event
433447
}
434448

@@ -517,7 +531,7 @@ func (a *App) initUI() {
517531
case 'C': // Global Copy View
518532
a.PerformCopyView()
519533
return nil
520-
case 'T': // Global Context Picker
534+
case 'O': // Global Context Picker
521535
a.ShowContextPicker()
522536
a.UpdateShortcuts()
523537
return nil
@@ -587,6 +601,8 @@ func (a *App) resolveDefaultView() string {
587601
return styles.TitleStacks
588602
case "tasks", "task":
589603
return styles.TitleTasks
604+
case "contexts", "context":
605+
return styles.TitleContexts
590606
default:
591607
return styles.TitleContainers
592608
}

internal/ui/app_navigation.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (a *App) ExecuteCmd(cmd string) {
3333
switchToRoot(styles.TitleNetworks)
3434
case "s", "se", "svc", "service", "services":
3535
switchToRoot(styles.TitleServices)
36-
case "no", "node", "nodes":
36+
case "d", "no", "node", "nodes":
3737
switchToRoot(styles.TitleNodes)
3838
case "p", "cp", "compose", "project", "projects":
3939
switchToRoot(styles.TitleCompose)
@@ -47,6 +47,8 @@ func (a *App) ExecuteCmd(cmd string) {
4747
switchToRoot(styles.TitleStacks)
4848
case "t", "task", "tasks":
4949
switchToRoot(styles.TitleTasks)
50+
case "o", "ctx", "context", "contexts":
51+
switchToRoot(styles.TitleContexts)
5052
case "h", "help", "?":
5153
a.Pages.AddPage("help", a.Help, true, true)
5254
default:

internal/ui/app_shortcuts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func (a *App) getCurrentShortcuts() []string {
2020
shortcuts = view.ShortcutsFunc()
2121
}
2222

23-
shortcuts = append(shortcuts, common.FormatSCHeaderGlobal("shift-t", "Context"))
23+
shortcuts = append(shortcuts, common.FormatSCHeaderGlobal("shift-o", "Context"))
2424
shortcuts = append(shortcuts, common.FormatSCHeaderGlobal("shift ←/→", "Sort"))
2525
shortcuts = append(shortcuts, common.FormatSCHeaderGlobal("shift-c", "Copy Table"))
2626
shortcuts = append(shortcuts, common.FormatSCHeaderGlobal("c", "Copy Cell"))

internal/ui/common/common.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ type AppController interface {
7373
RunInBackground(task func())
7474
SetPaused(paused bool)
7575

76+
// Context Management
77+
SetDefaultContext(contextName string)
78+
7679
// Refactoring: Auto Refresh Control
7780
StartAutoRefresh()
7881
StopAutoRefresh()

internal/ui/components/command/command.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ var availableCommands = []string{
117117
"configs",
118118
"stacks",
119119
"tasks",
120+
"contexts",
120121
"help",
121122
"aliases",
122123
"q",
@@ -130,6 +131,8 @@ var availableCommands = []string{
130131
"a",
131132
"k",
132133
"t",
134+
"o",
135+
"d",
133136
}
134137

135138
// findBestSuggestion finds the best matching command for autocompletion

internal/ui/dialogs/form.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ func ShowFormWithDescription(app common.AppController, title, description string
173173
SetBackgroundColorActivated(styles.ColorAccent).
174174
SetLabelColorActivated(styles.ColorBlack)
175175
confirmBtn.SetBackgroundColor(styles.ColorSelectBg)
176+
confirmBtn.SetStyle(tcell.StyleDefault.Foreground(styles.ColorBlack).Background(styles.ColorIdle))
176177

177178
confirmRow := tview.NewFlex().
178179
SetDirection(tview.FlexColumn).

internal/ui/dialogs/help.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ func NewHelpView(app common.AppController) tview.Primitive {
2828
{fmt.Sprintf("[%s::b]DOCKER", a), ""},
2929
{fmt.Sprintf("[%s]:c[-] Containers", k), fmt.Sprintf("[%s]:i[-] Images", k)},
3030
{fmt.Sprintf("[%s]:v[-] Volumes", k), fmt.Sprintf("[%s]:n[-] Networks", k)},
31-
{fmt.Sprintf("[%s]:p[-] Compose", k), ""},
31+
{fmt.Sprintf("[%s]:p[-] Compose", k), fmt.Sprintf("[%s]:o[-] Contexts", k)},
3232
{"", ""},
3333
{fmt.Sprintf("[%s::b]SWARM", a), ""},
34-
{fmt.Sprintf("[%s]:no[-] Nodes", k), fmt.Sprintf("[%s]:t[-] Tasks", k)},
34+
{fmt.Sprintf("[%s]:d[-] Nodes", k), fmt.Sprintf("[%s]:t[-] Tasks", k)},
3535
{fmt.Sprintf("[%s]:k[-] Stacks", k), fmt.Sprintf("[%s]:f[-] Configs", k)},
3636
{fmt.Sprintf("[%s]:s[-] Services", k), fmt.Sprintf("[%s]:x[-] Secrets", k)},
3737
{"", ""},

internal/ui/styles/styles.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ const (
138138
TitleConfigs = "Configs"
139139
TitleStacks = "Stacks"
140140
TitleTasks = "Tasks"
141+
TitleContexts = "Contexts"
141142
)
142143

143144
// invertColor inverts a tcell.Color by flipping its lightness while preserving hue and saturation.

internal/ui/views/aliases/aliases.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,12 @@ func Fetch(app common.AppController, v *view.ResourceView) ([]dao.Resource, erro
6464
{Title: styles.TitleVolumes, Resource: "volumes", Group: "docker", Shortcuts: []string{"v", "vo", "vol", "volume", "volumes"}},
6565
{Title: styles.TitleNetworks, Resource: "networks", Group: "docker", Shortcuts: []string{"n", "ne", "net", "network", "networks"}},
6666
{Title: styles.TitleServices, Resource: "services", Group: "swarm", Shortcuts: []string{"s", "se", "svc", "service", "services"}},
67-
{Title: styles.TitleNodes, Resource: "nodes", Group: "swarm", Shortcuts: []string{"no", "node", "nodes"}},
67+
{Title: styles.TitleNodes, Resource: "nodes", Group: "swarm", Shortcuts: []string{"d", "no", "node", "nodes"}},
6868
{Title: styles.TitleSecrets, Resource: "secrets", Group: "swarm", Shortcuts: []string{"x", "sec", "secret", "secrets"}},
6969
{Title: styles.TitleConfigs, Resource: "configs", Group: "swarm", Shortcuts: []string{"f", "cfg", "config", "configs"}},
7070
{Title: styles.TitleStacks, Resource: "stacks", Group: "swarm", Shortcuts: []string{"k", "st", "stack", "stacks"}},
7171
{Title: styles.TitleTasks, Resource: "tasks", Group: "swarm", Shortcuts: []string{"t", "task", "tasks"}},
72+
{Title: styles.TitleContexts, Resource: "contexts", Group: "docker", Shortcuts: []string{"o", "ctx", "context", "contexts"}},
7273
{Title: styles.TitleCompose, Resource: "compose", Group: "compose", Shortcuts: []string{"p", "cp", "compose", "project", "projects"}},
7374
}
7475

0 commit comments

Comments
 (0)