180 lines
3.7 KiB
Go
180 lines
3.7 KiB
Go
package ui
|
|
|
|
import (
|
|
"registry-tui/client"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/bubbles/textinput"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
type ViewState int
|
|
|
|
const (
|
|
StateLoading ViewState = iota
|
|
StateMainTable
|
|
StateConfirmDelete
|
|
StateNewTag
|
|
StateError
|
|
StateRegistryDown
|
|
)
|
|
|
|
type AppMode int
|
|
|
|
const (
|
|
ModeRegistry AppMode = iota
|
|
ModeLocal
|
|
)
|
|
|
|
type ImageRow = client.ImageRowData
|
|
|
|
type Model struct {
|
|
state ViewState
|
|
mode AppMode
|
|
client *client.RegistryClient
|
|
rows []ImageRow
|
|
localRows []ImageRow
|
|
registryRows []ImageRow
|
|
cursor int
|
|
err error
|
|
statusMsg string
|
|
textInput textinput.Model
|
|
version string
|
|
}
|
|
|
|
func NewModel(registryURL string, version string) Model {
|
|
ti := textinput.New()
|
|
ti.Placeholder = "ej. proyecto-web/alpine:v1.0"
|
|
ti.CharLimit = 128
|
|
ti.Width = 35
|
|
|
|
return Model{
|
|
state: StateLoading,
|
|
mode: ModeRegistry,
|
|
client: client.NewRegistryClient(registryURL),
|
|
textInput: ti,
|
|
version: version,
|
|
}
|
|
}
|
|
|
|
func (m Model) Init() tea.Cmd {
|
|
return fetchRegistryImagesCmd(m.client)
|
|
}
|
|
|
|
type imagesMsg struct {
|
|
rows []ImageRow
|
|
mode AppMode
|
|
}
|
|
type errorMsg error
|
|
type successMsg string
|
|
|
|
func fetchRegistryImagesCmd(c *client.RegistryClient) tea.Cmd {
|
|
return func() tea.Msg {
|
|
repos, err := c.GetCatalog()
|
|
if err != nil {
|
|
return errorMsg(err)
|
|
}
|
|
|
|
var rows []ImageRow
|
|
for _, repo := range repos {
|
|
tags, err := c.GetTags(repo)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
var project, imageName string
|
|
parts := strings.Split(repo, "/")
|
|
if len(parts) > 1 {
|
|
project = parts[0]
|
|
imageName = strings.Join(parts[1:], "/")
|
|
} else {
|
|
project = ""
|
|
imageName = repo
|
|
}
|
|
|
|
for _, tag := range tags {
|
|
rows = append(rows, ImageRow{
|
|
Project: project,
|
|
RepoName: repo,
|
|
ImageName: imageName,
|
|
Tag: tag,
|
|
})
|
|
}
|
|
}
|
|
|
|
sortRows(rows)
|
|
return imagesMsg{rows: rows, mode: ModeRegistry}
|
|
}
|
|
}
|
|
|
|
func fetchLocalImagesCmd(c *client.RegistryClient) tea.Cmd {
|
|
return func() tea.Msg {
|
|
rows, err := c.GetLocalImages()
|
|
if err != nil {
|
|
return errorMsg(err)
|
|
}
|
|
sortRows(rows)
|
|
return imagesMsg{rows: rows, mode: ModeLocal}
|
|
}
|
|
}
|
|
|
|
func sortRows(rows []ImageRow) {
|
|
sort.Slice(rows, func(i, j int) bool {
|
|
if rows[i].Project == rows[j].Project {
|
|
return rows[i].RepoName < rows[j].RepoName
|
|
}
|
|
return rows[i].Project < rows[j].Project
|
|
})
|
|
}
|
|
|
|
func deleteTagCmd(c *client.RegistryClient, repo, tag string) tea.Cmd {
|
|
return func() tea.Msg {
|
|
err := c.DeleteManifest(repo, tag)
|
|
if err != nil {
|
|
return errorMsg(err)
|
|
}
|
|
return successMsg("Tag borrado con éxito del registro")
|
|
}
|
|
}
|
|
|
|
func deleteLocalImageCmd(c *client.RegistryClient, repo, tag string) tea.Cmd {
|
|
return func() tea.Msg {
|
|
err := c.DeleteLocalImage(repo, tag)
|
|
if err != nil {
|
|
return errorMsg(err)
|
|
}
|
|
return successMsg("Imagen local borrada con éxito")
|
|
}
|
|
}
|
|
|
|
func copyImageCmd(c *client.RegistryClient, sourceRepo, sourceTag, destRepo, destTag string) tea.Cmd {
|
|
return func() tea.Msg {
|
|
err := c.CopyManifest(sourceRepo, sourceTag, destRepo, destTag)
|
|
if err != nil {
|
|
return errorMsg(err)
|
|
}
|
|
return successMsg("Imagen reestructurada con éxito en el registro")
|
|
}
|
|
}
|
|
|
|
func tagLocalImageCmd(c *client.RegistryClient, sourceRepo, sourceTag, destRepo, destTag string) tea.Cmd {
|
|
return func() tea.Msg {
|
|
err := c.TagLocalImage(sourceRepo, sourceTag, destRepo, destTag)
|
|
if err != nil {
|
|
return errorMsg(err)
|
|
}
|
|
return successMsg("Imagen local etiquetada con éxito")
|
|
}
|
|
}
|
|
|
|
func pushImageCmd(c *client.RegistryClient, repo, tag string) tea.Cmd {
|
|
return func() tea.Msg {
|
|
err := c.PushLocalImage(repo, tag)
|
|
if err != nil {
|
|
return errorMsg(err)
|
|
}
|
|
return successMsg("Imagen subida (Push) al registro con éxito")
|
|
}
|
|
}
|