Skip to content

Commit

Permalink
feat(konnect): allow binding KongConsumerGroup in KongPluginBinding
Browse files Browse the repository at this point in the history
  • Loading branch information
pmalek committed Sep 26, 2024
1 parent 9314676 commit 66cb3a6
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ metadata:
spec:
type: token
token: kpat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
serverURL: eu.api.konghq.tech
serverURL: eu.api.konghq.tech
---
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha1
Expand Down Expand Up @@ -46,14 +46,13 @@ config:
policy: local
plugin: rate-limiting
---
kind: KongConsumer
apiVersion: configuration.konghq.com/v1
kind: KongConsumerGroup
apiVersion: configuration.konghq.com/v1beta1
metadata:
name: consumer-for-service-plugin-binding
name: consumer-group-for-service-pluginbinding
namespace: default
username: consumer-for-service-plugin-binding
custom_id: 08433C12-2B81-4738-B61D-3AA2136F0102
spec:
name: consumer-group-for-service-pluginbinding
controlPlaneRef:
type: konnectNamespacedRef
konnectNamespacedRef:
Expand All @@ -62,7 +61,7 @@ spec:
apiVersion: configuration.konghq.com/v1alpha1
kind: KongPluginBinding
metadata:
name: plugin-binding-kongservice-kongroute
name: plugin-binding-kongservice-kongconsumergroup
spec:
controlPlaneRef:
type: konnectNamespacedRef
Expand All @@ -75,5 +74,5 @@ spec:
name: service-1
kind: KongService
group: configuration.konghq.com
consumerRef:
name: consumer-for-service-plugin-binding
consumerGroupRef:
name: consumer-group-for-service-pluginbinding
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ metadata:
spec:
type: token
token: kpat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
serverURL: eu.api.konghq.tech
serverURL: eu.api.konghq.tech
---
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha1
Expand Down
2 changes: 1 addition & 1 deletion config/samples/konnect-kongpluginbinding.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ metadata:
spec:
type: token
token: kpat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
serverURL: eu.api.konghq.tech
serverURL: eu.api.konghq.tech
---
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metadata:
spec:
type: token
token: kpat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
serverURL: eu.api.konghq.tech
serverURL: eu.api.konghq.tech
---
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha1
Expand Down
2 changes: 1 addition & 1 deletion config/samples/konnect-kongservice-plugin-annotated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metadata:
spec:
type: token
token: kpat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
serverURL: eu.api.konghq.tech
serverURL: eu.api.konghq.tech
---
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha1
Expand Down
17 changes: 15 additions & 2 deletions controller/konnect/ops/ops_kongpluginbinding.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

configurationv1 "github.com/kong/kubernetes-configuration/api/configuration/v1"
configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
configurationv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1"
"github.com/kong/kubernetes-configuration/pkg/metadata"
)

Expand Down Expand Up @@ -209,8 +210,17 @@ func getPluginBindingTargets(
}
targetObjects = append(targetObjects, &kongConsumer)
}
if targets.ConsumerGroupReference != nil {
ref := targets.ConsumerGroupReference

// TODO: https://github.com/Kong/gateway-operator/issues/527 add support for KongConsumerGroup
kongConsumerGroup := configurationv1beta1.KongConsumerGroup{}
kongConsumerGroup.SetName(ref.Name)
kongConsumerGroup.SetNamespace(pluginBinding.GetNamespace())
if err := cl.Get(ctx, client.ObjectKeyFromObject(&kongConsumerGroup), &kongConsumerGroup); err != nil {
return nil, err
}
targetObjects = append(targetObjects, &kongConsumerGroup)
}

