Skip to content

Commit 3e57ee9

Browse files
committed
test with adding dataplane using the KonnectExtension
1 parent d6031bd commit 3e57ee9

2 files changed

Lines changed: 161 additions & 26 deletions

File tree

test/helpers/deploy/deploy_resources.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ func WithKonnectConfiguration[T ObjectSupportingKonnectConfiguration](
10761076
case *konnectv1alpha1.KonnectGatewayControlPlane:
10771077
o.Spec.KonnectConfiguration = konnectConfiguration
10781078
case *konnectv1alpha1.KonnectExtension:
1079-
o.Spec.KonnectConfiguration = lo.ToPtr(konnectConfiguration)
1079+
o.Spec.Konnect.Configuration = lo.ToPtr(konnectConfiguration)
10801080
case *konnectv1alpha1.KonnectCloudGatewayNetwork:
10811081
o.Spec.KonnectConfiguration = konnectConfiguration
10821082
}

test/integration/test_konnect_extension.go

Lines changed: 160 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,31 @@ package integration
22

33
import (
44
"fmt"
5+
"net/http"
56
"testing"
7+
"time"
68

79
"github.com/google/uuid"
10+
"github.com/kong/kubernetes-testing-framework/pkg/utils/kubernetes/generators"
811
"github.com/samber/lo"
912
"github.com/stretchr/testify/assert"
1013
"github.com/stretchr/testify/require"
1114
corev1 "k8s.io/api/core/v1"
12-
"k8s.io/apimachinery/pkg/types"
15+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16+
k8stypes "k8s.io/apimachinery/pkg/types"
1317
"sigs.k8s.io/controller-runtime/pkg/client"
1418

19+
"github.com/kong/gateway-operator/pkg/consts"
1520
testutils "github.com/kong/gateway-operator/pkg/utils/test"
1621
"github.com/kong/gateway-operator/test"
1722
"github.com/kong/gateway-operator/test/helpers"
23+
"github.com/kong/gateway-operator/test/helpers/certificate"
1824
"github.com/kong/gateway-operator/test/helpers/deploy"
1925

2026
kcfgconsts "github.com/kong/kubernetes-configuration/api/common/consts"
27+
commonv1alpha1 "github.com/kong/kubernetes-configuration/api/common/v1alpha1"
28+
configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
29+
operatorv1beta1 "github.com/kong/kubernetes-configuration/api/gateway-operator/v1beta1"
2130
konnectv1alpha1 "github.com/kong/kubernetes-configuration/api/konnect/v1alpha1"
2231
)
2332

@@ -50,23 +59,61 @@ func TestKonnectExtension(t *testing.T) {
5059

5160
t.Logf("Waiting for Konnect ID to be assigned to ControlPlane %s/%s", cp.Namespace, cp.Name)
5261
require.EventuallyWithT(t, func(t *assert.CollectT) {
53-
err := GetClients().MgrClient.Get(GetCtx(), types.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}, cp)
62+
err := GetClients().MgrClient.Get(GetCtx(), k8stypes.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}, cp)
5463
require.NoError(t, err)
5564
assertKonnectEntityProgrammed(t, cp)
5665
}, testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
5766

67+
// Order of deleting objects with finalizers:
68+
// KongRoute & KongService -> DataPlane -> KonnectExtension -> Secret -> KonnectGatewayControlPlane.
69+
// The first object deleted by calling `deleteObjectAndWaitForDeletionFn` will be deleted last when added by `CleanUp`,
70+
// so the order of calling the deleting function should be a reverse of the order above.
71+
// After they are all deleted, the namespace can be deleted in the final clean up.
72+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, cp.DeepCopy()))
73+
5874
// Create a secret used as dataplane certificate for the KonnectExtension.
59-
caCert := helpers.CreateCA(t)
75+
76+
cert, key := certificate.MustGenerateSelfSignedCertPEMFormat()
6077

6178
dpCert1 := deploy.Secret(
6279
t, ctx, clientNamespaced,
63-
helpers.TLSSecretData(t, caCert,
64-
helpers.CreateCert(t,
65-
fmt.Sprintf("*.test-konnect-extension.%s.svc", ns.Name),
66-
caCert.Cert, caCert.Key),
67-
),
80+
map[string][]byte{
81+
consts.TLSCRT: cert,
82+
consts.TLSKey: key,
83+
},
6884
deploy.WithLabel("konghq.com/konnect-dp-cert", "true"),
6985
)
86+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, dpCert1.DeepCopy()))
87+
88+
t.Log("deploying backend deployment (httpbin) of HTTPRoute")
89+
container := generators.NewContainer("httpbin", testutils.HTTPBinImage, 80)
90+
deployment := generators.NewDeploymentForContainer(container)
91+
require.NoError(t, clientNamespaced.Create(ctx, deployment))
92+
93+
t.Logf("exposing deployment %s via service", deployment.Name)
94+
service := generators.NewServiceForDeployment(deployment, corev1.ServiceTypeClusterIP)
95+
require.NoError(t, clientNamespaced.Create(ctx, service))
96+
97+
t.Log("Creating a KongService and a KongRoute to the service")
98+
ks := deploy.KongService(t, ctx, clientNamespaced,
99+
deploy.WithKonnectNamespacedRefControlPlaneRef(cp),
100+
func(obj client.Object) {
101+
ks, ok := obj.(*configurationv1alpha1.KongService)
102+
require.True(t, ok)
103+
ks.Spec.KongServiceAPISpec = configurationv1alpha1.KongServiceAPISpec{
104+
Name: lo.ToPtr("httpbin"),
105+
URL: lo.ToPtr(fmt.Sprintf("http://%s.%s.svc.cluster.local/", service.Name, ns.Name)),
106+
Host: fmt.Sprintf("%s.%s.svc.cluster.local", service.Name, ns.Name),
107+
}
108+
},
109+
)
110+
t.Logf("Waiting for KongService to be updated with Konnect ID")
111+
require.EventuallyWithT(t, func(t *assert.CollectT) {
112+
err := GetClients().MgrClient.Get(GetCtx(), k8stypes.NamespacedName{Name: ks.Name, Namespace: ks.Namespace}, ks)
113+
require.NoError(t, err)
114+
assertKonnectEntityProgrammed(t, ks)
115+
}, testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
116+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, ks))
70117

71118
// Tests on KonnectExtension with KonnectID control plane ref.
72119
t.Logf("Creating a KonnectExtension with KonnectID typed control plane ref")
@@ -80,6 +127,7 @@ func TestKonnectExtension(t *testing.T) {
80127
deploy.WithKonnectIDControlPlaneRef(cp),
81128
setKonnectExtensionDPCertSecretRef(t, dpCert1),
82129
)
130+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, keWithKonnectIDCPRef.DeepCopy()))
83131

