Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend the images CMD with the --tui flag #50

Merged
merged 9 commits into from
Sep 3, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ dist_mac_m1.zip
*.swp
*.swo
slim.report.json
debug.log
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ require (
github.com/c-bata/go-prompt v0.2.3
github.com/c4milo/unpackit v0.0.0-20170704181138-4ed373e9ef1c
github.com/cespare/xxhash/v2 v2.2.0
github.com/charmbracelet/bubbles v0.19.0
github.com/charmbracelet/bubbletea v1.0.1
github.com/charmbracelet/lipgloss v0.13.0
github.com/compose-spec/compose-go v0.0.0-20210916141509-a7e1bc322970
github.com/containerd/console v1.0.3
github.com/containers/common v0.60.1
github.com/containers/podman/v5 v5.2.1
github.com/containers/storage v1.55.0
github.com/docker/docker v27.1.2+incompatible
github.com/docker/go-connections v0.5.0
github.com/dustin/go-humanize v1.0.0
github.com/dustin/go-humanize v1.0.1
github.com/fatih/color v1.15.0
github.com/fsouza/go-dockerclient v1.12.0
github.com/getkin/kin-openapi v0.76.0
Expand Down Expand Up @@ -62,8 +66,6 @@ require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
github.com/charmbracelet/bubbletea v1.0.1 // indirect
github.com/charmbracelet/lipgloss v0.13.0 // indirect
github.com/charmbracelet/x/ansi v0.1.4 // indirect
github.com/charmbracelet/x/input v0.1.0 // indirect
github.com/charmbracelet/x/term v0.1.1 // indirect
Expand All @@ -83,7 +85,6 @@ require (
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
github.com/containers/ocicrypt v1.2.0 // indirect
github.com/containers/psgo v1.9.0 // indirect
github.com/containers/storage v1.55.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
Expand Down
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:W
github.com/aws/aws-sdk-go v1.34.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -81,12 +83,16 @@ github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/bubbles v0.19.0 h1:gKZkKXPP6GlDk6EcfujDK19PCQqRjaJZQ7QRERx1UF0=
github.com/charmbracelet/bubbles v0.19.0/go.mod h1:WILteEqZ+krG5c3ntGEMeG99nCupcuIk7V0/zOP0tOA=
github.com/charmbracelet/bubbletea v1.0.1 h1:M89yCL4w2ekR7NiNw6s4JsbBE1NOuKdD7t6XEFdl1jw=
github.com/charmbracelet/bubbletea v1.0.1/go.mod h1:xc4gm5yv+7tbniEvQ0naiG9P3fzYhk16cTgDZQQW6YE=
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM=
github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ=
github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28=
github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI=
Expand Down Expand Up @@ -188,8 +194,8 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down
3 changes: 3 additions & 0 deletions pkg/app/master/command/images/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ const (
type CommandParams struct {
Runtime string `json:"runtime,omitempty"`
Filter string `json:"filter,omitempty"`
TUI bool `json:"tui"`
}

var ImagesFlags = []cli.Flag{
command.Cflag(command.FlagRuntime),
cflag(FlagFilter),
cflag(FlagTUI),
}

//todo soon: add a lot of useful filtering flags
Expand All @@ -46,6 +48,7 @@ var CLI = &cli.Command{
cparams := &CommandParams{
Runtime: ctx.String(command.FlagRuntime),
Filter: ctx.String(FlagFilter),
TUI: ctx.Bool(FlagTUI),
}

OnCommand(xc, gcvalues, cparams)
Expand Down
6 changes: 6 additions & 0 deletions pkg/app/master/command/images/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
const (
FlagFilter = "filter"
FlagFilterUsage = "container image filter pattern"
FlagTUI = "tui"
FlagTUIUsage = "terminal user interface"
)

var Flags = map[string]cli.Flag{
Expand All @@ -18,6 +20,10 @@ var Flags = map[string]cli.Flag{
Usage: FlagFilterUsage,
EnvVars: []string{"DSLIM_IMAGES_FILTER"},
},
FlagTUI: &cli.BoolFlag{
Name: FlagTUI,
Usage: FlagTUIUsage,
},
}

func cflag(name string) cli.Flag {
Expand Down
7 changes: 7 additions & 0 deletions pkg/app/master/command/images/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (

"github.com/mintoolkit/mint/pkg/app"
"github.com/mintoolkit/mint/pkg/app/master/command"
"github.com/mintoolkit/mint/pkg/app/master/tui"
"github.com/mintoolkit/mint/pkg/app/master/tui/models"
"github.com/mintoolkit/mint/pkg/app/master/version"
cmd "github.com/mintoolkit/mint/pkg/command"
"github.com/mintoolkit/mint/pkg/crt"
Expand Down Expand Up @@ -126,6 +128,11 @@ func OnCommand(
images, err := crtClient.ListImages(cparams.Filter)
xc.FailOn(err)

if cparams.TUI {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need a bit of extra logic to configure xc before OnCommand is called, so it knows it's executing in the TUI mode. That way the xc.Out.Info("cmd.input.params", ovars{ "runtime": rr, "filter": cparams.Filter, }) call earlier in OnCommand won't print stuff to console.

This snippet in cli.go for the command will need to be enhanced to know we are in the TUI mode: xc := app.NewExecutionContext( Name, gcvalues.QuietCLIMode, gcvalues.OutputFormat)

model := models.InitialImages(images)
tui.RunTUI(model)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be good to term this into else if xc.Out.Quiet with the next block of code that follows.


if xc.Out.Quiet {
if xc.Out.OutputFormat == command.OutputFormatJSON {
fmt.Printf("%s\n", jsonutil.ToPretty(images))
Expand Down
4 changes: 3 additions & 1 deletion pkg/app/master/command/tui/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tui

import (
tui "github.com/mintoolkit/mint/pkg/app/master/tui"
"github.com/mintoolkit/mint/pkg/app/master/tui/models"
cmd "github.com/mintoolkit/mint/pkg/command"
"github.com/urfave/cli/v2"
)
Expand All @@ -17,7 +18,8 @@ var CLI = &cli.Command{
Aliases: []string{Alias},
Usage: Usage,
Action: func(ctx *cli.Context) error {
tui.RunTUI()
m := models.InitialModel()
tui.RunTUI(m)
return nil
},
}
20 changes: 0 additions & 20 deletions pkg/app/master/tui/main.go

This file was deleted.

108 changes: 94 additions & 14 deletions pkg/app/master/tui/models/model.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,95 @@
package models

import (
"fmt"
"time"

"github.com/charmbracelet/bubbles/table"
"github.com/charmbracelet/lipgloss"
"github.com/dustin/go-humanize"
"github.com/mintoolkit/mint/pkg/crt"
"github.com/mintoolkit/mint/pkg/crt/docker/dockerutil"

tea "github.com/charmbracelet/bubbletea"
)

// Model represents the state of the TUI.
type Model struct {
// Add fields that represent the state of your TUI.
count int
// Images represents the state of the TUI.
type Images struct {
table table.Model
loaded bool
}

// InitialModel returns the initial state of the model.
func InitialModel() Model {
return Model{
count: 0, // Initialize any state variables here.
// InitialImages returns the initial state of the model.
func InitialImages(images map[string]crt.BasicImageInfo) *Images {
var rows []table.Row
for k, v := range images {
imageRow := []string{k, dockerutil.CleanImageID(v.ID)[:12], humanize.Time(time.Unix(v.Created, 0)), humanize.Bytes(uint64(v.Size))}
rows = append(rows, imageRow)
}

m := &Images{}
columns := []table.Column{
{Title: "Name", Width: 50},
{Title: "Image ID", Width: 15},
{Title: "Created", Width: 30},
{Title: "Size", Width: 8},
}
table := table.New(
table.WithColumns(columns),
table.WithRows(rows),
table.WithHeight(7),
)

m.table = table
return m
}

func (m Images) Init() tea.Cmd {
// Just return `nil`, which means "no I/O right now, please."
return nil
}

// Update is called to handle user input and update the model's state.
func (m Images) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
if !m.loaded {
m.loaded = true
}
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c":
return m, tea.Quit // Quit the program.
}
}
return m, nil
}

// View returns the view that should be displayed.
func (m Images) View() string {
if m.loaded {
content := m.table.View()

footerStyle := lipgloss.NewStyle().
Foreground(lipgloss.Color("#282828")).
Background(lipgloss.Color("#7c6f64"))

footerStr := "Press q to quit"
footer := footerStyle.Render(footerStr)
return lipgloss.JoinVertical(lipgloss.Left,
content,
footer,
)
} else {
return "loading"
}
}

// Default Model
type Model struct{}

func InitialModel() *Model {
m := &Model{}
return m
}

func (m Model) Init() tea.Cmd {
Expand All @@ -31,16 +104,23 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.String() {
case "q", "ctrl+c":
return m, tea.Quit // Quit the program.
case "up":
m.count++
case "down":
m.count--
}
}
return m, nil
}

// View returns the view that should be displayed.
func (m Model) View() string {
return "Press q to quit.\n" + "Count: " + fmt.Sprint(m.count)
content := "Coming soon..."

footerStyle := lipgloss.NewStyle().
Foreground(lipgloss.Color("#282828")).
Background(lipgloss.Color("#7c6f64"))

footerStr := "Press q to quit"
footer := footerStyle.Render(footerStr)
return lipgloss.JoinVertical(lipgloss.Left,
content,
footer,
)
}
26 changes: 26 additions & 0 deletions pkg/app/master/tui/tui.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tui

import (
"os"

"log"

tea "github.com/charmbracelet/bubbletea"
)

// RunTUI starts the TUI program.
func RunTUI(model tea.Model) {
f, err := tea.LogToFile("debug.log", "debug")
if err != nil {
log.Printf("RunTUI Logging - %v", err)
os.Exit(1)
}

defer f.Close()

p := tea.NewProgram(model)
if _, err := p.Run(); err != nil {
log.Printf("RunTUI error - %v", err)
os.Exit(1)
}
}
10 changes: 0 additions & 10 deletions pkg/app/master/tui/views/view.go

This file was deleted.

21 changes: 21 additions & 0 deletions vendor/github.com/charmbracelet/bubbles/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading