Skip to content

Commit

Permalink
Merge pull request #6274 from medyagh/add_table
Browse files Browse the repository at this point in the history
Improve "addon list" by viewing as a table
  • Loading branch information
medyagh authored Jan 13, 2020
2 parents f5ce7d9 + 39d1787 commit 2e3d3e0
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 63 deletions.
60 changes: 34 additions & 26 deletions cmd/minikube/cmd/config/addons_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ import (
"os"
"sort"
"strings"
"text/template"

"github.com/golang/glog"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/out"
)

const defaultAddonListFormat = "- {{.AddonName}}: {{.AddonStatus}}\n"

var addonListFormat string
var addonListOutput string

// AddonListTemplate represents the addon list template
Expand All @@ -50,10 +50,6 @@ var addonsListCmd = &cobra.Command{
exit.UsageT("usage: minikube addons list")
}

if addonListOutput != "list" && addonListFormat != defaultAddonListFormat {
exit.UsageT("Cannot use both --output and --format options")
}

switch strings.ToLower(addonListOutput) {
case "list":
printAddonsList()
Expand All @@ -66,14 +62,6 @@ var addonsListCmd = &cobra.Command{
}

func init() {
addonsListCmd.Flags().StringVarP(
&addonListFormat,
"format",
"f",
defaultAddonListFormat,
`Go template format string for the addon list output. The format for Go templates can be found here: https://golang.org/pkg/text/template/
For the list of accessible variables for the template, see the struct values here: https://godoc.org/k8s.io/minikube/cmd/minikube/cmd/config#AddonListTemplate`)

addonsListCmd.Flags().StringVarP(
&addonListOutput,
"output",
Expand All @@ -84,6 +72,13 @@ For the list of accessible variables for the template, see the struct values her
AddonsCmd.AddCommand(addonsListCmd)
}

var iconFromStatus = func(addonStatus bool) string {
if addonStatus {
return "✅"
}
return " " // because emoji indentation is different
}

var stringFromStatus = func(addonStatus bool) string {
if addonStatus {
return "enabled"
Expand All @@ -97,27 +92,39 @@ var printAddonsList = func() {
addonNames = append(addonNames, addonName)
}
sort.Strings(addonNames)
var tData [][]string
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Addon Name", "Profile", "Status"})
table.SetAutoFormatHeaders(true)
table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true})
table.SetCenterSeparator("|")
pName := viper.GetString(config.MachineProfile)

for _, addonName := range addonNames {
addonBundle := assets.Addons[addonName]
addonStatus, err := addonBundle.IsEnabled()
if err != nil {
exit.WithError("Error getting addons status", err)
}
tmpl, err := template.New("list").Parse(addonListFormat)
if err != nil {
exit.WithError("Error creating list template", err)
}
listTmplt := AddonListTemplate{addonName, stringFromStatus(addonStatus)}
err = tmpl.Execute(os.Stdout, listTmplt)
if err != nil {
exit.WithError("Error executing list template", err)
}
tData = append(tData, []string{addonName, pName, fmt.Sprintf("%s %s", stringFromStatus(addonStatus), iconFromStatus(addonStatus))})
}

table.AppendBulk(tData)
table.Render()

v, _, err := config.ListProfiles()
if err != nil {
glog.Infof("error getting list of porfiles: %v", err)
}
if len(v) > 1 {
out.T(out.Tip, "To see addons list for other profiles use: `minikube addons -p name list`")
}

}

var printAddonsJSON = func() {
addonNames := make([]string, 0, len(assets.Addons))
pName := viper.GetString(config.MachineProfile)
for addonName := range assets.Addons {
addonNames = append(addonNames, addonName)
}
Expand All @@ -134,7 +141,8 @@ var printAddonsJSON = func() {
}

addonsMap[addonName] = map[string]interface{}{
"Status": stringFromStatus(addonStatus),
"Status": stringFromStatus(addonStatus),
"Profile": pName,
}
}
jsonString, _ := json.Marshal(addonsMap)
Expand Down
1 change: 0 additions & 1 deletion cmd/minikube/cmd/config/profile_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ var profileListCmd = &cobra.Command{
var printProfilesTable = func() {

var validData [][]string

table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Profile", "VM Driver", "NodeIP", "Node Port", "Kubernetes Version", "Status"})
table.SetAutoFormatHeaders(false)
Expand Down
40 changes: 4 additions & 36 deletions test/integration/functional_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -548,46 +548,14 @@ func validateServiceCmd(ctx context.Context, t *testing.T, profile string) {

// validateAddonsCmd asserts basic "addon" command functionality
func validateAddonsCmd(ctx context.Context, t *testing.T, profile string) {

// Default output
// Table output
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list"))
if err != nil {
t.Errorf("%s failed: %v", rr.Args, err)
}
listLines := strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n")
r := regexp.MustCompile(`-\s[a-z|-]+:\s(enabled|disabled)`)
for _, line := range listLines {
match := r.MatchString(line)
if !match {
t.Errorf("Plugin output did not match expected format. Got: %s", line)
}
}

// Custom format
rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list", "--format", `"{{.AddonName}}":"{{.AddonStatus}}"`))
if err != nil {
t.Errorf("%s failed: %v", rr.Args, err)
}
listLines = strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n")
r = regexp.MustCompile(`"[a-z|-]+":"(enabled|disabled)"`)
for _, line := range listLines {
match := r.MatchString(line)
if !match {
t.Errorf("Plugin output did not match expected custom format. Got: %s", line)
}
}

// Custom format shorthand
rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "addons", "list", "-f", `"{{.AddonName}}":"{{.AddonStatus}}"`))
if err != nil {
t.Errorf("%s failed: %v", rr.Args, err)
}
listLines = strings.Split(strings.TrimSpace(rr.Stdout.String()), "\n")
r = regexp.MustCompile(`"[a-z|-]+":"(enabled|disabled)"`)
for _, line := range listLines {
match := r.MatchString(line)
if !match {
t.Errorf("Plugin output did not match expected custom format. Got: %s", line)
for _, a := range []string{"dashboard", "ingress", "ingress-dns"} {
if !strings.Contains(rr.Output(), a) {
t.Errorf("addon list expected to include %q but didn't output: %q", a, rr.Output())
}
}

Expand Down

0 comments on commit 2e3d3e0

Please sign in to comment.