11package integration
22
33import (
4+ "encoding/json"
45 "testing"
56 "time"
67
@@ -9,10 +10,13 @@ import (
910 "github.com/samber/lo"
1011 "github.com/stretchr/testify/assert"
1112 "github.com/stretchr/testify/require"
13+ apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
14+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1215 "k8s.io/apimachinery/pkg/types"
1316 "sigs.k8s.io/controller-runtime/pkg/client"
1417
1518 commonv1alpha1 "github.com/kong/kong-operator/api/common/v1alpha1"
19+ configurationv1 "github.com/kong/kong-operator/api/configuration/v1"
1620 configurationv1alpha1 "github.com/kong/kong-operator/api/configuration/v1alpha1"
1721 konnectv1alpha1 "github.com/kong/kong-operator/api/konnect/v1alpha1"
1822 sdkops "github.com/kong/kong-operator/controller/konnect/ops/sdk"
@@ -209,3 +213,211 @@ func TestKonnectEntityAdoption_ServiceAndRoute(t *testing.T) {
209213 "Did not see route in Konnect to be updated to match the spec of KongRoute" )
210214
211215}
216+
217+ func TestKonnectEntityAdoption_Plugin (t * testing.T ) {
218+ ns , _ := helpers .SetupTestEnv (t , GetCtx (), GetEnv ())
219+
220+ // Let's generate a unique test ID that we can refer to in Konnect entities.
221+ // Using only the first 8 characters of the UUID to keep the ID short enough for Konnect to accept it as a part
222+ // of an entity name.
223+ testID := uuid .NewString ()[:8 ]
224+ t .Logf ("Running Konnect entity adoption test for plugins with ID: %s" , testID )
225+
226+ clientNamespaced := client .NewNamespacedClient (GetClients ().MgrClient , ns .Name )
227+
228+ t .Log ("Creating Konnect API auth configuration and Konnect control plane" )
229+ authCfg := deploy .KonnectAPIAuthConfiguration (t , GetCtx (), clientNamespaced ,
230+ deploy .WithTestIDLabel (testID ),
231+ func (obj client.Object ) {
232+ authCfg := obj .(* konnectv1alpha1.KonnectAPIAuthConfiguration )
233+ authCfg .Spec .Type = konnectv1alpha1 .KonnectAPIAuthTypeToken
234+ authCfg .Spec .Token = test .KonnectAccessToken ()
235+ authCfg .Spec .ServerURL = test .KonnectServerURL ()
236+ },
237+ )
238+
239+ cp := deploy .KonnectGatewayControlPlane (t , GetCtx (), clientNamespaced , authCfg ,
240+ deploy .WithTestIDLabel (testID ),
241+ deploy .KonnectGatewayControlPlaneLabel (deploy .KonnectTestIDLabel , testID ),
242+ )
243+
244+ t .Cleanup (deleteObjectAndWaitForDeletionFn (t , cp .DeepCopy ()))
245+
246+ t .Logf ("Waiting for Konnect ID to be assigned to ControlPlane %s/%s" , cp .Namespace , cp .Name )
247+ require .EventuallyWithT (t , func (t * assert.CollectT ) {
248+ err := GetClients ().MgrClient .Get (GetCtx (), types.NamespacedName {Name : cp .Name , Namespace : cp .Namespace }, cp )
249+ require .NoError (t , err )
250+ assertKonnectEntityProgrammed (t , cp )
251+ }, testutils .ObjectUpdateTimeout , testutils .ObjectUpdateTick )
252+
253+ cpKonnectID := cp .GetKonnectID ()
254+
255+ t .Logf ("Create a global plugin by SDK for adoption" )
256+ server , err := server.NewServer [struct {}](test .KonnectServerURL ())
257+ require .NoError (t , err , "Should create a server successfully" )
258+ sdk := sdkops .NewSDKFactory ().NewKonnectSDK (server , sdkops .SDKToken (test .KonnectAccessToken ()))
259+ require .NotNil (t , sdk )
260+
261+ resp , err := sdk .GetPluginSDK ().CreatePlugin (
262+ t .Context (),
263+ cpKonnectID ,
264+ sdkkonnectcomp.Plugin {
265+ Name : "request-transformer" ,
266+ Config : map [string ]any {
267+ "add" : map [string ][]string {
268+ "headers" : {
269+ "X-Kong-Test:test" ,
270+ },
271+ },
272+ },
273+ },
274+ )
275+ require .NoError (t , err )
276+ require .NotNil (t , resp , "Should get a non-nil response for creating a plugin" )
277+ require .NotNil (t , resp .Plugin , "Should get a non-nil plugin in the response" )
278+ globalRequestTransformerPlugin := resp .Plugin
279+ require .NotNil (t , globalRequestTransformerPlugin .ID , "Should receive a non-nil plugin ID" )
280+
281+ buf , err := json .Marshal (globalRequestTransformerPlugin .Config )
282+ require .NoError (t , err , "Should marshal plugin configuration in JSON successfully" )
283+
284+ t .Log ("Creating a KongPlugin and a KongPluginBinding to adopt the plugin" )
285+ kongPluginReqTransformer := & configurationv1.KongPlugin {
286+ ObjectMeta : metav1.ObjectMeta {
287+ Namespace : ns .Name ,
288+ Name : "kongplugin-global-request-transformer" ,
289+ },
290+ PluginName : "request-transformer" ,
291+ Config : apiextensionsv1.JSON {
292+ Raw : buf ,
293+ },
294+ }
295+ require .NoError (t , clientNamespaced .Create (GetCtx (), kongPluginReqTransformer ))
296+ t .Cleanup (deleteObjectAndWaitForDeletionFn (t , kongPluginReqTransformer .DeepCopy ()))
297+
298+ kpbGlobal := deploy .KongPluginBinding (t , GetCtx (), clientNamespaced , & configurationv1alpha1.KongPluginBinding {
299+ Spec : configurationv1alpha1.KongPluginBindingSpec {
300+ PluginReference : configurationv1alpha1.PluginRef {
301+ Name : kongPluginReqTransformer .Name ,
302+ },
303+ Adopt : & commonv1alpha1.AdoptOptions {
304+ From : commonv1alpha1 .AdoptSourceKonnect ,
305+ Mode : commonv1alpha1 .AdoptModeOverride ,
306+ Konnect : & commonv1alpha1.AdoptKonnectOptions {
307+ ID : * globalRequestTransformerPlugin .ID ,
308+ },
309+ },
310+ Scope : configurationv1alpha1 .KongPluginBindingScopeGlobalInControlPlane ,
311+ },
312+ }, deploy .WithKonnectNamespacedRefControlPlaneRef (cp ))
313+ t .Cleanup (deleteObjectAndWaitForDeletionFn (t , kpbGlobal .DeepCopy ()))
314+
315+ t .Log ("Waiting for KongPluginBinding to be programmed and set Konnect ID" )
316+ require .EventuallyWithT (t , func (collect * assert.CollectT ) {
317+ err := clientNamespaced .Get (GetCtx (), client .ObjectKeyFromObject (kpbGlobal ), kpbGlobal )
318+ require .NoError (t , err )
319+
320+ assertKonnectEntityProgrammed (collect , kpbGlobal )
321+ assert .Equalf (collect , * globalRequestTransformerPlugin .ID , kpbGlobal .GetKonnectID (),
322+ "KongPluginBinding should set Konnect ID %s as the adopted plugin in status" ,
323+ * globalRequestTransformerPlugin .ID ,
324+ )
325+ }, testutils .ObjectUpdateTimeout , testutils .ObjectUpdateTick ,
326+ "Did not see KongPluginBinding set Konnect ID and Programmed condition to True" ,
327+ )
328+
329+ t .Log ("Creating a KongService to attach plugins to" )
330+ ks := deploy .KongService (t , GetCtx (), clientNamespaced , deploy .WithKonnectNamespacedRefControlPlaneRef (cp ))
331+ t .Cleanup (deleteObjectAndWaitForDeletionFn (t , ks .DeepCopy ()))
332+
333+ t .Log ("Waiting for the KongService to get a Konnect ID" )
334+ var serviceKonnectID string
335+ require .EventuallyWithT (t , func (collect * assert.CollectT ) {
336+ err := clientNamespaced .Get (GetCtx (), client .ObjectKeyFromObject (ks ), ks )
337+ require .NoError (t , err )
338+
339+ assertKonnectEntityProgrammed (collect , ks )
340+ assert .NotEmpty (collect , ks .GetKonnectID ())
341+ serviceKonnectID = ks .GetKonnectID ()
342+ }, testutils .ObjectUpdateTimeout , testutils .ObjectUpdateTick ,
343+ "Did not see KongService set Konnect ID and Programmed condition to True" ,
344+ )
345+
346+ t .Log ("Creating a plugin by SDK attached to the service for adopting" )
347+ resp , err = sdk .GetPluginSDK ().CreatePlugin (
348+ GetCtx (),
349+ cpKonnectID ,
350+ sdkkonnectcomp.Plugin {
351+ Name : "response-transformer" ,
352+ Config : map [string ]any {
353+ "add" : map [string ][]string {
354+ "headers" : {"X-Kong-Test:test" },
355+ },
356+ },
357+ Service : & sdkkonnectcomp.PluginService {
358+ ID : lo .ToPtr (serviceKonnectID ),
359+ },
360+ },
361+ )
362+ require .NoError (t , err )
363+ require .NoError (t , err )
364+ require .NotNil (t , resp , "Should get a non-nil response for creating a plugin" )
365+ require .NotNil (t , resp .Plugin , "Should get a non-nil plugin in the response" )
366+ serviceResponseTransformerPlugin := resp .Plugin
367+ require .NotNil (t , serviceResponseTransformerPlugin .ID , "Should receive a non-nil plugin ID" )
368+
369+ buf , err = json .Marshal (serviceResponseTransformerPlugin .Config )
370+ require .NoError (t , err , "Should marshal plugin configuration in JSON successfully" )
371+
372+ t .Log ("Creating a KongPlugin and a KongPluginBinding for adopting the plugin" )
373+ kongPluginResponseTransformer := & configurationv1.KongPlugin {
374+ ObjectMeta : metav1.ObjectMeta {
375+ Namespace : ns .Name ,
376+ Name : "kongplugin-service-response-transformer" ,
377+ },
378+ PluginName : "response-transformer" ,
379+ Config : apiextensionsv1.JSON {
380+ Raw : buf ,
381+ },
382+ }
383+ require .NoError (t , clientNamespaced .Create (GetCtx (), kongPluginResponseTransformer ))
384+ t .Cleanup (deleteObjectAndWaitForDeletionFn (t , kongPluginResponseTransformer .DeepCopy ()))
385+
386+ kpbService := deploy .KongPluginBinding (t , GetCtx (), clientNamespaced , & configurationv1alpha1.KongPluginBinding {
387+ Spec : configurationv1alpha1.KongPluginBindingSpec {
388+ PluginReference : configurationv1alpha1.PluginRef {
389+ Name : kongPluginResponseTransformer .Name ,
390+ },
391+ Adopt : & commonv1alpha1.AdoptOptions {
392+ From : commonv1alpha1 .AdoptSourceKonnect ,
393+ Mode : commonv1alpha1 .AdoptModeOverride ,
394+ Konnect : & commonv1alpha1.AdoptKonnectOptions {
395+ ID : * serviceResponseTransformerPlugin .ID ,
396+ },
397+ },
398+ Scope : configurationv1alpha1 .KongPluginBindingScopeOnlyTargets ,
399+ Targets : & configurationv1alpha1.KongPluginBindingTargets {
400+ ServiceReference : & configurationv1alpha1.TargetRefWithGroupKind {
401+ Name : ks .Name ,
402+ Kind : "KongService" ,
403+ Group : configurationv1alpha1 .GroupVersion .Group ,
404+ },
405+ },
406+ },
407+ }, deploy .WithKonnectNamespacedRefControlPlaneRef (cp ))
408+ t .Cleanup (deleteObjectAndWaitForDeletionFn (t , kpbService .DeepCopy ()))
409+
410+ t .Log ("Waiting for KongPluginBinding to be programmed and set Konnect ID" )
411+ require .EventuallyWithT (t , func (collect * assert.CollectT ) {
412+ err := clientNamespaced .Get (GetCtx (), client .ObjectKeyFromObject (kpbService ), kpbService )
413+ require .NoError (t , err )
414+
415+ assertKonnectEntityProgrammed (collect , kpbService )
416+ assert .Equalf (collect , * serviceResponseTransformerPlugin .ID , kpbService .GetKonnectID (),
417+ "KongPluginBinding should set Konnect ID %s as the adopted plugin in status" ,
418+ * serviceResponseTransformerPlugin .ID ,
419+ )
420+ }, testutils .ObjectUpdateTimeout , testutils .ObjectUpdateTick ,
421+ "Did not see KongPluginBinding set Konnect ID and Programmed condition to True" ,
422+ )
423+ }
0 commit comments