mirror of https://github.com/hashicorp/consul
Browse Source
The endpoints controller currently encodes the list of unique workload identities referenced by all workload matched by a Service into a special data-bearing status condition on that Service. This allows a downstream controller to avoid an expensive watch on the ServiceEndpoints type just to get this data. The current encoding does not lend itself well to machine parsing, which is what the field is meant for, so this PR simplifies the encoding from: "blah blah: " + strings.Join(ids, ",") + "." to strings.Join(ids, ",") It also provides an exported utility function to easily extract this data.pull/20466/head
R.B. Boyer
10 months ago
committed by
GitHub
4 changed files with 124 additions and 6 deletions
@ -0,0 +1,46 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package endpoints |
||||
|
||||
import ( |
||||
"sort" |
||||
"strings" |
||||
|
||||
"github.com/hashicorp/consul/proto-public/pbresource" |
||||
) |
||||
|
||||
// GetBoundIdentities returns the unique list of workload identity references
|
||||
// encoded into a data-bearing status condition on a Service resource by the
|
||||
// endpoints controller.
|
||||
//
|
||||
// This allows a controller to skip watching ServiceEndpoints (which is
|
||||
// expensive) to discover this data.
|
||||
func GetBoundIdentities(res *pbresource.Resource) []string { |
||||
if res.GetStatus() == nil { |
||||
return nil |
||||
} |
||||
|
||||
status, ok := res.GetStatus()[ControllerID] |
||||
if !ok { |
||||
return nil |
||||
} |
||||
|
||||
var encoded string |
||||
for _, cond := range status.GetConditions() { |
||||
if cond.GetType() == StatusConditionBoundIdentities && cond.GetState() == pbresource.Condition_STATE_TRUE { |
||||
encoded = cond.GetMessage() |
||||
break |
||||
} |
||||
} |
||||
if encoded == "" { |
||||
return nil |
||||
} |
||||
|
||||
identities := strings.Split(encoded, ",") |
||||
|
||||
// Ensure determinstic sort so we don't get into infinite-reconcile
|
||||
sort.Strings(identities) |
||||
|
||||
return identities |
||||
} |
@ -0,0 +1,63 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package endpoints_test |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/require" |
||||
|
||||
"github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" |
||||
"github.com/hashicorp/consul/internal/resource" |
||||
"github.com/hashicorp/consul/internal/resource/demo" |
||||
rtest "github.com/hashicorp/consul/internal/resource/resourcetest" |
||||
"github.com/hashicorp/consul/proto-public/pbresource" |
||||
pbdemo "github.com/hashicorp/consul/proto/private/pbdemo/v2" |
||||
) |
||||
|
||||
func TestGetBoundIdentities(t *testing.T) { |
||||
tenancy := resource.DefaultNamespacedTenancy() |
||||
|
||||
build := func(conds ...*pbresource.Condition) *pbresource.Resource { |
||||
b := rtest.Resource(demo.TypeV2Artist, "artist"). |
||||
WithTenancy(tenancy). |
||||
WithData(t, &pbdemo.Artist{Name: "very arty"}) |
||||
if len(conds) > 0 { |
||||
b.WithStatus(endpoints.ControllerID, &pbresource.Status{ |
||||
Conditions: conds, |
||||
}) |
||||
} |
||||
return b.Build() |
||||
} |
||||
|
||||
run := endpoints.GetBoundIdentities |
||||
|
||||
require.Empty(t, run(build(nil))) |
||||
require.Empty(t, run(build(&pbresource.Condition{ |
||||
Type: endpoints.StatusConditionBoundIdentities, |
||||
State: pbresource.Condition_STATE_TRUE, |
||||
Message: "", |
||||
}))) |
||||
require.Equal(t, []string{"foo"}, run(build(&pbresource.Condition{ |
||||
Type: endpoints.StatusConditionBoundIdentities, |
||||
State: pbresource.Condition_STATE_TRUE, |
||||
Message: "foo", |
||||
}))) |
||||
require.Empty(t, run(build(&pbresource.Condition{ |
||||
Type: endpoints.StatusConditionBoundIdentities, |
||||
State: pbresource.Condition_STATE_FALSE, |
||||
Message: "foo", |
||||
}))) |
||||
require.Equal(t, []string{"bar", "foo"}, run(build(&pbresource.Condition{ |
||||
Type: endpoints.StatusConditionBoundIdentities, |
||||
State: pbresource.Condition_STATE_TRUE, |
||||
Message: "bar,foo", // proper order
|
||||
}))) |
||||
require.Equal(t, []string{"bar", "foo"}, run(build(&pbresource.Condition{ |
||||
Type: endpoints.StatusConditionBoundIdentities, |
||||
State: pbresource.Condition_STATE_TRUE, |
||||
Message: "foo,bar", // incorrect order gets fixed
|
||||
}))) |
||||
|
||||
} |
Loading…
Reference in new issue