84132
t.Logf("Waiting for KonnectExtension %s/%s to have expected conditions set to True", keWithKonnectIDCPRef.Namespace, keWithKonnectIDCPRef.Name)
85133
require.EventuallyWithT(t, func(t *assert.CollectT) {
@@ -92,23 +140,119 @@ func TestKonnectExtension(t *testing.T) {
92140
checkKonnectExtensionStatus(keWithKonnectIDCPRef, cp.GetKonnectID(), dpCert1.Name),
93141
testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
94142

143+
// Create a DataPlane using the KonnectExension.
144+
t.Logf("Creating a DataPlane using the KonnectExtension %s/%s", keWithKonnectIDCPRef.Namespace, keWithKonnectIDCPRef.Name)
145+
dp := &operatorv1beta1.DataPlane{
146+
ObjectMeta: metav1.ObjectMeta{
147+
Namespace: ns.Name,
148+
Name: "test-konnect-extension-dp-1",
149+
},
150+
Spec: operatorv1beta1.DataPlaneSpec{
151+
DataPlaneOptions: operatorv1beta1.DataPlaneOptions{
152+
Deployment: operatorv1beta1.DataPlaneDeploymentOptions{
153+
DeploymentOptions: operatorv1beta1.DeploymentOptions{
154+
Replicas: lo.ToPtr(int32(1)),
155+
PodTemplateSpec: &corev1.PodTemplateSpec{
156+
Spec: corev1.PodSpec{
157+
Containers: []corev1.Container{
158+
{
159+
Name: consts.DataPlaneProxyContainerName,
160+
Image: consts.DefaultDataPlaneEnterpriseImage,
161+
Env: []corev1.EnvVar{
162+
{
163+
Name: "KONG_LOG_LEVEL",
164+
Value: "debug",
165+
},
166+
},
167+
},
168+
},
169+
},
170+
},
171+
},
172+
},
173+
Extensions: []commonv1alpha1.ExtensionRef{
174+
{
175+
Group: konnectv1alpha1.GroupVersion.Group,
176+
Kind: "KonnectExtension",
177+
NamespacedRef: commonv1alpha1.NamespacedRef{
178+
Name: keWithKonnectIDCPRef.Name,
179+
},
180+
},
181+
},
182+
},
183+
},
184+
}
185+
require.NoError(t, clientNamespaced.Create(ctx, dp))
186+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, dp))
187+
188+
dpName := k8stypes.NamespacedName{
189+
Namespace: dp.Namespace,
190+
Name: dp.Name,
191+
}
192+
193+
t.Log("verifying dataplane gets marked provisioned")
194+
require.Eventually(t, testutils.DataPlaneIsReady(t, GetCtx(), dpName, GetClients().OperatorClient), waitTime, tickTime)
195+
196+
t.Logf("verifying dataplane %s has ingress service", dpName)
197+
var dpIngressService corev1.Service
198+
require.Eventually(t, testutils.DataPlaneHasActiveService(t, GetCtx(), dpName, &dpIngressService, clients, client.MatchingLabels{
199+
consts.GatewayOperatorManagedByLabel: consts.DataPlaneManagedLabelValue,
200+
consts.DataPlaneServiceTypeLabel: string(consts.DataPlaneIngressServiceLabelValue),
201+
}), waitTime, tickTime)
202+
203+
t.Log("verifying dataplane services receive IP addresses")
204+
require.Eventually(t, func() bool {
205+
err := clientNamespaced.Get(ctx, k8stypes.NamespacedName{
206+
Namespace: dpIngressService.Namespace,
207+
Name: dpIngressService.Name,
208+
}, &dpIngressService)
209+
require.NoError(t, err)
210+
return len(dpIngressService.Status.LoadBalancer.Ingress) > 0
211+
}, waitTime, tickTime)
212+
dpIngressIP := dpIngressService.Status.LoadBalancer.Ingress[0].IP
213+
require.Eventuallyf(t, Expect404WithNoRouteFunc(t, GetCtx(), "http://"+dpIngressIP), waitTime, tickTime,
214+
"Should receive 'No Route' response from dataplane's ingress service IP %s", dpIngressIP)
215+
216+
kr := deploy.KongRouteAttachedToService(t, ctx, clientNamespaced, ks)
217+
t.Logf("Waiting for KongRoute to be updated with Konnect ID")
218+
require.EventuallyWithT(t, func(t *assert.CollectT) {
219+
err := GetClients().MgrClient.Get(GetCtx(), k8stypes.NamespacedName{Name: kr.Name, Namespace: kr.Namespace}, kr)
220+
require.NoError(t, err)
221+
222+
assertKonnectEntityProgrammed(t, kr)
223+
}, testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
224+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, kr))
225+
226+
t.Log("route to / path of service httpbin should receive a 200 OK response")
227+
httpClient, err := helpers.CreateHTTPClient(nil, "")
228+
require.NoError(t, err)
229+
const routeAccessTimeout = 3 * time.Minute
230+
request := helpers.MustBuildRequest(t, GetCtx(), http.MethodGet, "http://"+dpIngressIP+"/test", "")
231+
require.Eventually(
232+
t,
233+
testutils.GetResponseBodyContains(t, clients, httpClient, request, "<title>httpbin.org</title>"),
234+
routeAccessTimeout,
235+
time.Second,
236+
)
237+
95238
// Tests on KonnectExtension with KonnectNamespacedRef control plane ref.
96239
dpCert2 := deploy.Secret(
97240
t, ctx, clientNamespaced,
98-
helpers.TLSSecretData(t, caCert,
99-
helpers.CreateCert(t,
100-
fmt.Sprintf("*.test-konnect-extension.%s.svc", ns.Name),
101-
caCert.Cert, caCert.Key),
102-
),
241+
map[string][]byte{
242+
consts.TLSCRT: cert,
243+
consts.TLSKey: key,
244+
},
103245
deploy.WithLabel("konghq.com/konnect-dp-cert", "true"),
104246
)
247+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, dpCert2.DeepCopy()))
105248
t.Logf("Creating a KonnectExtension with KonnectNamespacedRef typed control plane ref")
106249
keWithNamespacedCPRef := deploy.KonnectExtension(
107250
t, ctx,
108251
clientNamespaced,
109252
deploy.WithKonnectNamespacedRefControlPlaneRef(cp),
110253
setKonnectExtensionDPCertSecretRef(t, dpCert2),
111254
)
255+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, keWithNamespacedCPRef.DeepCopy()))
112256

