Skip to content

Commit

Permalink
Backport of Add -output-format json to consul-k8s proxy list command …
Browse files Browse the repository at this point in the history
…into release/1.2.x (#3227)

* backport of commit 425c933

* backport of commit f064a09

* Add -output-format json to consul-k8s proxy list command (#3221)

* Add -o json to consul-k8s proxy list command

* added changelog

* dummy commit to trigger ci

* fix tests

---------

Co-authored-by: absolutelightning <[email protected]>
Co-authored-by: Ashesh Vidyut <[email protected]>
  • Loading branch information
3 people authored Nov 20, 2023
1 parent 52edd3c commit 96ae13d
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/3221.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
cli: Add -o json (-output-format json) to `consul-k8s proxy list` command that returns the result in json format.
```
23 changes: 22 additions & 1 deletion cli/cmd/proxy/list/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package list

import (
"encoding/json"
"errors"
"fmt"
"strings"
Expand All @@ -25,6 +26,7 @@ const (
flagNameAllNamespaces = "all-namespaces"
flagNameKubeConfig = "kubeconfig"
flagNameKubeContext = "context"
flagOutputFormat = "output-format"
)

// ListCommand is the command struct for the proxy list command.
Expand All @@ -37,6 +39,7 @@ type ListCommand struct {

flagNamespace string
flagAllNamespaces bool
flagOutputFormat string

flagKubeConfig string
flagKubeContext string
Expand All @@ -63,6 +66,13 @@ func (c *ListCommand) init() {
Usage: "List pods in all namespaces.",
Aliases: []string{"A"},
})
f.StringVar(&flag.StringVar{
Name: flagOutputFormat,
Default: "table",
Target: &c.flagOutputFormat,
Usage: "Output format",
Aliases: []string{"o"},
})

f = c.set.NewSet("Global Options")
f.StringVar(&flag.StringVar{
Expand Down Expand Up @@ -137,6 +147,7 @@ func (c *ListCommand) AutocompleteFlags() complete.Flags {
fmt.Sprintf("-%s", flagNameAllNamespaces): complete.PredictNothing,
fmt.Sprintf("-%s", flagNameKubeConfig): complete.PredictFiles("*"),
fmt.Sprintf("-%s", flagNameKubeContext): complete.PredictNothing,
fmt.Sprintf("-%s", flagOutputFormat): complete.PredictNothing,
}
}

Expand Down Expand Up @@ -282,5 +293,15 @@ func (c *ListCommand) output(pods []v1.Pod) {
}
}

c.UI.Table(tbl)
if c.flagOutputFormat == "json" {
tableJson := tbl.ToJson()
jsonSt, err := json.MarshalIndent(tableJson, "", " ")
if err != nil {
c.UI.Output("Error converting table to json: %v", err.Error(), terminal.WithErrorStyle())
} else {
c.UI.Output(string(jsonSt))
}
} else {
c.UI.Table(tbl)
}
}
79 changes: 79 additions & 0 deletions cli/cmd/proxy/list/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,85 @@ func TestListCommandOutput(t *testing.T) {
}
}

func TestListCommandOutputInJsonFormat(t *testing.T) {
// These regular expressions must be present in the output.
expected := ".*Name.*mesh-gateway.*\n.*Namespace.*consul.*\n.*Type.*Mesh Gateway.*\n.*\n.*\n.*Name.*terminating-gateway.*\n.*Namespace.*consul.*\n.*Type.*Terminating Gateway.*\n.*\n.*\n.*Name.*ingress-gateway.*\n.*Namespace.*default.*\n.*Type.*Ingress Gateway.*\n.*\n.*\n.*Name.*api-gateway.*\n.*Namespace.*consul.*\n.*Type.*API Gateway.*\n.*\n.*\n.*Name.*pod1.*\n.*Namespace.*default.*\n.*Type.*Sidecar.*"
notExpected := "default.*dont-fetch.*Sidecar"

pods := []v1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-gateway",
Namespace: "default",
Labels: map[string]string{
"component": "ingress-gateway",
"chart": "consul-helm",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "mesh-gateway",
Namespace: "consul",
Labels: map[string]string{
"component": "mesh-gateway",
"chart": "consul-helm",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "terminating-gateway",
Namespace: "consul",
Labels: map[string]string{
"component": "terminating-gateway",
"chart": "consul-helm",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "api-gateway",
Namespace: "consul",
Labels: map[string]string{
"api-gateway.consul.hashicorp.com/managed": "true",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "dont-fetch",
Namespace: "default",
Labels: map[string]string{},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
Namespace: "default",
Labels: map[string]string{
"consul.hashicorp.com/connect-inject-status": "injected",
},
},
},
}
client := fake.NewSimpleClientset(&v1.PodList{Items: pods})

buf := new(bytes.Buffer)
c := setupCommand(buf)
c.kubernetes = client

out := c.Run([]string{"-A", "-o", "json"})
require.Equal(t, 0, out)

actual := buf.String()

require.Regexp(t, expected, actual)
for _, expression := range notExpected {
require.NotRegexp(t, expression, actual)
}
}

func TestNoPodsFound(t *testing.T) {
cases := map[string]struct {
args []string
Expand Down
15 changes: 15 additions & 0 deletions cli/common/terminal/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ func (t *Table) AddRow(cols []string, colors []string) {
t.Rows = append(t.Rows, row)
}

func (t *Table) ToJson() []map[string]interface{} {
if t == nil {
return make([]map[string]interface{}, 0)
}
jsonRes := make([]map[string]interface{}, 0)
for _, row := range t.Rows {
jsonRow := make(map[string]interface{})
for i, ent := range row {
jsonRow[t.Headers[i]] = ent.Value
}
jsonRes = append(jsonRes, jsonRow)
}
return jsonRes
}

// Table implements UI.
func (u *basicUI) Table(tbl *Table, opts ...Option) {
// Build our config and set our options
Expand Down

0 comments on commit 96ae13d

Please sign in to comment.