Skip to content

Commit

Permalink
Add the endpoint ignoring logic for triggering gateway reconciliation (
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Stucki authored and absolutelightning committed Aug 4, 2023
1 parent 32e103d commit 49c3196
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 6 deletions.
13 changes: 7 additions & 6 deletions control-plane/api-gateway/controllers/gateway_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,6 @@ func SetupGatewayControllerWithManager(ctx context.Context, mgr ctrl.Manager, co
source.NewKindWithCache(&corev1.Secret{}, mgr.GetCache()),
handler.EnqueueRequestsFromMapFunc(r.transformSecret(ctx)),
).
Watches(
source.NewKindWithCache(&gwv1beta1.ReferenceGrant{}, mgr.GetCache()),
handler.EnqueueRequestsFromMapFunc(r.transformReferenceGrant(ctx)),
).
Watches(
source.NewKindWithCache(&v1alpha1.MeshService{}, mgr.GetCache()),
handler.EnqueueRequestsFromMapFunc(r.transformMeshService(ctx)),
Expand Down Expand Up @@ -573,9 +569,14 @@ func gatewayReferencesCertificate(certificateKey api.ResourceReference, gateway
// by a TCPRoute or HTTPRoute that references the service.
func (r *GatewayController) transformEndpoints(ctx context.Context) func(o client.Object) []reconcile.Request {
return func(o client.Object) []reconcile.Request {
key := client.ObjectKeyFromObject(o).String()
key := client.ObjectKeyFromObject(o)
endpoints := o.(*corev1.Endpoints)

if shouldIgnore(key.Namespace, r.denyK8sNamespacesSet, r.allowK8sNamespacesSet) || isLabeledIgnore(endpoints.Labels) {
return nil
}

return r.gatewaysForRoutesReferencing(ctx, TCPRoute_ServiceIndex, HTTPRoute_ServiceIndex, key)
return r.gatewaysForRoutesReferencing(ctx, TCPRoute_ServiceIndex, HTTPRoute_ServiceIndex, key.String())
}
}

Expand Down
254 changes: 254 additions & 0 deletions control-plane/api-gateway/controllers/gateway_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import (
"context"
"testing"

mapset "github.com/deckarep/golang-set"
"github.com/hashicorp/consul-k8s/control-plane/api-gateway/common"
"github.com/hashicorp/consul-k8s/control-plane/api/v1alpha1"
"github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants"

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -21,6 +24,257 @@ import (
gwv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
)

func TestTransformEndpoints(t *testing.T) {
t.Parallel()

httpRoute := &gwv1beta1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{
Name: "http",
Namespace: "test",
},
Spec: gwv1beta1.HTTPRouteSpec{
Rules: []gwv1beta1.HTTPRouteRule{
{BackendRefs: []gwv1beta1.HTTPBackendRef{
{BackendRef: gwv1beta1.BackendRef{
BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "http-test-namespace"},
}},
{BackendRef: gwv1beta1.BackendRef{
BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "http-other-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("other"))},
}},
{BackendRef: gwv1beta1.BackendRef{
BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "http-system-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("system"))},
}},
{BackendRef: gwv1beta1.BackendRef{
BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "http-public-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("public"))},
}},
{BackendRef: gwv1beta1.BackendRef{
BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "http-local-path-storage-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("local-path-storage"))},
}}},
},
},
CommonRouteSpec: gwv1beta1.CommonRouteSpec{
ParentRefs: []gwv1beta1.ParentReference{
{Name: "http-gateway"},
{Name: "general-gateway"},
},
},
},
}

tcpRoute := &gwv1alpha2.TCPRoute{
ObjectMeta: metav1.ObjectMeta{
Name: "tcp",
Namespace: "test",
},
Spec: gwv1alpha2.TCPRouteSpec{
Rules: []gwv1alpha2.TCPRouteRule{
{BackendRefs: []gwv1beta1.BackendRef{
{BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "tcp-test-namespace"}},
{BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "tcp-other-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("other"))}},
{BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "tcp-system-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("system"))}},
{BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "tcp-public-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("public"))}},
{BackendObjectReference: gwv1beta1.BackendObjectReference{Name: "tcp-local-path-storage-namespace", Namespace: common.PointerTo(gwv1beta1.Namespace("local-path-storage"))}},
}},
},
CommonRouteSpec: gwv1beta1.CommonRouteSpec{
ParentRefs: []gwv1beta1.ParentReference{
{Name: "tcp-gateway"},
{Name: "general-gateway"},
},
},
},
}

for name, tt := range map[string]struct {
endpoints *corev1.Endpoints
expected []reconcile.Request
allowedNamespaces []string
denyNamespaces []string
}{
"ignore system namespace": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-system-namespace",
Namespace: metav1.NamespaceSystem,
},
},
allowedNamespaces: []string{"*"},
},
"ignore public namespace": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-public-namespace",
Namespace: metav1.NamespacePublic,
},
},
allowedNamespaces: []string{"*"},
},
"ignore local-path-storage namespace": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-local-path-storage-namespace",
Namespace: "local-path-storage",
},
},
allowedNamespaces: []string{"*"},
},
"explicit deny namespace": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-test-namespace",
Namespace: "test",
},
},
allowedNamespaces: []string{"*"},
denyNamespaces: []string{"test"},
},
"ignore labels": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-test-namespace",
Namespace: "test",
Labels: map[string]string{
constants.LabelServiceIgnore: "true",
},
},
},
allowedNamespaces: []string{"test"},
},
"http same namespace wildcard allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-test-namespace",
Namespace: "test",
},
},
allowedNamespaces: []string{"*"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "http-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
"http same namespace explicit allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-test-namespace",
Namespace: "test",
},
},
allowedNamespaces: []string{"test"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "http-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
"http other namespace wildcard allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-other-namespace",
Namespace: "other",
},
},
allowedNamespaces: []string{"*"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "http-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
"http other namespace explicit allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "http-other-namespace",
Namespace: "other",
},
},
allowedNamespaces: []string{"other"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "http-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
"tcp same namespace wildcard allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "tcp-test-namespace",
Namespace: "test",
},
},
allowedNamespaces: []string{"*"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "tcp-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
"tcp same namespace explicit allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "tcp-test-namespace",
Namespace: "test",
},
},
allowedNamespaces: []string{"test"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "tcp-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
"tcp other namespace wildcard allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "tcp-other-namespace",
Namespace: "other",
},
},
allowedNamespaces: []string{"*"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "tcp-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
"tcp other namespace explicit allow": {
endpoints: &corev1.Endpoints{
ObjectMeta: metav1.ObjectMeta{
Name: "tcp-other-namespace",
Namespace: "other",
},
},
allowedNamespaces: []string{"other"},
expected: []reconcile.Request{
{NamespacedName: types.NamespacedName{Name: "tcp-gateway", Namespace: "test"}},
{NamespacedName: types.NamespacedName{Name: "general-gateway", Namespace: "test"}},
},
},
} {
t.Run(name, func(t *testing.T) {
s := runtime.NewScheme()
require.NoError(t, clientgoscheme.AddToScheme(s))
require.NoError(t, gwv1alpha2.Install(s))
require.NoError(t, gwv1beta1.Install(s))
require.NoError(t, v1alpha1.AddToScheme(s))

denySet := mapset.NewSet()
for _, v := range tt.denyNamespaces {
denySet.Add(v)
}
allowSet := mapset.NewSet()
for _, v := range tt.allowedNamespaces {
allowSet.Add(v)
}

fakeClient := registerFieldIndexersForTest(fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(httpRoute, tcpRoute)).Build()

controller := GatewayController{
Client: fakeClient,
denyK8sNamespacesSet: denySet,
allowK8sNamespacesSet: allowSet,
}

fn := controller.transformEndpoints(context.Background())
require.ElementsMatch(t, tt.expected, fn(tt.endpoints))
})
}
}

func TestTransformHTTPRoute(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit 49c3196

Please sign in to comment.