Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 9 additions & 19 deletions test/envtest/kongpluginbinding_adoption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
apiwatch "k8s.io/apimachinery/pkg/watch"
"sigs.k8s.io/controller-runtime/pkg/client"

commonv1alpha1 "github.com/kong/kong-operator/api/common/v1alpha1"
configurationv1alpha1 "github.com/kong/kong-operator/api/configuration/v1alpha1"
konnectv1alpha1 "github.com/kong/kong-operator/api/konnect/v1alpha1"
"github.com/kong/kong-operator/controller/konnect"
Expand Down Expand Up @@ -85,10 +86,10 @@ func TestKongPluginBindingAdoption(t *testing.T) {
WithPluginRef(proxyCacheKongPlugin.Name).
WithScope(configurationv1alpha1.KongPluginBindingScopeGlobalInControlPlane).
Build(),
setKongPluginBindingAdoptOptions(t, pluginID),
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongPluginBinding](commonv1alpha1.AdoptModeOverride, pluginID),
)

t.Log("Waiting for KongPluginBinding being Programmed and set Konnect ID")
t.Logf("Waiting for KongPluginBinding %s/%s being Programmed and set Konnect ID", ns.Name, kpbGlobal.Name)
watchFor(t, ctx, w,
apiwatch.Modified,
func(kpb *configurationv1alpha1.KongPluginBinding) bool {
Expand All @@ -100,7 +101,7 @@ func TestKongPluginBindingAdoption(t *testing.T) {
t.Log("Setting up SDK expectation for plugin deletion")
sdk.PluginSDK.EXPECT().DeletePlugin(mock.Anything, cp.GetKonnectID(), pluginID).Return(nil, nil)

t.Log("Deleting the KongPluginBinding")
t.Logf("Deleting the KongPluginBinding %s/%s", ns.Name, kpbGlobal.Name)
require.NoError(t, clientNamespaced.Delete(ctx, kpbGlobal))
eventually.WaitForObjectToNotExist(t, ctx, cl, kpbGlobal, waitTime, tickTime)
})
Expand Down Expand Up @@ -141,10 +142,10 @@ func TestKongPluginBindingAdoption(t *testing.T) {
WithPluginRef(proxyCacheKongPlugin.Name).
WithServiceTarget(kongService.Name).
Build(),
setKongPluginBindingAdoptOptions(t, pluginID),
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongPluginBinding](commonv1alpha1.AdoptModeOverride, pluginID),
)

t.Log("Waiting for KongPluginBinding being Programmed and set Konnect ID")
t.Logf("Waiting for KongPluginBinding %s/%s being Programmed and set Konnect ID", ns.Name, kpbService.Name)
watchFor(t, ctx, w,
apiwatch.Modified,
func(kpb *configurationv1alpha1.KongPluginBinding) bool {
Expand All @@ -156,7 +157,7 @@ func TestKongPluginBindingAdoption(t *testing.T) {
t.Log("Setting up SDK expectation for plugin deletion")
sdk.PluginSDK.EXPECT().DeletePlugin(mock.Anything, cp.GetKonnectID(), pluginID).Return(nil, nil)

t.Log("Deleting the KongPluginBinding")
t.Logf("Deleting the KongPluginBinding %s/%s", ns.Name, kpbService.Name)
require.NoError(t, clientNamespaced.Delete(ctx, kpbService))
eventually.WaitForObjectToNotExist(t, ctx, cl, kpbService, waitTime, tickTime)
})
Expand All @@ -183,10 +184,10 @@ func TestKongPluginBindingAdoption(t *testing.T) {
WithPluginRef("non-exist-plugin").
WithScope(configurationv1alpha1.KongPluginBindingScopeGlobalInControlPlane).
Build(),
setKongPluginBindingAdoptOptions(t, pluginID),
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongPluginBinding](commonv1alpha1.AdoptModeOverride, pluginID),
)

t.Log("Waiting for the KongPluginBinding to be marked as not programmed and not adopted")
t.Logf("Waiting for the KongPluginBinding %s/%s to be marked as not programmed and not adopted", ns.Name, kpbGlobal.Name)
watchFor(t, ctx, w,
apiwatch.Modified,
func(kpb *configurationv1alpha1.KongPluginBinding) bool {
Expand All @@ -198,14 +199,3 @@ func TestKongPluginBindingAdoption(t *testing.T) {
)
})
}

// setKongPluginBindingAdoptOptions returns a function to set the adopt options on a KongPluginBinding
// to adopt a plugin from the existing one with the given ID.
// TODO: Use a more generic way to set adopt options: https://github.com/Kong/kong-operator/issues/2660
func setKongPluginBindingAdoptOptions(t *testing.T, id string) func(obj client.Object) {
return func(obj client.Object) {
kpb, ok := obj.(*configurationv1alpha1.KongPluginBinding)
require.True(t, ok)
kpb.Spec.Adopt = deploy.AdoptOptionsOverrideModeWithID(id)
}
}
149 changes: 149 additions & 0 deletions test/envtest/konnect_entities_kongroute_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package envtest

import (
"fmt"
"slices"
"testing"

sdkkonnectcomp "github.com/Kong/sdk-konnect-go/models/components"
sdkkonnectops "github.com/Kong/sdk-konnect-go/models/operations"
"github.com/google/uuid"
"github.com/samber/lo"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apiwatch "k8s.io/apimachinery/pkg/watch"
"sigs.k8s.io/controller-runtime/pkg/client"

commonv1alpha1 "github.com/kong/kong-operator/api/common/v1alpha1"
configurationv1alpha1 "github.com/kong/kong-operator/api/configuration/v1alpha1"
konnectv1alpha1 "github.com/kong/kong-operator/api/konnect/v1alpha1"
"github.com/kong/kong-operator/controller/konnect"
"github.com/kong/kong-operator/modules/manager/logging"
"github.com/kong/kong-operator/modules/manager/scheme"
Expand Down Expand Up @@ -143,4 +148,148 @@ func TestKongRoute(t *testing.T) {

eventually.WaitForObjectToNotExist(t, ctx, cl, createdRoute, waitTime, tickTime)
})

t.Run("Adopting a route attached to a service", func(t *testing.T) {
routeID := uuid.NewString()
routeName := "test-adoption-" + uuid.NewString()[:8]

w := setupWatch[configurationv1alpha1.KongRouteList](t, ctx, cl, client.InNamespace(ns.Name))

t.Log("Setting up SDK expectations for getting and updating routes")
sdk.RoutesSDK.EXPECT().GetRoute(
mock.Anything,
routeID,
cp.GetKonnectID(),
).Return(&sdkkonnectops.GetRouteResponse{
Route: &sdkkonnectcomp.Route{
Type: sdkkonnectcomp.RouteTypeRouteJSON,
RouteJSON: &sdkkonnectcomp.RouteJSON{
ID: &routeID,
Name: &routeName,
Paths: []string{"/path"},
Service: &sdkkonnectcomp.RouteJSONService{
ID: lo.ToPtr(svc.GetKonnectID()),
},
},
},
}, nil)
sdk.RoutesSDK.EXPECT().UpsertRoute(
mock.Anything,
mock.MatchedBy(
func(req sdkkonnectops.UpsertRouteRequest) bool {
return req.RouteID == routeID
},
),
).Return(nil, nil)

t.Logf("Creating a KongRoute to adopt the existing route (ID: %s)", routeID)
createdRoute := deploy.KongRoute(t, ctx, clientNamespaced,
deploy.WithNamespacedKongServiceRef(svc),
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongRoute](commonv1alpha1.AdoptModeOverride, routeID),
)

t.Logf("Waiting for the KongRoute %s/%s to get KonnectID and marked as programmed", ns.Name, createdRoute.Name)
watchFor(t, ctx, w, apiwatch.Modified, func(r *configurationv1alpha1.KongRoute) bool {
return r.Name == createdRoute.Name && r.GetKonnectID() == routeID && k8sutils.IsProgrammed(r)
},
fmt.Sprintf("KongRoute did not get programmed and set KonnectID to %s", routeID),
)

t.Log("Setting up SDK expectations for route deletion")
sdk.RoutesSDK.EXPECT().DeleteRoute(mock.Anything, cp.GetKonnectID(), routeID).Return(nil, nil)

t.Logf("Deleting KongRoute %s/%s", ns.Name, createdRoute.Name)
require.NoError(t, clientNamespaced.Delete(ctx, createdRoute))

eventually.WaitForObjectToNotExist(t, ctx, cl, createdRoute, waitTime, tickTime)
})

t.Run("Adopting a standalone route", func(t *testing.T) {
routeID := uuid.NewString()
routeName := "test-adoption-" + uuid.NewString()[:8]

w := setupWatch[configurationv1alpha1.KongRouteList](t, ctx, cl, client.InNamespace(ns.Name))

t.Log("Setting up SDK expectations for getting and updating routes")
sdk.RoutesSDK.EXPECT().GetRoute(
mock.Anything,
routeID,
cp.GetKonnectID(),
).Return(&sdkkonnectops.GetRouteResponse{
Route: &sdkkonnectcomp.Route{
Type: sdkkonnectcomp.RouteTypeRouteJSON,
RouteJSON: &sdkkonnectcomp.RouteJSON{
ID: &routeID,
Name: &routeName,
Paths: []string{"/path"},
},
},
}, nil)
sdk.RoutesSDK.EXPECT().UpsertRoute(
mock.Anything,
mock.MatchedBy(
func(req sdkkonnectops.UpsertRouteRequest) bool {
return req.RouteID == routeID
},
),
).Return(nil, nil)

t.Logf("Creating a KongRoute to adopt the existing route (ID: %s)", routeID)
createdRoute := deploy.KongRoute(t, ctx, clientNamespaced,
deploy.WithKonnectNamespacedRefControlPlaneRef(cp),
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongRoute](commonv1alpha1.AdoptModeOverride, routeID),
)

t.Logf("Waiting for the KongRoute %s/%s to get KonnectID and marked as programmed", ns.Name, createdRoute.Name)
watchFor(t, ctx, w, apiwatch.Modified, func(r *configurationv1alpha1.KongRoute) bool {
return r.Name == createdRoute.Name && r.GetKonnectID() == routeID && k8sutils.IsProgrammed(r)
},
fmt.Sprintf("KongRoute did not get programmed and set KonnectID to %s", routeID),
)
})

t.Run("adopting a route with not matched service should fail", func(t *testing.T) {
routeID := uuid.NewString()
routeName := "test-adoption-" + uuid.NewString()[:8]

w := setupWatch[configurationv1alpha1.KongRouteList](t, ctx, cl, client.InNamespace(ns.Name))

t.Log("Setting up SDK expectations for getting routes")
sdk.RoutesSDK.EXPECT().GetRoute(
mock.Anything,
routeID,
cp.GetKonnectID(),
).Return(&sdkkonnectops.GetRouteResponse{
Route: &sdkkonnectcomp.Route{
Type: sdkkonnectcomp.RouteTypeRouteJSON,
RouteJSON: &sdkkonnectcomp.RouteJSON{
ID: &routeID,
Name: &routeName,
Paths: []string{"/path"},
Service: &sdkkonnectcomp.RouteJSONService{
ID: lo.ToPtr("another-service-id"),
},
},
},
}, nil)

t.Logf("Creating a KongRoute to adopt the existing route (ID: %s)", routeID)
createdRoute := deploy.KongRoute(t, ctx, clientNamespaced,
deploy.WithNamespacedKongServiceRef(svc),
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongRoute](commonv1alpha1.AdoptModeOverride, routeID),
)

t.Logf("Waiting for the KongRoute %s/%s to be marked as not programmed and not adopted", ns.Name, createdRoute.Name)
watchFor(t, ctx, w, apiwatch.Modified, func(r *configurationv1alpha1.KongRoute) bool {
return r.Name == createdRoute.Name &&
conditionsContainProgrammedFalse(r.GetConditions()) &&
lo.ContainsBy(r.GetConditions(), func(c metav1.Condition) bool {
return c.Type == konnectv1alpha1.KonnectEntityAdoptedConditionType &&
c.Status == metav1.ConditionFalse
})
},
fmt.Sprintf("KongRoute did not get programmed and set KonnectID to %s", routeID),
)

})
}
50 changes: 10 additions & 40 deletions test/envtest/konnect_entities_kongservice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,20 +447,10 @@ func TestKongService(t *testing.T) {

t.Log("Creating a KongService to adopt the existing service")
createdService := deploy.KongService(t, t.Context(), clientNamespaced, deploy.WithKonnectNamespacedRefControlPlaneRef(cp),
func(obj client.Object) {
ks, ok := obj.(*configurationv1alpha1.KongService)
require.True(t, ok)
ks.Spec.URL = lo.ToPtr("https://example.com/example")
ks.Spec.Adopt = &commonv1alpha1.AdoptOptions{
From: commonv1alpha1.AdoptSourceKonnect,
Mode: commonv1alpha1.AdoptModeOverride,
Konnect: &commonv1alpha1.AdoptKonnectOptions{
ID: serviceKonnectID,
},
}
})
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongService](commonv1alpha1.AdoptModeOverride, serviceKonnectID),
)

