1package get
2
3import (
4	"encoding/json"
5	"flag"
6	"fmt"
7	"io"
8	"sort"
9	"time"
10
11	"github.com/hashicorp/consul/command/flags"
12	"github.com/hashicorp/consul/command/intention"
13	"github.com/mitchellh/cli"
14	"github.com/ryanuber/columnize"
15)
16
17func New(ui cli.Ui) *cmd {
18	c := &cmd{UI: ui}
19	c.init()
20	return c
21}
22
23type cmd struct {
24	UI    cli.Ui
25	flags *flag.FlagSet
26	http  *flags.HTTPFlags
27	help  string
28
29	// testStdin is the input for testing.
30	testStdin io.Reader
31}
32
33func (c *cmd) init() {
34	c.flags = flag.NewFlagSet("", flag.ContinueOnError)
35	c.http = &flags.HTTPFlags{}
36	flags.Merge(c.flags, c.http.ClientFlags())
37	flags.Merge(c.flags, c.http.ServerFlags())
38	flags.Merge(c.flags, c.http.NamespaceFlags())
39	c.help = flags.Usage(help, c.flags)
40}
41
42func (c *cmd) Run(args []string) int {
43	if err := c.flags.Parse(args); err != nil {
44		return 1
45	}
46
47	// Create and test the HTTP client
48	client, err := c.http.APIClient()
49	if err != nil {
50		c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
51		return 1
52	}
53
54	ixn, err := intention.GetFromArgs(client, c.flags.Args())
55	if err != nil {
56		c.UI.Error(err.Error())
57		return 1
58	}
59
60	// Format the tabular data
61	data := []string{
62		fmt.Sprintf("Source:\x1f%s", ixn.SourceString()),
63		fmt.Sprintf("Destination:\x1f%s", ixn.DestinationString()),
64	}
65	if ixn.Action != "" {
66		data = append(data, fmt.Sprintf("Action:\x1f%s", ixn.Action))
67	}
68	if ixn.ID != "" {
69		data = append(data, fmt.Sprintf("ID:\x1f%s", ixn.ID))
70	}
71	if v := ixn.Description; v != "" {
72		data = append(data, fmt.Sprintf("Description:\x1f%s", v))
73	}
74	if len(ixn.Meta) > 0 {
75		var keys []string
76		for k := range ixn.Meta {
77			keys = append(keys, k)
78		}
79		sort.Strings(keys)
80		for _, k := range keys {
81			data = append(data, fmt.Sprintf("Meta[%s]:\x1f%s", k, ixn.Meta[k]))
82		}
83	}
84	data = append(data,
85		fmt.Sprintf("Created At:\x1f%s", ixn.CreatedAt.Local().Format(time.RFC850)),
86	)
87
88	c.UI.Output(columnize.Format(data, &columnize.Config{Delim: string([]byte{0x1f})}))
89
90	if len(ixn.Permissions) > 0 {
91		b, err := json.MarshalIndent(ixn.Permissions, "", "  ")
92		if err != nil {
93			c.UI.Error(err.Error())
94			return 1
95		}
96		c.UI.Output("Permissions:\n" + string(b))
97	}
98	return 0
99}
100
101func (c *cmd) Synopsis() string {
102	return synopsis
103}
104
105func (c *cmd) Help() string {
106	return c.help
107}
108
109const synopsis = "Show information about an intention."
110const help = `
111Usage: consul intention get [options] SRC DST
112Usage: consul intention get [options] ID
113
114  Read and show the details about an intention. The intention can be looked
115  up via an exact source/destination match or via the unique intention ID.
116
117      $ consul intention get web db
118
119`
120