api: IntentionMatch

This commit is contained in:
Mitchell Hashimoto 2018-03-28 10:14:32 -07:00
parent 663a12d96b
commit 4689d8373a
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 121 additions and 1 deletions

View File

@ -67,6 +67,22 @@ const (
IntentionSourceConsul IntentionSourceType = "consul"
)
// IntentionMatch are the arguments for the intention match API.
type IntentionMatch struct {
By IntentionMatchType
Names []string
}
// IntentionMatchType is the target for a match request. For example,
// matching by source will look for all intentions that match the given
// source value.
type IntentionMatchType string
const (
IntentionMatchSource IntentionMatchType = "source"
IntentionMatchDestination IntentionMatchType = "destination"
)
// Intentions returns the list of intentions.
func (h *Connect) Intentions(q *QueryOptions) ([]*Intention, *QueryMeta, error) {
r := h.c.newRequest("GET", "/v1/connect/intentions")
@ -88,6 +104,58 @@ func (h *Connect) Intentions(q *QueryOptions) ([]*Intention, *QueryMeta, error)
return out, qm, nil
}
// IntentionGet retrieves a single intention.
func (h *Connect) IntentionGet(id string, q *QueryOptions) (*Intention, *QueryMeta, error) {
r := h.c.newRequest("GET", "/v1/connect/intentions/"+id)
r.setQueryOptions(q)
rtt, resp, err := requireOK(h.c.doRequest(r))
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
qm := &QueryMeta{}
parseQueryMeta(resp, qm)
qm.RequestTime = rtt
var out Intention
if err := decodeBody(resp, &out); err != nil {
return nil, nil, err
}
return &out, qm, nil
}
// IntentionMatch returns the list of intentions that match a given source
// or destination. The returned intentions are ordered by precedence where
// result[0] is the highest precedence (if that matches, then that rule overrides
// all other rules).
//
// Matching can be done for multiple names at the same time. The resulting
// map is keyed by the given names. Casing is preserved.
func (h *Connect) IntentionMatch(args *IntentionMatch, q *QueryOptions) (map[string][]*Intention, *QueryMeta, error) {
r := h.c.newRequest("GET", "/v1/connect/intentions/match")
r.setQueryOptions(q)
r.params.Set("by", string(args.By))
for _, name := range args.Names {
r.params.Add("name", name)
}
rtt, resp, err := requireOK(h.c.doRequest(r))
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
qm := &QueryMeta{}
parseQueryMeta(resp, qm)
qm.RequestTime = rtt
var out map[string][]*Intention
if err := decodeBody(resp, &out); err != nil {
return nil, nil, err
}
return out, qm, nil
}
// IntentionCreate will create a new intention. The ID in the given
// structure must be empty and a generate ID will be returned on
// success.

View File

@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
)
func TestAPI_ConnectIntentionCreate(t *testing.T) {
func TestAPI_ConnectIntentionCreateListGet(t *testing.T) {
t.Parallel()
require := require.New(t)
@ -33,6 +33,58 @@ func TestAPI_ConnectIntentionCreate(t *testing.T) {
ixn.CreateIndex = actual.CreateIndex
ixn.ModifyIndex = actual.ModifyIndex
require.Equal(ixn, actual)
// Get it
actual, _, err = connect.IntentionGet(id, nil)
require.Nil(err)
require.Equal(ixn, actual)
}
func TestAPI_ConnectIntentionMatch(t *testing.T) {
t.Parallel()
require := require.New(t)
c, s := makeClient(t)
defer s.Stop()
connect := c.Connect()
// Create
{
insert := [][]string{
{"foo", "*"},
{"foo", "bar"},
{"foo", "baz"}, // shouldn't match
{"bar", "bar"}, // shouldn't match
{"bar", "*"}, // shouldn't match
{"*", "*"},
}
for _, v := range insert {
ixn := testIntention()
ixn.DestinationNS = v[0]
ixn.DestinationName = v[1]
id, _, err := connect.IntentionCreate(ixn, nil)
require.Nil(err)
require.NotEmpty(id)
}
}
// Match it
result, _, err := connect.IntentionMatch(&IntentionMatch{
By: IntentionMatchDestination,
Names: []string{"foo/bar"},
}, nil)
require.Nil(err)
require.Len(result, 1)
var actual [][]string
expected := [][]string{{"foo", "bar"}, {"foo", "*"}, {"*", "*"}}
for _, ixn := range result["foo/bar"] {
actual = append(actual, []string{ixn.DestinationNS, ixn.DestinationName})
}
require.Equal(expected, actual)
}
func testIntention() *Intention {