@@ -2,22 +2,31 @@ package integration
22
33import (
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
135270func 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
150285func 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