mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
feat: add table output to cli apply command (#7757)
* feat: add table output to cli apply command Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * factorise Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
parent
b6fb496d9b
commit
9bc540e454
7 changed files with 257 additions and 134 deletions
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/kyverno/kyverno/api/kyverno"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/color"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
|
@ -146,12 +147,14 @@ More info: https://kyverno.io/docs/kyverno-cli/
|
|||
|
||||
func Command() *cobra.Command {
|
||||
var cmd *cobra.Command
|
||||
var removeColor, compact, table bool
|
||||
applyCommandConfig := &ApplyCommandConfig{}
|
||||
cmd = &cobra.Command{
|
||||
Use: "apply",
|
||||
Short: "Applies policies on resources.",
|
||||
Example: applyHelp,
|
||||
RunE: func(cmd *cobra.Command, policyPaths []string) (err error) {
|
||||
color.InitColors(removeColor)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
|
@ -168,6 +171,8 @@ func Command() *cobra.Command {
|
|||
printSkippedAndInvalidPolicies(skipInvalidPolicies)
|
||||
if applyCommandConfig.PolicyReport {
|
||||
printReport(responses, applyCommandConfig.AuditWarn)
|
||||
} else if table {
|
||||
printTable(compact, applyCommandConfig.AuditWarn, responses...)
|
||||
} else {
|
||||
printViolations(rc)
|
||||
}
|
||||
|
@ -192,6 +197,9 @@ func Command() *cobra.Command {
|
|||
cmd.Flags().BoolVar(&applyCommandConfig.AuditWarn, "audit-warn", false, "If set to true, will flag audit policies as warnings instead of failures")
|
||||
cmd.Flags().IntVar(&applyCommandConfig.warnExitCode, "warn-exit-code", 0, "Set the exit code for warnings; if failures or errors are found, will exit 1")
|
||||
cmd.Flags().BoolVar(&applyCommandConfig.warnNoPassed, "warn-no-pass", false, "Specify if warning exit code should be raised if no objects satisfied a policy; can be used together with --warn-exit-code flag")
|
||||
cmd.Flags().BoolVar(&removeColor, "remove-color", false, "Remove any color from output")
|
||||
cmd.Flags().BoolVar(&compact, "compact", true, "Does not show detailed results")
|
||||
cmd.Flags().BoolVarP(&table, "table", "t", false, "Show results in table format")
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
|
66
cmd/cli/kubectl-kyverno/apply/table.go
Normal file
66
cmd/cli/kubectl-kyverno/apply/table.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package apply
|
||||
|
||||
import (
|
||||
"github.com/kyverno/kyverno/api/kyverno"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/color"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/output/table"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
)
|
||||
|
||||
func printTable(compact, auditWarn bool, engineResponses ...engineapi.EngineResponse) {
|
||||
var resultsTable table.Table
|
||||
id := 1
|
||||
for _, engineResponse := range engineResponses {
|
||||
var policyNamespace, policyName string
|
||||
var ann map[string]string
|
||||
|
||||
isVAP := engineResponse.IsValidatingAdmissionPolicy()
|
||||
|
||||
if isVAP {
|
||||
policy := engineResponse.ValidatingAdmissionPolicy()
|
||||
policyNamespace = policy.GetNamespace()
|
||||
policyName = policy.GetName()
|
||||
ann = policy.GetAnnotations()
|
||||
} else {
|
||||
policy := engineResponse.Policy()
|
||||
policyNamespace = policy.GetNamespace()
|
||||
policyName = policy.GetName()
|
||||
ann = policy.GetAnnotations()
|
||||
}
|
||||
resourceKind := engineResponse.Resource.GetKind()
|
||||
resourceNamespace := engineResponse.Resource.GetNamespace()
|
||||
resourceName := engineResponse.Resource.GetName()
|
||||
|
||||
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
|
||||
var row table.Row
|
||||
row.ID = id
|
||||
id++
|
||||
row.Policy = color.Policy(policyNamespace, policyName)
|
||||
if !isVAP {
|
||||
row.Rule = color.Rule(ruleResponse.Name())
|
||||
}
|
||||
row.Resource = color.Resource(resourceKind, resourceNamespace, resourceName)
|
||||
if ruleResponse.Status() == engineapi.RuleStatusPass {
|
||||
row.Result = color.ResultPass()
|
||||
} else if ruleResponse.Status() == engineapi.RuleStatusFail {
|
||||
if scored, ok := ann[kyverno.AnnotationPolicyScored]; ok && scored == "false" {
|
||||
row.Result = color.ResultWarn()
|
||||
} else if auditWarn && engineResponse.GetValidationFailureAction().Audit() {
|
||||
row.Result = color.ResultWarn()
|
||||
} else {
|
||||
row.Result = color.ResultFail()
|
||||
}
|
||||
} else if ruleResponse.Status() == engineapi.RuleStatusWarn {
|
||||
row.Result = color.ResultWarn()
|
||||
} else if ruleResponse.Status() == engineapi.RuleStatusError {
|
||||
row.Result = color.ResultError()
|
||||
} else if ruleResponse.Status() == engineapi.RuleStatusSkip {
|
||||
row.Result = color.ResultSkip()
|
||||
}
|
||||
row.Message = ruleResponse.Message()
|
||||
resultsTable.Add(row)
|
||||
}
|
||||
}
|
||||
printer := table.NewTablePrinter()
|
||||
printer.Print(resultsTable.Rows(compact))
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/kataras/tablewriter"
|
||||
"github.com/lensesio/tableprinter"
|
||||
)
|
||||
|
||||
var (
|
||||
boldGreen *color.Color
|
||||
boldRed *color.Color
|
||||
boldYellow *color.Color
|
||||
boldFgCyan *color.Color
|
||||
headerBgColor int
|
||||
headerFgColor int
|
||||
)
|
||||
|
||||
func initColors(noColor bool) {
|
||||
toggleColor := func(c *color.Color) *color.Color {
|
||||
if noColor {
|
||||
c.DisableColor()
|
||||
}
|
||||
return c
|
||||
}
|
||||
boldGreen = toggleColor(color.New(color.FgGreen).Add(color.Bold))
|
||||
boldRed = toggleColor(color.New(color.FgRed).Add(color.Bold))
|
||||
boldYellow = toggleColor(color.New(color.FgYellow).Add(color.Bold))
|
||||
boldFgCyan = toggleColor(color.New(color.FgCyan).Add(color.Bold))
|
||||
if !noColor {
|
||||
headerBgColor = tablewriter.BgBlackColor
|
||||
headerFgColor = tablewriter.FgGreenColor
|
||||
}
|
||||
}
|
||||
|
||||
func newTablePrinter() *tableprinter.Printer {
|
||||
printer := tableprinter.New(os.Stdout)
|
||||
printer.BorderTop, printer.BorderBottom, printer.BorderLeft, printer.BorderRight = true, true, true, true
|
||||
printer.CenterSeparator = "│"
|
||||
printer.ColumnSeparator = "│"
|
||||
printer.RowSeparator = "─"
|
||||
printer.RowCharLimit = 300
|
||||
printer.HeaderBgColor = headerBgColor
|
||||
printer.HeaderFgColor = headerFgColor
|
||||
printer.RowLengthTitle = func(rowsLength int) bool {
|
||||
return rowsLength > 10
|
||||
}
|
||||
return printer
|
||||
}
|
|
@ -7,6 +7,8 @@ import (
|
|||
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test/api"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test/manifest"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/color"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/output/table"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
"github.com/kyverno/kyverno/pkg/openapi"
|
||||
|
@ -27,7 +29,7 @@ func Command() *cobra.Command {
|
|||
Long: longHelp,
|
||||
Example: exampleHelp,
|
||||
RunE: func(cmd *cobra.Command, dirPath []string) (err error) {
|
||||
initColors(removeColor)
|
||||
color.InitColors(removeColor)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
|
@ -63,47 +65,6 @@ func Command() *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
type Table struct {
|
||||
rows []Row
|
||||
}
|
||||
|
||||
func (t *Table) Rows(compact bool) interface{} {
|
||||
if !compact {
|
||||
return t.rows
|
||||
}
|
||||
var rows []CompactRow
|
||||
for _, row := range t.rows {
|
||||
rows = append(rows, row.CompactRow)
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (t *Table) AddFailed(rows ...Row) {
|
||||
for _, row := range rows {
|
||||
if row.isFailure {
|
||||
t.rows = append(t.rows, row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Table) Add(rows ...Row) {
|
||||
t.rows = append(t.rows, rows...)
|
||||
}
|
||||
|
||||
type CompactRow struct {
|
||||
isFailure bool
|
||||
ID int `header:"id"`
|
||||
Policy string `header:"policy"`
|
||||
Rule string `header:"rule"`
|
||||
Resource string `header:"resource"`
|
||||
Result string `header:"result"`
|
||||
}
|
||||
|
||||
type Row struct {
|
||||
CompactRow `header:"inline"`
|
||||
Message string `header:"message"`
|
||||
}
|
||||
|
||||
type resultCounts struct {
|
||||
Skip int
|
||||
Pass int
|
||||
|
@ -136,7 +97,7 @@ func testCommandExecute(
|
|||
fmt.Printf("\n No test yamls available \n")
|
||||
}
|
||||
rc = &resultCounts{}
|
||||
var table Table
|
||||
var table table.Table
|
||||
for _, p := range policies {
|
||||
if reports, tests, err := applyPoliciesFromPath(
|
||||
fs,
|
||||
|
@ -152,7 +113,7 @@ func testCommandExecute(
|
|||
} else if t, err := printTestResult(reports, tests, rc, failOnly, compact); err != nil {
|
||||
return rc, sanitizederror.NewWithError("failed to print test result:", err)
|
||||
} else {
|
||||
table.AddFailed(t.rows...)
|
||||
table.AddFailed(t.RawRows...)
|
||||
}
|
||||
}
|
||||
if len(errors) > 0 && log.Log.V(1).Enabled() {
|
||||
|
@ -177,25 +138,25 @@ func testCommandExecute(
|
|||
return rc, nil
|
||||
}
|
||||
|
||||
func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, testResults []api.TestResults, rc *resultCounts, failOnly bool, compact bool) (Table, error) {
|
||||
printer := newTablePrinter()
|
||||
var table Table
|
||||
func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, testResults []api.TestResults, rc *resultCounts, failOnly bool, compact bool) (table.Table, error) {
|
||||
printer := table.NewTablePrinter()
|
||||
var resultsTable table.Table
|
||||
var countDeprecatedResource int
|
||||
testCount := 1
|
||||
for _, v := range testResults {
|
||||
var row Row
|
||||
var row table.Row
|
||||
row.ID = testCount
|
||||
if v.Resources == nil {
|
||||
testCount++
|
||||
}
|
||||
row.Policy = boldFgCyan.Sprint(v.Policy)
|
||||
row.Rule = boldFgCyan.Sprint(v.Rule)
|
||||
row.Policy = color.Policy("", v.Policy)
|
||||
row.Rule = color.Rule(v.Rule)
|
||||
|
||||
if v.Resources != nil {
|
||||
for _, resource := range v.Resources {
|
||||
row.ID = testCount
|
||||
testCount++
|
||||
row.Resource = boldFgCyan.Sprint(v.Namespace) + "/" + boldFgCyan.Sprint(v.Kind) + "/" + boldFgCyan.Sprint(resource)
|
||||
row.Resource = color.Resource(v.Kind, v.Namespace, resource)
|
||||
var ruleNameInResultKey string
|
||||
if !v.IsVap {
|
||||
if v.AutoGeneratedRule != "" {
|
||||
|
@ -227,11 +188,10 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
} else {
|
||||
resultKey = fmt.Sprintf("%s-%s-%s-%s", ns, v.Policy, v.Kind, resource)
|
||||
}
|
||||
|
||||
row.Policy = boldFgCyan.Sprint(ns) + "/" + boldFgCyan.Sprint(v.Policy)
|
||||
row.Resource = boldFgCyan.Sprint(v.Namespace) + "/" + boldFgCyan.Sprint(v.Kind) + "/" + boldFgCyan.Sprint(resource)
|
||||
row.Policy = color.Policy(ns, v.Policy)
|
||||
row.Resource = color.Resource(v.Kind, v.Namespace, resource)
|
||||
} else if v.Namespace != "" {
|
||||
row.Resource = boldFgCyan.Sprint(v.Namespace) + "/" + boldFgCyan.Sprint(v.Kind) + "/" + boldFgCyan.Sprint(resource)
|
||||
row.Resource = color.Resource(v.Kind, v.Namespace, resource)
|
||||
|
||||
if !v.IsVap {
|
||||
resultKey = fmt.Sprintf("%s-%s-%s-%s-%s", v.Policy, ruleNameInResultKey, v.Namespace, v.Kind, resource)
|
||||
|
@ -245,10 +205,10 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
testRes = val
|
||||
} else {
|
||||
log.Log.V(2).Info("result not found", "key", resultKey)
|
||||
row.Result = boldYellow.Sprint("Not found")
|
||||
row.Result = color.NotFound()
|
||||
rc.Fail++
|
||||
row.isFailure = true
|
||||
table.Add(row)
|
||||
row.IsFailure = true
|
||||
resultsTable.Add(row)
|
||||
continue
|
||||
}
|
||||
row.Message = testRes.Message
|
||||
|
@ -257,7 +217,7 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
}
|
||||
|
||||
if testRes.Result == v.Result {
|
||||
row.Result = boldGreen.Sprint("Pass")
|
||||
row.Result = color.ResultPass()
|
||||
if testRes.Result == policyreportv1alpha2.StatusSkip {
|
||||
rc.Skip++
|
||||
} else {
|
||||
|
@ -265,22 +225,22 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
}
|
||||
} else {
|
||||
log.Log.V(2).Info("result mismatch", "expected", v.Result, "received", testRes.Result, "key", resultKey)
|
||||
row.Result = boldRed.Sprint("Fail")
|
||||
row.Result = color.ResultFail()
|
||||
rc.Fail++
|
||||
row.isFailure = true
|
||||
row.IsFailure = true
|
||||
}
|
||||
|
||||
if failOnly {
|
||||
if row.Result == boldRed.Sprintf("Fail") || row.Result == "Fail" {
|
||||
table.Add(row)
|
||||
if row.Result == color.ResultFail() || row.Result == "Fail" {
|
||||
resultsTable.Add(row)
|
||||
}
|
||||
} else {
|
||||
table.Add(row)
|
||||
resultsTable.Add(row)
|
||||
}
|
||||
}
|
||||
} else if v.Resource != "" {
|
||||
countDeprecatedResource++
|
||||
row.Resource = boldFgCyan.Sprint(v.Namespace) + "/" + boldFgCyan.Sprint(v.Kind) + "/" + boldFgCyan.Sprint(v.Resource)
|
||||
row.Resource = color.Resource(v.Kind, v.Namespace, v.Resource)
|
||||
var ruleNameInResultKey string
|
||||
if !v.IsVap {
|
||||
if v.AutoGeneratedRule != "" {
|
||||
|
@ -313,10 +273,10 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
resultKey = fmt.Sprintf("%s-%s-%s-%s", ns, v.Policy, v.Kind, v.Resource)
|
||||
}
|
||||
|
||||
row.Policy = boldFgCyan.Sprint(ns) + "/" + boldFgCyan.Sprint(v.Policy)
|
||||
row.Resource = boldFgCyan.Sprint(v.Namespace) + "/" + boldFgCyan.Sprint(v.Kind) + "/" + boldFgCyan.Sprint(v.Resource)
|
||||
row.Policy = color.Policy(ns, v.Policy)
|
||||
row.Resource = color.Resource(v.Kind, v.Namespace, v.Resource)
|
||||
} else if v.Namespace != "" {
|
||||
row.Resource = boldFgCyan.Sprint(v.Namespace) + "/" + boldFgCyan.Sprint(v.Kind) + "/" + boldFgCyan.Sprint(v.Resource)
|
||||
row.Resource = color.Resource(v.Kind, v.Namespace, v.Resource)
|
||||
|
||||
if !v.IsVap {
|
||||
resultKey = fmt.Sprintf("%s-%s-%s-%s-%s", v.Policy, ruleNameInResultKey, v.Namespace, v.Kind, v.Resource)
|
||||
|
@ -330,10 +290,10 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
testRes = val
|
||||
} else {
|
||||
log.Log.V(2).Info("result not found", "key", resultKey)
|
||||
row.Result = boldYellow.Sprint("Not found")
|
||||
row.Result = color.NotFound()
|
||||
rc.Fail++
|
||||
row.isFailure = true
|
||||
table.Add(row)
|
||||
row.IsFailure = true
|
||||
resultsTable.Add(row)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -344,7 +304,7 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
}
|
||||
|
||||
if testRes.Result == v.Result {
|
||||
row.Result = boldGreen.Sprint("Pass")
|
||||
row.Result = color.ResultPass()
|
||||
if testRes.Result == policyreportv1alpha2.StatusSkip {
|
||||
rc.Skip++
|
||||
} else {
|
||||
|
@ -352,31 +312,31 @@ func printTestResult(resps map[string]policyreportv1alpha2.PolicyReportResult, t
|
|||
}
|
||||
} else {
|
||||
log.Log.V(2).Info("result mismatch", "expected", v.Result, "received", testRes.Result, "key", resultKey)
|
||||
row.Result = boldRed.Sprint("Fail")
|
||||
row.Result = color.ResultFail()
|
||||
rc.Fail++
|
||||
row.isFailure = true
|
||||
row.IsFailure = true
|
||||
}
|
||||
|
||||
if failOnly {
|
||||
if row.Result == boldRed.Sprintf("Fail") || row.Result == "Fail" {
|
||||
table.Add(row)
|
||||
if row.Result == color.ResultFail() || row.Result == "Fail" {
|
||||
resultsTable.Add(row)
|
||||
}
|
||||
} else {
|
||||
table.Add(row)
|
||||
resultsTable.Add(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
printer.Print(table.Rows(compact))
|
||||
return table, nil
|
||||
printer.Print(resultsTable.Rows(compact))
|
||||
return resultsTable, nil
|
||||
}
|
||||
|
||||
func printFailedTestResult(table Table, compact bool) {
|
||||
printer := newTablePrinter()
|
||||
for i := range table.rows {
|
||||
table.rows[i].ID = i + 1
|
||||
func printFailedTestResult(resultsTable table.Table, compact bool) {
|
||||
printer := table.NewTablePrinter()
|
||||
for i := range resultsTable.RawRows {
|
||||
resultsTable.RawRows[i].ID = i + 1
|
||||
}
|
||||
fmt.Printf("Aggregated Failed Test Cases : ")
|
||||
fmt.Println()
|
||||
printer.Print(table.Rows(compact))
|
||||
printer.Print(resultsTable.Rows(compact))
|
||||
}
|
||||
|
|
74
cmd/cli/kubectl-kyverno/utils/color/color.go
Normal file
74
cmd/cli/kubectl-kyverno/utils/color/color.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package color
|
||||
|
||||
import (
|
||||
"github.com/fatih/color"
|
||||
"github.com/kataras/tablewriter"
|
||||
)
|
||||
|
||||
var (
|
||||
BoldGreen *color.Color
|
||||
BoldRed *color.Color
|
||||
BoldYellow *color.Color
|
||||
BoldFgCyan *color.Color
|
||||
HeaderBgColor int
|
||||
HeaderFgColor int
|
||||
)
|
||||
|
||||
func InitColors(noColor bool) {
|
||||
toggleColor := func(c *color.Color) *color.Color {
|
||||
if noColor {
|
||||
c.DisableColor()
|
||||
}
|
||||
return c
|
||||
}
|
||||
BoldGreen = toggleColor(color.New(color.FgGreen).Add(color.Bold))
|
||||
BoldRed = toggleColor(color.New(color.FgRed).Add(color.Bold))
|
||||
BoldYellow = toggleColor(color.New(color.FgYellow).Add(color.Bold))
|
||||
BoldFgCyan = toggleColor(color.New(color.FgCyan).Add(color.Bold))
|
||||
if !noColor {
|
||||
HeaderBgColor = tablewriter.BgBlackColor
|
||||
HeaderFgColor = tablewriter.FgGreenColor
|
||||
}
|
||||
}
|
||||
|
||||
func Policy(namespace, name string) string {
|
||||
if namespace == "" {
|
||||
return BoldFgCyan.Sprint(name)
|
||||
}
|
||||
return BoldFgCyan.Sprint(namespace) + "/" + BoldFgCyan.Sprint(name)
|
||||
}
|
||||
|
||||
func Rule(name string) string {
|
||||
return BoldFgCyan.Sprint(name)
|
||||
}
|
||||
|
||||
func Resource(kind, namespace, name string) string {
|
||||
if namespace == "" {
|
||||
return BoldFgCyan.Sprint(kind) + "/" + BoldFgCyan.Sprint(name)
|
||||
}
|
||||
return BoldFgCyan.Sprint(namespace) + "/" + BoldFgCyan.Sprint(kind) + "/" + BoldFgCyan.Sprint(name)
|
||||
}
|
||||
|
||||
func NotFound() string {
|
||||
return BoldYellow.Sprint("Not found")
|
||||
}
|
||||
|
||||
func ResultPass() string {
|
||||
return BoldGreen.Sprint("Pass")
|
||||
}
|
||||
|
||||
func ResultFail() string {
|
||||
return BoldRed.Sprint("Fail")
|
||||
}
|
||||
|
||||
func ResultWarn() string {
|
||||
return BoldYellow.Sprint("Warn")
|
||||
}
|
||||
|
||||
func ResultError() string {
|
||||
return BoldRed.Sprint("Error")
|
||||
}
|
||||
|
||||
func ResultSkip() string {
|
||||
return BoldFgCyan.Sprint("Skip")
|
||||
}
|
23
cmd/cli/kubectl-kyverno/utils/output/table/printer.go
Normal file
23
cmd/cli/kubectl-kyverno/utils/output/table/printer.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/color"
|
||||
"github.com/lensesio/tableprinter"
|
||||
)
|
||||
|
||||
func NewTablePrinter() *tableprinter.Printer {
|
||||
printer := tableprinter.New(os.Stdout)
|
||||
printer.BorderTop, printer.BorderBottom, printer.BorderLeft, printer.BorderRight = true, true, true, true
|
||||
printer.CenterSeparator = "│"
|
||||
printer.ColumnSeparator = "│"
|
||||
printer.RowSeparator = "─"
|
||||
printer.RowCharLimit = 300
|
||||
printer.HeaderBgColor = color.HeaderBgColor
|
||||
printer.HeaderFgColor = color.HeaderFgColor
|
||||
printer.RowLengthTitle = func(rowsLength int) bool {
|
||||
return rowsLength > 10
|
||||
}
|
||||
return printer
|
||||
}
|
42
cmd/cli/kubectl-kyverno/utils/output/table/table.go
Normal file
42
cmd/cli/kubectl-kyverno/utils/output/table/table.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package table
|
||||
|
||||
type Table struct {
|
||||
RawRows []Row
|
||||
}
|
||||
|
||||
func (t *Table) Rows(compact bool) interface{} {
|
||||
if !compact {
|
||||
return t.RawRows
|
||||
}
|
||||
var rows []CompactRow
|
||||
for _, row := range t.RawRows {
|
||||
rows = append(rows, row.CompactRow)
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (t *Table) AddFailed(rows ...Row) {
|
||||
for _, row := range rows {
|
||||
if row.IsFailure {
|
||||
t.RawRows = append(t.RawRows, row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Table) Add(rows ...Row) {
|
||||
t.RawRows = append(t.RawRows, rows...)
|
||||
}
|
||||
|
||||
type CompactRow struct {
|
||||
IsFailure bool
|
||||
ID int `header:"id"`
|
||||
Policy string `header:"policy"`
|
||||
Rule string `header:"rule"`
|
||||
Resource string `header:"resource"`
|
||||
Result string `header:"result"`
|
||||
}
|
||||
|
||||
type Row struct {
|
||||
CompactRow `header:"inline"`
|
||||
Message string `header:"message"`
|
||||
}
|
Loading…
Reference in a new issue