New output flag for list command (#1215)
* New output flag for list command Support output as json Add new formatters file to handle extrac formatting to its own concern New config interface to support list command specification * Fix usage message * Add error handling for formatters
This commit is contained in:
parent
71bb7354e7
commit
e0a793b7c5
14
main.go
14
main.go
|
|
@ -471,7 +471,13 @@ func main() {
|
||||||
{
|
{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "list releases defined in state file",
|
Usage: "list releases defined in state file",
|
||||||
Flags: []cli.Flag{},
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "output",
|
||||||
|
Value: "",
|
||||||
|
Usage: "output releases list as a json string",
|
||||||
|
},
|
||||||
|
},
|
||||||
Action: action(func(run *app.App, c configImpl) error {
|
Action: action(func(run *app.App, c configImpl) error {
|
||||||
return run.ListReleases(c)
|
return run.ListReleases(c)
|
||||||
}),
|
}),
|
||||||
|
|
@ -597,6 +603,12 @@ func (c configImpl) Timeout() int {
|
||||||
return c.c.Int("timeout")
|
return c.c.Int("timeout")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListConfig
|
||||||
|
|
||||||
|
func (c configImpl) Output() string {
|
||||||
|
return c.c.String("output")
|
||||||
|
}
|
||||||
|
|
||||||
// GlobalConfig
|
// GlobalConfig
|
||||||
|
|
||||||
func (c configImpl) HelmBinary() string {
|
func (c configImpl) HelmBinary() string {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/gosuri/uitable"
|
|
||||||
"github.com/roboll/helmfile/pkg/argparser"
|
"github.com/roboll/helmfile/pkg/argparser"
|
||||||
"github.com/roboll/helmfile/pkg/helmexec"
|
"github.com/roboll/helmfile/pkg/helmexec"
|
||||||
"github.com/roboll/helmfile/pkg/remote"
|
"github.com/roboll/helmfile/pkg/remote"
|
||||||
|
|
@ -60,6 +59,13 @@ type App struct {
|
||||||
helmsMutex sync.Mutex
|
helmsMutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HelmRelease struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Namespace string `json:"namespace"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
Labels string `json:"labels"`
|
||||||
|
}
|
||||||
|
|
||||||
func New(conf ConfigProvider) *App {
|
func New(conf ConfigProvider) *App {
|
||||||
return Init(&App{
|
return Init(&App{
|
||||||
OverrideKubeContext: conf.KubeContext(),
|
OverrideKubeContext: conf.KubeContext(),
|
||||||
|
|
@ -259,9 +265,8 @@ func (a *App) PrintState(c StateConfigProvider) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) ListReleases(c StateConfigProvider) error {
|
func (a *App) ListReleases(c ListConfigProvider) error {
|
||||||
table := uitable.New()
|
var releases []*HelmRelease
|
||||||
table.AddRow("NAME", "NAMESPACE", "ENABLED", "LABELS")
|
|
||||||
|
|
||||||
err := a.VisitDesiredStatesWithReleasesFiltered(a.FileOrDir, func(st *state.HelmState) []error {
|
err := a.VisitDesiredStatesWithReleasesFiltered(a.FileOrDir, func(st *state.HelmState) []error {
|
||||||
//var releases m
|
//var releases m
|
||||||
|
|
@ -270,12 +275,28 @@ func (a *App) ListReleases(c StateConfigProvider) error {
|
||||||
for k, v := range r.Labels {
|
for k, v := range r.Labels {
|
||||||
labels = fmt.Sprintf("%s,%s:%s", labels, k, v)
|
labels = fmt.Sprintf("%s,%s:%s", labels, k, v)
|
||||||
}
|
}
|
||||||
|
labels = strings.Trim(labels, ",")
|
||||||
installed := r.Installed == nil || *r.Installed
|
installed := r.Installed == nil || *r.Installed
|
||||||
table.AddRow(r.Name, r.Namespace, fmt.Sprintf("%t", installed), strings.Trim(labels, ","))
|
releases = append(releases, &HelmRelease{
|
||||||
|
Name: r.Name,
|
||||||
|
Namespace: r.Namespace,
|
||||||
|
Enabled: installed,
|
||||||
|
Labels: labels,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return []error{}
|
return []error{}
|
||||||
})
|
})
|
||||||
fmt.Println(table.String())
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Output() == "json" {
|
||||||
|
err = FormatAsJson(releases)
|
||||||
|
} else {
|
||||||
|
err = FormatAsTable(releases)
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1962,7 +1962,8 @@ services:
|
||||||
}
|
}
|
||||||
|
|
||||||
type configImpl struct {
|
type configImpl struct {
|
||||||
set []string
|
set []string
|
||||||
|
output string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c configImpl) Set() []string {
|
func (c configImpl) Set() []string {
|
||||||
|
|
@ -1993,6 +1994,10 @@ func (c configImpl) Concurrency() int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c configImpl) Output() string {
|
||||||
|
return c.output
|
||||||
|
}
|
||||||
|
|
||||||
type applyConfig struct {
|
type applyConfig struct {
|
||||||
args string
|
args string
|
||||||
values []string
|
values []string
|
||||||
|
|
@ -3849,6 +3854,63 @@ myrelease4 true id:myrelease1
|
||||||
assert.Equal(t, expected, out)
|
assert.Equal(t, expected, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestListWithJsonOutput(t *testing.T) {
|
||||||
|
files := map[string]string{
|
||||||
|
"/path/to/helmfile.d/first.yaml": `
|
||||||
|
releases:
|
||||||
|
- name: myrelease1
|
||||||
|
chart: mychart1
|
||||||
|
installed: no
|
||||||
|
labels:
|
||||||
|
id: myrelease1
|
||||||
|
- name: myrelease2
|
||||||
|
chart: mychart1
|
||||||
|
`,
|
||||||
|
"/path/to/helmfile.d/second.yaml": `
|
||||||
|
releases:
|
||||||
|
- name: myrelease3
|
||||||
|
chart: mychart1
|
||||||
|
installed: yes
|
||||||
|
- name: myrelease4
|
||||||
|
chart: mychart1
|
||||||
|
labels:
|
||||||
|
id: myrelease1
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
stdout := os.Stdout
|
||||||
|
defer func() { os.Stdout = stdout }()
|
||||||
|
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
logger := helmexec.NewLogger(&buffer, "debug")
|
||||||
|
|
||||||
|
app := appWithFs(&App{
|
||||||
|
OverrideHelmBinary: DefaultHelmBinary,
|
||||||
|
glob: filepath.Glob,
|
||||||
|
abs: filepath.Abs,
|
||||||
|
OverrideKubeContext: "default",
|
||||||
|
Env: "default",
|
||||||
|
Logger: logger,
|
||||||
|
Namespace: "testNamespace",
|
||||||
|
}, files)
|
||||||
|
|
||||||
|
expectNoCallsToHelm(app)
|
||||||
|
|
||||||
|
out := captureStdout(func() {
|
||||||
|
err := app.ListReleases(configImpl{
|
||||||
|
output: "json",
|
||||||
|
})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
expected := "[" +
|
||||||
|
"{\"name\":\"myrelease1\",\"namespace\":\"\",\"enabled\":false,\"labels\":\"id:myrelease1\"}," +
|
||||||
|
"{\"name\":\"myrelease2\",\"namespace\":\"\",\"enabled\":true,\"labels\":\"\"}," +
|
||||||
|
"{\"name\":\"myrelease3\",\"namespace\":\"\",\"enabled\":true,\"labels\":\"\"}," +
|
||||||
|
"{\"name\":\"myrelease4\",\"namespace\":\"\",\"enabled\":true,\"labels\":\"id:myrelease1\"}" +
|
||||||
|
"]\n"
|
||||||
|
assert.Equal(t, expected, out)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSetValuesTemplate(t *testing.T) {
|
func TestSetValuesTemplate(t *testing.T) {
|
||||||
files := map[string]string{
|
files := map[string]string{
|
||||||
"/path/to/helmfile.yaml": `
|
"/path/to/helmfile.yaml": `
|
||||||
|
|
|
||||||
|
|
@ -156,3 +156,7 @@ type loggingConfig interface {
|
||||||
type interactive interface {
|
type interactive interface {
|
||||||
Interactive() bool
|
Interactive() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ListConfigProvider interface {
|
||||||
|
Output() string
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gosuri/uitable"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FormatAsTable(releases []*HelmRelease) error {
|
||||||
|
table := uitable.New()
|
||||||
|
table.AddRow("NAME", "NAMESPACE", "ENABLED", "LABELS")
|
||||||
|
|
||||||
|
for _, r := range releases {
|
||||||
|
table.AddRow(r.Name, r.Namespace, fmt.Sprintf("%t", r.Enabled), r.Labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(table.String())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatAsJson(releases []*HelmRelease) error {
|
||||||
|
output, err := json.Marshal(releases)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error generating json: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(output))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue