From 82866cd213aa873fd725a3a1cdb1263ca173deaf Mon Sep 17 00:00:00 2001 From: Cassowary Rusnov Date: Sat, 3 Dec 2022 23:09:45 -0800 Subject: [PATCH] Partial implementation of machine readable output. - Implement global flag for machine readable output. - Add machine readable output (as JSON) to list command. --- cli/app/list.go | 153 +++++++++++++++++++++++--------------------- cli/internal/cli.go | 10 +++ 2 files changed, 91 insertions(+), 72 deletions(-) diff --git a/cli/app/list.go b/cli/app/list.go index ba54fccf..b10663f0 100644 --- a/cli/app/list.go +++ b/cli/app/list.go @@ -1,6 +1,7 @@ package app import ( + "encoding/json" "fmt" "sort" "strings" @@ -39,22 +40,22 @@ var listAppServerFlag = &cli.StringFlag{ } type appStatus struct { - server string - recipe string - appName string - domain string - status string - version string - upgrade string + Server string `json:"server"` + Recipe string `json:"recipe"` + AppName string `json:"appName"` + Domain string `json:"domain"` + Status string `json:"status"` + Version string `json:"version"` + Upgrade string `json:"upgrade"` } type serverStatus struct { - apps []appStatus - appCount int - versionCount int - unversionedCount int - latestCount int - upgradeCount int + Apps []appStatus `json:"apps"` + AppCount int `json:"appCount"` + VersionCount int `json:"versionCount"` + UnversionedCount int `json:"unversionedCount"` + LatestCount int `json:"latestCount"` + UpgradeCount int `json:"upgradeCount"` } var appListCommand = cli.Command{ @@ -71,6 +72,7 @@ can take some time. `, Flags: []cli.Flag{ internal.DebugFlag, + internal.MachineReadableFlag, statusFlag, listAppServerFlag, recipeFlag, @@ -135,7 +137,7 @@ can take some time. } appStats := appStatus{} - stats.appCount++ + stats.AppCount++ totalAppsCount++ if status { @@ -150,13 +152,13 @@ can take some time. if statusMeta["status"] != "" { status = statusMeta["status"] } - stats.versionCount++ + stats.VersionCount++ } else { - stats.unversionedCount++ + stats.UnversionedCount++ } - appStats.status = status - appStats.version = version + appStats.Status = status + appStats.Version = version var newUpdates []string if version != "unknown" { @@ -184,81 +186,88 @@ can take some time. if len(newUpdates) == 0 { if version == "unknown" { - appStats.upgrade = "unknown" + appStats.Upgrade = "unknown" } else { - appStats.upgrade = "latest" - stats.latestCount++ + appStats.Upgrade = "latest" + stats.LatestCount++ } } else { newUpdates = internal.ReverseStringList(newUpdates) - appStats.upgrade = strings.Join(newUpdates, "\n") - stats.upgradeCount++ + appStats.Upgrade = strings.Join(newUpdates, "\n") + stats.UpgradeCount++ } } - appStats.server = app.Server - appStats.recipe = app.Recipe - appStats.appName = app.Name - appStats.domain = app.Domain + appStats.Server = app.Server + appStats.Recipe = app.Recipe + appStats.AppName = app.Name + appStats.Domain = app.Domain - stats.apps = append(stats.apps, appStats) + stats.Apps = append(stats.Apps, appStats) } - allStats[app.Server] = stats } - - alreadySeen := make(map[string]bool) - for _, app := range apps { - if _, ok := alreadySeen[app.Server]; ok { - continue + if internal.MachineReadable { + jsonstring, err := json.Marshal(allStats) + if err != nil { + fmt.Println("Error marshalling data to JSON:") + fmt.Println(err) + } else { + fmt.Println(string(jsonstring)) } - - serverStat := allStats[app.Server] - - tableCol := []string{"recipe", "domain"} - if status { - tableCol = append(tableCol, []string{"status", "version", "upgrade"}...) - } - - table := formatter.CreateTable(tableCol) - - for _, appStat := range serverStat.apps { - tableRow := []string{appStat.recipe, appStat.domain} - if status { - tableRow = append(tableRow, []string{appStat.status, appStat.version, appStat.upgrade}...) + } else { + alreadySeen := make(map[string]bool) + for _, app := range apps { + if _, ok := alreadySeen[app.Server]; ok { + continue } - table.Append(tableRow) - } - if table.NumLines() > 0 { - table.Render() + serverStat := allStats[app.Server] + tableCol := []string{"recipe", "domain"} if status { - fmt.Println(fmt.Sprintf( - "server: %s | total apps: %v | versioned: %v | unversioned: %v | latest: %v | upgrade: %v", - app.Server, - serverStat.appCount, - serverStat.versionCount, - serverStat.unversionedCount, - serverStat.latestCount, - serverStat.upgradeCount, - )) - } else { - fmt.Println(fmt.Sprintf("server: %s | total apps: %v", app.Server, serverStat.appCount)) + tableCol = append(tableCol, []string{"status", "version", "upgrade"}...) } + + table := formatter.CreateTable(tableCol) + + for _, appStat := range serverStat.Apps { + tableRow := []string{appStat.Recipe, appStat.Domain} + if status { + tableRow = append(tableRow, []string{appStat.Status, appStat.Version, appStat.Upgrade}...) + } + table.Append(tableRow) + } + + if table.NumLines() > 0 { + table.Render() + + if status { + fmt.Println(fmt.Sprintf( + "server: %s | total apps: %v | versioned: %v | unversioned: %v | latest: %v | upgrade: %v", + app.Server, + serverStat.AppCount, + serverStat.VersionCount, + serverStat.UnversionedCount, + serverStat.LatestCount, + serverStat.UpgradeCount, + )) + } else { + fmt.Println(fmt.Sprintf("server: %s | total apps: %v", app.Server, serverStat.AppCount)) + } + } + + if len(allStats) > 1 && table.NumLines() > 0 { + fmt.Println() // newline separator for multiple servers + } + + alreadySeen[app.Server] = true } - if len(allStats) > 1 && table.NumLines() > 0 { - fmt.Println() // newline separator for multiple servers + if len(allStats) > 1 { + fmt.Println(fmt.Sprintf("total servers: %v | total apps: %v ", totalServersCount, totalAppsCount)) } - - alreadySeen[app.Server] = true } - - if len(allStats) > 1 { - fmt.Println(fmt.Sprintf("total servers: %v | total apps: %v ", totalServersCount, totalAppsCount)) - } - return nil }, } diff --git a/cli/internal/cli.go b/cli/internal/cli.go index d8a67a20..e3cdcf75 100644 --- a/cli/internal/cli.go +++ b/cli/internal/cli.go @@ -243,6 +243,16 @@ var DebugFlag = &cli.BoolFlag{ Usage: "Show DEBUG messages", } +// MachineReadable stores the variable from MachineReadableFlag +var MachineReadable bool + +// MachineReadableFlag turns on/off machine readable output where supported +var MachineReadableFlag = &cli.BoolFlag{ + Name: "machine, m", + Destination: &MachineReadable, + Usage: "Output in a machine-readable format (where supported)", +} + // RC signifies the latest release candidate var RC bool