return targetObjects, nil
}
Expand Down Expand Up @@ -282,7 +292,10 @@ func kongPluginWithTargetsToKongPluginInput(
pluginInput.Consumer = &sdkkonnectcomp.PluginConsumer{
ID: lo.ToPtr(id),
}
// TODO: https://github.com/Kong/gateway-operator/issues/527 add support for KongConsumerGroup
case *configurationv1beta1.KongConsumerGroup:
pluginInput.ConsumerGroup = &sdkkonnectcomp.PluginConsumerGroup{
ID: lo.ToPtr(id),
}
default:
return nil, fmt.Errorf("unsupported target type %T", t)
}
Expand Down
4 changes: 2 additions & 2 deletions test/envtest/deploy_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ func deployKongConsumerGroupAttachedToCP(
cl client.Client,
cgName string,
cp *konnectv1alpha1.KonnectGatewayControlPlane,
) configurationv1beta1.KongConsumerGroup {
) *configurationv1beta1.KongConsumerGroup {
t.Helper()

cg := configurationv1beta1.KongConsumerGroup{
Expand All @@ -409,7 +409,7 @@ func deployKongConsumerGroupAttachedToCP(
require.NoError(t, cl.Create(ctx, &cg))
t.Logf("deployed new KongConsumerGroup %s", client.ObjectKeyFromObject(&cg))

return cg
return &cg
}

func deployKongVaultAttachedToCP(
Expand Down
125 changes: 125 additions & 0 deletions test/envtest/kongpluginbinding_unmanaged_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,4 +534,129 @@ func TestKongPluginBindingUnmanaged(t *testing.T) {
assert.True(c, sdk.PluginSDK.AssertExpectations(t))
}, waitTime, tickTime)
})

