forked from toolshed/abra
.gitea
cli
cmd
pkg
app
autocomplete
catalogue
client
config
container
context
dns
envfile
formatter
formatter.go
git
integration
limit
lint
log
recipe
secret
server
service
ssh
test
upstream
web
scripts
tests
.dockerignore
.drone.yml
.envrc.sample
.gitignore
.goreleaser.yml
AUTHORS.md
Dockerfile
LICENSE
Makefile
README.md
go.mod
go.sum
renovate.json
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])
|
|
}
|