140 lines
3.1 KiB
Go
140 lines
3.1 KiB
Go
package formatter
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/charmbracelet/lipgloss"
|
|
"github.com/charmbracelet/lipgloss/table"
|
|
"github.com/docker/go-units"
|
|
"golang.org/x/term"
|
|
|
|
"coopcloud.tech/abra/pkg/log"
|
|
"github.com/schollz/progressbar/v3"
|
|
)
|
|
|
|
var BoldStyle = lipgloss.NewStyle().
|
|
Bold(true).
|
|
Underline(true)
|
|
|
|
func ShortenID(str string) string {
|
|
return str[:12]
|
|
}
|
|
|
|
func SmallSHA(hash string) string {
|
|
return hash[:8]
|
|
}
|
|
|
|
// RemoveSha remove image sha from a string that are added in some docker outputs
|
|
func RemoveSha(str string) string {
|
|
return strings.Split(str, "@")[0]
|
|
}
|
|
|
|
// HumanDuration from docker/cli RunningFor() to be accessible outside of the class
|
|
func HumanDuration(timestamp int64) string {
|
|
date := time.Unix(timestamp, 0)
|
|
now := time.Now().UTC()
|
|
return units.HumanDuration(now.Sub(date)) + " ago"
|
|
}
|
|
|
|
// CreateTable prepares a table layout for output.
|
|
func CreateTable() (*table.Table, error) {
|
|
width, _, err := term.GetSize(0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if width-10 < 79 {
|
|
width = 79
|
|
}
|
|
|
|
return table.New().
|
|
Width(width - 10).
|
|
Border(lipgloss.ThickBorder()).
|
|
BorderStyle(
|
|
lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("63")),
|
|
), nil
|
|
}
|
|
|
|
// ToJSON converts a lipgloss.Table to JSON representation. It's not a robust
|
|
// implementation and mainly caters for our current use case which is basically
|
|
// a bunch of strings. See https://github.com/charmbracelet/lipgloss/issues/335
|
|
// for the real thing (hopefully).
|
|
func ToJSON(headers []string, rows [][]string) (string, error) {
|
|
var buff bytes.Buffer
|
|
|
|
buff.Write([]byte("["))
|
|
|
|
for _, row := range rows {
|
|
payload := make(map[string]string)
|
|
|
|
for idx, header := range headers {
|
|
payload[strings.ToLower(header)] = row[idx]
|
|
}
|
|
|
|
serialized, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
buff.Write(serialized)
|
|
}
|
|
|
|
buff.Write([]byte("]"))
|
|
|
|
return buff.String(), nil
|
|
}
|
|
|
|
// CreateProgressbar generates a progress bar
|
|
func CreateProgressbar(length int, title string) *progressbar.ProgressBar {
|
|
return progressbar.NewOptions(
|
|
length,
|
|
progressbar.OptionClearOnFinish(),
|
|
progressbar.OptionSetPredictTime(false),
|
|
progressbar.OptionShowCount(),
|
|
progressbar.OptionFullWidth(),
|
|
progressbar.OptionSetDescription(title),
|
|
)
|
|
}
|
|
|
|
// StripTagMeta strips front-matter image tag data that we don't need for parsing.
|
|
func StripTagMeta(image string) string {
|
|
originalImage := image
|
|
|
|
if strings.Contains(image, "docker.io") {
|
|
image = strings.Split(image, "/")[1]
|
|
}
|
|
|
|
if strings.Contains(image, "library") {
|
|
image = strings.Split(image, "/")[1]
|
|
}
|
|
|
|
if originalImage != image {
|
|
log.Debugf("stripped %s to %s for parsing", originalImage, image)
|
|
}
|
|
|
|
return image
|
|
}
|
|
|
|
// ByteCountSI presents a human friendly representation of a byte count. See
|
|
// https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format.
|
|
func ByteCountSI(b uint64) string {
|
|
const unit = 1000
|
|
|
|
if b < unit {
|
|
return fmt.Sprintf("%d B", b)
|
|
}
|
|
|
|
div, exp := uint64(unit), 0
|
|
for n := b / unit; n >= unit; n /= unit {
|
|
div *= unit
|
|
exp++
|
|
}
|
|
|
|
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
|
|
}
|