t.Log("Waiting for the service to be programmed and get Konnect ID")
t.Logf("Waiting for the KongService %s/%s to be programmed and get Konnect ID", ns.Name, createdService.Name)
watchFor(t, t.Context(), w, apiwatch.Modified, func(ks *configurationv1alpha1.KongService) bool {
return ks.Name == createdService.Name &&
ks.GetKonnectID() == serviceKonnectID && k8sutils.IsProgrammed(ks)
Expand All @@ -475,7 +465,7 @@ func TestKongService(t *testing.T) {
serviceKonnectID,
).Return(&sdkkonnectops.DeleteServiceResponse{}, nil)

t.Log("Deleting the KongService")
t.Logf("Deleting the KongService %s/%s", ns.Name, createdService.Name)
require.NoError(t, clientNamespaced.Delete(t.Context(), createdService))

t.Log("Waiting for the SDK's DeleteService to be called")
Expand All @@ -502,20 +492,10 @@ func TestKongService(t *testing.T) {

t.Log("Creating a KongService to adopt the existing service")
createdService := deploy.KongService(t, t.Context(), clientNamespaced, deploy.WithKonnectNamespacedRefControlPlaneRef(cp),
func(obj client.Object) {
ks, ok := obj.(*configurationv1alpha1.KongService)
require.True(t, ok)
ks.Spec.URL = lo.ToPtr("https://example.com/example")
ks.Spec.Adopt = &commonv1alpha1.AdoptOptions{
From: commonv1alpha1.AdoptSourceKonnect,
Mode: commonv1alpha1.AdoptModeOverride,
Konnect: &commonv1alpha1.AdoptKonnectOptions{
ID: serviceKonnectID,
},
}
})
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongService](commonv1alpha1.AdoptModeOverride, serviceKonnectID),
)

t.Log("Waiting for the KongService to be marked as not programmed")
t.Logf("Waiting for the KongService %s/%s to be marked as not programmed", ns.Name, createdService.Name)
watchFor(t, t.Context(), w, apiwatch.Modified, func(ks *configurationv1alpha1.KongService) bool {
return ks.Name == createdService.Name &&
conditionsContainProgrammedFalse(ks.GetConditions()) &&
Expand Down Expand Up @@ -555,20 +535,10 @@ func TestKongService(t *testing.T) {

t.Log("Creating a KongService to adopt the existing service")
createdService := deploy.KongService(t, t.Context(), clientNamespaced, deploy.WithKonnectNamespacedRefControlPlaneRef(cp),
func(obj client.Object) {
ks, ok := obj.(*configurationv1alpha1.KongService)
require.True(t, ok)
ks.Spec.URL = lo.ToPtr("https://example.com/example")
ks.Spec.Adopt = &commonv1alpha1.AdoptOptions{
From: commonv1alpha1.AdoptSourceKonnect,
Mode: commonv1alpha1.AdoptModeOverride,
Konnect: &commonv1alpha1.AdoptKonnectOptions{
ID: serviceKonnectID,
},
}
})
deploy.WithKonnectAdoptOptions[*configurationv1alpha1.KongService](commonv1alpha1.AdoptModeOverride, serviceKonnectID),
)

t.Log("Waiting for the KongService to be marked as not programmed")
t.Logf("Waiting for the KongService %s/%s to be marked as not programmed", ns.Name, createdService.Name)
watchFor(t, t.Context(), w, apiwatch.Modified, func(ks *configurationv1alpha1.KongService) bool {
return ks.Name == createdService.Name &&
conditionsContainProgrammedFalse(ks.GetConditions()) &&
Expand Down
Loading
Loading