Skip to content

Commit

Permalink
cli: Add consul intention list command (based on PR #6825) (#9468)
Browse files Browse the repository at this point in the history
This PR is based on the previous work by @snuggie12 in PR #6825. It adds the command consul intention list to list all available intentions. The list functionality for intentions seems a bit overdue as it's just very handy. The web UI cannot list intentions outside of the default namespace, and using the API is sometimes not the friendliest option. ;)

I cherry picked snuggie12's commits who did most of the heavy lifting (thanks again @snuggie12 for your great work!). The changes in the original commit mostly still worked on the current HEAD. On top of that I added support for namespaces and fixed the docs as they are managed differently today. Also the requested changes related to the "Connect" references in the original PRs have been addressed.

Fixes #5652

Co-authored-by: Matt Hoey <mhoey05@jcu.edu>
  • Loading branch information
2 people authored and hashicorp-ci committed Jan 12, 2021
1 parent 515426f commit 8541244
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .changelog/9468.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
cli: The `consul intention` command now has a new `list` subcommand to allow the listing of configured intentions. It also supports the `-namespace=` option.
```
2 changes: 2 additions & 0 deletions command/commands_oss.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import (
ixncreate "github.com/hashicorp/consul/command/intention/create"
ixndelete "github.com/hashicorp/consul/command/intention/delete"
ixnget "github.com/hashicorp/consul/command/intention/get"
ixnlist "github.com/hashicorp/consul/command/intention/list"
ixnmatch "github.com/hashicorp/consul/command/intention/match"
"github.com/hashicorp/consul/command/join"
"github.com/hashicorp/consul/command/keygen"
Expand Down Expand Up @@ -182,6 +183,7 @@ func init() {
Register("intention create", func(ui cli.Ui) (cli.Command, error) { return ixncreate.New(ui), nil })
Register("intention delete", func(ui cli.Ui) (cli.Command, error) { return ixndelete.New(ui), nil })
Register("intention get", func(ui cli.Ui) (cli.Command, error) { return ixnget.New(ui), nil })
Register("intention list", func(ui cli.Ui) (cli.Command, error) { return ixnlist.New(ui), nil })
Register("intention match", func(ui cli.Ui) (cli.Command, error) { return ixnmatch.New(ui), nil })
Register("join", func(ui cli.Ui) (cli.Command, error) { return join.New(ui), nil })
Register("keygen", func(ui cli.Ui) (cli.Command, error) { return keygen.New(ui), nil })
Expand Down
4 changes: 4 additions & 0 deletions command/intention/intention.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ Usage: consul intention <subcommand> [options] [args]
$ consul intention check web db
List all intentions:
$ consul intention list
Find all intentions for communicating to the "db" service:
$ consul intention match db
Expand Down
85 changes: 85 additions & 0 deletions command/intention/list/intention_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package list

import (
"flag"
"fmt"

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

func New(ui cli.Ui) *cmd {
c := &cmd{UI: ui}
c.init()
return c
}

type cmd struct {
UI cli.Ui
flags *flag.FlagSet
http *flags.HTTPFlags
help string
}

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

c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
flags.Merge(c.flags, c.http.NamespaceFlags())
c.help = flags.Usage(help, c.flags)
}

func (c *cmd) Run(args []string) int {
if err := c.flags.Parse(args); err != nil {
return 1
}

client, err := c.http.APIClient()
if err != nil {
c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
return 1
}

ixns, _, err := client.Connect().Intentions(nil)
if err != nil {
c.UI.Error(fmt.Sprintf("Failed to retrieve the intentions list: %s", err))
return 1
}

if len(ixns) == 0 {
c.UI.Error(fmt.Sprintf("There are no intentions."))
return 2
}

result := make([]string, 0, len(ixns))
header := "ID\x1fSource\x1fAction\x1fDestination\x1fPrecedence"
result = append(result, header)
for _, ixn := range ixns {
line := fmt.Sprintf("%s\x1f%s\x1f%s\x1f%s\x1f%d",
ixn.ID, ixn.SourceName, ixn.Action, ixn.DestinationName, ixn.Precedence)
result = append(result, line)
}

output := columnize.Format(result, &columnize.Config{Delim: string([]byte{0x1f})})
c.UI.Output(output)

return 0
}

func (c *cmd) Synopsis() string {
return synopsis
}

func (c *cmd) Help() string {
return c.help
}

const synopsis = "List intentions."
const help = `
Usage: consul intention list
List all intentions.
`
47 changes: 47 additions & 0 deletions command/intention/list/intention_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package list

import (
"strings"
"testing"

"github.com/hashicorp/consul/agent"
"github.com/hashicorp/consul/api"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/require"
)

func TestIntentionListCommand_noTabs(t *testing.T) {
t.Parallel()
if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
t.Fatal("help has tabs")
}
}

func TestIntentionListCommand(t *testing.T) {
t.Parallel()
require := require.New(t)
a := agent.NewTestAgent(t, ``)
defer a.Shutdown()
client := a.Client()

// Create the intention
var id string
{
var err error
//nolint:staticcheck
id, _, err = client.Connect().IntentionCreate(&api.Intention{
SourceName: "web",
DestinationName: "db",
Action: api.IntentionActionAllow,
}, nil)
require.NoError(err)
}

// List all intentions
ui := cli.NewMockUi()
cmd := New(ui)
args := []string{"-http-addr=" + a.HTTPAddr()}

require.Equal(0, cmd.Run(args), ui.ErrorWriter.String())
require.Contains(ui.OutputWriter.String(), id)
}
11 changes: 9 additions & 2 deletions website/content/commands/intention/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ API](/api/connect/intentions).

Usage: `consul intention <subcommand>`

For the exact documentation for your Consul version, run `consul intention -h` to view
the complete list of subcommands.
For the exact documentation for your Consul version, run `consul intention -h`
to view the complete list of subcommands.

```text
Usage: consul intention <subcommand> [options] [args]
Expand All @@ -34,6 +34,7 @@ Subcommands:
check Check whether a connection between two services is allowed.
create Create intentions for service connections.
delete Delete an intention.
list Lists all intentions.
get Show information about an intention.
match Show intentions that match a source or destination.
```
Expand Down Expand Up @@ -62,6 +63,12 @@ Test whether a "web" is allowed to connect to "db":
$ consul intention check web db
```

List all intentions:

```shell-session
$ consul intention list
```

Find all intentions for communicating to the "db" service:

```shell-session
Expand Down
34 changes: 34 additions & 0 deletions website/content/commands/intention/list.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
layout: commands
page_title: 'Commands: Intention List'
sidebar_title: list
---

# Consul Intention List

Command: `consul intention list`

The `intention list` command shows all intentions including ID and precedence.

## Usage

Usage:

- `consul intention list`

#### API Options

@include 'http_api_options_client.mdx'

#### Enterprise Options

@include 'http_api_namespace_options.mdx'

## Examples

```shell-session
$ consul intention list
ID Source Action Destination Precedence
web allow db 9
36a6cf15-5f0e-a388-163e-0f608009704a dashboard allow counting 9
```

1 comment on commit 8541244

@vercel
Copy link

@vercel vercel bot commented on 8541244 Jan 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.