t.Run("binding to KongService and KongConsumerGroup", func(t *testing.T) {
proxyCacheKongPlugin := deployProxyCachePlugin(t, ctx, clientNamespaced)

serviceID := uuid.NewString()
consumerGroupID := uuid.NewString()
pluginID := uuid.NewString()
cgName := "test-group-" + uuid.NewString()

kongService := deployKongServiceAttachedToCP(t, ctx, clientNamespaced, cp)
t.Cleanup(func() {
require.NoError(t, client.IgnoreNotFound(clientNamespaced.Delete(ctx, kongService)))
})
updateKongServiceStatusWithProgrammed(t, ctx, clientNamespaced, kongService, serviceID, cp.GetKonnectStatus().GetKonnectID())
kongConsumerGroup := deployKongConsumerGroupAttachedToCP(t, ctx, clientNamespaced, cgName, cp)
t.Cleanup(func() {
require.NoError(t, client.IgnoreNotFound(clientNamespaced.Delete(ctx, kongConsumerGroup)))
})
updateKongConsumerGroupStatusWithKonnectID(t, ctx, clientNamespaced, kongConsumerGroup, consumerGroupID, cp.GetKonnectStatus().GetKonnectID())

wKongPlugin := setupWatch[configurationv1.KongPluginList](t, ctx, clientWithWatch, client.InNamespace(ns.Name))
sdk.PluginSDK.EXPECT().
CreatePlugin(
mock.Anything,
cp.GetKonnectStatus().GetKonnectID(),
mock.MatchedBy(func(pi sdkkonnectcomp.PluginInput) bool {
return pi.ConsumerGroup != nil && pi.ConsumerGroup.ID != nil && *pi.ConsumerGroup.ID == consumerGroupID &&
pi.Service != nil && pi.Service.ID != nil && *pi.Service.ID == serviceID
})).
Return(
&sdkkonnectops.CreatePluginResponse{
Plugin: &sdkkonnectcomp.Plugin{
ID: lo.ToPtr(pluginID),
},
},
nil,
)
kpb := deployKongPluginBinding(t, ctx, clientNamespaced,
&configurationv1alpha1.KongPluginBinding{
Spec: configurationv1alpha1.KongPluginBindingSpec{
ControlPlaneRef: &configurationv1alpha1.ControlPlaneRef{
Type: configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef,
KonnectNamespacedRef: &configurationv1alpha1.KonnectNamespacedRef{
Name: cp.Name,
},
},
PluginReference: configurationv1alpha1.PluginRef{
Name: proxyCacheKongPlugin.Name,
},
Targets: configurationv1alpha1.KongPluginBindingTargets{
ConsumerGroupReference: &configurationv1alpha1.TargetRef{
Name: kongConsumerGroup.Name,
},
ServiceReference: &configurationv1alpha1.TargetRefWithGroupKind{
Group: configurationv1alpha1.GroupVersion.Group,
Kind: "KongService",
Name: kongService.Name,
},
},
},
},
)
t.Logf(
"wait for the controller to pick the new unmanaged KongPluginBinding %s and put a %s finalizer on the referenced plugin %s",
client.ObjectKeyFromObject(kpb),
consts.PluginInUseFinalizer,
client.ObjectKeyFromObject(proxyCacheKongPlugin),
)
_ = watchFor(t, ctx, wKongPlugin, watch.Modified,
func(kp *configurationv1.KongPlugin) bool {
return kp.Name == proxyCacheKongPlugin.Name &&
controllerutil.ContainsFinalizer(kp, consts.PluginInUseFinalizer)
},
"KongPlugin wasn't updated to get the plugin-in-use finalizer",
)
assert.EventuallyWithT(t, func(c *assert.CollectT) {
assert.True(c, sdk.PluginSDK.AssertExpectations(t))
}, waitTime, tickTime)

sdk.PluginSDK.EXPECT().
DeletePlugin(mock.Anything, cp.GetKonnectStatus().GetKonnectID(), mock.Anything).
Return(
&sdkkonnectops.DeletePluginResponse{
StatusCode: 200,
},
nil,
)

t.Logf("delete the KongPlugin %s, then check it does not get collected", client.ObjectKeyFromObject(proxyCacheKongPlugin))
require.NoError(t, clientNamespaced.Delete(ctx, proxyCacheKongPlugin))
assert.EventuallyWithT(t, func(c *assert.CollectT) {
assert.False(c, k8serrors.IsNotFound(
clientNamespaced.Get(ctx, client.ObjectKeyFromObject(proxyCacheKongPlugin), proxyCacheKongPlugin),
))
assert.True(c, proxyCacheKongPlugin.DeletionTimestamp != nil)
assert.True(c, controllerutil.ContainsFinalizer(proxyCacheKongPlugin, consts.PluginInUseFinalizer))
}, waitTime, tickTime)

t.Logf("delete the unmanaged KongPluginBinding %s, then check the proxy-cache KongPlugin %s gets collected",
client.ObjectKeyFromObject(kpb),
client.ObjectKeyFromObject(proxyCacheKongPlugin),
)
require.NoError(t, clientNamespaced.Delete(ctx, kpb))
_ = watchFor(t, ctx, wKongPlugin, watch.Deleted,
func(kp *configurationv1.KongPlugin) bool {
return kp.Name == proxyCacheKongPlugin.Name
},
"KongPlugin did not got deleted but shouldn't have",
)

t.Logf(
"delete the KongConsumerGroup %s and check it gets collected, as the KongPluginBinding finalizer should have been removed",
client.ObjectKeyFromObject(kongConsumerGroup),
)
require.NoError(t, clientNamespaced.Delete(ctx, kongConsumerGroup))
assert.EventuallyWithT(t, func(c *assert.CollectT) {
assert.True(c, k8serrors.IsNotFound(
clientNamespaced.Get(ctx, client.ObjectKeyFromObject(kongConsumerGroup), kongConsumerGroup),
))
}, waitTime, tickTime)

assert.EventuallyWithT(t, func(c *assert.CollectT) {
assert.True(c, sdk.PluginSDK.AssertExpectations(t))
}, waitTime, tickTime)
})
}
17 changes: 17 additions & 0 deletions test/envtest/update_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

configurationv1 "github.com/kong/kubernetes-configuration/api/configuration/v1"
configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
configurationv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1"
konnectv1alpha1 "github.com/kong/kubernetes-configuration/api/konnect/v1alpha1"
)

Expand All @@ -32,6 +33,22 @@ func updateKongConsumerStatusWithKonnectID(
require.NoError(t, cl.Status().Update(ctx, obj))
}

func updateKongConsumerGroupStatusWithKonnectID(
t *testing.T,
ctx context.Context,
cl client.Client,
obj *configurationv1beta1.KongConsumerGroup,
id string,
cpID string,
) {
obj.Status.Konnect = &konnectv1alpha1.KonnectEntityStatusWithControlPlaneRef{
ControlPlaneID: cpID,
KonnectEntityStatus: konnectEntityStatus(id),
}

require.NoError(t, cl.Status().Update(ctx, obj))
}

func updateKongServiceStatusWithProgrammed(
t *testing.T,
ctx context.Context,
Expand Down

0 comments on commit 66cb3a6

Please sign in to comment.