diff --git a/api/configuration/v1/kongconsumer_types.go b/api/configuration/v1/kongconsumer_types.go index 3e1f8fe..3f238c9 100644 --- a/api/configuration/v1/kongconsumer_types.go +++ b/api/configuration/v1/kongconsumer_types.go @@ -34,6 +34,7 @@ import ( // +kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status` // +kubebuilder:validation:XValidation:rule="has(self.username) || has(self.custom_id)", message="Need to provide either username or custom_id" // +kubebuilder:validation:XValidation:rule="!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)", message="controlPlaneRef is required once set" +// +kubebuilder:validation:XValidation:rule="!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)", message="spec.controlPlaneRef cannot specify namespace for namespaced resource" // +kubebuilder:validation:XValidation:rule="(!has(self.status) || !self.status.conditions.exists(c, c.type == 'Programmed' && c.status == 'True')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef", message="spec.controlPlaneRef is immutable when an entity is already Programmed" // KongConsumer is the Schema for the kongconsumers API. diff --git a/api/configuration/v1alpha1/kong_ca_certificate.go b/api/configuration/v1alpha1/kong_ca_certificate.go index 938faab..33e967d 100644 --- a/api/configuration/v1alpha1/kong_ca_certificate.go +++ b/api/configuration/v1alpha1/kong_ca_certificate.go @@ -15,6 +15,7 @@ import ( // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Programmed",description="The Resource is Programmed on Konnect",type=string,JSONPath=`.status.conditions[?(@.type=='Programmed')].status` // +kubebuilder:validation:XValidation:rule="!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)", message="controlPlaneRef is required once set" +// +kubebuilder:validation:XValidation:rule="!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)", message="spec.controlPlaneRef cannot specify namespace for namespaced resource" // +kubebuilder:validation:XValidation:rule="(!self.status.conditions.exists(c, c.type == 'Programmed' && c.status == 'True')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef", message="spec.controlPlaneRef is immutable when an entity is already Programmed" type KongCACertificate struct { metav1.TypeMeta `json:",inline"` diff --git a/api/configuration/v1alpha1/kongservice_types.go b/api/configuration/v1alpha1/kongservice_types.go index 8611e79..59471f2 100644 --- a/api/configuration/v1alpha1/kongservice_types.go +++ b/api/configuration/v1alpha1/kongservice_types.go @@ -35,6 +35,7 @@ import ( // +kubebuilder:printcolumn:name="Protocol",type=string,JSONPath=`.spec.procol`,description="Protocol of the service" // +kubebuilder:printcolumn:name="Programmed",description="The Resource is Programmed on Konnect",type=string,JSONPath=`.status.conditions[?(@.type=='Programmed')].status` // +kubebuilder:validation:XValidation:rule="!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)", message="controlPlaneRef is required once set" +// +kubebuilder:validation:XValidation:rule="!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)", message="spec.controlPlaneRef cannot specify namespace for namespaced resource" // +kubebuilder:validation:XValidation:rule="(!self.status.conditions.exists(c, c.type == 'Programmed' && c.status == 'True')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef", message="spec.controlPlaneRef is immutable when an entity is already Programmed" type KongService struct { metav1.TypeMeta `json:",inline"` diff --git a/api/configuration/v1alpha1/kongupstream_types.go b/api/configuration/v1alpha1/kongupstream_types.go index 061f21e..db09101 100644 --- a/api/configuration/v1alpha1/kongupstream_types.go +++ b/api/configuration/v1alpha1/kongupstream_types.go @@ -33,6 +33,7 @@ import ( // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Programmed",description="The Resource is Programmed on Konnect",type=string,JSONPath=`.status.conditions[?(@.type=='Programmed')].status` // +kubebuilder:validation:XValidation:rule="!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)", message="controlPlaneRef is required once set" +// +kubebuilder:validation:XValidation:rule="!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)", message="spec.controlPlaneRef cannot specify namespace for namespaced resource" // +kubebuilder:validation:XValidation:rule="(!self.status.conditions.exists(c, c.type == 'Programmed' && c.status == 'True')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef", message="spec.controlPlaneRef is immutable when an entity is already Programmed" type KongUpstream struct { metav1.TypeMeta `json:",inline"` diff --git a/api/configuration/v1alpha1/konnect_controlplaneref_types.go b/api/configuration/v1alpha1/konnect_controlplaneref_types.go index a593b0a..2e4086b 100644 --- a/api/configuration/v1alpha1/konnect_controlplaneref_types.go +++ b/api/configuration/v1alpha1/konnect_controlplaneref_types.go @@ -41,4 +41,10 @@ type KonnectNamespacedRef struct { // TODO: Implement cross namespace references: // https://github.com/Kong/kubernetes-configuration/issues/36 + + // Namespace is the namespace where the Konnect Control Plane is in. + // Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + // + // +optional + Namespace string `json:"namespace,omitempty"` } diff --git a/api/configuration/v1beta1/kongconsumergroup_types.go b/api/configuration/v1beta1/kongconsumergroup_types.go index 83fa98b..968e79d 100644 --- a/api/configuration/v1beta1/kongconsumergroup_types.go +++ b/api/configuration/v1beta1/kongconsumergroup_types.go @@ -32,6 +32,7 @@ import ( // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`,description="Age" // +kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status` // +kubebuilder:validation:XValidation:rule="!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)", message="controlPlaneRef is required once set" +// +kubebuilder:validation:XValidation:rule="!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)", message="spec.controlPlaneRef cannot specify namespace for namespaced resource" // +kubebuilder:validation:XValidation:rule="(!has(self.status) || !self.status.conditions.exists(c, c.type == 'Programmed' && c.status == 'True')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef", message="spec.controlPlaneRef is immutable when an entity is already Programmed" // KongConsumerGroup is the Schema for the kongconsumergroups API. diff --git a/config/crd/bases/configuration.konghq.com_kongcacertificates.yaml b/config/crd/bases/configuration.konghq.com_kongcacertificates.yaml index 336d1f2..358119c 100644 --- a/config/crd/bases/configuration.konghq.com_kongcacertificates.yaml +++ b/config/crd/bases/configuration.konghq.com_kongcacertificates.yaml @@ -67,6 +67,11 @@ spec: name: description: Name is the name of the Konnect Control Plane. type: string + namespace: + description: |- + Namespace is the namespace where the Konnect Control Plane is in. + Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + type: string required: - name type: object @@ -194,6 +199,8 @@ spec: x-kubernetes-validations: - message: controlPlaneRef is required once set rule: '!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)' + - message: spec.controlPlaneRef cannot specify namespace for namespaced resource + rule: '!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)' - message: spec.controlPlaneRef is immutable when an entity is already Programmed rule: '(!self.status.conditions.exists(c, c.type == ''Programmed'' && c.status == ''True'')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef' diff --git a/config/crd/bases/configuration.konghq.com_kongconsumergroups.yaml b/config/crd/bases/configuration.konghq.com_kongconsumergroups.yaml index 562ef45..f1f697b 100644 --- a/config/crd/bases/configuration.konghq.com_kongconsumergroups.yaml +++ b/config/crd/bases/configuration.konghq.com_kongconsumergroups.yaml @@ -68,6 +68,11 @@ spec: name: description: Name is the name of the Konnect Control Plane. type: string + namespace: + description: |- + Namespace is the namespace where the Konnect Control Plane is in. + Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + type: string required: - name type: object @@ -195,6 +200,8 @@ spec: x-kubernetes-validations: - message: controlPlaneRef is required once set rule: '!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)' + - message: spec.controlPlaneRef cannot specify namespace for namespaced resource + rule: '!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)' - message: spec.controlPlaneRef is immutable when an entity is already Programmed rule: '(!has(self.status) || !self.status.conditions.exists(c, c.type == ''Programmed'' && c.status == ''True'')) ? true : oldSelf.spec.controlPlaneRef diff --git a/config/crd/bases/configuration.konghq.com_kongconsumers.yaml b/config/crd/bases/configuration.konghq.com_kongconsumers.yaml index 96205f3..9e98665 100644 --- a/config/crd/bases/configuration.konghq.com_kongconsumers.yaml +++ b/config/crd/bases/configuration.konghq.com_kongconsumers.yaml @@ -93,6 +93,11 @@ spec: name: description: Name is the name of the Konnect Control Plane. type: string + namespace: + description: |- + Namespace is the namespace where the Konnect Control Plane is in. + Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + type: string required: - name type: object @@ -222,6 +227,8 @@ spec: rule: has(self.username) || has(self.custom_id) - message: controlPlaneRef is required once set rule: '!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)' + - message: spec.controlPlaneRef cannot specify namespace for namespaced resource + rule: '!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)' - message: spec.controlPlaneRef is immutable when an entity is already Programmed rule: '(!has(self.status) || !self.status.conditions.exists(c, c.type == ''Programmed'' && c.status == ''True'')) ? true : oldSelf.spec.controlPlaneRef diff --git a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml index fba1059..08ec523 100644 --- a/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml +++ b/config/crd/bases/configuration.konghq.com_kongpluginbindings.yaml @@ -71,6 +71,11 @@ spec: name: description: Name is the name of the Konnect Control Plane. type: string + namespace: + description: |- + Namespace is the namespace where the Konnect Control Plane is in. + Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + type: string required: - name type: object diff --git a/config/crd/bases/configuration.konghq.com_kongservices.yaml b/config/crd/bases/configuration.konghq.com_kongservices.yaml index 495033e..39fa971 100644 --- a/config/crd/bases/configuration.konghq.com_kongservices.yaml +++ b/config/crd/bases/configuration.konghq.com_kongservices.yaml @@ -76,6 +76,11 @@ spec: name: description: Name is the name of the Konnect Control Plane. type: string + namespace: + description: |- + Namespace is the namespace where the Konnect Control Plane is in. + Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + type: string required: - name type: object @@ -255,6 +260,8 @@ spec: x-kubernetes-validations: - message: controlPlaneRef is required once set rule: '!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)' + - message: spec.controlPlaneRef cannot specify namespace for namespaced resource + rule: '!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)' - message: spec.controlPlaneRef is immutable when an entity is already Programmed rule: '(!self.status.conditions.exists(c, c.type == ''Programmed'' && c.status == ''True'')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef' diff --git a/config/crd/bases/configuration.konghq.com_kongupstreams.yaml b/config/crd/bases/configuration.konghq.com_kongupstreams.yaml index 6451161..8e7607f 100644 --- a/config/crd/bases/configuration.konghq.com_kongupstreams.yaml +++ b/config/crd/bases/configuration.konghq.com_kongupstreams.yaml @@ -73,6 +73,11 @@ spec: name: description: Name is the name of the Konnect Control Plane. type: string + namespace: + description: |- + Namespace is the namespace where the Konnect Control Plane is in. + Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + type: string required: - name type: object @@ -411,6 +416,8 @@ spec: x-kubernetes-validations: - message: controlPlaneRef is required once set rule: '!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)' + - message: spec.controlPlaneRef cannot specify namespace for namespaced resource + rule: '!has(self.spec.controlPlaneRef.konnectNamespacedRef) ? true : !has(self.spec.controlPlaneRef.konnectNamespacedRef.__namespace__)' - message: spec.controlPlaneRef is immutable when an entity is already Programmed rule: '(!self.status.conditions.exists(c, c.type == ''Programmed'' && c.status == ''True'')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef' diff --git a/config/crd/bases/configuration.konghq.com_kongvaults.yaml b/config/crd/bases/configuration.konghq.com_kongvaults.yaml index 24914bd..ebce8df 100644 --- a/config/crd/bases/configuration.konghq.com_kongvaults.yaml +++ b/config/crd/bases/configuration.konghq.com_kongvaults.yaml @@ -96,6 +96,11 @@ spec: name: description: Name is the name of the Konnect Control Plane. type: string + namespace: + description: |- + Namespace is the namespace where the Konnect Control Plane is in. + Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. + type: string required: - name type: object diff --git a/docs/api-reference.md b/docs/api-reference.md index 78049b9..268f25e 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -1019,6 +1019,7 @@ KonnectNamespacedRef is the schema for the KonnectNamespacedRef type. | Field | Description | | --- | --- | | `name` _string_ | Name is the name of the Konnect Control Plane. | +| `namespace` _string_ | Namespace is the namespace where the Konnect Control Plane is in. Currently only cluster scoped resources (KongVault) are allowed to set `konnectNamespacedRef.namespace`. | _Appears in:_ diff --git a/test/crdsvalidation/kongconsumer/testcases/common.go b/test/crdsvalidation/kongconsumer/testcases/common.go index bee516d..b4f5bcb 100644 --- a/test/crdsvalidation/kongconsumer/testcases/common.go +++ b/test/crdsvalidation/kongconsumer/testcases/common.go @@ -28,6 +28,7 @@ var TestCases = []testCasesGroup{} func init() { TestCases = append(TestCases, + controlPlaneRef, requiredFields, updatesNotAllowedForStatus, ) diff --git a/test/crdsvalidation/kongconsumer/testcases/controlplaneref.go b/test/crdsvalidation/kongconsumer/testcases/controlplaneref.go new file mode 100644 index 0000000..ce1a475 --- /dev/null +++ b/test/crdsvalidation/kongconsumer/testcases/controlplaneref.go @@ -0,0 +1,31 @@ +package testcases + +import ( + "github.com/samber/lo" + + configurationv1 "github.com/kong/kubernetes-configuration/api/configuration/v1" + configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1" +) + +var controlPlaneRef = testCasesGroup{ + Name: "fields of controlPlaneRef", + TestCases: []testCase{ + { + Name: "cpRef cannot have namespace", + KongConsumer: configurationv1.KongConsumer{ + ObjectMeta: commonObjectMeta, + Spec: configurationv1.KongConsumerSpec{ + ControlPlaneRef: &configurationv1alpha1.ControlPlaneRef{ + Type: configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef, + KonnectNamespacedRef: &configurationv1alpha1.KonnectNamespacedRef{ + Name: "test-konnect-control-plane", + Namespace: "another-namespace", + }, + }, + }, + Username: "username-1", + }, + ExpectedErrorMessage: lo.ToPtr("spec.controlPlaneRef cannot specify namespace for namespaced resource"), + }, + }, +} diff --git a/test/crdsvalidation/kongconsumergroup/testcases/common.go b/test/crdsvalidation/kongconsumergroup/testcases/common.go index 28bf091..b1747ee 100644 --- a/test/crdsvalidation/kongconsumergroup/testcases/common.go +++ b/test/crdsvalidation/kongconsumergroup/testcases/common.go @@ -29,6 +29,7 @@ var TestCases = []testCasesGroup{} func init() { TestCases = append(TestCases, fields, + controlPlaneRef, updatesNotAllowedForStatus, ) } diff --git a/test/crdsvalidation/kongconsumergroup/testcases/controlplaneref.go b/test/crdsvalidation/kongconsumergroup/testcases/controlplaneref.go new file mode 100644 index 0000000..be5f3a4 --- /dev/null +++ b/test/crdsvalidation/kongconsumergroup/testcases/controlplaneref.go @@ -0,0 +1,30 @@ +package testcases + +import ( + "github.com/samber/lo" + + configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1" + configurationv1beta1 "github.com/kong/kubernetes-configuration/api/configuration/v1beta1" +) + +var controlPlaneRef = testCasesGroup{ + Name: "fields of controlPlaneRef", + TestCases: []testCase{ + { + Name: "cpRef cannot have namespace", + KongConsumerGroup: configurationv1beta1.KongConsumerGroup{ + ObjectMeta: commonObjectMeta, + Spec: configurationv1beta1.KongConsumerGroupSpec{ + ControlPlaneRef: &configurationv1alpha1.ControlPlaneRef{ + Type: configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef, + KonnectNamespacedRef: &configurationv1alpha1.KonnectNamespacedRef{ + Name: "test-konnect-control-plane", + Namespace: "another-namespace", + }, + }, + }, + }, + ExpectedErrorMessage: lo.ToPtr("spec.controlPlaneRef cannot specify namespace for namespaced resource"), + }, + }, +} diff --git a/test/crdsvalidation/kongservice/testcases/controlplaneref.go b/test/crdsvalidation/kongservice/testcases/controlplaneref.go index e42fc40..06cb09c 100644 --- a/test/crdsvalidation/kongservice/testcases/controlplaneref.go +++ b/test/crdsvalidation/kongservice/testcases/controlplaneref.go @@ -57,6 +57,25 @@ var cpRef = testCasesGroup{ }, ExpectedErrorMessage: lo.ToPtr("when type is konnectID, konnectID must be set"), }, + { + Name: "providing namespace in konnectNamespacedRef yields an error", + KongService: configurationv1alpha1.KongService{ + ObjectMeta: commonObjectMeta, + Spec: configurationv1alpha1.KongServiceSpec{ + ControlPlaneRef: &configurationv1alpha1.ControlPlaneRef{ + Type: configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef, + KonnectNamespacedRef: &configurationv1alpha1.KonnectNamespacedRef{ + Name: "test-konnect-control-plane", + Namespace: "another-namespace", + }, + }, + KongServiceAPISpec: configurationv1alpha1.KongServiceAPISpec{ + Host: "example.com", + }, + }, + }, + ExpectedErrorMessage: lo.ToPtr("spec.controlPlaneRef cannot specify namespace for namespaced resource"), + }, { Name: "konnectNamespacedRef reference name cannot be changed when an entity is Programmed", KongService: configurationv1alpha1.KongService{ diff --git a/test/crdsvalidation/kongupstream/testcases/controlplaneref.go b/test/crdsvalidation/kongupstream/testcases/controlplaneref.go index ee214cb..a2ffe8f 100644 --- a/test/crdsvalidation/kongupstream/testcases/controlplaneref.go +++ b/test/crdsvalidation/kongupstream/testcases/controlplaneref.go @@ -51,6 +51,23 @@ var cpRef = testCasesGroup{ }, ExpectedErrorMessage: lo.ToPtr("when type is konnectID, konnectID must be set"), }, + { + Name: "providing namespace in konnectNamespacedRef yields an error", + KongUpstream: configurationv1alpha1.KongUpstream{ + ObjectMeta: commonObjectMeta, + Spec: configurationv1alpha1.KongUpstreamSpec{ + ControlPlaneRef: &configurationv1alpha1.ControlPlaneRef{ + Type: configurationv1alpha1.ControlPlaneRefKonnectNamespacedRef, + KonnectNamespacedRef: &configurationv1alpha1.KonnectNamespacedRef{ + Name: "test-konnect-control-plane", + Namespace: "another-namespace", + }, + }, + KongUpstreamAPISpec: configurationv1alpha1.KongUpstreamAPISpec{}, + }, + }, + ExpectedErrorMessage: lo.ToPtr("spec.controlPlaneRef cannot specify namespace for namespaced resource"), + }, { Name: "konnectNamespacedRef reference name cannot be changed when an entity is Programmed", KongUpstream: configurationv1alpha1.KongUpstream{