Skip to content

Commit 1ae3c8e

Browse files
committed
test: add integration tests for KonnectExtension
1 parent 3dc74aa commit 1ae3c8e

3 files changed

Lines changed: 199 additions & 0 deletions

File tree

test/helpers/deploy/deploy_resources.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,57 @@ func KongDataPlaneClientCertificateAttachedToCP(
10101010
return cert
10111011
}
10121012

1013+
// KonnectExtension deploys a KonnectExtension.
1014+
func KonnectExtension(
1015+
t *testing.T,
1016+
ctx context.Context,
1017+
cl client.Client,
1018+
opts ...ObjOption,
1019+
) *konnectv1alpha1.KonnectExtension {
1020+
t.Helper()
1021+
1022+
ke := &konnectv1alpha1.KonnectExtension{
1023+
ObjectMeta: metav1.ObjectMeta{
1024+
GenerateName: "konnect-extension-",
1025+
},
1026+
}
1027+
for _, opt := range opts {
1028+
opt(ke)
1029+
}
1030+
1031+
require.NoError(t, cl.Create(ctx, ke))
1032+
logObjectCreate(t, ke)
1033+
return ke
1034+
}
1035+
1036+
// KonnectExtensionWithAPIAuthRefAndCPID deploys a KonnectExtension attaching to control plane
1037+
// by the CP's ID and the API auth configuration to the Konnect server where the CP is in.
1038+
func KonnectExtensionWithAPIAuthRefAndCPID(
1039+
t *testing.T,
1040+
ctx context.Context,
1041+
cl client.Client,
1042+
apiAuth konnectv1alpha1.KonnectAPIAuthConfigurationRef,
1043+
cpID string,
1044+
opts ...ObjOption,
1045+
) *konnectv1alpha1.KonnectExtension {
1046+
opts = append(opts, func(obj client.Object) {
1047+
ke, ok := obj.(*konnectv1alpha1.KonnectExtension)
1048+
require.Truef(t, ok, "Expect object %s/%s to be a KonnectExtension, actual type %T",
1049+
obj.GetNamespace(), obj.GetName(), obj)
1050+
ke.Spec.KonnectConfiguration = &konnectv1alpha1.KonnectConfiguration{
1051+
APIAuthConfigurationRef: apiAuth,
1052+
}
1053+
ke.Spec.KonnectControlPlane.ControlPlaneRef = commonv1alpha1.ControlPlaneRef{
1054+
Type: commonv1alpha1.ControlPlaneRefKonnectID,
1055+
KonnectID: lo.ToPtr(cpID),
1056+
}
1057+
})
1058+
return KonnectExtension(
1059+
t, ctx, cl,
1060+
opts...,
1061+
)
1062+
}
1063+
10131064
func logObjectCreate[
10141065
T interface {
10151066
client.Object
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package integration
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
8+
"github.com/google/uuid"
9+
"github.com/samber/lo"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
corev1 "k8s.io/api/core/v1"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
"k8s.io/apimachinery/pkg/types"
15+
"sigs.k8s.io/controller-runtime/pkg/client"
16+
17+
testutils "github.com/kong/gateway-operator/pkg/utils/test"
18+
"github.com/kong/gateway-operator/test"
19+
"github.com/kong/gateway-operator/test/helpers"
20+
"github.com/kong/gateway-operator/test/helpers/deploy"
21+
22+
konnectv1alpha1 "github.com/kong/kubernetes-configuration/api/konnect/v1alpha1"
23+
)
24+
25+
func TestKonnectExtension(t *testing.T) {
26+
ns, _ := helpers.SetupTestEnv(t, GetCtx(), GetEnv())
27+
28+
// Let's generate a unique test ID that we can refer to in Konnect entities.
29+
// Using only the first 8 characters of the UUID to keep the ID short enough for Konnect to accept it as a part
30+
// of an entity name.
31+
testID := uuid.NewString()[:8]
32+
t.Logf("Running Konnect extensions test with ID: %s", testID)
33+
34+
// Create an APIAuth for test.
35+
clientNamespaced := client.NewNamespacedClient(GetClients().MgrClient, ns.Name)
36+
37+
authCfg := deploy.KonnectAPIAuthConfiguration(t, GetCtx(), clientNamespaced,
38+
deploy.WithTestIDLabel(testID),
39+
func(obj client.Object) {
40+
authCfg := obj.(*konnectv1alpha1.KonnectAPIAuthConfiguration)
41+
authCfg.Spec.Type = konnectv1alpha1.KonnectAPIAuthTypeToken
42+
authCfg.Spec.Token = test.KonnectAccessToken()
43+
authCfg.Spec.ServerURL = test.KonnectServerURL()
44+
},
45+
)
46+
47+
// Create a Konnect control plane for the KonnectExtension to attach to.
48+
cp := deploy.KonnectGatewayControlPlane(t, GetCtx(), clientNamespaced, authCfg,
49+
deploy.WithTestIDLabel(testID),
50+
)
51+
52+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, cp.DeepCopy()))
53+
54+
t.Logf("Waiting for Konnect ID to be assigned to ControlPlane %s/%s", cp.Namespace, cp.Name)
55+
require.EventuallyWithT(t, func(t *assert.CollectT) {
56+
err := GetClients().MgrClient.Get(GetCtx(), types.NamespacedName{Name: cp.Name, Namespace: cp.Namespace}, cp)
57+
require.NoError(t, err)
58+
assertKonnectEntityProgrammed(t, cp)
59+
}, testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
60+
61+
// Create a secret used as dataplane certificate for the KonnectExtension.
62+
s := deploy.Secret(
63+
t, ctx, clientNamespaced,
64+
// TODO: Fill real certificate data here after DP certifcates provisioning is done:
65+
// https://github.com/Kong/gateway-operator/issues/874
66+
map[string][]byte{},
67+
)
68+
// Create a KonnectExtension attaching to the CP by its ID.
69+
t.Logf("Creating a KonnectExtension and waiting for Konnect control plane ref resolved")
70+
ke := deploy.KonnectExtensionWithAPIAuthRefAndCPID(
71+
t, ctx, clientNamespaced,
72+
konnectv1alpha1.KonnectAPIAuthConfigurationRef{
73+
Name: authCfg.Name,
74+
},
75+
cp.GetKonnectID(),
76+
setKonnectExtensionDPCertSecretRef(t, s),
77+
)
78+
79+
t.Cleanup(deleteObjectAndWaitForDeletionFn(t, ke.DeepCopy()))
80+
81+
t.Logf("Waiting for KonnectExtension %s/%s to have expected conditions set to True", ke.Namespace, ke.Name)
82+
require.EventuallyWithT(t, func(t *assert.CollectT) {
83+
ok, msg := checkKonnectExtensionConditions(t, ke)
84+
assert.Truef(t, ok, "condition check failed: %s, conditions: %+v", msg, ke.Status.Conditions)
85+
}, testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
86+
87+
t.Logf("waiting for status.konnect and status.dataPlaneClientAuth to be set for KonnectExtension %s/%s", ke.Namespace, ke.Name)
88+
require.EventuallyWithT(t, func(t *assert.CollectT) {
89+
err := GetClients().MgrClient.Get(GetCtx(), types.NamespacedName{Name: ke.Name, Namespace: ke.Namespace}, ke)
90+
require.NoError(t, err)
91+
// Check Konnect control plane ID
92+
assert.NotNil(t, ke.Status.Konnect, "status.konnect should be present")
93+
assert.Equal(t, cp.GetKonnectID(), ke.Status.Konnect.ControlPlaneID, "Konnect control plane ID should be set in status")
94+
// Check dataplane client auth
95+
assert.NotNil(t, ke.Status.DataPlaneClientAuth, "status.dataPlaneClientAuth should be present")
96+
assert.NotNil(t, ke.Status.DataPlaneClientAuth.CertificateSecretRef, "status.dataPlaneClientAuth.certiifcateSecretRef should be present")
97+
assert.Equal(t, s.Name, ke.Status.DataPlaneClientAuth.CertificateSecretRef.Name,
98+
"status.dataPlaneClientAuth.certiifcateSecretRef should have the expected secret name")
99+
100+
}, testutils.ObjectUpdateTimeout, testutils.ObjectUpdateTick)
101+
102+
// TODO: Create DataPlanes using the KonnectExtension after DP certifcates provisioning is done:
103+
// https://github.com/Kong/gateway-operator/issues/874
104+
105+
}
106+
107+
func setKonnectExtensionDPCertSecretRef(t *testing.T, s *corev1.Secret) func(client.Object) {
108+
return func(obj client.Object) {
109+
ke, ok := obj.(*konnectv1alpha1.KonnectExtension)
110+
require.True(t, ok)
111+
ke.Spec.DataPlaneClientAuth = &konnectv1alpha1.DataPlaneClientAuth{
112+
CertificateSecret: konnectv1alpha1.CertificateSecret{
113+
Provisioning: lo.ToPtr(konnectv1alpha1.ManualSecretProvisioning),
114+
CertificateSecretRef: &konnectv1alpha1.SecretRef{
115+
Name: s.Name,
116+
},
117+
},
118+
}
119+
}
120+
}
121+
122+
func checkKonnectExtensionConditions(t *assert.CollectT, ke *konnectv1alpha1.KonnectExtension) (bool, string) {
123+
err := GetClients().MgrClient.Get(GetCtx(), types.NamespacedName{Name: ke.Name, Namespace: ke.Namespace}, ke)
124+
require.NoError(t, err)
125+
126+
checkConditionTypes := []string{
127+
konnectv1alpha1.ControlPlaneRefValidConditionType,
128+
konnectv1alpha1.DataPlaneCertificateProvisionedConditionType,
129+
konnectv1alpha1.KonnectExtensionReadyConditionType,
130+
}
131+
failedConditionTypes := make([]string, 0, len(checkConditionTypes))
132+
conditionMap := lo.SliceToMap(ke.Status.Conditions, func(condition metav1.Condition) (string, metav1.ConditionStatus) {
133+
return condition.Type, condition.Status
134+
})
135+
136+
for _, conditionType := range checkConditionTypes {
137+
status, ok := conditionMap[conditionType]
138+
if !ok || status != metav1.ConditionTrue {
139+
failedConditionTypes = append(failedConditionTypes, conditionType)
140+
}
141+
}
142+
143+
if len(failedConditionTypes) > 0 {
144+
return false, fmt.Sprintf("condition(s) %s not set to True", strings.Join(failedConditionTypes, ", "))
145+
}
146+
return true, ""
147+
}

test/integration/zz_generated.registered_testcases.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)