command/intention/finder: package for finding based on src/dst
This commit is contained in:
parent
a1a7eaa876
commit
77d0360de1
|
@ -53,17 +53,30 @@ type Intention struct {
|
|||
|
||||
// String returns human-friendly output describing ths intention.
|
||||
func (i *Intention) String() string {
|
||||
source := i.SourceName
|
||||
if i.SourceNS != "" {
|
||||
source = i.SourceNS + "/" + source
|
||||
return fmt.Sprintf("%s => %s (%s)",
|
||||
i.SourceString(),
|
||||
i.DestinationString(),
|
||||
i.Action)
|
||||
}
|
||||
|
||||
// SourceString returns the namespace/name format for the source, or
|
||||
// just "name" if the namespace is the default namespace.
|
||||
func (i *Intention) SourceString() string {
|
||||
return i.partString(i.SourceNS, i.SourceName)
|
||||
}
|
||||
|
||||
// DestinationString returns the namespace/name format for the source, or
|
||||
// just "name" if the namespace is the default namespace.
|
||||
func (i *Intention) DestinationString() string {
|
||||
return i.partString(i.DestinationNS, i.DestinationName)
|
||||
}
|
||||
|
||||
func (i *Intention) partString(ns, n string) string {
|
||||
if ns != "" {
|
||||
n = ns + "/" + n
|
||||
}
|
||||
|
||||
dest := i.DestinationName
|
||||
if i.DestinationNS != "" {
|
||||
dest = i.DestinationNS + "/" + dest
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s => %s (%s)", source, dest, i.Action)
|
||||
return n
|
||||
}
|
||||
|
||||
// IntentionAction is the action that the intention represents. This
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package finder
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
// Finder finds intentions by a src/dst exact match. There is currently
|
||||
// no direct API to do this so this struct downloads all intentions and
|
||||
// caches them once, and searches in-memory for this. For now this works since
|
||||
// even with a very large number of intentions, the size of the data gzipped
|
||||
// over HTTP will be relatively small.
|
||||
type Finder struct {
|
||||
// Client is the API client to use for any requests.
|
||||
Client *api.Client
|
||||
|
||||
lock sync.Mutex
|
||||
ixns []*api.Intention // cached list of intentions
|
||||
}
|
||||
|
||||
// Find finds the intention that matches the given src and dst. This will
|
||||
// return nil when the result is not found.
|
||||
func (f *Finder) Find(src, dst string) (*api.Intention, error) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
// If the list of ixns is nil, then we haven't fetched yet, so fetch
|
||||
if f.ixns == nil {
|
||||
ixns, _, err := f.Client.Connect().Intentions(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.ixns = ixns
|
||||
}
|
||||
|
||||
// Go through the intentions and find an exact match
|
||||
for _, ixn := range f.ixns {
|
||||
if ixn.SourceString() == src && ixn.DestinationString() == dst {
|
||||
return ixn, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package finder
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/agent"
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFinder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require := require.New(t)
|
||||
a := agent.NewTestAgent(t.Name(), ``)
|
||||
defer a.Shutdown()
|
||||
client := a.Client()
|
||||
|
||||
// Create a set of intentions
|
||||
var ids []string
|
||||
{
|
||||
insert := [][]string{
|
||||
[]string{"a", "b", "c", "d"},
|
||||
}
|
||||
|
||||
for _, v := range insert {
|
||||
ixn := &api.Intention{
|
||||
SourceNS: v[0],
|
||||
SourceName: v[1],
|
||||
DestinationNS: v[2],
|
||||
DestinationName: v[3],
|
||||
Action: api.IntentionActionAllow,
|
||||
}
|
||||
|
||||
id, _, err := client.Connect().IntentionCreate(ixn, nil)
|
||||
require.NoError(err)
|
||||
ids = append(ids, id)
|
||||
}
|
||||
}
|
||||
|
||||
finder := &Finder{Client: client}
|
||||
ixn, err := finder.Find("a/b", "c/d")
|
||||
require.NoError(err)
|
||||
require.Equal(ids[0], ixn.ID)
|
||||
|
||||
ixn, err = finder.Find("a/c", "c/d")
|
||||
require.NoError(err)
|
||||
require.Nil(ixn)
|
||||
}
|
Loading…
Reference in New Issue