mirror of https://github.com/fluxcd/cli-utils.git
155 lines
3.9 KiB
Go
155 lines
3.9 KiB
Go
// Copyright 2020 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package table
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
|
|
|
pe "github.com/fluxcd/cli-utils/pkg/kstatus/polling/event"
|
|
"github.com/fluxcd/cli-utils/pkg/object"
|
|
"github.com/fluxcd/cli-utils/pkg/print/common"
|
|
)
|
|
|
|
// ColumnDefinition defines the columns that should be printed.
|
|
type ColumnDefinition interface {
|
|
Name() string
|
|
Header() string
|
|
Width() int
|
|
PrintResource(w io.Writer, width int, r Resource) (int, error)
|
|
}
|
|
|
|
// ResourceStates defines the interface that must be implemented
|
|
// by the object that provides information about the resources
|
|
// that should be printed.
|
|
type ResourceStates interface {
|
|
Resources() []Resource
|
|
Error() error
|
|
}
|
|
|
|
// Resource defines the interface that each of the Resource
|
|
// objects must implement.
|
|
type Resource interface {
|
|
Identifier() object.ObjMetadata
|
|
ResourceStatus() *pe.ResourceStatus
|
|
SubResources() []Resource
|
|
}
|
|
|
|
// BaseTablePrinter provides functionality for printing information
|
|
// about a set of resources into a table format.
|
|
// The printer will print to the Out stream defined in IOStreams,
|
|
// and will print into the format defined by the Column definitions.
|
|
type BaseTablePrinter struct {
|
|
IOStreams genericclioptions.IOStreams
|
|
Columns []ColumnDefinition
|
|
}
|
|
|
|
// PrintTable prints the resources defined in ResourceStates. It will
|
|
// print subresources if they exist.
|
|
// moveUpCount defines how many lines the printer should move up
|
|
// before starting printing. The return value is how many lines
|
|
// were printed.
|
|
func (t *BaseTablePrinter) PrintTable(rs ResourceStates,
|
|
moveUpCount int) int {
|
|
for i := 0; i < moveUpCount; i++ {
|
|
t.moveUp()
|
|
t.eraseCurrentLine()
|
|
}
|
|
|
|
linePrintCount := 0
|
|
for i, column := range t.Columns {
|
|
format := fmt.Sprintf("%%-%ds", column.Width())
|
|
t.printOrDie(format, column.Header())
|
|
if i == len(t.Columns)-1 {
|
|
t.printOrDie("\n")
|
|
linePrintCount++
|
|
} else {
|
|
t.printOrDie(" ")
|
|
}
|
|
}
|
|
|
|
for _, resource := range rs.Resources() {
|
|
for i, column := range t.Columns {
|
|
written, err := column.PrintResource(t.IOStreams.Out, column.Width(), resource)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
remainingSpace := column.Width() - written
|
|
t.printOrDie("%s", strings.Repeat(" ", remainingSpace))
|
|
if i == len(t.Columns)-1 {
|
|
t.printOrDie("\n")
|
|
linePrintCount++
|
|
} else {
|
|
t.printOrDie(" ")
|
|
}
|
|
}
|
|
|
|
linePrintCount += t.printSubTable(resource.SubResources(), "")
|
|
}
|
|
|
|
return linePrintCount
|
|
}
|
|
|
|
// printSubTable prints out any subresources that belong to the
|
|
// top-level resources. This function takes care of printing the correct tree
|
|
// structure and indentation.
|
|
func (t *BaseTablePrinter) printSubTable(resources []Resource,
|
|
prefix string) int {
|
|
linePrintCount := 0
|
|
for j, resource := range resources {
|
|
for i, column := range t.Columns {
|
|
availableWidth := column.Width()
|
|
if column.Name() == "resource" {
|
|
if j < len(resources)-1 {
|
|
t.printOrDie("%s", prefix+`├─ `)
|
|
} else {
|
|
t.printOrDie("%s", prefix+`└─ `)
|
|
}
|
|
availableWidth -= utf8.RuneCountInString(prefix) + 3
|
|
}
|
|
written, err := column.PrintResource(t.IOStreams.Out,
|
|
availableWidth, resource)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
remainingSpace := availableWidth - written
|
|
t.printOrDie("%s", strings.Repeat(" ", remainingSpace))
|
|
if i == len(t.Columns)-1 {
|
|
t.printOrDie("\n")
|
|
linePrintCount++
|
|
} else {
|
|
t.printOrDie(" ")
|
|
}
|
|
}
|
|
|
|
var prefix string
|
|
if j < len(resources)-1 {
|
|
prefix = `│ `
|
|
} else {
|
|
prefix = " "
|
|
}
|
|
linePrintCount += t.printSubTable(resource.SubResources(), prefix)
|
|
}
|
|
return linePrintCount
|
|
}
|
|
|
|
func (t *BaseTablePrinter) printOrDie(format string, a ...interface{}) {
|
|
_, err := fmt.Fprintf(t.IOStreams.Out, format, a...)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func (t *BaseTablePrinter) moveUp() {
|
|
t.printOrDie("%c[%dA", common.ESC, 1)
|
|
}
|
|
|
|
func (t *BaseTablePrinter) eraseCurrentLine() {
|
|
t.printOrDie("%c[2K\r", common.ESC)
|
|
}
|