Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve "addon list" by viewing as a table #6274

Merged
merged 3 commits into from
Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
1 change: 0 additions & 1 deletion test/integration/guest_env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
func TestGuestEnvironment(t *testing.T) {
MaybeParallel(t)


profile := UniqueProfileName("guest")
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
defer CleanupWithLogs(t, profile, cancel)
Expand Down