113257
t.Logf("Waiting for KonnectExtension %s/%s to have expected conditions set to True", keWithNamespacedCPRef.Namespace, keWithNamespacedCPRef.Name)
114258
require.EventuallyWithT(t, func(t *assert.CollectT) {
@@ -121,22 +265,13 @@ func TestKonnectExtension(t *testing.T) {
121265
checkKonnectExtensionStatus(keWithNamespacedCPRef, cp.GetKonnectID(), dpCert2.Name),
122266
testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
123267

124-
// Order of deleting objects with finalizers:
125-
// KonnectExtension -> Secret -> KonnectGatewayControlPlane.
126-
// After they are all deleted, the namespace can be deleted in the final clean up.
127-
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, cp.DeepCopy()))
128-
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, dpCert1.DeepCopy()))
129-
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, dpCert2.DeepCopy()))
130-
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, keWithKonnectIDCPRef.DeepCopy()))
131-
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, keWithNamespacedCPRef.DeepCopy()))
132-
133268
}
134269

135270
func setKonnectExtensionDPCertSecretRef(t *testing.T, s *corev1.Secret) deploy.ObjOption {
136271
return func(obj client.Object) {
137272
ke, ok := obj.(*konnectv1alpha1.KonnectExtension)
138273
require.True(t, ok)
139-
ke.Spec.DataPlaneClientAuth = &konnectv1alpha1.DataPlaneClientAuth{
274+
ke.Spec.ClientAuth = &konnectv1alpha1.KonnectExtensionClientAuth{
140275
CertificateSecret: konnectv1alpha1.CertificateSecret{
141276
Provisioning: lo.ToPtr(konnectv1alpha1.ManualSecretProvisioning),
142277
CertificateSecretRef: &konnectv1alpha1.SecretRef{
@@ -148,7 +283,7 @@ func setKonnectExtensionDPCertSecretRef(t *testing.T, s *corev1.Secret) deploy.O
148283
}
149284

150285
func checkKonnectExtensionConditions(t *assert.CollectT, ke *konnectv1alpha1.KonnectExtension) (bool, string) {
151-
err := GetClients().MgrClient.Get(GetCtx(), types.NamespacedName{Name: ke.Name, Namespace: ke.Namespace}, ke)
286+
err := GetClients().MgrClient.Get(GetCtx(), k8stypes.NamespacedName{Name: ke.Name, Namespace: ke.Namespace}, ke)
152287
require.NoError(t, err)
153288

154289
checkConditionTypes := []kcfgconsts.ConditionType{
@@ -165,7 +300,7 @@ func checkKonnectExtensionStatus(
165300
expectedDPCertificateSecretName string,
166301
) func(t *assert.CollectT) {
167302
return func(t *assert.CollectT) {
168-
err := GetClients().MgrClient.Get(GetCtx(), types.NamespacedName{Name: ke.Name, Namespace: ke.Namespace}, ke)
303+
err := GetClients().MgrClient.Get(GetCtx(), k8stypes.NamespacedName{Name: ke.Name, Namespace: ke.Namespace}, ke)
169304
require.NoError(t, err)
170305
// Check Konnect control plane ID
171306
require.NotNil(t, ke.Status.Konnect, "status.konnect should be present")

0 commit comments

Comments
 (0)