diff --git a/agent/consul/intention_endpoint.go b/agent/consul/intention_endpoint.go index 56f310e18f..c3723d7081 100644 --- a/agent/consul/intention_endpoint.go +++ b/agent/consul/intention_endpoint.go @@ -86,6 +86,11 @@ func (s *Intention) Apply( // We always update the updatedat field. This has no effect for deletion. args.Intention.UpdatedAt = time.Now() + // Default source type + if args.Intention.SourceType == "" { + args.Intention.SourceType = structs.IntentionSourceConsul + } + // Until we support namespaces, we force all namespaces to be default if args.Intention.SourceNS == "" { args.Intention.SourceNS = structs.IntentionDefaultNamespace diff --git a/agent/consul/intention_endpoint_test.go b/agent/consul/intention_endpoint_test.go index 2ee49f207a..3c38e695ab 100644 --- a/agent/consul/intention_endpoint_test.go +++ b/agent/consul/intention_endpoint_test.go @@ -33,6 +33,7 @@ func TestIntentionApply_new(t *testing.T) { DestinationNS: structs.IntentionDefaultNamespace, DestinationName: "test", Action: structs.IntentionActionAllow, + SourceType: structs.IntentionSourceConsul, Meta: map[string]string{}, }, } @@ -93,6 +94,61 @@ func TestIntentionApply_new(t *testing.T) { } } +// Test the source type defaults +func TestIntentionApply_defaultSourceType(t *testing.T) { + t.Parallel() + dir1, s1 := testServer(t) + defer os.RemoveAll(dir1) + defer s1.Shutdown() + codec := rpcClient(t, s1) + defer codec.Close() + + testrpc.WaitForLeader(t, s1.RPC, "dc1") + + // Setup a basic record to create + ixn := structs.IntentionRequest{ + Datacenter: "dc1", + Op: structs.IntentionOpCreate, + Intention: &structs.Intention{ + SourceNS: structs.IntentionDefaultNamespace, + SourceName: "test", + DestinationNS: structs.IntentionDefaultNamespace, + DestinationName: "test", + Action: structs.IntentionActionAllow, + }, + } + var reply string + + // Create + if err := msgpackrpc.CallWithCodec(codec, "Intention.Apply", &ixn, &reply); err != nil { + t.Fatalf("err: %v", err) + } + if reply == "" { + t.Fatal("reply should be non-empty") + } + + // 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 actual.SourceType != structs.IntentionSourceConsul { + t.Fatalf("bad:\n\n%#v\n\n%#v", actual, ixn.Intention) + } + } +} + // Shouldn't be able to create with an ID set func TestIntentionApply_createWithID(t *testing.T) { t.Parallel() @@ -143,6 +199,7 @@ func TestIntentionApply_updateGood(t *testing.T) { DestinationNS: structs.IntentionDefaultNamespace, DestinationName: "test", Action: structs.IntentionActionAllow, + SourceType: structs.IntentionSourceConsul, Meta: map[string]string{}, }, } diff --git a/agent/structs/intention.go b/agent/structs/intention.go index a8da939f7d..579fef6c10 100644 --- a/agent/structs/intention.go +++ b/agent/structs/intention.go @@ -147,6 +147,13 @@ func (x *Intention) Validate() error { "Action must be set to 'allow' or 'deny'")) } + switch x.SourceType { + case IntentionSourceConsul: + default: + result = multierror.Append(result, fmt.Errorf( + "SourceType must be set to 'consul'")) + } + return result } diff --git a/agent/structs/intention_test.go b/agent/structs/intention_test.go index 500b24d5aa..ec0a2de669 100644 --- a/agent/structs/intention_test.go +++ b/agent/structs/intention_test.go @@ -92,6 +92,18 @@ func TestIntentionValidate(t *testing.T) { }, "follow wildcard", }, + + { + "SourceType is not set", + func(x *Intention) { x.SourceType = "" }, + "SourceType must", + }, + + { + "SourceType is other", + func(x *Intention) { x.SourceType = IntentionSourceType("other") }, + "SourceType must", + }, } for _, tc := range cases { diff --git a/agent/structs/testing_intention.go b/agent/structs/testing_intention.go index b653c1174e..930e27869e 100644 --- a/agent/structs/testing_intention.go +++ b/agent/structs/testing_intention.go @@ -11,5 +11,7 @@ func TestIntention(t testing.T) *Intention { SourceName: "api", DestinationNS: "eng", DestinationName: "db", + Action: IntentionActionAllow, + SourceType: IntentionSourceConsul, } }