From e8c4156f0784aac50941ddd9bb999670eeb221eb Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 28 Feb 2018 10:44:49 -0800 Subject: [PATCH] agent/consul: Intention.Get endpoint --- agent/consul/intention_endpoint.go | 31 +++++++++++++++++++++++++ agent/consul/intention_endpoint_test.go | 25 +++++++++++++++++++- agent/structs/intention.go | 17 ++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/agent/consul/intention_endpoint.go b/agent/consul/intention_endpoint.go index 8d07b4e7b9..3313c03f7a 100644 --- a/agent/consul/intention_endpoint.go +++ b/agent/consul/intention_endpoint.go @@ -65,6 +65,37 @@ func (s *Intention) Apply( return nil } +// Get returns a single intention by ID. +func (s *Intention) Get( + args *structs.IntentionQueryRequest, + reply *structs.IndexedIntentions) error { + // Forward if necessary + if done, err := s.srv.forward("Intention.Get", args, args, reply); done { + return err + } + + return s.srv.blockingQuery( + &args.QueryOptions, + &reply.QueryMeta, + func(ws memdb.WatchSet, state *state.Store) error { + index, ixn, err := state.IntentionGet(ws, args.IntentionID) + if err != nil { + return err + } + if ixn == nil { + return ErrQueryNotFound + } + + reply.Index = index + reply.Intentions = structs.Intentions{ixn} + + // TODO: acl filtering + + return nil + }, + ) +} + // List returns all the intentions. func (s *Intention) List( args *structs.DCSpecificRequest, diff --git a/agent/consul/intention_endpoint_test.go b/agent/consul/intention_endpoint_test.go index 51fa635e3f..5a2405d897 100644 --- a/agent/consul/intention_endpoint_test.go +++ b/agent/consul/intention_endpoint_test.go @@ -2,6 +2,7 @@ package consul import ( "os" + "reflect" "testing" "github.com/hashicorp/consul/agent/structs" @@ -37,7 +38,29 @@ func TestIntentionApply_new(t *testing.T) { t.Fatal("reply should be non-empty") } - // TODO test read + // Read + ixn.Intention.ID = reply + { + req := &structs.IntentionQueryRequest{ + Datacenter: "dc1", + IntentionID: ixn.Intention.ID, + } + var resp structs.IndexedIntentions + if err := msgpackrpc.CallWithCodec(codec, "Intention.Get", req, &resp); err != nil { + t.Fatalf("err: %v", err) + } + if len(resp.Intentions) != 1 { + t.Fatalf("bad: %v", resp) + } + actual := resp.Intentions[0] + if resp.Index != actual.ModifyIndex { + t.Fatalf("bad index: %d", resp.Index) + } + actual.CreateIndex, actual.ModifyIndex = 0, 0 + if !reflect.DeepEqual(actual, ixn.Intention) { + t.Fatalf("bad: %v", actual) + } + } } func TestIntentionList(t *testing.T) { diff --git a/agent/structs/intention.go b/agent/structs/intention.go index 81f07080c5..cce6e3e0f8 100644 --- a/agent/structs/intention.go +++ b/agent/structs/intention.go @@ -99,3 +99,20 @@ type IntentionRequest struct { func (q *IntentionRequest) RequestDatacenter() string { return q.Datacenter } + +// IntentionQueryRequest is used to query intentions. +type IntentionQueryRequest struct { + // Datacenter is the target this request is intended for. + Datacenter string + + // IntentionID is the ID of a specific intention. + IntentionID string + + // Options for queries + QueryOptions +} + +// RequestDatacenter returns the datacenter for a given request. +func (q *IntentionQueryRequest) RequestDatacenter() string { + return q.Datacenter +}