Skip to content

Commit

Permalink
Added format option for pretty print
Browse files Browse the repository at this point in the history
  • Loading branch information
tauhid621 committed Jan 25, 2024
1 parent 92c7e4e commit 3aa9612
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 9 deletions.
85 changes: 78 additions & 7 deletions command/exportedservices/exported_services.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,28 @@ import (
"encoding/json"
"flag"
"fmt"
"strings"

"github.com/hashicorp/consul/command/flags"
"github.com/mitchellh/cli"

"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/command/flags"
"github.com/ryanuber/columnize"
)

const (
PrettyFormat string = "pretty"
JSONFormat string = "json"
)

func getSupportedFormats() []string {
return []string{PrettyFormat, JSONFormat}
}

func formatIsValid(f string) bool {
return f == PrettyFormat || f == JSONFormat
}

func New(ui cli.Ui) *cmd {
c := &cmd{UI: ui}
c.init()
Expand All @@ -23,10 +40,20 @@ type cmd struct {
flags *flag.FlagSet
http *flags.HTTPFlags
help string

format string
}

func (c *cmd) init() {
c.flags = flag.NewFlagSet("", flag.ContinueOnError)

c.flags.StringVar(
&c.format,
"format",
PrettyFormat,
fmt.Sprintf("Output format {%s} (default: %s)", strings.Join(getSupportedFormats(), "|"), PrettyFormat),
)

c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
Expand All @@ -39,6 +66,11 @@ func (c *cmd) Run(args []string) int {
return 1
}

if !formatIsValid(c.format) {
c.UI.Error(fmt.Sprintf("Invalid format, valid formats are {%s}", strings.Join(getSupportedFormats(), "|")))
return 1
}

client, err := c.http.APIClient()
if err != nil {
c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err))
Expand All @@ -51,16 +83,55 @@ func (c *cmd) Run(args []string) int {
return 1
}

b, err := json.MarshalIndent(exportedServices, "", " ")
if err != nil {
c.UI.Error("Failed to encode output data")
return 1
if len(exportedServices) == 0 {
c.UI.Info("No exported services found")
return 0
}

c.UI.Info(string(b))
if c.format == JSONFormat {
output, err := json.MarshalIndent(exportedServices, "", " ")
if err != nil {
c.UI.Error(fmt.Sprintf("Error marshalling JSON: %s", err))
return 1
}
c.UI.Output(string(output))
return 0
}

c.UI.Output(formatExportedServices(exportedServices))

return 0
}

func formatExportedServices(services []api.ResolvedExportedService) string {
result := make([]string, 0, len(services)+1)

if services[0].Partition != "" {
result = append(result, "Service\x1fPartition\x1fNamespace\x1fConsumer")
} else {
result = append(result, "Service\x1fConsumer")
}

for _, expService := range services {
service := ""
if expService.Partition != "" {
service = fmt.Sprintf("%s\x1f%s\x1f%s", expService.Service, expService.Partition, expService.Namespace)
} else {
service = expService.Service
}

for _, peer := range expService.Consumers.Peers {
result = append(result, fmt.Sprintf("%s\x1fPeer: %s", service, peer))
}
for _, partition := range expService.Consumers.Partitions {
result = append(result, fmt.Sprintf("%s\x1fPartition: %s", service, partition))
}

}

return columnize.Format(result, &columnize.Config{Delim: string([]byte{0x1f})})
}

func (c *cmd) Synopsis() string {
return synopsis
}
Expand All @@ -74,7 +145,7 @@ const (
help = `
Usage: consul exported-services [options]
Lists all the exported services and their consumers. Wildcards and sameness groups are expanded.
Lists all the exported services and their consumers. Wildcards and sameness groups(Enterprise) are expanded.
Example:
Expand Down
100 changes: 98 additions & 2 deletions command/exportedservices/exported_services_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/consul/agent"
"github.com/hashicorp/consul/api"
"github.com/mitchellh/cli"

"github.com/stretchr/testify/require"
)

Expand All @@ -19,7 +20,48 @@ func TestExportedServices_noTabs(t *testing.T) {
require.NotContains(t, New(cli.NewMockUi()).Help(), "\t")
}

func TestExportedServices(t *testing.T) {
func TestExportedServices_Error(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}

t.Parallel()

a := agent.NewTestAgent(t, ``)
defer a.Shutdown()

t.Run("No exported services", func(t *testing.T) {
ui := cli.NewMockUi()
cmd := New(ui)

args := []string{
"-http-addr=" + a.HTTPAddr(),
}

code := cmd.Run(args)
require.Equal(t, 0, code)

output := ui.OutputWriter.String()
require.Equal(t, "No exported services found\n", output)
})

t.Run("invalid format", func(t *testing.T) {
ui := cli.NewMockUi()
cmd := New(ui)

args := []string{
"-http-addr=" + a.HTTPAddr(),
"-format=toml",
}

code := cmd.Run(args)
require.Equal(t, 1, code, "exited successfully when it should have failed")
output := ui.ErrorWriter.String()
require.Contains(t, output, "Invalid format")
})
}

func TestExportedServices_Pretty(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}
Expand All @@ -37,7 +79,7 @@ func TestExportedServices(t *testing.T) {
Name: "default",
Services: []api.ExportedService{
{
Name: "web",
Name: "db",
Consumers: []api.ServiceConsumer{
{
Peer: "east",
Expand All @@ -47,6 +89,50 @@ func TestExportedServices(t *testing.T) {
},
},
},
{
Name: "web",
Consumers: []api.ServiceConsumer{
{
Peer: "east",
},
},
},
},
}, nil)
require.NoError(t, err)
require.True(t, set)

args := []string{
"-http-addr=" + a.HTTPAddr(),
}

code := c.Run(args)
require.Equal(t, 0, code)

output := ui.OutputWriter.String()

// Spot check some fields and values
require.Contains(t, output, "db")
require.Contains(t, output, "web")
}

func TestExportedServices_JSON(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}

t.Parallel()

a := agent.NewTestAgent(t, ``)
defer a.Shutdown()
client := a.Client()

ui := cli.NewMockUi()
c := New(ui)

set, _, err := client.ConfigEntries().Set(&api.ExportedServicesConfigEntry{
Name: "default",
Services: []api.ExportedService{
{
Name: "db",
Consumers: []api.ServiceConsumer{
Expand All @@ -58,13 +144,22 @@ func TestExportedServices(t *testing.T) {
},
},
},
{
Name: "web",
Consumers: []api.ServiceConsumer{
{
Peer: "east",
},
},
},
},
}, nil)
require.NoError(t, err)
require.True(t, set)

args := []string{
"-http-addr=" + a.HTTPAddr(),
"-format=json",
}

code := c.Run(args)
Expand All @@ -79,4 +174,5 @@ func TestExportedServices(t *testing.T) {
require.Equal(t, "db", resp[0].Service)
require.Equal(t, "web", resp[1].Service)
require.Equal(t, []string{"east", "west"}, resp[0].Consumers.Peers)
require.Equal(t, []string{"east"}, resp[1].Consumers.Peers)
}

0 comments on commit 3aa9612

Please sign in to comment.