From 18b19e01ae4f1cc8f61abda761947ad4b2b59f79 Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Thu, 16 Apr 2026 09:05:12 +0200 Subject: [PATCH 01/13] respect external port when constructing front-proxy Service/URLs (#212) On-behalf-of: @SAP christoph.mewes@sap.com --- internal/resources/frontproxy/service.go | 17 +- internal/resources/frontproxy/service_test.go | 223 ++++++++++++++++++ internal/resources/kubeconfig/secret.go | 15 +- internal/resources/rootshard/service.go | 29 ++- internal/resources/shard/service.go | 29 ++- internal/resources/utils/frontproxy.go | 55 +++++ 6 files changed, 337 insertions(+), 31 deletions(-) create mode 100644 internal/resources/frontproxy/service_test.go create mode 100644 internal/resources/utils/frontproxy.go diff --git a/internal/resources/frontproxy/service.go b/internal/resources/frontproxy/service.go index b645de49..b25fce47 100644 --- a/internal/resources/frontproxy/service.go +++ b/internal/resources/frontproxy/service.go @@ -36,8 +36,21 @@ func (r *reconciler) serviceName() string { } } +func (r *reconciler) getExternalPort() int { + // We're reconciling a regular FrontProxy. + if r.frontProxy != nil { + return utils.GetFrontProxyExternalPort(r.frontProxy, r.rootShard) + } + + // We're reconciling the rootshard's internal proxy. + // This proxy is not meant to be exposed, but only used internally by + // the kcp-operator, so we never allow to customize its port. + return 6443 +} + func (r *reconciler) serviceReconciler() reconciling.NamedServiceReconcilerFactory { var tpl *operatorv1alpha1.ServiceTemplate + switch { case r.frontProxy != nil: tpl = r.frontProxy.Spec.ServiceTemplate @@ -45,6 +58,8 @@ func (r *reconciler) serviceReconciler() reconciling.NamedServiceReconcilerFacto tpl = r.rootShard.Spec.Proxy.ServiceTemplate } + portNumber := r.getExternalPort() + return func() (string, reconciling.ServiceReconciler) { return r.serviceName(), func(svc *corev1.Service) (*corev1.Service, error) { svc.SetLabels(r.resourceLabels) @@ -57,7 +72,7 @@ func (r *reconciler) serviceReconciler() reconciling.NamedServiceReconcilerFacto port.Name = "https" port.Protocol = corev1.ProtocolTCP - port.Port = 6443 + port.Port = int32(portNumber) port.TargetPort = intstr.FromInt32(6443) port.AppProtocol = ptr.To("https") diff --git a/internal/resources/frontproxy/service_test.go b/internal/resources/frontproxy/service_test.go new file mode 100644 index 00000000..8cdabb19 --- /dev/null +++ b/internal/resources/frontproxy/service_test.go @@ -0,0 +1,223 @@ +/* +Copyright 2026 The kcp Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package frontproxy + +import ( + "testing" + + "github.com/stretchr/testify/require" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" +) + +func TestGetExternalPort(t *testing.T) { + tests := []struct { + name string + frontProxy *operatorv1alpha1.FrontProxy + rootShard *operatorv1alpha1.RootShard + expectedPort int + }{ + { + name: "FrontProxy with explicit External.Port", + frontProxy: &operatorv1alpha1.FrontProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, + Spec: operatorv1alpha1.FrontProxySpec{ + RootShard: operatorv1alpha1.RootShardConfig{ + Reference: &corev1.LocalObjectReference{Name: "test-root-shard"}, + }, + External: operatorv1alpha1.ExternalConfig{ + Port: 8443, + }, + }, + }, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 6443, + }, + }, + }, + expectedPort: 8443, + }, + { + name: "FrontProxy with deprecated ExternalHostname including port", + frontProxy: &operatorv1alpha1.FrontProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, + Spec: operatorv1alpha1.FrontProxySpec{ + RootShard: operatorv1alpha1.RootShardConfig{ + Reference: &corev1.LocalObjectReference{Name: "test-root-shard"}, + }, + ExternalHostname: "kcp.example.com:9443", + }, + }, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 6443, + }, + }, + }, + expectedPort: 9443, + }, + { + name: "FrontProxy External.Port takes precedence over deprecated ExternalHostname", + frontProxy: &operatorv1alpha1.FrontProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, + Spec: operatorv1alpha1.FrontProxySpec{ + RootShard: operatorv1alpha1.RootShardConfig{ + Reference: &corev1.LocalObjectReference{Name: "test-root-shard"}, + }, + External: operatorv1alpha1.ExternalConfig{ + Port: 8443, + }, + ExternalHostname: "kcp.example.com:9443", + }, + }, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 6443, + }, + }, + }, + expectedPort: 8443, + }, + { + name: "FrontProxy falls back to RootShard External.Port", + frontProxy: &operatorv1alpha1.FrontProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, + Spec: operatorv1alpha1.FrontProxySpec{ + RootShard: operatorv1alpha1.RootShardConfig{ + Reference: &corev1.LocalObjectReference{Name: "test-root-shard"}, + }, + }, + }, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 7443, + }, + }, + }, + expectedPort: 7443, + }, + { + name: "FrontProxy with ExternalHostname without a port defaults to 6443", + frontProxy: &operatorv1alpha1.FrontProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, + Spec: operatorv1alpha1.FrontProxySpec{ + RootShard: operatorv1alpha1.RootShardConfig{ + Reference: &corev1.LocalObjectReference{Name: "test-root-shard"}, + }, + ExternalHostname: "kcp.example.com", + }, + }, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 7443, + }, + }, + }, + expectedPort: 6443, + }, + { + name: "FrontProxy with non-numeric port in ExternalHostname defaults to 6443", + frontProxy: &operatorv1alpha1.FrontProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, + Spec: operatorv1alpha1.FrontProxySpec{ + RootShard: operatorv1alpha1.RootShardConfig{ + Reference: &corev1.LocalObjectReference{Name: "test-root-shard"}, + }, + ExternalHostname: "kcp.example.com:invalid", + }, + }, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 7443, + }, + }, + }, + expectedPort: 6443, + }, + { + name: "FrontProxy with no port configuration uses default 6443", + frontProxy: &operatorv1alpha1.FrontProxy{ + ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, + Spec: operatorv1alpha1.FrontProxySpec{ + RootShard: operatorv1alpha1.RootShardConfig{ + Reference: &corev1.LocalObjectReference{Name: "test-root-shard"}, + }, + }, + }, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 0, + }, + }, + }, + expectedPort: 6443, + }, + { + name: "RootShard internal proxy always uses default 6443", + frontProxy: nil, + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}, + Spec: operatorv1alpha1.RootShardSpec{ + External: operatorv1alpha1.ExternalConfig{ + Hostname: "kcp.example.com", + Port: 8443, + }, + }, + }, + expectedPort: 6443, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var rec *reconciler + if tt.frontProxy != nil { + rec = NewFrontProxy(tt.frontProxy, tt.rootShard) + } else { + rec = NewRootShardProxy(tt.rootShard) + } + + actualPort := rec.getExternalPort() + require.Equal(t, tt.expectedPort, actualPort) + }) + } +} diff --git a/internal/resources/kubeconfig/secret.go b/internal/resources/kubeconfig/secret.go index 906de270..cdb3c4ac 100644 --- a/internal/resources/kubeconfig/secret.go +++ b/internal/resources/kubeconfig/secret.go @@ -18,6 +18,7 @@ package kubeconfig import ( "fmt" + "net" "net/url" "k8c.io/reconciler/pkg/reconciling" @@ -122,11 +123,17 @@ func KubeconfigSecretReconciler( } var serverURL string - // New flow: - if frontProxy.Spec.External.Hostname != "" { + switch { + case frontProxy.Spec.External.Hostname != "": serverURL = fmt.Sprintf("https://%s:%d", frontProxy.Spec.External.Hostname, frontProxy.Spec.External.Port) - } else { - // Old flow: + case frontProxy.Spec.ExternalHostname != "": + _, _, err := net.SplitHostPort(frontProxy.Spec.ExternalHostname) + if err == nil { + serverURL = fmt.Sprintf("https://%s", frontProxy.Spec.ExternalHostname) + } else { + serverURL = fmt.Sprintf("https://%s:6443", frontProxy.Spec.ExternalHostname) + } + default: serverURL = fmt.Sprintf("https://%s:%d", rootShard.Spec.External.Hostname, rootShard.Spec.External.Port) } diff --git a/internal/resources/rootshard/service.go b/internal/resources/rootshard/service.go index 639a1a4d..a458459b 100644 --- a/internal/resources/rootshard/service.go +++ b/internal/resources/rootshard/service.go @@ -31,25 +31,28 @@ import ( func ServiceReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedServiceReconcilerFactory { return func() (string, reconciling.ServiceReconciler) { return resources.GetRootShardServiceName(rootShard), func(svc *corev1.Service) (*corev1.Service, error) { - labels := resources.GetRootShardResourceLabels(rootShard) - svc.SetLabels(labels) - svc.Spec.Type = corev1.ServiceTypeClusterIP - svc.Spec.Ports = []corev1.ServicePort{ - { - Name: "https", - Protocol: corev1.ProtocolTCP, - Port: 6443, - TargetPort: intstr.FromInt32(6443), - AppProtocol: ptr.To("https"), - }, - { + ports := []corev1.ServicePort{{ + Name: "https", + Protocol: corev1.ProtocolTCP, + Port: 6443, + TargetPort: intstr.FromInt32(6443), + AppProtocol: ptr.To("https"), + }} + + if rootShard.Spec.KCPVirtualWorkspace == nil { + ports = append(ports, corev1.ServicePort{ Name: "https-virtual-workspaces", Protocol: corev1.ProtocolTCP, Port: 6444, TargetPort: intstr.FromInt32(6444), AppProtocol: ptr.To("https"), - }, + }) } + + labels := resources.GetRootShardResourceLabels(rootShard) + svc.SetLabels(labels) + svc.Spec.Type = corev1.ServiceTypeClusterIP + svc.Spec.Ports = ports svc.Spec.Selector = labels return utils.ApplyServiceTemplate(svc, rootShard.Spec.ServiceTemplate), nil diff --git a/internal/resources/shard/service.go b/internal/resources/shard/service.go index e94336be..ea75ee8d 100644 --- a/internal/resources/shard/service.go +++ b/internal/resources/shard/service.go @@ -31,25 +31,28 @@ import ( func ServiceReconciler(shard *operatorv1alpha1.Shard) reconciling.NamedServiceReconcilerFactory { return func() (string, reconciling.ServiceReconciler) { return resources.GetShardServiceName(shard), func(svc *corev1.Service) (*corev1.Service, error) { - labels := resources.GetShardResourceLabels(shard) - svc.SetLabels(labels) - svc.Spec.Type = corev1.ServiceTypeClusterIP - svc.Spec.Ports = []corev1.ServicePort{ - { - Name: "https", - Protocol: corev1.ProtocolTCP, - Port: 6443, - TargetPort: intstr.FromInt32(6443), - AppProtocol: ptr.To("https"), - }, - { + ports := []corev1.ServicePort{{ + Name: "https", + Protocol: corev1.ProtocolTCP, + Port: 6443, + TargetPort: intstr.FromInt32(6443), + AppProtocol: ptr.To("https"), + }} + + if shard.Spec.KCPVirtualWorkspace == nil { + ports = append(ports, corev1.ServicePort{ Name: "https-virtual-workspaces", Protocol: corev1.ProtocolTCP, Port: 6444, TargetPort: intstr.FromInt32(6444), AppProtocol: ptr.To("https"), - }, + }) } + + labels := resources.GetShardResourceLabels(shard) + svc.SetLabels(labels) + svc.Spec.Type = corev1.ServiceTypeClusterIP + svc.Spec.Ports = ports svc.Spec.Selector = labels return utils.ApplyServiceTemplate(svc, shard.Spec.ServiceTemplate), nil diff --git a/internal/resources/utils/frontproxy.go b/internal/resources/utils/frontproxy.go new file mode 100644 index 00000000..6bbe5370 --- /dev/null +++ b/internal/resources/utils/frontproxy.go @@ -0,0 +1,55 @@ +/* +Copyright 2026 The kcp Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "net" + "strconv" + + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" +) + +func GetFrontProxyExternalPort(fp *operatorv1alpha1.FrontProxy, r *operatorv1alpha1.RootShard) int { + // easy, the user explicitly configured an external port on the FrontProxy itself + if port := fp.Spec.External.Port; port > 0 { + return int(port) + } + + // fallback to deprecated ExternalHostname + if extName := fp.Spec.ExternalHostname; extName != "" { + _, port, err := net.SplitHostPort(extName) + if err == nil { + parsed, err := strconv.Atoi(port) + if err == nil { + return parsed + } + } + + // no port was given in the URL; assume the default + return 6443 + } + + // if nothing valid is configured on the FrontProxy, check the RootShard + if r != nil { + if port := r.Spec.External.Port; port > 0 { + return int(port) + } + } + + // last resort, fallback to the default kcp port + return 6443 +} From c0654644ed236125a93f5b935fddd59fcedead93 Mon Sep 17 00:00:00 2001 From: Robert Vasek Date: Fri, 17 Apr 2026 11:05:11 +0200 Subject: [PATCH 02/13] Add --requestheader-allowed-names where necessary (#214) Adds --requestheader-allowed-names to RootShard, Shard and VirtualWorkspace deployments. k/k 1.35 requires --requestheader-allowed-names to be passed if --requestheader-client-ca-file and --client-ca-file point to the same cert. On-behalf-of: @SAP robert.vasek@sap.com Signed-off-by: Robert Vasek --- internal/resources/frontproxy/certificates.go | 4 ++-- internal/resources/resources.go | 6 ++++++ internal/resources/rootshard/deployment.go | 1 + internal/resources/shard/deployment.go | 1 + internal/resources/virtualworkspace/deployment.go | 1 + 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/internal/resources/frontproxy/certificates.go b/internal/resources/frontproxy/certificates.go index c61a048c..4c1dddf1 100644 --- a/internal/resources/frontproxy/certificates.go +++ b/internal/resources/frontproxy/certificates.go @@ -50,9 +50,9 @@ func (r *reconciler) certName(certKind operatorv1alpha1.Certificate) string { func (r *reconciler) certCommonName() string { if r.frontProxy != nil { - return "kcp-front-proxy" + return resources.FrontProxyCommonName } else { - return "kcp-root-shard-proxy" + return resources.RootShardProxyCommonName } } diff --git a/internal/resources/resources.go b/internal/resources/resources.go index 24cfe15b..608ca930 100644 --- a/internal/resources/resources.go +++ b/internal/resources/resources.go @@ -27,6 +27,12 @@ import ( ) const ( + // FrontProxyCommonName is the CommonName used in the requestheader client certificate for a FrontProxy. + FrontProxyCommonName = "kcp-front-proxy" + + // RootShardProxyCommonName is the CommonName used in the requestheader client certificate for a RootShard's built-in proxy. + RootShardProxyCommonName = "kcp-root-shard-proxy" + ImageRepository = "ghcr.io/kcp-dev/kcp" // ImageTag is the default tag to be used for any kcp component. diff --git a/internal/resources/rootshard/deployment.go b/internal/resources/rootshard/deployment.go index d3d118c7..0f279c79 100644 --- a/internal/resources/rootshard/deployment.go +++ b/internal/resources/rootshard/deployment.go @@ -218,6 +218,7 @@ func getArgs(rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.Virt // Requestheader configuration. fmt.Sprintf("--requestheader-client-ca-file=%s/tls.crt", getCAMountPath(operatorv1alpha1.RequestHeaderClientCA)), + fmt.Sprintf("--requestheader-allowed-names=%s,%s", resources.FrontProxyCommonName, resources.RootShardProxyCommonName), "--requestheader-username-headers=X-Remote-User", "--requestheader-group-headers=X-Remote-Group", "--requestheader-extra-headers-prefix=X-Remote-Extra-", diff --git a/internal/resources/shard/deployment.go b/internal/resources/shard/deployment.go index 97b5a793..1ce48d4b 100644 --- a/internal/resources/shard/deployment.go +++ b/internal/resources/shard/deployment.go @@ -238,6 +238,7 @@ func getArgs(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShar // Requestheader configuration. fmt.Sprintf("--requestheader-client-ca-file=%s/tls.crt", getCAMountPath(operatorv1alpha1.RequestHeaderClientCA)), + fmt.Sprintf("--requestheader-allowed-names=%s,%s", resources.FrontProxyCommonName, resources.RootShardProxyCommonName), "--requestheader-username-headers=X-Remote-User", "--requestheader-group-headers=X-Remote-Group", "--requestheader-extra-headers-prefix=X-Remote-Extra-", diff --git a/internal/resources/virtualworkspace/deployment.go b/internal/resources/virtualworkspace/deployment.go index 9deaf5d1..8293ec42 100644 --- a/internal/resources/virtualworkspace/deployment.go +++ b/internal/resources/virtualworkspace/deployment.go @@ -248,6 +248,7 @@ func getArgs(vw *operatorv1alpha1.VirtualWorkspace, rootShard *operatorv1alpha1. // requestheader CA fmt.Sprintf("--requestheader-client-ca-file=%s/tls.crt", getCAMountPath(operatorv1alpha1.RequestHeaderClientCA)), + fmt.Sprintf("--requestheader-allowed-names=%s,%s", resources.FrontProxyCommonName, resources.RootShardProxyCommonName), "--requestheader-username-headers=X-Remote-User", "--requestheader-group-headers=X-Remote-Group", "--requestheader-extra-headers-prefix=X-Remote-Extra-", From 8c8ecde135abc124d73269b3af69e91546756be4 Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Fri, 17 Apr 2026 12:44:10 +0200 Subject: [PATCH 03/13] Add shardBaseURL hostname to certificate DNS SANs (#215) Fixes #213 When spec.shardBaseURL is set to a value different from spec.external.hostname, the shardBaseURL hostname is now extracted and included in the server certificate's DNS Subject Alternative Names. This prevents TLS certificate validation errors when clients connect using the shardBaseURL instead of the external hostname. Changes: - Add ExtractHostnameFromURL utility function to parse hostnames from URLs - Update RootShard server certificates to include shardBaseURL hostname - Update Shard server certificates to include shardBaseURL hostname - Add comprehensive tests for URL hostname extraction - Add tests for DNS name building in both RootShard and Shard certificates On-behalf-of: @SAP christoph.mewes@sap.com --- internal/resources/rootshard/certificates.go | 26 ++- .../resources/rootshard/certificates_test.go | 153 ++++++++++++++++++ internal/resources/shard/certificates.go | 26 ++- internal/resources/shard/certificates_test.go | 117 ++++++++++++++ internal/resources/utils/certificates.go | 16 ++ internal/resources/utils/certificates_test.go | 61 +++++++ 6 files changed, 391 insertions(+), 8 deletions(-) create mode 100644 internal/resources/rootshard/certificates_test.go create mode 100644 internal/resources/shard/certificates_test.go diff --git a/internal/resources/rootshard/certificates.go b/internal/resources/rootshard/certificates.go index b9b8e099..eb6e32f6 100644 --- a/internal/resources/rootshard/certificates.go +++ b/internal/resources/rootshard/certificates.go @@ -20,6 +20,8 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" certmanagermetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/utils" @@ -56,10 +58,7 @@ func ServerCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil certmanagerv1.UsageDigitalSignature, }, - DNSNames: []string{ - resources.GetRootShardBaseHost(rootShard), - rootShard.Spec.External.Hostname, - }, + DNSNames: buildRootShardDNSNames(rootShard), IssuerRef: certmanagermetav1.ObjectReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), @@ -345,3 +344,22 @@ func ClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil } } } + +// buildRootShardDNSNames builds the list of DNS names for the root shard server certificate. +// It includes the internal Kubernetes service host, the external hostname, and if shardBaseURL +// is set, it also extracts and includes the hostname from that URL. +func buildRootShardDNSNames(rootShard *operatorv1alpha1.RootShard) []string { + dnsNames := sets.New( + resources.GetRootShardBaseHost(rootShard), + rootShard.Spec.External.Hostname, + ) + + // If shardBaseURL is set, extract and add its hostname + if rootShard.Spec.ShardBaseURL != "" { + if hostname := utils.ExtractHostnameFromURL(rootShard.Spec.ShardBaseURL); hostname != "" { + dnsNames.Insert(hostname) + } + } + + return sets.List(dnsNames) +} diff --git a/internal/resources/rootshard/certificates_test.go b/internal/resources/rootshard/certificates_test.go new file mode 100644 index 00000000..900b369a --- /dev/null +++ b/internal/resources/rootshard/certificates_test.go @@ -0,0 +1,153 @@ +/* +Copyright 2026 The kcp Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rootshard + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" +) + +func TestBuildRootShardDNSNames(t *testing.T) { + tests := []struct { + name string + rootShard *operatorv1alpha1.RootShard + expected []string + }{ + { + name: "without shardBaseURL", + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-shard", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.RootShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ClusterDomain: "cluster.local", + }, + External: operatorv1alpha1.ExternalConfig{ + Hostname: "api.example.com", + }, + }, + }, + expected: []string{ + "test-shard-kcp.kcp.svc.cluster.local", + "api.example.com", + }, + }, + { + name: "with shardBaseURL matching external hostname", + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-shard", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.RootShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ClusterDomain: "cluster.local", + ShardBaseURL: "https://api.example.com:6443", + }, + External: operatorv1alpha1.ExternalConfig{ + Hostname: "api.example.com", + }, + }, + }, + expected: []string{ + "test-shard-kcp.kcp.svc.cluster.local", + "api.example.com", + }, + }, + { + name: "with shardBaseURL different from external hostname", + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "root", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.RootShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ClusterDomain: "cluster.local", + ShardBaseURL: "https://root.shard.kcp.example.com:6443", + }, + External: operatorv1alpha1.ExternalConfig{ + Hostname: "api.kcp.example.com", + }, + }, + }, + expected: []string{ + "root-kcp.kcp.svc.cluster.local", + "api.kcp.example.com", + "root.shard.kcp.example.com", + }, + }, + { + name: "with invalid shardBaseURL", + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-shard", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.RootShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ClusterDomain: "cluster.local", + ShardBaseURL: "not-a-valid-url", + }, + External: operatorv1alpha1.ExternalConfig{ + Hostname: "api.example.com", + }, + }, + }, + expected: []string{ + "test-shard-kcp.kcp.svc.cluster.local", + "api.example.com", + }, + }, + { + name: "with shardBaseURL containing subdomain", + rootShard: &operatorv1alpha1.RootShard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "prod", + Namespace: "kcp-system", + }, + Spec: operatorv1alpha1.RootShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ShardBaseURL: "https://prod.shard.kcp.devsecops.dev.codefabric.cloud:6443", + }, + External: operatorv1alpha1.ExternalConfig{ + Hostname: "api.kcp.devsecops.dev.codefabric.cloud", + }, + }, + }, + expected: []string{ + "prod-kcp.kcp-system.svc.cluster.local", + "api.kcp.devsecops.dev.codefabric.cloud", + "prod.shard.kcp.devsecops.dev.codefabric.cloud", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := buildRootShardDNSNames(tt.rootShard) + assert.ElementsMatch(t, tt.expected, result) + }) + } +} diff --git a/internal/resources/shard/certificates.go b/internal/resources/shard/certificates.go index 734bfaac..bc190b1d 100644 --- a/internal/resources/shard/certificates.go +++ b/internal/resources/shard/certificates.go @@ -22,6 +22,8 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" certmanagermetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/utils" @@ -60,10 +62,7 @@ func ServerCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *opera certmanagerv1.UsageDigitalSignature, }, - DNSNames: []string{ - "localhost", - resources.GetShardBaseHost(shard), - }, + DNSNames: buildShardDNSNames(shard), IssuerRef: certmanagermetav1.ObjectReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), @@ -307,3 +306,22 @@ func ExternalLogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Sh } } } + +// buildShardDNSNames builds the list of DNS names for the shard server certificate. +// It includes localhost, the internal Kubernetes service host, and if shardBaseURL +// is set, it also extracts and includes the hostname from that URL. +func buildShardDNSNames(shard *operatorv1alpha1.Shard) []string { + dnsNames := sets.New( + "localhost", + resources.GetShardBaseHost(shard), + ) + + // If shardBaseURL is set, extract and add its hostname + if shard.Spec.ShardBaseURL != "" { + if hostname := utils.ExtractHostnameFromURL(shard.Spec.ShardBaseURL); hostname != "" { + dnsNames.Insert(hostname) + } + } + + return sets.List(dnsNames) +} diff --git a/internal/resources/shard/certificates_test.go b/internal/resources/shard/certificates_test.go new file mode 100644 index 00000000..8b238b64 --- /dev/null +++ b/internal/resources/shard/certificates_test.go @@ -0,0 +1,117 @@ +/* +Copyright 2026 The kcp Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package shard + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" +) + +func TestBuildShardDNSNames(t *testing.T) { + tests := []struct { + name string + shard *operatorv1alpha1.Shard + expected []string + }{ + { + name: "without shardBaseURL", + shard: &operatorv1alpha1.Shard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-shard", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.ShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ClusterDomain: "cluster.local", + }, + }, + }, + expected: []string{ + "localhost", + "test-shard-shard-kcp.kcp.svc.cluster.local", + }, + }, + { + name: "with shardBaseURL", + shard: &operatorv1alpha1.Shard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "worker-1", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.ShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ClusterDomain: "cluster.local", + ShardBaseURL: "https://worker-1.shard.kcp.example.com:6443", + }, + }, + }, + expected: []string{ + "localhost", + "worker-1-shard-kcp.kcp.svc.cluster.local", + "worker-1.shard.kcp.example.com", + }, + }, + { + name: "with shardBaseURL matching localhost", + shard: &operatorv1alpha1.Shard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "local-shard", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.ShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ShardBaseURL: "https://localhost:6443", + }, + }, + }, + expected: []string{ + "localhost", + "local-shard-shard-kcp.kcp.svc.cluster.local", + }, + }, + { + name: "with invalid shardBaseURL", + shard: &operatorv1alpha1.Shard{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-shard", + Namespace: "kcp", + }, + Spec: operatorv1alpha1.ShardSpec{ + CommonShardSpec: operatorv1alpha1.CommonShardSpec{ + ShardBaseURL: "not-a-valid-url", + }, + }, + }, + expected: []string{ + "localhost", + "test-shard-shard-kcp.kcp.svc.cluster.local", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := buildShardDNSNames(tt.shard) + assert.ElementsMatch(t, tt.expected, result) + }) + } +} diff --git a/internal/resources/utils/certificates.go b/internal/resources/utils/certificates.go index abfcff88..551bdeef 100644 --- a/internal/resources/utils/certificates.go +++ b/internal/resources/utils/certificates.go @@ -21,6 +21,7 @@ import ( "encoding/pem" "fmt" "maps" + "net/url" "os" certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" @@ -244,3 +245,18 @@ func MergeCABundlesFiles(caFile1, caFile2 string) ([]byte, error) { return merged, nil } + +// ExtractHostnameFromURL extracts the hostname from a URL string. +// Returns empty string if the URL is invalid or empty. +func ExtractHostnameFromURL(rawURL string) string { + if rawURL == "" { + return "" + } + + parsed, err := url.Parse(rawURL) + if err != nil { + return "" + } + + return parsed.Hostname() +} diff --git a/internal/resources/utils/certificates_test.go b/internal/resources/utils/certificates_test.go index a9699269..852b24ba 100644 --- a/internal/resources/utils/certificates_test.go +++ b/internal/resources/utils/certificates_test.go @@ -122,3 +122,64 @@ YWJjZGVmZ2hpams= }) } } + +func TestExtractHostnameFromURL(t *testing.T) { + tests := []struct { + name string + url string + expected string + }{ + { + name: "empty URL", + url: "", + expected: "", + }, + { + name: "valid URL with https", + url: "https://api.example.com", + expected: "api.example.com", + }, + { + name: "valid URL with port", + url: "https://api.example.com:6443", + expected: "api.example.com", + }, + { + name: "valid URL with http", + url: "http://localhost:8080", + expected: "localhost", + }, + { + name: "URL with path", + url: "https://api.example.com:6443/path/to/resource", + expected: "api.example.com", + }, + { + name: "subdomain URL", + url: "https://root.shard.kcp.example.com:6443", + expected: "root.shard.kcp.example.com", + }, + { + name: "invalid URL", + url: "not-a-valid-url", + expected: "", + }, + { + name: "URL with IPv4 address", + url: "https://192.168.1.1:6443", + expected: "192.168.1.1", + }, + { + name: "URL with IPv6 address", + url: "https://[2001:db8::1]:6443", + expected: "2001:db8::1", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ExtractHostnameFromURL(tt.url) + assert.Equal(t, tt.expected, result) + }) + } +} From f088332760b21839f9062f35fe1894fadb1c11bc Mon Sep 17 00:00:00 2001 From: Mangirdas Judeikis Date: Fri, 17 Apr 2026 14:59:10 +0300 Subject: [PATCH 04/13] Support matrix (#207) --- README.md | 13 ++++++------- docs/content/README.md | 12 ++++++------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 84154c71..9b611f6f 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,12 @@ The table below marks known support of a kcp version in kcp-operator versions. -| kcp | `main` | 0.1.x | -| ------ | ------------------ | ------------------ | -| `main` | :warning: | :question: | -| 0.30.x | :white_check_mark: | :question: | -| 0.29.x | :white_check_mark: | :question: | -| 0.28.x | :white_check_mark: | :question: | -| 0.27.x | :question: | :white_check_mark: | +| kcp | `main` | 0.7.x | 0.6.x | 0.5.x | +| ------ | ------------------ | ------------------ | ------------------ | ------------------ | +| `main` | :warning: | :question: | :question: | :question: | +| 0.31.x | :white_check_mark: | :white_check_mark: | :white_check_mark: | :question: | +| 0.30.x | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 0.29.x | :question: | :question: | :question: | :white_check_mark: | [^1]: While we try to support kcp's `main` branch, this support is best effort and should not be used for deploying actual kcp instances. diff --git a/docs/content/README.md b/docs/content/README.md index a9991359..fa4f20f2 100644 --- a/docs/content/README.md +++ b/docs/content/README.md @@ -22,12 +22,12 @@ The table below marks known support of a kcp version in kcp-operator versions. -| kcp | `main` | 0.1.x | -| ------ | ------------------ | ------------------ | -| `main` | :warning: | :question: | -| 0.29.x | :white_check_mark: | :question: | -| 0.28.x | :white_check_mark: | :question: | -| 0.27.x | :question: | :white_check_mark: | +| kcp | `main` | 0.7.x | 0.6.x | 0.5.x | +| ------ | ------------------ | ------------------ | ------------------ | ------------------ | +| `main` | :warning: | :question: | :question: | :question: | +| 0.31.x | :white_check_mark: | :white_check_mark: | :white_check_mark: | :question: | +| 0.30.x | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| 0.29.x | :question: | :question: | :question: | :white_check_mark: | *Explanation*: From e4c1f707733fe93b7b8c6cb830f7a6d6dbd62300 Mon Sep 17 00:00:00 2001 From: Mangirdas Judeikis Date: Fri, 17 Apr 2026 14:59:17 +0300 Subject: [PATCH 05/13] rework release docs (#208) --- docs/content/contributing/releasing.md | 61 ++++++++++++++++---------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/docs/content/contributing/releasing.md b/docs/content/contributing/releasing.md index ae08128b..827c5024 100644 --- a/docs/content/contributing/releasing.md +++ b/docs/content/contributing/releasing.md @@ -5,39 +5,52 @@ description: > # Release Process -The guide describes how to release a new version of the kcp-operator. +This document describes the end-to-end process for publishing a new kcp-operator release. ## Prerequisites -1. Have all desired changes merged and/or cherrypicked into the appropriate - release branch. +- Push access to the `kcp-dev/kcp-operator` repository. +- All desired changes merged (and cherry-picked for patch releases). -## Minor Release +## 1. Bump the Default KCP Image Tag -Minor releases (0.x) are tagged directly on the `main` branch and the `v0.X.0` -tag represents where the corresponding `release/v0.X` branch branches off. +Update the compiled-in default image tag in `internal/resources/resources.go`: -1. Checkout the desired `main` branch commit. -1. Tag the main module: `git tag -m "version 0.X" v0.X.0` -1. Tag the SDK module: `git tag -m "SDK version 0.X" sdk/v0.X.0` -1. Push the tags: `git push upstream v0.X.0 sdk/v0.X.0` -1. Create the release branch: `git checkout -B release-0.X` -1. Push the release branch: `git push -u upstream release-0.X` +```go +const ( + ImageRepository = "ghcr.io/kcp-dev/kcp" + ImageTag = "v0.XX.Y" // <-- update this +) +``` -Once the tag and branch have been pushed, the documentation has to be manually -updated to include the new minor release. +Commit and merge the change before tagging. -1. Navigate to https://github.com/kcp-dev/kcp-operator/actions/workflows/docs-gen-and-push.yaml -1. Run the workflow manually on the new release branch. +## 2. Tag the Release -Within a few minutes of the action finishing, the new branch should show up on -https://docs.kcp.io/kcp-operator/. +### Minor release (v0.X.0) -## Patch Releases +```bash +git checkout main +git tag -m "version 0.X" v0.X.0 +git tag -m "SDK version 0.X" sdk/v0.X.0 +git push upstream v0.X.0 sdk/v0.X.0 -Patch releases (v0.x.y) are tagged with in a release branch. +# Create the release branch +git checkout -B release-0.X +git push -u upstream release-0.X +``` -1. Checkout the desired `release/v0.X` branch commit. -1. Tag the main module: `git tag -m "version 0.X.Y" v0.X.Y` -1. Tag the SDK module: `git tag -m "SDK version 0.X.Y" sdk/v0.X.Y` -1. Push the tags: `git push upstream v0.X.Y sdk/v0.X.Y` +### Patch release (v0.X.Y) + +```bash +git checkout release-0.X +git tag -m "version 0.X.Y" v0.X.Y +git tag -m "SDK version 0.X.Y" sdk/v0.X.Y +git push upstream v0.X.Y sdk/v0.X.Y +``` + +## 3. Publish Documentation + +1. Go to the [docs-gen-and-push workflow](https://github.com/kcp-dev/kcp-operator/actions/workflows/docs-gen-and-push.yaml). +2. Run the workflow manually on the release branch. +3. Verify the new version appears on [docs.kcp.io/kcp-operator](https://docs.kcp.io/kcp-operator/). From d98dc31fa5236011d8ab23a17997eb11481340cd Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Mon, 20 Apr 2026 08:05:11 +0200 Subject: [PATCH 06/13] bump dependencies to kcp 0.31 (kube 1.35) (#219) * bump dependencies to kcp 0.31 (kube 1.35) On-behalf-of: @SAP christoph.mewes@sap.com * adjust to deprecated IssuerRef type On-behalf-of: @SAP christoph.mewes@sap.com --- cmd/operator/main.go | 2 +- go.mod | 134 ++++---- go.sum | 318 +++++++++--------- internal/controller/shard/controller.go | 2 +- .../resources/cacheserver/certificates.go | 6 +- internal/resources/frontproxy/certificates.go | 8 +- internal/resources/kubeconfig/certificate.go | 2 +- .../resources/rootshard/ca_certificates.go | 4 +- internal/resources/rootshard/certificates.go | 14 +- internal/resources/shard/certificates.go | 12 +- internal/resources/utils/certificates.go | 2 +- .../resources/virtualworkspace/certificate.go | 4 +- 12 files changed, 251 insertions(+), 257 deletions(-) diff --git a/cmd/operator/main.go b/cmd/operator/main.go index 762bdacf..0f22fe9d 100644 --- a/cmd/operator/main.go +++ b/cmd/operator/main.go @@ -25,7 +25,7 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/go-logr/zapr" - kcpcorev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1" + kcpcorev1alpha1 "github.com/kcp-dev/sdk/apis/core/v1alpha1" "github.com/spf13/pflag" "go.uber.org/zap/zapcore" diff --git a/go.mod b/go.mod index 806c8900..97e03a44 100644 --- a/go.mod +++ b/go.mod @@ -1,31 +1,30 @@ module github.com/kcp-dev/kcp-operator -go 1.24.0 +go 1.25.0 replace github.com/kcp-dev/kcp-operator/sdk => ./sdk require ( - github.com/Masterminds/semver/v3 v3.2.1 - github.com/cert-manager/cert-manager v1.18.5 + github.com/Masterminds/semver/v3 v3.4.0 + github.com/cert-manager/cert-manager v1.20.2 github.com/go-logr/logr v1.4.3 github.com/go-logr/zapr v1.3.0 - github.com/go-test/deep v1.1.0 - github.com/kcp-dev/kcp-operator/sdk v0.0.0-00010101000000-000000000000 - github.com/kcp-dev/kcp/sdk v0.28.3 + github.com/go-test/deep v1.1.1 + github.com/kcp-dev/kcp-operator/sdk v0.7.0 github.com/kcp-dev/logicalcluster/v3 v3.0.5 - github.com/kcp-dev/sdk v0.30.0 - github.com/prometheus/client_golang v1.22.0 - github.com/spf13/pflag v1.0.6 + github.com/kcp-dev/sdk v0.31.0 + github.com/prometheus/client_golang v1.23.2 + github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 - go.uber.org/zap v1.27.0 + go.uber.org/zap v1.27.1 k8c.io/reconciler v0.5.0 - k8s.io/api v0.34.2 - k8s.io/apimachinery v0.34.2 - k8s.io/client-go v0.34.2 - k8s.io/component-base v0.34.2 - k8s.io/klog/v2 v2.130.1 - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 - sigs.k8s.io/controller-runtime v0.19.0 + k8s.io/api v0.35.4 + k8s.io/apimachinery v0.35.4 + k8s.io/client-go v0.35.4 + k8s.io/component-base v0.35.4 + k8s.io/klog/v2 v2.140.0 + k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 + sigs.k8s.io/controller-runtime v0.23.3 sigs.k8s.io/yaml v1.6.0 ) @@ -38,72 +37,79 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/egymgmbh/go-prefix-writer v0.0.0-20180609083313-7326ea162eca // indirect - github.com/emicklei/go-restful/v3 v3.12.2 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/cel-go v0.26.0 // indirect - github.com/google/gnostic-models v0.7.0 // indirect + github.com/go-openapi/jsonpointer v0.23.0 // indirect + github.com/go-openapi/jsonreference v0.21.5 // indirect + github.com/go-openapi/swag v0.26.0 // indirect + github.com/go-openapi/swag/cmdutils v0.26.0 // indirect + github.com/go-openapi/swag/conv v0.26.0 // indirect + github.com/go-openapi/swag/fileutils v0.26.0 // indirect + github.com/go-openapi/swag/jsonname v0.26.0 // indirect + github.com/go-openapi/swag/jsonutils v0.26.0 // indirect + github.com/go-openapi/swag/loading v0.26.0 // indirect + github.com/go-openapi/swag/mangling v0.26.0 // indirect + github.com/go-openapi/swag/netutils v0.26.0 // indirect + github.com/go-openapi/swag/stringutils v0.26.0 // indirect + github.com/go-openapi/swag/typeutils v0.26.0 // indirect + github.com/go-openapi/swag/yamlutils v0.26.0 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/cel-go v0.28.0 // indirect + github.com/google/gnostic-models v0.7.1 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.9.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/onsi/gomega v1.36.2 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/onsi/gomega v1.39.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/spf13/cobra v1.9.1 // indirect - github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + github.com/spf13/cobra v1.10.2 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0 // indirect - go.opentelemetry.io/otel v1.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.41.0 // indirect - go.opentelemetry.io/otel/metric v1.41.0 // indirect - go.opentelemetry.io/otel/sdk v1.41.0 // indirect - go.opentelemetry.io/otel/trace v1.41.0 // indirect - go.opentelemetry.io/proto/otlp v1.9.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect go.uber.org/goleak v1.3.1-0.20251210191316-2b7fd8a0d244 // indirect go.uber.org/multierr v1.11.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 // indirect - golang.org/x/net v0.50.0 // indirect - golang.org/x/oauth2 v0.35.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.41.0 // indirect - golang.org/x/term v0.40.0 // indirect - golang.org/x/text v0.34.0 // indirect - golang.org/x/time v0.14.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect + golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/text v0.36.0 // indirect + golang.org/x/time v0.15.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect google.golang.org/grpc v1.80.0 // indirect google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.34.2 // indirect - k8s.io/apiserver v0.34.2 // indirect - k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect - sigs.k8s.io/gateway-api v1.1.0 // indirect - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + k8s.io/apiextensions-apiserver v0.35.4 // indirect + k8s.io/apiserver v0.35.4 // indirect + k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect + sigs.k8s.io/gateway-api v1.5.1 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.4.0 // indirect ) diff --git a/go.sum b/go.sum index 0fd54fcb..a1851a6e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -10,8 +10,8 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= -github.com/cert-manager/cert-manager v1.18.5 h1:Gx4FSpSPYcSC4MQf43QjbxDfyTEbwZgfZQs5Lq9QlBs= -github.com/cert-manager/cert-manager v1.18.5/go.mod h1:HbPSO5MW/44wu19t84eY/K4c4/WwyPB4bA3uffOH92s= +github.com/cert-manager/cert-manager v1.20.2 h1:CimnY00nLqB2lmxhoSuEC4GDMFDK7JCXqyjwMM9ndIQ= +github.com/cert-manager/cert-manager v1.20.2/go.mod h1:1g/+a/WK5zWH/dXPZa3dMD3aJQJNRXQu+PN17C6WrOw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -21,18 +21,18 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/egymgmbh/go-prefix-writer v0.0.0-20180609083313-7326ea162eca h1:7oodhZp9MZW0DBkrZXyUsJWKQFy35SVxjZ8K4vHXnk8= github.com/egymgmbh/go-prefix-writer v0.0.0-20180609083313-7326ea162eca/go.mod h1:UhMFM+dnOcm1f0Pve8uqRaxAhEYki+/CuA2BTDp2T04= -github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= -github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= -github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ= +github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -40,49 +40,71 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/jsonpointer v0.23.0 h1:c25HFTJ6uWGmoe5BQI6p72p4o7KnlWYsy1MeFlAumsw= +github.com/go-openapi/jsonpointer v0.23.0/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY= +github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= +github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= +github.com/go-openapi/swag v0.26.0 h1:GVDXCmfvhfu1BxiHo8/FA+BbKmhecHnG3varjON5/RI= +github.com/go-openapi/swag v0.26.0/go.mod h1:82g3193sZJRbocs7bNCqGfIgq8pkuwVwCfhKIRlEQF0= +github.com/go-openapi/swag/cmdutils v0.26.0 h1:iowihOcvq7y4egO8cOq0dmfohz6wfeQ63U1EnuhO2TU= +github.com/go-openapi/swag/cmdutils v0.26.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= +github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I= +github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE= +github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU= +github.com/go-openapi/swag/fileutils v0.26.0/go.mod h1:0WDJ7lp67eNjPMO50wAWYlKvhOb6CQ37rzR7wrgI8Tc= +github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w= +github.com/go-openapi/swag/jsonname v0.26.0/go.mod h1:urBBR8bZNoDYGr653ynhIx+gTeIz0ARZxHkAPktJK2M= +github.com/go-openapi/swag/jsonutils v0.26.0 h1:FawFML2iAXsPqmERscuMPIHmFsoP1tOqWkxBaKNMsnA= +github.com/go-openapi/swag/jsonutils v0.26.0/go.mod h1:2VmA0CJlyFqgawOaPI9psnjFDqzyivIqLYN34t9p91E= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0 h1:apqeINu/ICHouqiRZbyFvuDge5jCmmLTqGQ9V95EaOM= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0/go.mod h1:AyM6QT8uz5IdKxk5akv0y6u4QvcL9GWERt0Jx/F/R8Y= +github.com/go-openapi/swag/loading v0.26.0 h1:Apg6zaKhCJurpJer0DCxq99qwmhFddBhaMX7kilDcko= +github.com/go-openapi/swag/loading v0.26.0/go.mod h1:dBxQ/6V2uBaAQdevN18VELE6xSpJWZxLX4txe12JwDg= +github.com/go-openapi/swag/mangling v0.26.0 h1:Du2YC4YLA/Y5m/YKQd7AnY5qq0wRKSFZTTt8ktFaXcQ= +github.com/go-openapi/swag/mangling v0.26.0/go.mod h1:jifS7W9vbg+pw63bT+GI53otluMQL3CeemuyCHKwVx0= +github.com/go-openapi/swag/netutils v0.26.0 h1:CmZp+ZT7HrmFwrC3GdGsXBq2+42T1bjKBapcqVpIs3c= +github.com/go-openapi/swag/netutils v0.26.0/go.mod h1:5iK+Ok3ZohWWex1C50BFTPexi03UaPwjW4Oj8kgrpwo= +github.com/go-openapi/swag/stringutils v0.26.0 h1:qZQngLxs5s7SLijc3N2ZO+fUq2o8LjuWAASSrJuh+xg= +github.com/go-openapi/swag/stringutils v0.26.0/go.mod h1:sWn5uY+QIIspwPhvgnqJsH8xqFT2ZbYcvbcFanRyhFE= +github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFuuyQIKYybfq4= +github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE= +github.com/go-openapi/swag/yamlutils v0.26.0 h1:H7O8l/8NJJQ/oiReEN+oMpnGMyt8G0hl460nRZxhLMQ= +github.com/go-openapi/swag/yamlutils v0.26.0/go.mod h1:1evKEGAtP37Pkwcc7EWMF0hedX0/x3Rkvei2wtG/TbU= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.2 h1:5zRca5jw7lzVREKCZVNBpysDNBjj74rBh0N2BGQbSR0= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.2/go.mod h1:XVevPw5hUXuV+5AkI1u1PeAm27EQVrhXTTCPAF85LmE= +github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4= +github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= -github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= -github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= -github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= -github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/cel-go v0.28.0 h1:KjSWstCpz/MN5t4a8gnGJNIYUsJRpdi/r97xWDphIQc= +github.com/google/cel-go v0.28.0/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8= +github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c= +github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.1-0.20210504230335-f78f29fc09ea h1:VcIYpAGBae3Z6BVncE0OnTE/ZjlDXqtYhOZky88neLM= github.com/google/gofuzz v1.2.1-0.20210504230335-f78f29fc09ea/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kcp-dev/kcp/sdk v0.28.3 h1:TS2nJOVBjenBd3fz1+y3aNrqZWqmakalNAIcQM9SukQ= -github.com/kcp-dev/kcp/sdk v0.28.3/go.mod h1:8oZpWxkoMu2TDpx5DgdIGDigByKHKkeqVMA4GiWneoI= github.com/kcp-dev/logicalcluster/v3 v3.0.5 h1:JbYakokb+5Uinz09oTXomSUJVQsqfxEvU4RyHUYxHOU= github.com/kcp-dev/logicalcluster/v3 v3.0.5/go.mod h1:EWBUBxdr49fUB1cLMO4nOdBWmYifLbP1LfoL20KkXYY= -github.com/kcp-dev/sdk v0.30.0 h1:BdDiKJ7SeVfzLIxueQwbADTrH7bfZ7b5ACYSrx6P93Y= -github.com/kcp-dev/sdk v0.30.0/go.mod h1:H3PkpM33QqwPMgGOOw3dfqbQ8dF2gu4NeIsufSlS5KE= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kcp-dev/sdk v0.31.0 h1:fLqgY6MHVmmBcttqR/V3h2Dnv7xmab84FTKTwV08+Bo= +github.com/kcp-dev/sdk v0.31.0/go.mod h1:GpNW9wPULY9+UuLVAaB5z/sJ8r0Jo/l0Jgy4BKnIJTE= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -91,8 +113,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -101,128 +121,97 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM= -github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/ginkgo/v2 v2.28.0 h1:Rrf+lVLmtlBIKv6KrIGJCjyY8N36vDVcutbGJkyqjJc= +github.com/onsi/ginkgo/v2 v2.28.0/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= -github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0 h1:PnV4kVnw0zOmwwFkAzCN5O07fw1YOIQor120zrh0AVo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.66.0/go.mod h1:ofAwF4uinaf8SXdVzzbL4OsxJ3VfeEg3f/F6CeF49/Y= -go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c= -go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0 h1:ao6Oe+wSebTlQ1OEht7jlYTzQKE+pnx/iNywFvTbuuI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.41.0/go.mod h1:u3T6vz0gh/NVzgDgiwkgLxpsSF6PaPmo2il0apGJbls= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.41.0 h1:mq/Qcf28TWz719lE3/hMB4KkyDuLJIvgJnFGcd0kEUI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.41.0/go.mod h1:yk5LXEYhsL2htyDNJbEq7fWzNEigeEdV5xBF/Y+kAv0= -go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ= -go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps= -go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8= -go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90= -go.opentelemetry.io/otel/sdk/metric v1.41.0 h1:siZQIYBAUd1rlIWQT2uCxWJxcCO7q3TriaMlf08rXw8= -go.opentelemetry.io/otel/sdk/metric v1.41.0/go.mod h1:HNBuSvT7ROaGtGI50ArdRLUnvRTRGniSUZbxiWxSO8Y= -go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= -go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= -go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= -go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/goleak v1.3.1-0.20251210191316-2b7fd8a0d244 h1:OdZ8e4E9yDUGiis9x2ta/Ec5yhMAKT6ZivRvakyxC7E= go.uber.org/goleak v1.3.1-0.20251210191316-2b7fd8a0d244/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 h1:DHNhtq3sNNzrvduZZIiFyXWOL9IWaDPHqTnLJp+rCBY= -golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= -golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= +gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0= -google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec= +google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= @@ -230,44 +219,43 @@ google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8c.io/reconciler v0.5.0 h1:BHpelg1UfI/7oBFctqOq8sX6qzflXpl3SlvHe7e8wak= k8c.io/reconciler v0.5.0/go.mod h1:pT1+SVcVXJQeBJhpJBXQ5XW64QnKKeYTnVlQf0dGE0k= -k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= -k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= -k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo= -k8s.io/apiextensions-apiserver v0.34.2/go.mod h1:398CJrsgXF1wytdaanynDpJ67zG4Xq7yj91GrmYN2SE= -k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= -k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/apiserver v0.34.2 h1:2/yu8suwkmES7IzwlehAovo8dDE07cFRC7KMDb1+MAE= -k8s.io/apiserver v0.34.2/go.mod h1:gqJQy2yDOB50R3JUReHSFr+cwJnL8G1dzTA0YLEqAPI= -k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M= -k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE= -k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ= -k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= -sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= -sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM= -sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +k8s.io/api v0.35.4 h1:P7nFYKl5vo9AGUp1Z+Pmd3p2tA7bX2wbFWCvDeRv988= +k8s.io/api v0.35.4/go.mod h1:yl4lqySWOgYJJf9RERXKUwE9g2y+CkuwG+xmcOK8wXU= +k8s.io/apiextensions-apiserver v0.35.4 h1:HeP+Upp7ItdvnyGmub0yoix+2z5+ev4M5cE5TCgtOUU= +k8s.io/apiextensions-apiserver v0.35.4/go.mod h1:ogQlk+stIE8mnoRthSYCwlOS12fVqgWFiErMwPaXA7c= +k8s.io/apimachinery v0.35.4 h1:xtdom9RG7e+yDp71uoXoJDWEE2eOiHgeO4GdBzwWpds= +k8s.io/apimachinery v0.35.4/go.mod h1:NNi1taPOpep0jOj+oRha3mBJPqvi0hGdaV8TCqGQ+cc= +k8s.io/apiserver v0.35.4 h1:vtuFqNFmF9bPRdHDL2lpK6qCTPWDreZJL4LRPwVM6ho= +k8s.io/apiserver v0.35.4/go.mod h1:JnBcb+J8kFXKpZkgcbcUnPBBHi4qgBii1I7dLxFY/oo= +k8s.io/client-go v0.35.4 h1:DN6fyaGuzK64UvnKO5fOA6ymSjvfGAnCAHAR0C66kD8= +k8s.io/client-go v0.35.4/go.mod h1:2Pg9WpsS4NeOpoYTfHHfMxBG8zFMSAUi4O/qoiJC3nY= +k8s.io/component-base v0.35.4 h1:6n1tNJ87johN0Hif0Fs8K2GMthsaUwMqCebUDLYyv7U= +k8s.io/component-base v0.35.4/go.mod h1:qaDJgz5c1KYKla9occFmlJEfPpkuA55s90G509R+PeY= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f h1:4Qiq0YAoQATdgmHALJWz9rJ4fj20pB3xebpB4CFNhYM= +k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= +sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= +sigs.k8s.io/gateway-api v1.5.1 h1:RqVRIlkhLhUO8wOHKTLnTJA6o/1un4po4/6M1nRzdd0= +sigs.k8s.io/gateway-api v1.5.1/go.mod h1:GvCETiaMAlLym5CovLxGjS0NysqFk3+Yuq3/rh6QL2o= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.4.0 h1:qmp2e3ZfFi1/jJbDGpD4mt3wyp6PE1NfKHCYLqgNQJo= +sigs.k8s.io/structured-merge-diff/v6 v6.4.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/internal/controller/shard/controller.go b/internal/controller/shard/controller.go index ee98db43..2dd0d642 100644 --- a/internal/controller/shard/controller.go +++ b/internal/controller/shard/controller.go @@ -24,8 +24,8 @@ import ( "time" certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - kcpcorev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1" "github.com/kcp-dev/logicalcluster/v3" + kcpcorev1alpha1 "github.com/kcp-dev/sdk/apis/core/v1alpha1" k8creconciling "k8c.io/reconciler/pkg/reconciling" appsv1 "k8s.io/api/apps/v1" diff --git a/internal/resources/cacheserver/certificates.go b/internal/resources/cacheserver/certificates.go index f0146b33..82fad5f7 100644 --- a/internal/resources/cacheserver/certificates.go +++ b/internal/resources/cacheserver/certificates.go @@ -56,7 +56,7 @@ func RootCACertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili Size: 4096, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: server.Spec.Certificates.IssuerRef.Name, Kind: server.Spec.Certificates.IssuerRef.Kind, Group: server.Spec.Certificates.IssuerRef.Group, @@ -105,7 +105,7 @@ func ClientCertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili certmanagerv1.UsageDigitalSignature, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetCacheServerCAName(server.Name, operatorv1alpha1.RootCA), Kind: "Issuer", Group: "cert-manager.io", @@ -153,7 +153,7 @@ func ServerCertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili resources.GetCacheServerBaseHost(server), }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetCacheServerCAName(server.Name, operatorv1alpha1.RootCA), Kind: "Issuer", Group: "cert-manager.io", diff --git a/internal/resources/frontproxy/certificates.go b/internal/resources/frontproxy/certificates.go index 4c1dddf1..bb12d2f1 100644 --- a/internal/resources/frontproxy/certificates.go +++ b/internal/resources/frontproxy/certificates.go @@ -120,7 +120,7 @@ func (r *reconciler) serverCertificateReconciler() reconciling.NamedCertificateR DNSNames: dnsNames, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", @@ -165,7 +165,7 @@ func (r *reconciler) adminKubeconfigCertificateReconciler() reconciling.NamedCer Organizations: []string{"system:kcp:external-logical-cluster-admin"}, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.FrontProxyClientCA), Kind: "Issuer", Group: "cert-manager.io", @@ -209,7 +209,7 @@ func (r *reconciler) kubeconfigCertificateReconciler() reconciling.NamedCertific certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", @@ -249,7 +249,7 @@ func (r *reconciler) requestHeaderCertificateReconciler() reconciling.NamedCerti certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.RequestHeaderClientCA), Kind: "Issuer", Group: "cert-manager.io", diff --git a/internal/resources/kubeconfig/certificate.go b/internal/resources/kubeconfig/certificate.go index 65545d86..f8906bef 100644 --- a/internal/resources/kubeconfig/certificate.go +++ b/internal/resources/kubeconfig/certificate.go @@ -58,7 +58,7 @@ func ClientCertificateReconciler(kubeConfig *operatorv1alpha1.Kubeconfig, issuer Organizations: sets.List(orgs), }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: issuerName, Kind: "Issuer", Group: "cert-manager.io", diff --git a/internal/resources/rootshard/ca_certificates.go b/internal/resources/rootshard/ca_certificates.go index 18a776ba..94d40496 100644 --- a/internal/resources/rootshard/ca_certificates.go +++ b/internal/resources/rootshard/ca_certificates.go @@ -56,7 +56,7 @@ func RootCACertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil Size: 4096, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: rootShard.Spec.Certificates.IssuerRef.Name, Kind: rootShard.Spec.Certificates.IssuerRef.Kind, Group: rootShard.Spec.Certificates.IssuerRef.Group, @@ -92,7 +92,7 @@ func CACertificateReconciler(rootShard *operatorv1alpha1.RootShard, ca operatorv Size: 4096, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.RootCA), Kind: "Issuer", Group: "cert-manager.io", diff --git a/internal/resources/rootshard/certificates.go b/internal/resources/rootshard/certificates.go index eb6e32f6..8cdb8c08 100644 --- a/internal/resources/rootshard/certificates.go +++ b/internal/resources/rootshard/certificates.go @@ -60,7 +60,7 @@ func ServerCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil DNSNames: buildRootShardDNSNames(rootShard), - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", @@ -104,7 +104,7 @@ func VirtualWorkspacesCertificateReconciler(rootShard *operatorv1alpha1.RootShar rootShard.Spec.External.Hostname, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", @@ -146,7 +146,7 @@ func ServiceAccountCertificateReconciler(rootShard *operatorv1alpha1.RootShard) Size: 4096, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Kind: "Issuer", Group: "cert-manager.io", @@ -191,7 +191,7 @@ func LogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha1.RootSh certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", @@ -236,7 +236,7 @@ func ExternalLogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Kind: "Issuer", Group: "cert-manager.io", @@ -281,7 +281,7 @@ func OperatorClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ // This shard is meant to be used against shards directly (cluster-local) or with // the internal root shard proxy (also cluster-local). All of these are configured // to use the regular client CA (not like "normal" front-proxies, which have their @@ -333,7 +333,7 @@ func ClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", diff --git a/internal/resources/shard/certificates.go b/internal/resources/shard/certificates.go index bc190b1d..87093bec 100644 --- a/internal/resources/shard/certificates.go +++ b/internal/resources/shard/certificates.go @@ -64,7 +64,7 @@ func ServerCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *opera DNSNames: buildShardDNSNames(shard), - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", @@ -110,7 +110,7 @@ func VirtualWorkspacesCertificateReconciler(shard *operatorv1alpha1.Shard, rootS resources.GetShardBaseHost(shard), }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", @@ -154,7 +154,7 @@ func ServiceAccountCertificateReconciler(shard *operatorv1alpha1.Shard, rootShar Size: 4096, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Kind: "Issuer", Group: "cert-manager.io", @@ -201,7 +201,7 @@ func RootShardClientCertificateReconciler(shard *operatorv1alpha1.Shard, rootSha certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", @@ -248,7 +248,7 @@ func LogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Shard, roo certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", @@ -295,7 +295,7 @@ func ExternalLogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Sh certmanagerv1.UsageClientAuth, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Kind: "Issuer", Group: "cert-manager.io", diff --git a/internal/resources/utils/certificates.go b/internal/resources/utils/certificates.go index 551bdeef..5824a8c9 100644 --- a/internal/resources/utils/certificates.go +++ b/internal/resources/utils/certificates.go @@ -101,7 +101,7 @@ func applyCertificateSpecTemplate(cert *certmanagerv1.Certificate, tpl *operator cert.Spec.SecretTemplate.Labels = addNewKeys(cert.Spec.SecretTemplate.Labels, secretTpl.Labels) } if tpl.IssuerRef != nil { - cert.Spec.IssuerRef = cmmeta.ObjectReference{ + cert.Spec.IssuerRef = cmmeta.IssuerReference{ Name: tpl.IssuerRef.Name, Kind: tpl.IssuerRef.Kind, Group: tpl.IssuerRef.Group, diff --git a/internal/resources/virtualworkspace/certificate.go b/internal/resources/virtualworkspace/certificate.go index 067cfd88..e0b4e4e1 100644 --- a/internal/resources/virtualworkspace/certificate.go +++ b/internal/resources/virtualworkspace/certificate.go @@ -68,7 +68,7 @@ func ClientCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, issuerNa Organizations: []string{"system:masters"}, }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: issuerName, Kind: "Issuer", Group: "cert-manager.io", @@ -116,7 +116,7 @@ func ServerCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShar resources.GetVirtualWorkspaceBaseHost(vw), }, - IssuerRef: certmanagermetav1.ObjectReference{ + IssuerRef: certmanagermetav1.IssuerReference{ Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", From 7ba6f8dd6af4dd72dfa6da1281bf85c7b8d8986d Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Mon, 20 Apr 2026 08:42:10 +0200 Subject: [PATCH 07/13] bump cert-manager to 1.20.2 (#220) On-behalf-of: @SAP christoph.mewes@sap.com --- .../continuous-integration/index.md | 2 +- docs/content/contributing/local-setup.md | 2 +- hack/ci/run-e2e-tests.sh | 2 +- hack/run-e2e-tests.sh | 2 +- test/crds/README.md | 2 +- test/crds/cert-manager.crds.yaml | 203 ++++++++++++------ 6 files changed, 140 insertions(+), 73 deletions(-) diff --git a/docs/content/contributing/continuous-integration/index.md b/docs/content/contributing/continuous-integration/index.md index 343e51fd..83987178 100644 --- a/docs/content/contributing/continuous-integration/index.md +++ b/docs/content/contributing/continuous-integration/index.md @@ -13,6 +13,6 @@ Here are the most important links: In order to run the E2E tests locally, you will need to setup cert-manager with the sample clusterissuer: ```sh -helm upgrade --install --namespace cert-manager --create-namespace --version v1.19.3 --set crds.enabled=true cert-manager jetstack/cert-manager +helm upgrade --install --namespace cert-manager --create-namespace --version v1.20.2 --set crds.enabled=true cert-manager jetstack/cert-manager kubectl apply -n cert-manager --filename hack/ci/testdata/clusterissuer.yaml ``` diff --git a/docs/content/contributing/local-setup.md b/docs/content/contributing/local-setup.md index 4c423886..da63b949 100644 --- a/docs/content/contributing/local-setup.md +++ b/docs/content/contributing/local-setup.md @@ -31,7 +31,7 @@ kind create cluster Install cert-manager, it is required to create kcp's PKI: ```sh -kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.3/cert-manager.yaml +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.yaml ``` Set up two etcd instances, one for the root shard and one for a supplementary shard: diff --git a/hack/ci/run-e2e-tests.sh b/hack/ci/run-e2e-tests.sh index b2662086..b3203465 100755 --- a/hack/ci/run-e2e-tests.sh +++ b/hack/ci/run-e2e-tests.sh @@ -134,7 +134,7 @@ echo "Deploying cert-manager..." --install \ --namespace cert-manager \ --create-namespace \ - --version v1.19.3 \ + --version v1.20.2 \ --set crds.enabled=true \ cert-manager jetstack/cert-manager diff --git a/hack/run-e2e-tests.sh b/hack/run-e2e-tests.sh index 1d427f48..03ce138d 100755 --- a/hack/run-e2e-tests.sh +++ b/hack/run-e2e-tests.sh @@ -139,7 +139,7 @@ echo "Deploying cert-manager..." --install \ --namespace cert-manager \ --create-namespace \ - --version v1.19.3 \ + --version v1.20.2 \ --set crds.enabled=true \ --atomic \ cert-manager jetstack/cert-manager diff --git a/test/crds/README.md b/test/crds/README.md index b855f44f..e7a658a1 100644 --- a/test/crds/README.md +++ b/test/crds/README.md @@ -1,4 +1,4 @@ # Third-party CRDs Sourced from: -- `https://github.com/cert-manager/cert-manager/releases/download/v1.19.3/cert-manager.crds.yaml` +- `https://github.com/cert-manager/cert-manager/releases/download/v1.20.2/cert-manager.crds.yaml` diff --git a/test/crds/cert-manager.crds.yaml b/test/crds/cert-manager.crds.yaml index f4cf1864..16c2a983 100644 --- a/test/crds/cert-manager.crds.yaml +++ b/test/crds/cert-manager.crds.yaml @@ -24,7 +24,7 @@ metadata: app.kubernetes.io/name: "cert-manager" app.kubernetes.io/instance: "cert-manager" app.kubernetes.io/component: "crds" - app.kubernetes.io/version: "v1.19.3" + app.kubernetes.io/version: "v1.20.2" spec: group: acme.cert-manager.io names: @@ -299,6 +299,22 @@ spec: The TenantID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientID and ClientSecret must also be set. type: string + zoneType: + description: |- + ZoneType determines which type of Azure DNS zone to use. + + Valid values are: + - AzurePublicZone (default): Use a public Azure DNS zone. + - AzurePrivateZone: Use an Azure Private DNS zone. + + If not specified, AzurePublicZone is used. + + Support for Azure Private DNS zones is currently + experimental and may change in future releases. + enum: + - AzurePublicZone + - AzurePrivateZone + type: string required: - resourceGroupName - subscriptionID @@ -422,7 +438,7 @@ spec: description: |- The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be - enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + enclosed in square brackets (e.g [2001:db8::1]); port is optional. This field is required. type: string protocol: @@ -472,8 +488,8 @@ spec: description: |- The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: string accessKeyIDSecretRef: @@ -481,8 +497,8 @@ spec: The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials properties: key: @@ -571,8 +587,8 @@ spec: secretAccessKeySecretRef: description: |- The SecretAccessKey is used for authentication. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials properties: key: @@ -1929,9 +1945,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -3140,9 +3157,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -3290,6 +3308,10 @@ spec: - metadata - spec type: object + selectableFields: + - jsonPath: .spec.issuerRef.group + - jsonPath: .spec.issuerRef.kind + - jsonPath: .spec.issuerRef.name served: true storage: true subresources: @@ -3307,7 +3329,7 @@ metadata: app.kubernetes.io/name: "cert-manager" app.kubernetes.io/instance: "cert-manager" app.kubernetes.io/component: "crds" - app.kubernetes.io/version: "v1.19.3" + app.kubernetes.io/version: "v1.20.2" spec: group: acme.cert-manager.io names: @@ -3566,6 +3588,10 @@ spec: - metadata - spec type: object + selectableFields: + - jsonPath: .spec.issuerRef.group + - jsonPath: .spec.issuerRef.kind + - jsonPath: .spec.issuerRef.name served: true storage: true subresources: @@ -3583,7 +3609,7 @@ metadata: app.kubernetes.io/name: "cert-manager" app.kubernetes.io/instance: "cert-manager" app.kubernetes.io/component: "crds" - app.kubernetes.io/version: "v1.19.3" + app.kubernetes.io/version: "v1.20.2" spec: group: cert-manager.io names: @@ -3887,6 +3913,10 @@ spec: type: string type: object type: object + selectableFields: + - jsonPath: .spec.issuerRef.group + - jsonPath: .spec.issuerRef.kind + - jsonPath: .spec.issuerRef.name served: true storage: true subresources: @@ -3904,7 +3934,7 @@ metadata: app.kubernetes.io/name: "cert-manager" app.kubernetes.io/instance: "cert-manager" app.kubernetes.io/component: "crds" - app.kubernetes.io/version: "v1.19.3" + app.kubernetes.io/version: "v1.20.2" spec: group: cert-manager.io names: @@ -4347,9 +4377,6 @@ spec: will be generated whenever a re-issuance occurs. Default is `Always`. The default was changed from `Never` to `Always` in cert-manager >=v1.18.0. - The new default can be disabled by setting the - `--feature-gates=DefaultPrivateKeyRotationPolicyAlways=false` option on - the controller component. enum: - Never - Always @@ -4705,6 +4732,10 @@ spec: type: integer type: object type: object + selectableFields: + - jsonPath: .spec.issuerRef.group + - jsonPath: .spec.issuerRef.kind + - jsonPath: .spec.issuerRef.name served: true storage: true subresources: @@ -4722,7 +4753,7 @@ metadata: app.kubernetes.io/name: "cert-manager" app.kubernetes.io/instance: "cert-manager" app.kubernetes.io/component: "crds" - app.kubernetes.io/version: "v1.19.3" + app.kubernetes.io/version: "v1.20.2" spec: group: cert-manager.io names: @@ -5110,6 +5141,22 @@ spec: The TenantID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientID and ClientSecret must also be set. type: string + zoneType: + description: |- + ZoneType determines which type of Azure DNS zone to use. + + Valid values are: + - AzurePublicZone (default): Use a public Azure DNS zone. + - AzurePrivateZone: Use an Azure Private DNS zone. + + If not specified, AzurePublicZone is used. + + Support for Azure Private DNS zones is currently + experimental and may change in future releases. + enum: + - AzurePublicZone + - AzurePrivateZone + type: string required: - resourceGroupName - subscriptionID @@ -5233,7 +5280,7 @@ spec: description: |- The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be - enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + enclosed in square brackets (e.g [2001:db8::1]); port is optional. This field is required. type: string protocol: @@ -5283,8 +5330,8 @@ spec: description: |- The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: string accessKeyIDSecretRef: @@ -5292,8 +5339,8 @@ spec: The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials properties: key: @@ -5382,8 +5429,8 @@ spec: secretAccessKeySecretRef: description: |- The SecretAccessKey is used for authentication. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials properties: key: @@ -6740,9 +6787,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -7951,9 +7999,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -8210,8 +8259,8 @@ spec: properties: audiences: description: |- - TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token - consisting of the issuer's namespace and name is always included. + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. + The default audiences are always included in the token. items: type: string type: array @@ -8339,16 +8388,16 @@ spec: type: object venafi: description: |- - Venafi configures this issuer to sign certificates using a Venafi TPP - or Venafi Cloud policy zone. + Venafi configures this issuer to sign certificates using a CyberArk Certificate Manager Self-Hosted + or SaaS policy zone. properties: cloud: description: |- - Cloud specifies the Venafi cloud configuration settings. - Only one of TPP or Cloud may be specified. + Cloud specifies the CyberArk Certificate Manager SaaS configuration settings. + Only one of CyberArk Certificate Manager may be specified. properties: apiTokenSecretRef: - description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + description: APITokenSecretRef is a secret key selector for the CyberArk Certificate Manager SaaS API token. properties: key: description: |- @@ -8366,7 +8415,7 @@ spec: type: object url: description: |- - URL is the base URL for Venafi Cloud. + URL is the base URL for CyberArk Certificate Manager SaaS. Defaults to "https://api.venafi.cloud/". type: string required: @@ -8374,13 +8423,13 @@ spec: type: object tpp: description: |- - TPP specifies Trust Protection Platform configuration settings. - Only one of TPP or Cloud may be specified. + TPP specifies CyberArk Certificate Manager Self-Hosted configuration settings. + Only one of CyberArk Certificate Manager may be specified. properties: caBundle: description: |- Base64-encoded bundle of PEM CAs which will be used to validate the certificate - chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + chain presented by the CyberArk Certificate Manager Self-Hosted server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. format: byte @@ -8388,7 +8437,7 @@ spec: caBundleSecretRef: description: |- Reference to a Secret containing a base64-encoded bundle of PEM CAs - which will be used to validate the certificate chain presented by the TPP server. + which will be used to validate the certificate chain presented by the CyberArk Certificate Manager Self-Hosted server. Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. @@ -8409,7 +8458,7 @@ spec: type: object credentialsRef: description: |- - CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + CredentialsRef is a reference to a Secret containing the CyberArk Certificate Manager Self-Hosted API credentials. The secret must contain the key 'access-token' for the Access Token Authentication, or two keys, 'username' and 'password' for the API Keys Authentication. properties: @@ -8423,7 +8472,7 @@ spec: type: object url: description: |- - URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + URL is the base URL for the vedsdk endpoint of the CyberArk Certificate Manager Self-Hosted instance, for example: "https://tpp.example.com/vedsdk". type: string required: @@ -8432,8 +8481,8 @@ spec: type: object zone: description: |- - Zone is the Venafi Policy Zone to use for this issuer. - All requests made to the Venafi platform will be restricted by the named + Zone is the Certificate Manager Policy Zone to use for this issuer. + All requests made to the Certificate Manager platform will be restricted by the named zone policy. This field is required. type: string @@ -8539,7 +8588,7 @@ metadata: app.kubernetes.io/name: "cert-manager" app.kubernetes.io/instance: "cert-manager" app.kubernetes.io/component: "crds" - app.kubernetes.io/version: "v1.19.3" + app.kubernetes.io/version: "v1.20.2" spec: group: cert-manager.io names: @@ -8926,6 +8975,22 @@ spec: The TenantID of the Azure Service Principal used to authenticate with Azure DNS. If set, ClientID and ClientSecret must also be set. type: string + zoneType: + description: |- + ZoneType determines which type of Azure DNS zone to use. + + Valid values are: + - AzurePublicZone (default): Use a public Azure DNS zone. + - AzurePrivateZone: Use an Azure Private DNS zone. + + If not specified, AzurePublicZone is used. + + Support for Azure Private DNS zones is currently + experimental and may change in future releases. + enum: + - AzurePublicZone + - AzurePrivateZone + type: string required: - resourceGroupName - subscriptionID @@ -9049,7 +9114,7 @@ spec: description: |- The IP address or hostname of an authoritative DNS server supporting RFC2136 in the form host:port. If the host is an IPv6 address it must be - enclosed in square brackets (e.g [2001:db8::1]) ; port is optional. + enclosed in square brackets (e.g [2001:db8::1]); port is optional. This field is required. type: string protocol: @@ -9099,8 +9164,8 @@ spec: description: |- The AccessKeyID is used for authentication. Cannot be set when SecretAccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials type: string accessKeyIDSecretRef: @@ -9108,8 +9173,8 @@ spec: The SecretAccessKey is used for authentication. If set, pull the AWS access key ID from a key within a Kubernetes Secret. Cannot be set when AccessKeyID is set. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials properties: key: @@ -9198,8 +9263,8 @@ spec: secretAccessKeySecretRef: description: |- The SecretAccessKey is used for authentication. - If neither the Access Key nor Key ID are set, we fall-back to using env - vars, shared credentials file or AWS Instance metadata, + If neither the Access Key nor Key ID are set, we fall back to using env + vars, shared credentials file, or AWS Instance metadata, see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials properties: key: @@ -10556,9 +10621,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -11767,9 +11833,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -12026,8 +12093,8 @@ spec: properties: audiences: description: |- - TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. The default token - consisting of the issuer's namespace and name is always included. + TokenAudiences is an optional list of extra audiences to include in the token passed to Vault. + The default audiences are always included in the token. items: type: string type: array @@ -12155,16 +12222,16 @@ spec: type: object venafi: description: |- - Venafi configures this issuer to sign certificates using a Venafi TPP - or Venafi Cloud policy zone. + Venafi configures this issuer to sign certificates using a CyberArk Certificate Manager Self-Hosted + or SaaS policy zone. properties: cloud: description: |- - Cloud specifies the Venafi cloud configuration settings. - Only one of TPP or Cloud may be specified. + Cloud specifies the CyberArk Certificate Manager SaaS configuration settings. + Only one of CyberArk Certificate Manager may be specified. properties: apiTokenSecretRef: - description: APITokenSecretRef is a secret key selector for the Venafi Cloud API token. + description: APITokenSecretRef is a secret key selector for the CyberArk Certificate Manager SaaS API token. properties: key: description: |- @@ -12182,7 +12249,7 @@ spec: type: object url: description: |- - URL is the base URL for Venafi Cloud. + URL is the base URL for CyberArk Certificate Manager SaaS. Defaults to "https://api.venafi.cloud/". type: string required: @@ -12190,13 +12257,13 @@ spec: type: object tpp: description: |- - TPP specifies Trust Protection Platform configuration settings. - Only one of TPP or Cloud may be specified. + TPP specifies CyberArk Certificate Manager Self-Hosted configuration settings. + Only one of CyberArk Certificate Manager may be specified. properties: caBundle: description: |- Base64-encoded bundle of PEM CAs which will be used to validate the certificate - chain presented by the TPP server. Only used if using HTTPS; ignored for HTTP. + chain presented by the CyberArk Certificate Manager Self-Hosted server. Only used if using HTTPS; ignored for HTTP. If undefined, the certificate bundle in the cert-manager controller container is used to validate the chain. format: byte @@ -12204,7 +12271,7 @@ spec: caBundleSecretRef: description: |- Reference to a Secret containing a base64-encoded bundle of PEM CAs - which will be used to validate the certificate chain presented by the TPP server. + which will be used to validate the certificate chain presented by the CyberArk Certificate Manager Self-Hosted server. Only used if using HTTPS; ignored for HTTP. Mutually exclusive with CABundle. If neither CABundle nor CABundleSecretRef is defined, the certificate bundle in the cert-manager controller container is used to validate the TLS connection. @@ -12225,7 +12292,7 @@ spec: type: object credentialsRef: description: |- - CredentialsRef is a reference to a Secret containing the Venafi TPP API credentials. + CredentialsRef is a reference to a Secret containing the CyberArk Certificate Manager Self-Hosted API credentials. The secret must contain the key 'access-token' for the Access Token Authentication, or two keys, 'username' and 'password' for the API Keys Authentication. properties: @@ -12239,7 +12306,7 @@ spec: type: object url: description: |- - URL is the base URL for the vedsdk endpoint of the Venafi TPP instance, + URL is the base URL for the vedsdk endpoint of the CyberArk Certificate Manager Self-Hosted instance, for example: "https://tpp.example.com/vedsdk". type: string required: @@ -12248,8 +12315,8 @@ spec: type: object zone: description: |- - Zone is the Venafi Policy Zone to use for this issuer. - All requests made to the Venafi platform will be restricted by the named + Zone is the Certificate Manager Policy Zone to use for this issuer. + All requests made to the Certificate Manager platform will be restricted by the named zone policy. This field is required. type: string From 584d97a3ee2e9ab02e9ab931af2100c970dc5a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=BB=8Cla=CC=81mile=CC=81kan?= Date: Mon, 20 Apr 2026 07:42:18 +0100 Subject: [PATCH 08/13] deprecate ClientSecret in the OIDC Configuration (#222) --- config/crd/bases/operator.kcp.io_frontproxies.yaml | 6 ++++-- config/crd/bases/operator.kcp.io_rootshards.yaml | 6 ++++-- config/crd/bases/operator.kcp.io_shards.yaml | 6 ++++-- sdk/apis/operator/v1alpha1/common.go | 7 +++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/config/crd/bases/operator.kcp.io_frontproxies.yaml b/config/crd/bases/operator.kcp.io_frontproxies.yaml index 0e088ce9..54807a9a 100644 --- a/config/crd/bases/operator.kcp.io_frontproxies.yaml +++ b/config/crd/bases/operator.kcp.io_frontproxies.yaml @@ -112,8 +112,10 @@ spec: type: string clientSecret: description: |- - Optionally provide the client secret for the OIDC client. This is not used by kcp itself, but is used to generate - a OIDC kubeconfig that can be shared with users to log in via the OIDC provider. + ClientSecret is the OIDC client secret configured on the issuer side for this kcp instance. + This is not used by kcp itself, but is used to generate a OIDC kubeconfig that can be + shared with users to log in via the OIDC provider. + Deprecated: kube OIDC is secretless. type: string groupsClaim: description: 'Experimental: Optionally provides a custom claim diff --git a/config/crd/bases/operator.kcp.io_rootshards.yaml b/config/crd/bases/operator.kcp.io_rootshards.yaml index e1bec84e..d53d2f61 100644 --- a/config/crd/bases/operator.kcp.io_rootshards.yaml +++ b/config/crd/bases/operator.kcp.io_rootshards.yaml @@ -174,8 +174,10 @@ spec: type: string clientSecret: description: |- - Optionally provide the client secret for the OIDC client. This is not used by kcp itself, but is used to generate - a OIDC kubeconfig that can be shared with users to log in via the OIDC provider. + ClientSecret is the OIDC client secret configured on the issuer side for this kcp instance. + This is not used by kcp itself, but is used to generate a OIDC kubeconfig that can be + shared with users to log in via the OIDC provider. + Deprecated: kube OIDC is secretless. type: string groupsClaim: description: 'Experimental: Optionally provides a custom claim diff --git a/config/crd/bases/operator.kcp.io_shards.yaml b/config/crd/bases/operator.kcp.io_shards.yaml index 8c245c5c..42ddf6f7 100644 --- a/config/crd/bases/operator.kcp.io_shards.yaml +++ b/config/crd/bases/operator.kcp.io_shards.yaml @@ -174,8 +174,10 @@ spec: type: string clientSecret: description: |- - Optionally provide the client secret for the OIDC client. This is not used by kcp itself, but is used to generate - a OIDC kubeconfig that can be shared with users to log in via the OIDC provider. + ClientSecret is the OIDC client secret configured on the issuer side for this kcp instance. + This is not used by kcp itself, but is used to generate a OIDC kubeconfig that can be + shared with users to log in via the OIDC provider. + Deprecated: kube OIDC is secretless. type: string groupsClaim: description: 'Experimental: Optionally provides a custom claim diff --git a/sdk/apis/operator/v1alpha1/common.go b/sdk/apis/operator/v1alpha1/common.go index fa8f459c..66814585 100644 --- a/sdk/apis/operator/v1alpha1/common.go +++ b/sdk/apis/operator/v1alpha1/common.go @@ -418,8 +418,11 @@ type OIDCConfiguration struct { // ClientID is the OIDC client ID configured on the issuer side for this kcp instance. ClientID string `json:"clientID"` - // Optionally provide the client secret for the OIDC client. This is not used by kcp itself, but is used to generate - // a OIDC kubeconfig that can be shared with users to log in via the OIDC provider. + // ClientSecret is the OIDC client secret configured on the issuer side for this kcp instance. + // This is not used by kcp itself, but is used to generate a OIDC kubeconfig that can be + // shared with users to log in via the OIDC provider. + // +optional + // Deprecated: kube OIDC is secretless. ClientSecret string `json:"clientSecret,omitempty"` // Experimental: Optionally provides a custom claim for fetching groups. The claim must be a string or an array of strings. From 7c1c9e092a1d6b252330e67a8fb218008e923221 Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Mon, 13 Apr 2026 18:34:01 +0200 Subject: [PATCH 09/13] define new naming scheme abstraction On-behalf-of: @SAP christoph.mewes@sap.com --- internal/resources/naming/scheme.go | 78 +++++++++ internal/resources/naming/v1.go | 263 ++++++++++++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 internal/resources/naming/scheme.go create mode 100644 internal/resources/naming/v1.go diff --git a/internal/resources/naming/scheme.go b/internal/resources/naming/scheme.go new file mode 100644 index 00000000..fb0407b0 --- /dev/null +++ b/internal/resources/naming/scheme.go @@ -0,0 +1,78 @@ +/* +Copyright 2026 The kcp Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package naming + +import ( + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" +) + +type Scheme interface { + // RootShard naming + GetRootShardDeploymentName(r *operatorv1alpha1.RootShard) string + GetRootShardProxyDeploymentName(r *operatorv1alpha1.RootShard) string + GetRootShardServiceName(r *operatorv1alpha1.RootShard) string + GetRootShardResourceLabels(r *operatorv1alpha1.RootShard) map[string]string + GetRootShardProxyResourceLabels(r *operatorv1alpha1.RootShard) map[string]string + GetRootShardBaseHost(r *operatorv1alpha1.RootShard) string + GetRootShardBaseURL(r *operatorv1alpha1.RootShard) string + GetRootShardCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string + GetRootShardProxyCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string + GetRootShardCAName(r *operatorv1alpha1.RootShard, caName operatorv1alpha1.CA) string + GetRootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string + GetRootShardProxyConfigName(r *operatorv1alpha1.RootShard) string + GetRootShardProxyServiceName(r *operatorv1alpha1.RootShard) string + GetRootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string + + // Shard naming + GetShardDeploymentName(s *operatorv1alpha1.Shard) string + GetShardServiceName(s *operatorv1alpha1.Shard) string + GetShardResourceLabels(s *operatorv1alpha1.Shard) map[string]string + GetShardBaseHost(s *operatorv1alpha1.Shard) string + GetShardBaseURL(s *operatorv1alpha1.Shard) string + GetShardCertificateName(s *operatorv1alpha1.Shard, certName operatorv1alpha1.Certificate) string + GetShardKubeconfigSecret(shard *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string + + // CacheServer naming + GetCacheServerDeploymentName(s *operatorv1alpha1.CacheServer) string + GetCacheServerServiceName(s *operatorv1alpha1.CacheServer) string + GetCacheServerResourceLabels(s *operatorv1alpha1.CacheServer) map[string]string + GetCacheServerBaseHost(s *operatorv1alpha1.CacheServer) string + GetCacheServerBaseURL(s *operatorv1alpha1.CacheServer) string + GetCacheServerCertificateName(s *operatorv1alpha1.CacheServer, certName operatorv1alpha1.Certificate) string + GetCacheServerCAName(cacheServerName string, caName operatorv1alpha1.CA) string + GetCacheServerClientCertificateName(s *operatorv1alpha1.CacheServer) string + GetCacheServerKubeconfigName(cacheServerName string) string + + // VirtualWorkspace naming + GetVirtualWorkspaceDeploymentName(vw *operatorv1alpha1.VirtualWorkspace) string + GetVirtualWorkspaceResourceLabels(vw *operatorv1alpha1.VirtualWorkspace) map[string]string + GetVirtualWorkspaceBaseHost(s *operatorv1alpha1.VirtualWorkspace) string + GetVirtualWorkspaceBaseURL(s *operatorv1alpha1.VirtualWorkspace) string + GetVirtualWorkspaceCertificateName(vw *operatorv1alpha1.VirtualWorkspace, certName operatorv1alpha1.Certificate) string + + // FrontProxy naming + GetFrontProxyResourceLabels(f *operatorv1alpha1.FrontProxy) map[string]string + GetFrontProxyDeploymentName(f *operatorv1alpha1.FrontProxy) string + GetFrontProxyCertificateName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy, certName operatorv1alpha1.Certificate) string + GetFrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy) string + GetFrontProxyConfigName(f *operatorv1alpha1.FrontProxy) string + GetFrontProxyServiceName(f *operatorv1alpha1.FrontProxy) string + + // Bundle naming + GetBundleName(ownerName string) string + GetMergedClientCAName(ownerName string) string +} diff --git a/internal/resources/naming/v1.go b/internal/resources/naming/v1.go new file mode 100644 index 00000000..22066cd7 --- /dev/null +++ b/internal/resources/naming/v1.go @@ -0,0 +1,263 @@ +/* +Copyright 2026 The kcp Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package naming + +import ( + "fmt" + + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" +) + +const ( + appNameLabel = "app.kubernetes.io/name" + appInstanceLabel = "app.kubernetes.io/instance" + appManagedByLabel = "app.kubernetes.io/managed-by" + appComponentLabel = "app.kubernetes.io/component" + + defaultClusterDomain = "cluster.local" +) + +type version1 struct{} + +func NewVersion1() Scheme { + return &version1{} +} + +func (v *version1) getResourceLabels(instance, component string) map[string]string { + return map[string]string{ + appManagedByLabel: "kcp-operator", + appNameLabel: "kcp", + appInstanceLabel: instance, + appComponentLabel: component, + } +} + +// RootShard naming + +func (v *version1) GetRootShardDeploymentName(r *operatorv1alpha1.RootShard) string { + return fmt.Sprintf("%s-kcp", r.Name) +} + +func (v *version1) GetRootShardProxyDeploymentName(r *operatorv1alpha1.RootShard) string { + return fmt.Sprintf("%s-proxy", r.Name) +} + +func (v *version1) GetRootShardServiceName(r *operatorv1alpha1.RootShard) string { + return fmt.Sprintf("%s-kcp", r.Name) +} + +func (v *version1) GetRootShardResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { + return v.getResourceLabels(r.Name, "rootshard") +} + +func (v *version1) GetRootShardProxyResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { + return v.getResourceLabels(r.Name, "rootshard-proxy") +} + +func (v *version1) GetRootShardBaseHost(r *operatorv1alpha1.RootShard) string { + clusterDomain := r.Spec.ClusterDomain + if clusterDomain == "" { + clusterDomain = defaultClusterDomain + } + + return fmt.Sprintf("%s-kcp.%s.svc.%s", r.Name, r.Namespace, clusterDomain) +} + +func (v *version1) GetRootShardBaseURL(r *operatorv1alpha1.RootShard) string { + if r.Spec.ShardBaseURL != "" { + return r.Spec.ShardBaseURL + } + return fmt.Sprintf("https://%s:6443", v.GetRootShardBaseHost(r)) +} + +func (v *version1) GetRootShardCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", r.Name, certName) +} + +func (v *version1) GetRootShardProxyCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-proxy-%s", r.Name, certName) +} + +func (v *version1) GetRootShardCAName(r *operatorv1alpha1.RootShard, caName operatorv1alpha1.CA) string { + if caName == operatorv1alpha1.RootCA { + return fmt.Sprintf("%s-ca", r.Name) + } + return fmt.Sprintf("%s-%s-ca", r.Name, caName) +} + +func (v *version1) GetRootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string { + return fmt.Sprintf("%s-proxy-dynamic-kubeconfig", r.Name) +} + +func (v *version1) GetRootShardProxyConfigName(r *operatorv1alpha1.RootShard) string { + return fmt.Sprintf("%s-proxy-config", r.Name) +} + +func (v *version1) GetRootShardProxyServiceName(r *operatorv1alpha1.RootShard) string { + return fmt.Sprintf("%s-proxy", r.Name) +} + +func (v *version1) GetRootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s-kubeconfig", r.Name, cert) +} + +// Shard naming + +func (v *version1) GetShardDeploymentName(s *operatorv1alpha1.Shard) string { + return fmt.Sprintf("%s-shard-kcp", s.Name) +} + +func (v *version1) GetShardServiceName(s *operatorv1alpha1.Shard) string { + return fmt.Sprintf("%s-shard-kcp", s.Name) +} + +func (v *version1) GetShardResourceLabels(s *operatorv1alpha1.Shard) map[string]string { + return v.getResourceLabels(s.Name, "shard") +} + +func (v *version1) GetShardBaseHost(s *operatorv1alpha1.Shard) string { + clusterDomain := s.Spec.ClusterDomain + if clusterDomain == "" { + clusterDomain = defaultClusterDomain + } + + return fmt.Sprintf("%s-shard-kcp.%s.svc.%s", s.Name, s.Namespace, clusterDomain) +} + +func (v *version1) GetShardBaseURL(s *operatorv1alpha1.Shard) string { + if s.Spec.ShardBaseURL != "" { + return s.Spec.ShardBaseURL + } + return fmt.Sprintf("https://%s:6443", v.GetShardBaseHost(s)) +} + +func (v *version1) GetShardCertificateName(s *operatorv1alpha1.Shard, certName operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", s.Name, certName) +} + +func (v *version1) GetShardKubeconfigSecret(shard *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s-kubeconfig", shard.Name, cert) +} + +// CacheServer naming + +func (v *version1) GetCacheServerDeploymentName(s *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("%s-cache-server", s.Name) +} + +func (v *version1) GetCacheServerServiceName(s *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("%s-cache-server", s.Name) +} + +func (v *version1) GetCacheServerResourceLabels(s *operatorv1alpha1.CacheServer) map[string]string { + return v.getResourceLabels(s.Name, "cache-server") +} + +func (v *version1) GetCacheServerBaseHost(s *operatorv1alpha1.CacheServer) string { + clusterDomain := s.Spec.ClusterDomain + if clusterDomain == "" { + clusterDomain = defaultClusterDomain + } + + return fmt.Sprintf("%s-cache-server.%s.svc.%s", s.Name, s.Namespace, clusterDomain) +} + +func (v *version1) GetCacheServerBaseURL(s *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("https://%s:6443", v.GetCacheServerBaseHost(s)) +} + +func (v *version1) GetCacheServerCertificateName(s *operatorv1alpha1.CacheServer, certName operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", s.Name, certName) +} + +func (v *version1) GetCacheServerCAName(cacheServerName string, caName operatorv1alpha1.CA) string { + if caName == operatorv1alpha1.RootCA { + return fmt.Sprintf("%s-ca", cacheServerName) + } + return fmt.Sprintf("%s-%s-ca", cacheServerName, caName) +} + +func (v *version1) GetCacheServerClientCertificateName(s *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("%s-client-certificate", s.Name) +} + +func (v *version1) GetCacheServerKubeconfigName(cacheServerName string) string { + return fmt.Sprintf("%s-kubeconfig", cacheServerName) +} + +// VirtualWorkspace naming + +func (v *version1) GetVirtualWorkspaceDeploymentName(vw *operatorv1alpha1.VirtualWorkspace) string { + return fmt.Sprintf("%s-virtual-workspace", vw.Name) +} + +func (v *version1) GetVirtualWorkspaceResourceLabels(vw *operatorv1alpha1.VirtualWorkspace) map[string]string { + return v.getResourceLabels(vw.Name, "virtual-workspace") +} + +func (v *version1) GetVirtualWorkspaceBaseHost(s *operatorv1alpha1.VirtualWorkspace) string { + clusterDomain := s.Spec.ClusterDomain + if clusterDomain == "" { + clusterDomain = defaultClusterDomain + } + + return fmt.Sprintf("%s-virtual-workspace.%s.svc.%s", s.Name, s.Namespace, clusterDomain) +} + +func (v *version1) GetVirtualWorkspaceBaseURL(s *operatorv1alpha1.VirtualWorkspace) string { + return fmt.Sprintf("https://%s:6443", v.GetVirtualWorkspaceBaseHost(s)) +} + +func (v *version1) GetVirtualWorkspaceCertificateName(vw *operatorv1alpha1.VirtualWorkspace, certName operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", vw.Name, certName) +} + +// FrontProxy naming + +func (v *version1) GetFrontProxyResourceLabels(f *operatorv1alpha1.FrontProxy) map[string]string { + return v.getResourceLabels(f.Name, "front-proxy") +} + +func (v *version1) GetFrontProxyDeploymentName(f *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-front-proxy", f.Name) +} + +func (v *version1) GetFrontProxyCertificateName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy, certName operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s-%s", r.Name, f.Name, certName) +} + +func (v *version1) GetFrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-%s-dynamic-kubeconfig", r.Name, f.Name) +} + +func (v *version1) GetFrontProxyConfigName(f *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-config", f.Name) +} + +func (v *version1) GetFrontProxyServiceName(f *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-front-proxy", f.Name) +} + +// Bundle naming + +func (v *version1) GetBundleName(ownerName string) string { + return fmt.Sprintf("%s-bundle", ownerName) +} + +func (v *version1) GetMergedClientCAName(ownerName string) string { + return fmt.Sprintf("%s-merged-client-ca", ownerName) +} From f45f74186208da76e59426d6d883df7b11cf2ae4 Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Mon, 13 Apr 2026 18:48:37 +0200 Subject: [PATCH 10/13] refactor reconciling naming scheme to use an exchangeable naming scheme to prepare for the overhaul On-behalf-of: @SAP christoph.mewes@sap.com --- internal/client/clients.go | 27 +-- internal/client/frontproxy.go | 8 +- internal/controller/bundle/helpers.go | 9 +- internal/controller/cacheserver/controller.go | 17 +- internal/controller/frontproxy/controller.go | 21 +- internal/controller/kubeconfig/controller.go | 20 +- internal/controller/rootshard/controller.go | 53 +++-- internal/controller/shard/controller.go | 48 ++-- .../controller/virtualworkspace/controller.go | 70 ++++-- .../resources/cacheserver/certificates.go | 25 +- internal/resources/cacheserver/deployment.go | 15 +- internal/resources/cacheserver/issuers.go | 8 +- internal/resources/cacheserver/kubeconfigs.go | 8 +- internal/resources/cacheserver/service.go | 8 +- internal/resources/frontproxy/ca_bundle.go | 4 +- internal/resources/frontproxy/certificates.go | 12 +- internal/resources/frontproxy/configmap.go | 7 +- .../resources/frontproxy/configmap_test.go | 5 +- internal/resources/frontproxy/deployment.go | 12 +- .../resources/frontproxy/deployment_test.go | 46 ++-- internal/resources/frontproxy/reconciler.go | 13 +- internal/resources/frontproxy/secrets.go | 8 +- internal/resources/frontproxy/service.go | 5 +- internal/resources/kubeconfig/certificate.go | 6 +- internal/resources/kubeconfig/secret.go | 7 +- internal/resources/naming/scheme.go | 106 +++++---- internal/resources/naming/v1.go | 175 ++++++-------- internal/resources/resources.go | 220 ------------------ internal/resources/rootshard/ca_bundle.go | 5 +- .../resources/rootshard/ca_certificates.go | 15 +- internal/resources/rootshard/certificates.go | 63 ++--- internal/resources/rootshard/deployment.go | 25 +- internal/resources/rootshard/issuers.go | 26 +-- internal/resources/rootshard/kubeconfigs.go | 16 +- internal/resources/rootshard/service.go | 8 +- internal/resources/shard/ca_bundle.go | 5 +- internal/resources/shard/certificates.go | 57 ++--- internal/resources/shard/deployment.go | 25 +- internal/resources/shard/kubeconfigs.go | 12 +- internal/resources/shard/service.go | 8 +- internal/resources/utils/authentication.go | 16 +- .../resources/utils/authentication_test.go | 13 +- internal/resources/utils/deployments.go | 5 +- .../resources/virtualworkspace/certificate.go | 15 +- .../resources/virtualworkspace/deployment.go | 27 +-- .../resources/virtualworkspace/service.go | 12 +- test/e2e/cacheserver/cacheserver_test.go | 13 +- test/e2e/frontproxies/frontproxies_test.go | 4 +- test/e2e/kubeconfig-rbac/frontproxies_test.go | 4 +- test/e2e/rootshards/proxy_test.go | 4 +- test/e2e/rootshards/rootshards_test.go | 4 +- test/e2e/shards/shards_test.go | 7 +- .../virtualworkspaces_test.go | 13 +- test/utils/deploy.go | 10 +- test/utils/utils.go | 8 +- 55 files changed, 616 insertions(+), 767 deletions(-) diff --git a/internal/client/clients.go b/internal/client/clients.go index 41a6421b..b3099ce1 100644 --- a/internal/client/clients.go +++ b/internal/client/clients.go @@ -28,56 +28,57 @@ import ( "k8s.io/client-go/rest" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) // NewRootShardClient returns a new client for talking to the kcp root shard service directly. -func NewRootShardClient(ctx context.Context, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { - baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", resources.GetRootShardServiceName(rootShard), rootShard.Namespace) +func NewRootShardClient(ctx context.Context, names naming.Scheme, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { + baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", names.RootShardServiceName(rootShard), rootShard.Namespace) if !cluster.Empty() { baseUrl = fmt.Sprintf("%s/clusters/%s", baseUrl, cluster.String()) } - return newClient(ctx, c, baseUrl, scheme, rootShard) + return newClient(ctx, names, c, baseUrl, scheme, rootShard) } // NewRootShardClient returns a new client that connects to the operator's internal front-proxy. -func NewRootShardProxyClient(ctx context.Context, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { - baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", resources.GetRootShardProxyServiceName(rootShard), rootShard.Namespace) +func NewRootShardProxyClient(ctx context.Context, names naming.Scheme, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { + baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", names.RootShardProxyServiceName(rootShard), rootShard.Namespace) if !cluster.Empty() { baseUrl = fmt.Sprintf("%s/clusters/%s", baseUrl, cluster.String()) } - return newClient(ctx, c, baseUrl, scheme, rootShard) + return newClient(ctx, names, c, baseUrl, scheme, rootShard) } // NewShardClient returns a new client for talking to a kcp shard service directly. -func NewShardClient(ctx context.Context, c ctrlruntimeclient.Client, shard *operatorv1alpha1.Shard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { +func NewShardClient(ctx context.Context, names naming.Scheme, c ctrlruntimeclient.Client, shard *operatorv1alpha1.Shard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { rootShard, err := getRootShardForShard(ctx, c, shard) if err != nil { return nil, fmt.Errorf("failed to determine effective RootShard: %w", err) } - baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", resources.GetShardServiceName(shard), shard.Namespace) + baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", names.ShardServiceName(shard), shard.Namespace) if !cluster.Empty() { baseUrl = fmt.Sprintf("%s/clusters/%s", baseUrl, cluster.String()) } - return newClient(ctx, c, baseUrl, scheme, rootShard) + return newClient(ctx, names, c, baseUrl, scheme, rootShard) } func newClient( ctx context.Context, + names naming.Scheme, c ctrlruntimeclient.Client, url string, scheme *runtime.Scheme, rootShard *operatorv1alpha1.RootShard, ) (ctrlruntimeclient.Client, error) { - tlsConfig, err := getTLSConfig(ctx, c, rootShard) + tlsConfig, err := getTLSConfig(ctx, names, c, rootShard) if err != nil { return nil, fmt.Errorf("failed to determine TLS settings: %w", err) } @@ -93,11 +94,11 @@ func newClient( // +kubebuilder:rbac:groups=core,resources=secrets,verbs=get // getTLSConfig returns the CA and serving certificate for a RootShard. -func getTLSConfig(ctx context.Context, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard) (rest.TLSClientConfig, error) { +func getTLSConfig(ctx context.Context, names naming.Scheme, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard) (rest.TLSClientConfig, error) { // get the secret for the kcp-operator client cert key := types.NamespacedName{ Namespace: rootShard.Namespace, - Name: resources.GetRootShardCertificateName(rootShard, operatorv1alpha1.OperatorCertificate), + Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.OperatorCertificate), } certSecret := &corev1.Secret{} diff --git a/internal/client/frontproxy.go b/internal/client/frontproxy.go index a708c601..1b2793bf 100644 --- a/internal/client/frontproxy.go +++ b/internal/client/frontproxy.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/types" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -39,6 +40,7 @@ import ( // does not drop groups/permissions). func NewInternalKubeconfigClient(ctx context.Context, c ctrlruntimeclient.Client, kubeconfig *operatorv1alpha1.Kubeconfig, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { target := kubeconfig.Spec.Target + namingScheme := naming.NewVersion1() switch { case target.RootShardRef != nil: @@ -47,7 +49,7 @@ func NewInternalKubeconfigClient(ctx context.Context, c ctrlruntimeclient.Client return nil, fmt.Errorf("failed to get RootShard: %w", err) } - return NewRootShardClient(ctx, c, rootShard, cluster, scheme) + return NewRootShardClient(ctx, namingScheme, c, rootShard, cluster, scheme) case target.ShardRef != nil: shard := &operatorv1alpha1.Shard{} @@ -55,7 +57,7 @@ func NewInternalKubeconfigClient(ctx context.Context, c ctrlruntimeclient.Client return nil, fmt.Errorf("failed to get Shard: %w", err) } - return NewShardClient(ctx, c, shard, cluster, scheme) + return NewShardClient(ctx, namingScheme, c, shard, cluster, scheme) case target.FrontProxyRef != nil: frontProxy := &operatorv1alpha1.FrontProxy{} @@ -68,7 +70,7 @@ func NewInternalKubeconfigClient(ctx context.Context, c ctrlruntimeclient.Client return nil, fmt.Errorf("failed to get RootShard: %w", err) } - return NewRootShardProxyClient(ctx, c, rootShard, cluster, scheme) + return NewRootShardProxyClient(ctx, namingScheme, c, rootShard, cluster, scheme) default: return nil, errors.New("no valid target configured in Kubeconfig: neither rootShard, shard nor frontProxy ref set") diff --git a/internal/controller/bundle/helpers.go b/internal/controller/bundle/helpers.go index 0e2f19ac..b6424d55 100644 --- a/internal/controller/bundle/helpers.go +++ b/internal/controller/bundle/helpers.go @@ -29,19 +29,20 @@ import ( ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) // EnsureBundleForOwner ensures that a Bundle object exists for the given owner if it has the bundle annotation. // If the annotation is present and no Bundle exists, it creates one owned by the object. // Returns the Bundle object if it exists/was created, or nil if no bundle annotation is present. -func EnsureBundleForOwner(ctx context.Context, client ctrlruntimeclient.Client, scheme *runtime.Scheme, owner ctrlruntimeclient.Object) (*operatorv1alpha1.Bundle, error) { +func EnsureBundleForOwner(ctx context.Context, client ctrlruntimeclient.Client, scheme *runtime.Scheme, owner ctrlruntimeclient.Object, names naming.Scheme) (*operatorv1alpha1.Bundle, error) { annotations := owner.GetAnnotations() if annotations == nil || annotations[resources.BundleAnnotation] == "" { return nil, nil } - bundleName := resources.GetBundleName(owner.GetName()) + bundleName := names.BundleName(owner.GetName()) bundle := &operatorv1alpha1.Bundle{} err := client.Get(ctx, types.NamespacedName{ @@ -100,7 +101,7 @@ func buildBundleTarget(owner ctrlruntimeclient.Object) operatorv1alpha1.BundleTa // GetBundleReadyCondition checks if the Bundle associated with the owner is ready. // Returns a condition that can be added to the owner's status. -func GetBundleReadyCondition(ctx context.Context, client ctrlruntimeclient.Client, owner ctrlruntimeclient.Object, generation int64) metav1.Condition { +func GetBundleReadyCondition(ctx context.Context, client ctrlruntimeclient.Client, owner ctrlruntimeclient.Object, generation int64, names naming.Scheme) metav1.Condition { annotations := owner.GetAnnotations() if annotations == nil || annotations[resources.BundleAnnotation] == "" { // No bundle annotation, return ready condition @@ -113,7 +114,7 @@ func GetBundleReadyCondition(ctx context.Context, client ctrlruntimeclient.Clien } } - bundleName := resources.GetBundleName(owner.GetName()) + bundleName := names.BundleName(owner.GetName()) bundle := &operatorv1alpha1.Bundle{} err := client.Get(ctx, types.NamespacedName{ diff --git a/internal/controller/cacheserver/controller.go b/internal/controller/cacheserver/controller.go index 7599dd37..c9d8f30e 100644 --- a/internal/controller/cacheserver/controller.go +++ b/internal/controller/cacheserver/controller.go @@ -34,6 +34,7 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/reconciling/modifier" "github.com/kcp-dev/kcp-operator/internal/resources/cacheserver" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -84,25 +85,27 @@ func (r *CacheServerReconciler) Reconcile(ctx context.Context, req ctrlruntime.R } func (r *CacheServerReconciler) reconcile(ctx context.Context, server *operatorv1alpha1.CacheServer) error { + namingScheme := naming.NewVersion1() + ownerRefWrapper := k8creconciling.OwnerRefWrapper(*metav1.NewControllerRef(server, operatorv1alpha1.SchemeGroupVersion.WithKind("CacheServer"))) revisionLabels := modifier.RelatedRevisionsLabels(ctx, r.Client) if err := reconciling.ReconcileCertificates(ctx, []reconciling.NamedCertificateReconcilerFactory{ - cacheserver.RootCACertificateReconciler(server), - cacheserver.ServerCertificateReconciler(server), - cacheserver.ClientCertificateReconciler(server), + cacheserver.RootCACertificateReconciler(server, namingScheme), + cacheserver.ServerCertificateReconciler(server, namingScheme), + cacheserver.ClientCertificateReconciler(server, namingScheme), }, server.Namespace, r.Client, ownerRefWrapper); err != nil { return err } if err := reconciling.ReconcileIssuers(ctx, []reconciling.NamedIssuerReconcilerFactory{ - cacheserver.RootCAIssuerReconciler(server), + cacheserver.RootCAIssuerReconciler(server, namingScheme), }, server.Namespace, r.Client, ownerRefWrapper); err != nil { return err } if err := k8creconciling.ReconcileSecrets(ctx, []k8creconciling.NamedSecretReconcilerFactory{ - cacheserver.KubeconfigReconciler(server), + cacheserver.KubeconfigReconciler(server, namingScheme), }, server.Namespace, r.Client, ownerRefWrapper); err != nil { return err } @@ -111,7 +114,7 @@ func (r *CacheServerReconciler) reconcile(ctx context.Context, server *operatorv // requeueing to eventually get there in the end. Importantly, reconciling Deployments has to happen // after all Secrets have been reconciled. if err := k8creconciling.ReconcileDeployments(ctx, []k8creconciling.NamedDeploymentReconcilerFactory{ - cacheserver.DeploymentReconciler(server), + cacheserver.DeploymentReconciler(server, namingScheme), }, server.Namespace, r.Client, ownerRefWrapper, revisionLabels); err != nil { // Swallow these errors and instead rely on us watching Secrets and re-reconciling whenever they change. if errors.Is(err, modifier.ErrMountNotFound) { @@ -121,7 +124,7 @@ func (r *CacheServerReconciler) reconcile(ctx context.Context, server *operatorv } if err := k8creconciling.ReconcileServices(ctx, []k8creconciling.NamedServiceReconcilerFactory{ - cacheserver.ServiceReconciler(server), + cacheserver.ServiceReconciler(server, namingScheme), }, server.Namespace, r.Client, ownerRefWrapper); err != nil { return err } diff --git a/internal/controller/frontproxy/controller.go b/internal/controller/frontproxy/controller.go index 9ccb21bf..43587010 100644 --- a/internal/controller/frontproxy/controller.go +++ b/internal/controller/frontproxy/controller.go @@ -41,8 +41,8 @@ import ( bundlehelper "github.com/kcp-dev/kcp-operator/internal/controller/bundle" "github.com/kcp-dev/kcp-operator/internal/controller/util" "github.com/kcp-dev/kcp-operator/internal/metrics" - "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/frontproxy" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -113,16 +113,18 @@ func (r *FrontProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, nil } - conditions, recErr := r.reconcile(ctx, &frontProxy) + namingScheme := naming.NewVersion1() - if err := r.reconcileStatus(ctx, &frontProxy, conditions); err != nil { + conditions, recErr := r.reconcile(ctx, &frontProxy, namingScheme) + + if err := r.reconcileStatus(ctx, &frontProxy, conditions, namingScheme); err != nil { recErr = kerrors.NewAggregate([]error{recErr, err}) } return ctrl.Result{}, recErr } -func (r *FrontProxyReconciler) reconcile(ctx context.Context, frontProxy *operatorv1alpha1.FrontProxy) ([]metav1.Condition, error) { +func (r *FrontProxyReconciler) reconcile(ctx context.Context, frontProxy *operatorv1alpha1.FrontProxy, names naming.Scheme) ([]metav1.Condition, error) { var ( conditions []metav1.Condition errs []error @@ -133,7 +135,7 @@ func (r *FrontProxyReconciler) reconcile(ctx context.Context, frontProxy *operat } // Ensure Bundle object exists if annotation is present - if _, err := bundlehelper.EnsureBundleForOwner(ctx, r.Client, r.Scheme, frontProxy); err != nil { + if _, err := bundlehelper.EnsureBundleForOwner(ctx, r.Client, r.Scheme, frontProxy, names); err != nil { errs = append(errs, fmt.Errorf("failed to ensure bundle: %w", err)) } @@ -144,7 +146,7 @@ func (r *FrontProxyReconciler) reconcile(ctx context.Context, frontProxy *operat return conditions, nil } - fpReconciler := frontproxy.NewFrontProxy(frontProxy, rootShard) + fpReconciler := frontproxy.NewFrontProxy(frontProxy, rootShard, names) // Deployment will be scaled to 0 if bundle annotation is present if err := fpReconciler.Reconcile(ctx, r.Client, frontProxy.Namespace); err != nil { @@ -154,12 +156,12 @@ func (r *FrontProxyReconciler) reconcile(ctx context.Context, frontProxy *operat return conditions, kerrors.NewAggregate(errs) } -func (r *FrontProxyReconciler) reconcileStatus(ctx context.Context, oldFrontProxy *operatorv1alpha1.FrontProxy, conditions []metav1.Condition) error { +func (r *FrontProxyReconciler) reconcileStatus(ctx context.Context, oldFrontProxy *operatorv1alpha1.FrontProxy, conditions []metav1.Condition, names naming.Scheme) error { frontProxy := oldFrontProxy.DeepCopy() var errs []error // Add Bundle condition - bundleCond := bundlehelper.GetBundleReadyCondition(ctx, r.Client, frontProxy, frontProxy.Generation) + bundleCond := bundlehelper.GetBundleReadyCondition(ctx, r.Client, frontProxy, frontProxy.Generation, names) conditions = append(conditions, bundleCond) // Check if frontproxy is bundled (has bundle annotation with Ready bundle) @@ -167,7 +169,8 @@ func (r *FrontProxyReconciler) reconcileStatus(ctx context.Context, oldFrontProx // Only check deployment status if not bundled if !isBundled { - depKey := types.NamespacedName{Namespace: frontProxy.Namespace, Name: resources.GetFrontProxyDeploymentName(frontProxy)} + namingScheme := naming.NewVersion1() + depKey := types.NamespacedName{Namespace: frontProxy.Namespace, Name: namingScheme.FrontProxyDeploymentName(frontProxy)} cond, err := util.GetDeploymentAvailableCondition(ctx, r.Client, depKey) if err != nil { errs = append(errs, err) diff --git a/internal/controller/kubeconfig/controller.go b/internal/controller/kubeconfig/controller.go index 3eb37fc9..f7cf8317 100644 --- a/internal/controller/kubeconfig/controller.go +++ b/internal/controller/kubeconfig/controller.go @@ -42,8 +42,8 @@ import ( "github.com/kcp-dev/kcp-operator/internal/controller/util" "github.com/kcp-dev/kcp-operator/internal/metrics" "github.com/kcp-dev/kcp-operator/internal/reconciling" - "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/kubeconfig" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -128,6 +128,8 @@ func (r *KubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) func (r *KubeconfigReconciler) reconcile(ctx context.Context, kc *operatorv1alpha1.Kubeconfig, req types.NamespacedName) ([]metav1.Condition, error) { var conditions []metav1.Condition + namingScheme := naming.NewVersion1() + rootShard := &operatorv1alpha1.RootShard{} shard := &operatorv1alpha1.Shard{} var frontProxy operatorv1alpha1.FrontProxy @@ -151,8 +153,8 @@ func (r *KubeconfigReconciler) reconcile(ctx context.Context, kc *operatorv1alph return conditions, err } - clientCertIssuer = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA) - serverCA = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + clientCertIssuer = namingScheme.RootShardCAName(rootShard, operatorv1alpha1.ClientCA) + serverCA = namingScheme.RootShardCAName(rootShard, operatorv1alpha1.ServerCA) case kc.Spec.Target.ShardRef != nil: if err := r.Get(ctx, types.NamespacedName{Name: kc.Spec.Target.ShardRef.Name, Namespace: req.Namespace}, shard); err != nil { @@ -189,8 +191,8 @@ func (r *KubeconfigReconciler) reconcile(ctx context.Context, kc *operatorv1alph } // The client CA is shared among all shards and owned by the root shard. - clientCertIssuer = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA) - serverCA = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + clientCertIssuer = namingScheme.RootShardCAName(rootShard, operatorv1alpha1.ClientCA) + serverCA = namingScheme.RootShardCAName(rootShard, operatorv1alpha1.ServerCA) case kc.Spec.Target.FrontProxyRef != nil: if err := r.Get(ctx, types.NamespacedName{Name: kc.Spec.Target.FrontProxyRef.Name, Namespace: req.Namespace}, &frontProxy); err != nil { @@ -226,8 +228,8 @@ func (r *KubeconfigReconciler) reconcile(ctx context.Context, kc *operatorv1alph return conditions, err } - clientCertIssuer = resources.GetRootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA) - serverCA = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + clientCertIssuer = namingScheme.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA) + serverCA = namingScheme.RootShardCAName(rootShard, operatorv1alpha1.ServerCA) if frontProxy.Spec.CABundleSecretRef != nil { caBundle = &corev1.Secret{} @@ -262,7 +264,7 @@ func (r *KubeconfigReconciler) reconcile(ctx context.Context, kc *operatorv1alph }) certReconcilers := []reconciling.NamedCertificateReconcilerFactory{ - kubeconfig.ClientCertificateReconciler(kc, clientCertIssuer), + kubeconfig.ClientCertificateReconciler(kc, clientCertIssuer, namingScheme), } if err := reconciling.ReconcileCertificates(ctx, certReconcilers, req.Namespace, r.Client); err != nil { @@ -307,7 +309,7 @@ func (r *KubeconfigReconciler) reconcile(ctx context.Context, kc *operatorv1alph return conditions, nil } - reconciler, err := kubeconfig.KubeconfigSecretReconciler(kc, rootShard, shard, frontProxy, serverCASecret, clientCertSecret, caBundle) + reconciler, err := kubeconfig.KubeconfigSecretReconciler(kc, rootShard, shard, frontProxy, serverCASecret, clientCertSecret, caBundle, namingScheme) if err != nil { return conditions, err } diff --git a/internal/controller/rootshard/controller.go b/internal/controller/rootshard/controller.go index 9efce18d..ffc99e0b 100644 --- a/internal/controller/rootshard/controller.go +++ b/internal/controller/rootshard/controller.go @@ -46,8 +46,8 @@ import ( "github.com/kcp-dev/kcp-operator/internal/metrics" "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/reconciling/modifier" - "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/frontproxy" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/rootshard" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -146,9 +146,12 @@ func (r *RootShardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( return ctrl.Result{}, nil } - conditions, recErr := r.reconcile(ctx, &rootShard) + // Instantiate the naming scheme + namingScheme := naming.NewVersion1() - if err := r.reconcileStatus(ctx, &rootShard, conditions); err != nil { + conditions, recErr := r.reconcile(ctx, &rootShard, namingScheme) + + if err := r.reconcileStatus(ctx, &rootShard, conditions, namingScheme); err != nil { recErr = kerrors.NewAggregate([]error{recErr, err}) } @@ -156,7 +159,7 @@ func (r *RootShardReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( } //nolint:unparam // Keep the controller working the same as all the others, even though currently it does always return nil conditions. -func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operatorv1alpha1.RootShard) ([]metav1.Condition, error) { +func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) ([]metav1.Condition, error) { var ( errs []error conditions []metav1.Condition @@ -167,7 +170,7 @@ func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operator } // Ensure Bundle object exists if annotation is present - if _, err := bundlehelper.EnsureBundleForOwner(ctx, r.Client, r.Scheme, rootShard); err != nil { + if _, err := bundlehelper.EnsureBundleForOwner(ctx, r.Client, r.Scheme, rootShard, names); err != nil { errs = append(errs, fmt.Errorf("failed to ensure bundle: %w", err)) } @@ -175,17 +178,17 @@ func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operator revisionLabels := modifier.RelatedRevisionsLabels(ctx, r.Client) issuerReconcilers := []reconciling.NamedIssuerReconcilerFactory{ - rootshard.RootCAIssuerReconciler(rootShard), + rootshard.RootCAIssuerReconciler(rootShard, names), } certReconcilers := []reconciling.NamedCertificateReconcilerFactory{ - rootshard.ServerCertificateReconciler(rootShard), - rootshard.ServiceAccountCertificateReconciler(rootShard), - rootshard.VirtualWorkspacesCertificateReconciler(rootShard), - rootshard.LogicalClusterAdminCertificateReconciler(rootShard), - rootshard.ExternalLogicalClusterAdminCertificateReconciler(rootShard), - rootshard.ClientCertificateReconciler(rootShard), - rootshard.OperatorClientCertificateReconciler(rootShard), + rootshard.ServerCertificateReconciler(rootShard, names), + rootshard.ServiceAccountCertificateReconciler(rootShard, names), + rootshard.VirtualWorkspacesCertificateReconciler(rootShard, names), + rootshard.LogicalClusterAdminCertificateReconciler(rootShard, names), + rootshard.ExternalLogicalClusterAdminCertificateReconciler(rootShard, names), + rootshard.ClientCertificateReconciler(rootShard, names), + rootshard.OperatorClientCertificateReconciler(rootShard, names), } // Intermediate CAs that we need to generate a certificate and an issuer for. @@ -198,11 +201,11 @@ func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operator } for _, ca := range intermediateCAs { - certReconcilers = append(certReconcilers, rootshard.CACertificateReconciler(rootShard, ca)) - issuerReconcilers = append(issuerReconcilers, rootshard.CAIssuerReconciler(rootShard, ca)) + certReconcilers = append(certReconcilers, rootshard.CACertificateReconciler(rootShard, ca, names)) + issuerReconcilers = append(issuerReconcilers, rootshard.CAIssuerReconciler(rootShard, ca, names)) } if rootShard.Spec.Certificates.IssuerRef != nil { - certReconcilers = append(certReconcilers, rootshard.RootCACertificateReconciler(rootShard)) + certReconcilers = append(certReconcilers, rootshard.RootCACertificateReconciler(rootShard, names)) } if err := reconciling.ReconcileCertificates(ctx, certReconcilers, rootShard.Namespace, r.Client, ownerRefWrapper); err != nil { @@ -215,15 +218,15 @@ func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operator if rootShard.Spec.CABundleSecretRef != nil { if err := k8creconciling.ReconcileSecrets(ctx, []k8creconciling.NamedSecretReconcilerFactory{ - rootshard.MergedCABundleSecretReconciler(ctx, rootShard, r.Client), + rootshard.MergedCABundleSecretReconciler(ctx, rootShard, r.Client, names), }, rootShard.Namespace, r.Client, ownerRefWrapper); err != nil { errs = append(errs, err) } } if err := k8creconciling.ReconcileSecrets(ctx, []k8creconciling.NamedSecretReconcilerFactory{ - rootshard.LogicalClusterAdminKubeconfigReconciler(rootShard), - rootshard.ExternalLogicalClusterAdminKubeconfigReconciler(rootShard), + rootshard.LogicalClusterAdminKubeconfigReconciler(rootShard, names), + rootshard.ExternalLogicalClusterAdminKubeconfigReconciler(rootShard, names), }, rootShard.Namespace, r.Client, ownerRefWrapper); err != nil { errs = append(errs, err) } @@ -246,7 +249,7 @@ func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operator // Deployment will be scaled to 0 if bundle annotation is present if vwConfigValid { if err := k8creconciling.ReconcileDeployments(ctx, []k8creconciling.NamedDeploymentReconcilerFactory{ - rootshard.DeploymentReconciler(rootShard, kcpVW), + rootshard.DeploymentReconciler(rootShard, kcpVW, names), }, rootShard.Namespace, r.Client, ownerRefWrapper, revisionLabels); err != nil { // Swallow these errors and instead rely on us watching Secrets and re-reconciling whenever they change. if !errors.Is(err, modifier.ErrMountNotFound) { @@ -256,12 +259,12 @@ func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operator } if err := k8creconciling.ReconcileServices(ctx, []k8creconciling.NamedServiceReconcilerFactory{ - rootshard.ServiceReconciler(rootShard), + rootshard.ServiceReconciler(rootShard, names), }, rootShard.Namespace, r.Client, ownerRefWrapper); err != nil { errs = append(errs, err) } - if err := frontproxy.NewRootShardProxy(rootShard).Reconcile(ctx, r.Client, rootShard.Namespace); err != nil { + if err := frontproxy.NewRootShardProxy(rootShard, names).Reconcile(ctx, r.Client, rootShard.Namespace); err != nil { errs = append(errs, fmt.Errorf("failed to reconcile proxy: %w", err)) } @@ -269,12 +272,12 @@ func (r *RootShardReconciler) reconcile(ctx context.Context, rootShard *operator } // reconcileStatus sets both phase and conditions on the reconciled RootShard object. -func (r *RootShardReconciler) reconcileStatus(ctx context.Context, oldRootShard *operatorv1alpha1.RootShard, conditions []metav1.Condition) error { +func (r *RootShardReconciler) reconcileStatus(ctx context.Context, oldRootShard *operatorv1alpha1.RootShard, conditions []metav1.Condition, names naming.Scheme) error { rootShard := oldRootShard.DeepCopy() var errs []error // Add Bundle condition - bundleCond := bundlehelper.GetBundleReadyCondition(ctx, r.Client, rootShard, rootShard.Generation) + bundleCond := bundlehelper.GetBundleReadyCondition(ctx, r.Client, rootShard, rootShard.Generation, names) conditions = append(conditions, bundleCond) // Check if rootshard is bundled (has bundle annotation with Ready bundle) @@ -282,7 +285,7 @@ func (r *RootShardReconciler) reconcileStatus(ctx context.Context, oldRootShard // Only check deployment status if not bundled if !isBundled { - depKey := types.NamespacedName{Namespace: rootShard.Namespace, Name: resources.GetRootShardDeploymentName(rootShard)} + depKey := types.NamespacedName{Namespace: rootShard.Namespace, Name: names.RootShardDeploymentName(rootShard)} cond, err := util.GetDeploymentAvailableCondition(ctx, r.Client, depKey) if err != nil { errs = append(errs, err) diff --git a/internal/controller/shard/controller.go b/internal/controller/shard/controller.go index 2dd0d642..c3f952c0 100644 --- a/internal/controller/shard/controller.go +++ b/internal/controller/shard/controller.go @@ -51,7 +51,7 @@ import ( "github.com/kcp-dev/kcp-operator/internal/metrics" "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/reconciling/modifier" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/shard" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -143,23 +143,25 @@ func (r *ShardReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res return ctrl.Result{}, nil } - conditions, recErr := r.reconcile(ctx, &s) + namingScheme := naming.NewVersion1() - if err := r.reconcileStatus(ctx, &s, conditions); err != nil { + conditions, recErr := r.reconcile(ctx, &s, namingScheme) + + if err := r.reconcileStatus(ctx, &s, conditions, namingScheme); err != nil { recErr = kerrors.NewAggregate([]error{recErr, err}) } return ctrl.Result{}, recErr } -func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Shard) ([]metav1.Condition, error) { +func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Shard, names naming.Scheme) ([]metav1.Condition, error) { var ( errs []error conditions []metav1.Condition ) if s.DeletionTimestamp != nil { - return r.handleDeletion(ctx, s) + return r.handleDeletion(ctx, s, names) } // Ensure finalizer before any other work @@ -170,7 +172,7 @@ func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Sha } // Ensure Bundle object exists if annotation is present - if _, err := bundlehelper.EnsureBundleForOwner(ctx, r.Client, r.Scheme, s); err != nil { + if _, err := bundlehelper.EnsureBundleForOwner(ctx, r.Client, r.Scheme, s, names); err != nil { errs = append(errs, fmt.Errorf("failed to ensure bundle: %w", err)) } @@ -185,12 +187,12 @@ func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Sha revisionLabels := modifier.RelatedRevisionsLabels(ctx, r.Client) certReconcilers := []reconciling.NamedCertificateReconcilerFactory{ - shard.ServerCertificateReconciler(s, rootShard), - shard.ServiceAccountCertificateReconciler(s, rootShard), - shard.VirtualWorkspacesCertificateReconciler(s, rootShard), - shard.RootShardClientCertificateReconciler(s, rootShard), - shard.LogicalClusterAdminCertificateReconciler(s, rootShard), - shard.ExternalLogicalClusterAdminCertificateReconciler(s, rootShard), + shard.ServerCertificateReconciler(s, rootShard, names), + shard.ServiceAccountCertificateReconciler(s, rootShard, names), + shard.VirtualWorkspacesCertificateReconciler(s, rootShard, names), + shard.RootShardClientCertificateReconciler(s, rootShard, names), + shard.LogicalClusterAdminCertificateReconciler(s, rootShard, names), + shard.ExternalLogicalClusterAdminCertificateReconciler(s, rootShard, names), } if err := reconciling.ReconcileCertificates(ctx, certReconcilers, s.Namespace, r.Client, ownerRefWrapper); err != nil { @@ -198,16 +200,16 @@ func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Sha } if err := k8creconciling.ReconcileSecrets(ctx, []k8creconciling.NamedSecretReconcilerFactory{ - shard.RootShardClientKubeconfigReconciler(s, rootShard), - shard.LogicalClusterAdminKubeconfigReconciler(s, rootShard), - shard.ExternalLogicalClusterAdminKubeconfigReconciler(s, rootShard), + shard.RootShardClientKubeconfigReconciler(s, rootShard, names), + shard.LogicalClusterAdminKubeconfigReconciler(s, rootShard, names), + shard.ExternalLogicalClusterAdminKubeconfigReconciler(s, rootShard, names), }, s.Namespace, r.Client, ownerRefWrapper); err != nil { errs = append(errs, err) } if s.Spec.CABundleSecretRef != nil { if err := k8creconciling.ReconcileSecrets(ctx, []k8creconciling.NamedSecretReconcilerFactory{ - shard.MergedCABundleSecretReconciler(ctx, s, r.Client), + shard.MergedCABundleSecretReconciler(ctx, s, r.Client, names), }, s.Namespace, r.Client, ownerRefWrapper); err != nil { errs = append(errs, err) } @@ -231,7 +233,7 @@ func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Sha // Deployment will be scaled to 0 if bundle annotation is present if vwConfigValid { if err := k8creconciling.ReconcileDeployments(ctx, []k8creconciling.NamedDeploymentReconcilerFactory{ - shard.DeploymentReconciler(s, rootShard, kcpVW), + shard.DeploymentReconciler(s, rootShard, kcpVW, names), }, s.Namespace, r.Client, ownerRefWrapper, revisionLabels); err != nil { // Swallow these errors and instead rely on us watching Secrets and re-reconciling whenever they change. if !errors.Is(err, modifier.ErrMountNotFound) { @@ -241,7 +243,7 @@ func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Sha } if err := k8creconciling.ReconcileServices(ctx, []k8creconciling.NamedServiceReconcilerFactory{ - shard.ServiceReconciler(s), + shard.ServiceReconciler(s, names), }, s.Namespace, r.Client, ownerRefWrapper); err != nil { errs = append(errs, err) } @@ -250,12 +252,12 @@ func (r *ShardReconciler) reconcile(ctx context.Context, s *operatorv1alpha1.Sha } // reconcileStatus sets both phase and conditions on the reconciled Shard object. -func (r *ShardReconciler) reconcileStatus(ctx context.Context, oldShard *operatorv1alpha1.Shard, conditions []metav1.Condition) error { +func (r *ShardReconciler) reconcileStatus(ctx context.Context, oldShard *operatorv1alpha1.Shard, conditions []metav1.Condition, names naming.Scheme) error { newShard := oldShard.DeepCopy() var errs []error // Add Bundle condition - bundleCond := bundlehelper.GetBundleReadyCondition(ctx, r.Client, newShard, newShard.Generation) + bundleCond := bundlehelper.GetBundleReadyCondition(ctx, r.Client, newShard, newShard.Generation, names) conditions = append(conditions, bundleCond) // Check if shard is bundled (has bundle annotation with Ready bundle) @@ -263,7 +265,7 @@ func (r *ShardReconciler) reconcileStatus(ctx context.Context, oldShard *operato // Only check deployment status if not bundled if !isBundled { - depKey := types.NamespacedName{Namespace: newShard.Namespace, Name: resources.GetShardDeploymentName(newShard)} + depKey := types.NamespacedName{Namespace: newShard.Namespace, Name: names.ShardDeploymentName(newShard)} cond, err := util.GetDeploymentAvailableCondition(ctx, r.Client, depKey) if err != nil { errs = append(errs, err) @@ -311,7 +313,7 @@ func (r *ShardReconciler) reconcileStatus(ctx context.Context, oldShard *operato return kerrors.NewAggregate(errs) } -func (r *ShardReconciler) handleDeletion(ctx context.Context, s *operatorv1alpha1.Shard) ([]metav1.Condition, error) { +func (r *ShardReconciler) handleDeletion(ctx context.Context, s *operatorv1alpha1.Shard, names naming.Scheme) ([]metav1.Condition, error) { logger := log.FromContext(ctx) if !slices.Contains(s.Finalizers, cleanupFinalizer) { @@ -330,7 +332,7 @@ func (r *ShardReconciler) handleDeletion(ctx context.Context, s *operatorv1alpha } // Create client to root shard - kcpClient, err := client.NewRootShardClient(ctx, r.Client, rootShard, logicalcluster.Name("root"), r.Scheme) + kcpClient, err := client.NewRootShardClient(ctx, names, r.Client, rootShard, logicalcluster.Name("root"), r.Scheme) if err != nil { return nil, fmt.Errorf("failed to create root shard client: %w", err) } diff --git a/internal/controller/virtualworkspace/controller.go b/internal/controller/virtualworkspace/controller.go index 2e26402a..ef724ff6 100644 --- a/internal/controller/virtualworkspace/controller.go +++ b/internal/controller/virtualworkspace/controller.go @@ -42,7 +42,7 @@ import ( "github.com/kcp-dev/kcp-operator/internal/metrics" "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/reconciling/modifier" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/virtualworkspace" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -104,18 +104,20 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl. return ctrl.Result{}, nil } + namingScheme := naming.NewVersion1() + vwCopy := vw.DeepCopy() - conditions, recErr := r.reconcile(ctx, vwCopy) + conditions, recErr := r.reconcile(ctx, vwCopy, namingScheme) - if err := r.reconcileStatus(ctx, vw, vwCopy, conditions); err != nil { + if err := r.reconcileStatus(ctx, vw, vwCopy, conditions, namingScheme); err != nil { recErr = kerrors.NewAggregate([]error{recErr, err}) } return ctrl.Result{}, recErr } -func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.VirtualWorkspace) ([]metav1.Condition, error) { +func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.VirtualWorkspace, names naming.Scheme) ([]metav1.Condition, error) { var conditions []metav1.Condition var ( @@ -139,8 +141,8 @@ func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.Virtual return conditions, err } - clientCertIssuer = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA) - // serverCA = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + clientCertIssuer = names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA) + // serverCA = namingScheme.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) case vw.Spec.Target.ShardRef != nil: shard = &operatorv1alpha1.Shard{} @@ -181,8 +183,8 @@ func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.Virtual } // The client CA is shared among all shards and owned by the root shard. - clientCertIssuer = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA) - // serverCA = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + clientCertIssuer = names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA) + // serverCA = namingScheme.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) default: err := errors.New("no valid target for VirtualWorkspace found") @@ -206,14 +208,14 @@ func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.Virtual revisionLabels := modifier.RelatedRevisionsLabels(ctx, r.Client) if err := reconciling.ReconcileCertificates(ctx, []reconciling.NamedCertificateReconcilerFactory{ - virtualworkspace.ClientCertificateReconciler(vw, clientCertIssuer), - virtualworkspace.ServerCertificateReconciler(vw, rootShard), + virtualworkspace.ClientCertificateReconciler(vw, clientCertIssuer, names), + virtualworkspace.ServerCertificateReconciler(vw, rootShard, names), }, vw.Namespace, r.Client, ownerRefWrapper); err != nil { return conditions, err } if err := k8creconciling.ReconcileDeployments(ctx, []k8creconciling.NamedDeploymentReconcilerFactory{ - virtualworkspace.DeploymentReconciler(vw, rootShard, shard), + virtualworkspace.DeploymentReconciler(vw, rootShard, shard, names), }, vw.Namespace, r.Client, ownerRefWrapper, revisionLabels); err != nil { // Swallow these errors and instead rely on us watching Secrets and re-reconciling whenever they change. if errors.Is(err, modifier.ErrMountNotFound) { @@ -224,7 +226,7 @@ func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.Virtual } if err := k8creconciling.ReconcileServices(ctx, []k8creconciling.NamedServiceReconcilerFactory{ - virtualworkspace.ServiceReconciler(vw), + virtualworkspace.ServiceReconciler(vw, names), }, vw.Namespace, r.Client, ownerRefWrapper); err != nil { return conditions, err } @@ -232,9 +234,9 @@ func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.Virtual return conditions, nil } -func (r *Reconciler) reconcileStatus(ctx context.Context, oldVW *operatorv1alpha1.VirtualWorkspace, vw *operatorv1alpha1.VirtualWorkspace, conditions []metav1.Condition) error { +func (r *Reconciler) reconcileStatus(ctx context.Context, oldVW *operatorv1alpha1.VirtualWorkspace, vw *operatorv1alpha1.VirtualWorkspace, conditions []metav1.Condition, names naming.Scheme) error { // Check deployment status - depKey := types.NamespacedName{Namespace: vw.Namespace, Name: resources.GetVirtualWorkspaceDeploymentName(vw)} + depKey := types.NamespacedName{Namespace: vw.Namespace, Name: names.VirtualWorkspaceDeploymentName(vw)} cond, err := util.GetDeploymentAvailableCondition(ctx, r.Client, depKey) if err != nil { return err @@ -277,35 +279,57 @@ func (r *Reconciler) mapIssuerToVirtualWorkspaces(ctx context.Context, obj ctrlr logger := log.FromContext(ctx).WithValues("issuer", obj.GetName()) logger.V(4).Info("Mapping Issuer to VirtualWorkspaces") - // Find all VirtualWorkspaces that use this Issuer for their client certificate + // Find all VirtualWorkspaces that use this Issuer for their server/client certificates var virtualWorkspaces operatorv1alpha1.VirtualWorkspaceList if err := r.List(ctx, &virtualWorkspaces, ctrlruntimeclient.InNamespace(obj.GetNamespace())); err != nil { logger.Error(err, "Failed to list VirtualWorkspaces") return []ctrl.Request{} } + allNamingSchemes := []naming.Scheme{ + naming.NewVersion1(), + } + var requests []ctrl.Request for _, vw := range virtualWorkspaces.Items { - var expectedIssuer string + var rootShard *operatorv1alpha1.RootShard + switch { case vw.Spec.Target.RootShardRef != nil: - rootShard := &operatorv1alpha1.RootShard{} - if err := r.Get(ctx, types.NamespacedName{Name: vw.Spec.Target.RootShardRef.Name, Namespace: vw.Namespace}, rootShard); err == nil { - expectedIssuer = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA) + rootShard = &operatorv1alpha1.RootShard{} + if err := r.Get(ctx, types.NamespacedName{Name: vw.Spec.Target.RootShardRef.Name, Namespace: vw.Namespace}, rootShard); err != nil { + logger.Error(err, "Failed to get RootShard") } case vw.Spec.Target.ShardRef != nil: shard := &operatorv1alpha1.Shard{} if err := r.Get(ctx, types.NamespacedName{Name: vw.Spec.Target.ShardRef.Name, Namespace: vw.Namespace}, shard); err == nil { if ref := shard.Spec.RootShard.Reference; ref != nil { - rootShard := &operatorv1alpha1.RootShard{} - if err := r.Get(ctx, types.NamespacedName{Name: ref.Name, Namespace: vw.Namespace}, rootShard); err == nil { - expectedIssuer = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA) + rootShard = &operatorv1alpha1.RootShard{} + if err := r.Get(ctx, types.NamespacedName{Name: ref.Name, Namespace: vw.Namespace}, rootShard); err != nil { + logger.Error(err, "Failed to get RootShard") } } } } - if expectedIssuer == obj.GetName() { + // check name in case the .Get() call failed + if rootShard == nil || rootShard.Name == "" { + continue + } + + // Enqueue this issuer if it is being used by any existing naming scheme for either the ServerCA or Client CA. + issuerName := obj.GetName() + + var enqueue bool + for _, names := range allNamingSchemes { + // In the kcp-operator, the name of the Issuer is always identical to the name of the CA. + if issuerName == names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA) || issuerName == names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA) { + enqueue = true + break + } + } + + if enqueue { requests = append(requests, ctrl.Request{ NamespacedName: types.NamespacedName{ Name: vw.Name, diff --git a/internal/resources/cacheserver/certificates.go b/internal/resources/cacheserver/certificates.go index 82fad5f7..892a5844 100644 --- a/internal/resources/cacheserver/certificates.go +++ b/internal/resources/cacheserver/certificates.go @@ -22,13 +22,14 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) // RootCACertificateReconciler creates a standalone CA just for a single cache-server. -func RootCACertificateReconciler(server *operatorv1alpha1.CacheServer) reconciling.NamedCertificateReconcilerFactory { - name := resources.GetCacheServerCAName(server.Name, operatorv1alpha1.RootCA) +func RootCACertificateReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { + name := names.CacheServerCAName(server.Name, operatorv1alpha1.RootCA) template := server.Spec.CertificateTemplates.CATemplate(operatorv1alpha1.RootCA) if server.Spec.Certificates.IssuerRef == nil { @@ -37,7 +38,7 @@ func RootCACertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetCacheServerResourceLabels(server)) + cert.SetLabels(names.CacheServerResourceLabels(server)) cert.Spec = certmanagerv1.CertificateSpec{ IsCA: true, @@ -70,13 +71,13 @@ func RootCACertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili // ClientCertificateReconciler creates a client certificate for authenticating to the cache server. // This certificate is mounted by shards that connect to the cache server. -func ClientCertificateReconciler(server *operatorv1alpha1.CacheServer) reconciling.NamedCertificateReconcilerFactory { - name := resources.GetCacheServerClientCertificateName(server) +func ClientCertificateReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { + name := names.CacheServerClientCertificateName(server) template := server.Spec.CertificateTemplates.CertificateTemplate(operatorv1alpha1.ClientCertificate) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetCacheServerResourceLabels(server)) + cert.SetLabels(names.CacheServerResourceLabels(server)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -106,7 +107,7 @@ func ClientCertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetCacheServerCAName(server.Name, operatorv1alpha1.RootCA), + Name: names.CacheServerCAName(server.Name, operatorv1alpha1.RootCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -117,15 +118,15 @@ func ClientCertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili } } -func ServerCertificateReconciler(server *operatorv1alpha1.CacheServer) reconciling.NamedCertificateReconcilerFactory { +func ServerCertificateReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ServerCertificate - name := resources.GetCacheServerCertificateName(server, certKind) + name := names.CacheServerCertificateName(server, certKind) template := server.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetCacheServerResourceLabels(server)) + cert.SetLabels(names.CacheServerResourceLabels(server)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -150,11 +151,11 @@ func ServerCertificateReconciler(server *operatorv1alpha1.CacheServer) reconcili DNSNames: []string{ "localhost", - resources.GetCacheServerBaseHost(server), + names.CacheServerBaseHost(server), }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetCacheServerCAName(server.Name, operatorv1alpha1.RootCA), + Name: names.CacheServerCAName(server.Name, operatorv1alpha1.RootCA), Kind: "Issuer", Group: "cert-manager.io", }, diff --git a/internal/resources/cacheserver/deployment.go b/internal/resources/cacheserver/deployment.go index 43629b4c..48a084a5 100644 --- a/internal/resources/cacheserver/deployment.go +++ b/internal/resources/cacheserver/deployment.go @@ -31,6 +31,7 @@ import ( "k8s.io/utils/ptr" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -75,10 +76,10 @@ func getClientCertificateMountPath() string { return "/etc/cache-server/tls/client-certificate" } -func DeploymentReconciler(server *operatorv1alpha1.CacheServer) reconciling.NamedDeploymentReconcilerFactory { +func DeploymentReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) reconciling.NamedDeploymentReconcilerFactory { return func() (string, reconciling.DeploymentReconciler) { - return resources.GetCacheServerDeploymentName(server), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { - labels := resources.GetCacheServerResourceLabels(server) + return names.CacheServerDeploymentName(server), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { + labels := names.CacheServerResourceLabels(server) dep.SetLabels(labels) dep.Spec.Selector = &metav1.LabelSelector{ MatchLabels: labels, @@ -101,7 +102,7 @@ func DeploymentReconciler(server *operatorv1alpha1.CacheServer) reconciling.Name volumes, volumeMounts := getVolumeMounts(server) - for _, sm := range getSecretMounts(server, version) { + for _, sm := range getSecretMounts(server, version, names) { v, vm := sm.Build() volumes = append(volumes, v) volumeMounts = append(volumeMounts, vm) @@ -241,11 +242,11 @@ func getArgs(server *operatorv1alpha1.CacheServer, version *semver.Version) []st return args } -func getSecretMounts(server *operatorv1alpha1.CacheServer, version *semver.Version) []utils.SecretMount { +func getSecretMounts(server *operatorv1alpha1.CacheServer, version *semver.Version, names naming.Scheme) []utils.SecretMount { secretMounts := []utils.SecretMount{ { VolumeName: "serving-cert", - SecretName: resources.GetCacheServerCertificateName(server, operatorv1alpha1.ServerCertificate), + SecretName: names.CacheServerCertificateName(server, operatorv1alpha1.ServerCertificate), MountPath: getCertificateMountPath(operatorv1alpha1.ServerCertificate), }, } @@ -253,7 +254,7 @@ func getSecretMounts(server *operatorv1alpha1.CacheServer, version *semver.Versi if hasAuthenticatedCache(version) { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "client-ca", - SecretName: resources.GetCacheServerCAName(server.Name, operatorv1alpha1.RootCA), + SecretName: names.CacheServerCAName(server.Name, operatorv1alpha1.RootCA), MountPath: getCAMountPath(operatorv1alpha1.RootCA), }) } diff --git a/internal/resources/cacheserver/issuers.go b/internal/resources/cacheserver/issuers.go index f1441191..ff2712e3 100644 --- a/internal/resources/cacheserver/issuers.go +++ b/internal/resources/cacheserver/issuers.go @@ -20,12 +20,12 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/kcp-dev/kcp-operator/internal/reconciling" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func RootCAIssuerReconciler(server *operatorv1alpha1.CacheServer) reconciling.NamedIssuerReconcilerFactory { - name := resources.GetCacheServerCAName(server.Name, operatorv1alpha1.RootCA) +func RootCAIssuerReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) reconciling.NamedIssuerReconcilerFactory { + name := names.CacheServerCAName(server.Name, operatorv1alpha1.RootCA) secretName := name if server.Spec.Certificates.CASecretRef != nil { @@ -34,7 +34,7 @@ func RootCAIssuerReconciler(server *operatorv1alpha1.CacheServer) reconciling.Na return func() (string, reconciling.IssuerReconciler) { return name, func(issuer *certmanagerv1.Issuer) (*certmanagerv1.Issuer, error) { - issuer.SetLabels(resources.GetCacheServerResourceLabels(server)) + issuer.SetLabels(names.CacheServerResourceLabels(server)) issuer.Spec = certmanagerv1.IssuerSpec{ IssuerConfig: certmanagerv1.IssuerConfig{ CA: &certmanagerv1.CAIssuer{ diff --git a/internal/resources/cacheserver/kubeconfigs.go b/internal/resources/cacheserver/kubeconfigs.go index 90d8966b..3039fedf 100644 --- a/internal/resources/cacheserver/kubeconfigs.go +++ b/internal/resources/cacheserver/kubeconfigs.go @@ -23,18 +23,18 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func KubeconfigReconciler(server *operatorv1alpha1.CacheServer) k8creconciling.NamedSecretReconcilerFactory { +func KubeconfigReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { const ( serverName = "cache" contextName = "cache" ) return func() (string, k8creconciling.SecretReconciler) { - return resources.GetCacheServerKubeconfigName(server.Name), func(secret *corev1.Secret) (*corev1.Secret, error) { + return names.CacheServerKubeconfigName(server.Name), func(secret *corev1.Secret) (*corev1.Secret, error) { var config *clientcmdapi.Config if secret.Data == nil { secret.Data = make(map[string][]byte) @@ -43,7 +43,7 @@ func KubeconfigReconciler(server *operatorv1alpha1.CacheServer) k8creconciling.N config = &clientcmdapi.Config{ Clusters: map[string]*clientcmdapi.Cluster{ serverName: { - Server: resources.GetCacheServerBaseURL(server), + Server: names.CacheServerBaseURL(server), CertificateAuthority: getCAMountPath(operatorv1alpha1.RootCA) + "/tls.crt", }, }, diff --git a/internal/resources/cacheserver/service.go b/internal/resources/cacheserver/service.go index 112d670b..a5de0ebe 100644 --- a/internal/resources/cacheserver/service.go +++ b/internal/resources/cacheserver/service.go @@ -23,15 +23,15 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func ServiceReconciler(server *operatorv1alpha1.CacheServer) reconciling.NamedServiceReconcilerFactory { +func ServiceReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) reconciling.NamedServiceReconcilerFactory { return func() (string, reconciling.ServiceReconciler) { - return resources.GetCacheServerServiceName(server), func(svc *corev1.Service) (*corev1.Service, error) { - labels := resources.GetCacheServerResourceLabels(server) + return names.CacheServerServiceName(server), func(svc *corev1.Service) (*corev1.Service, error) { + labels := names.CacheServerResourceLabels(server) svc.SetLabels(labels) svc.Spec.Type = corev1.ServiceTypeClusterIP svc.Spec.Ports = []corev1.ServicePort{ diff --git a/internal/resources/frontproxy/ca_bundle.go b/internal/resources/frontproxy/ca_bundle.go index ea9f907f..ec4d9b97 100644 --- a/internal/resources/frontproxy/ca_bundle.go +++ b/internal/resources/frontproxy/ca_bundle.go @@ -44,7 +44,7 @@ func (r *reconciler) mergedClientCASecretName() string { func (r *reconciler) mergedClientCASecretReconciler(ctx context.Context, kubeClient ctrlruntimeclient.Client) k8creconciling.NamedSecretReconcilerFactory { getCA := func(caType operatorv1alpha1.CA) ([]byte, error) { caSecret := &corev1.Secret{} - caSecretName := resources.GetRootShardCAName(r.rootShard, caType) + caSecretName := r.names.RootShardCAName(r.rootShard, caType) if err := kubeClient.Get(ctx, types.NamespacedName{ Namespace: r.rootShard.Namespace, Name: caSecretName, @@ -108,7 +108,7 @@ func (r *reconciler) mergedCABundleSecretReconciler(ctx context.Context, kubeCli // Get ServerCA certificate from the rootshard serverCASecret := &corev1.Secret{} - serverCASecretName := resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.ServerCA) + serverCASecretName := r.names.RootShardCAName(r.rootShard, operatorv1alpha1.ServerCA) err := kubeClient.Get(ctx, types.NamespacedName{ Name: serverCASecretName, Namespace: r.rootShard.Namespace, diff --git a/internal/resources/frontproxy/certificates.go b/internal/resources/frontproxy/certificates.go index bb12d2f1..a3bf2fd7 100644 --- a/internal/resources/frontproxy/certificates.go +++ b/internal/resources/frontproxy/certificates.go @@ -42,9 +42,9 @@ func (r *reconciler) certSecretLabels() map[string]string { func (r *reconciler) certName(certKind operatorv1alpha1.Certificate) string { if r.frontProxy != nil { - return resources.GetFrontProxyCertificateName(r.rootShard, r.frontProxy, certKind) + return r.names.FrontProxyCertificateName(r.rootShard, r.frontProxy, certKind) } else { - return resources.GetRootShardProxyCertificateName(r.rootShard, certKind) + return r.names.RootShardProxyCertificateName(r.rootShard, certKind) } } @@ -121,7 +121,7 @@ func (r *reconciler) serverCertificateReconciler() reconciling.NamedCertificateR DNSNames: dnsNames, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.ServerCA), + Name: r.names.RootShardCAName(r.rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -166,7 +166,7 @@ func (r *reconciler) adminKubeconfigCertificateReconciler() reconciling.NamedCer }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.FrontProxyClientCA), + Name: r.names.RootShardCAName(r.rootShard, operatorv1alpha1.FrontProxyClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -210,7 +210,7 @@ func (r *reconciler) kubeconfigCertificateReconciler() reconciling.NamedCertific }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.ClientCA), + Name: r.names.RootShardCAName(r.rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -250,7 +250,7 @@ func (r *reconciler) requestHeaderCertificateReconciler() reconciling.NamedCerti }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.RequestHeaderClientCA), + Name: r.names.RootShardCAName(r.rootShard, operatorv1alpha1.RequestHeaderClientCA), Kind: "Issuer", Group: "cert-manager.io", }, diff --git a/internal/resources/frontproxy/configmap.go b/internal/resources/frontproxy/configmap.go index a0da91f9..89b95f3b 100644 --- a/internal/resources/frontproxy/configmap.go +++ b/internal/resources/frontproxy/configmap.go @@ -22,15 +22,14 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/yaml" - "github.com/kcp-dev/kcp-operator/internal/resources" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) func (r *reconciler) pathMappingConfigMapName() string { if r.frontProxy != nil { - return resources.GetFrontProxyConfigName(r.frontProxy) + return r.names.FrontProxyConfigName(r.frontProxy) } else { - return resources.GetRootShardProxyConfigName(r.rootShard) + return r.names.RootShardProxyConfigName(r.rootShard) } } @@ -59,7 +58,7 @@ func (r *reconciler) pathMappingConfigMapReconciler() reconciling.NamedConfigMap // defaultPathMappings sets up default paths for a front-proxy func (r *reconciler) defaultPathMappings() []operatorv1alpha1.PathMappingEntry { - url := resources.GetRootShardBaseURL(r.rootShard) + url := r.names.RootShardBaseURL(r.rootShard) // Determine CA path based on CABundleSecretRef backendCA := kcpBasepath + "/tls/ca/tls.crt" diff --git a/internal/resources/frontproxy/configmap_test.go b/internal/resources/frontproxy/configmap_test.go index 55af6750..d1584210 100644 --- a/internal/resources/frontproxy/configmap_test.go +++ b/internal/resources/frontproxy/configmap_test.go @@ -24,6 +24,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -81,9 +82,11 @@ func TestDefaultPathMappings(t *testing.T) { }, } + version1 := naming.NewVersion1() + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - rec := NewFrontProxy(tt.frontProxy, tt.rootShard) + rec := NewFrontProxy(tt.frontProxy, tt.rootShard, version1) mappings := rec.defaultPathMappings() require.Len(t, mappings, 2) diff --git a/internal/resources/frontproxy/deployment.go b/internal/resources/frontproxy/deployment.go index 24668d49..378d732b 100644 --- a/internal/resources/frontproxy/deployment.go +++ b/internal/resources/frontproxy/deployment.go @@ -43,13 +43,13 @@ func (r *reconciler) deploymentReconciler() reconciling.NamedDeploymentReconcile ) if r.frontProxy != nil { - name = resources.GetFrontProxyDeploymentName(r.frontProxy) + name = r.names.FrontProxyDeploymentName(r.frontProxy) imageSpec = r.frontProxy.Spec.Image depResources = r.frontProxy.Spec.Resources template = r.frontProxy.Spec.DeploymentTemplate replicas = r.frontProxy.Spec.Replicas } else { - name = resources.GetRootShardProxyDeploymentName(r.rootShard) + name = r.names.RootShardProxyDeploymentName(r.rootShard) if r.rootShard.Spec.Proxy != nil { imageSpec = r.rootShard.Spec.Proxy.Image @@ -149,9 +149,9 @@ func (r *reconciler) deploymentReconciler() reconciling.NamedDeploymentReconcile { var secretName string if r.frontProxy != nil { - secretName = resources.GetFrontProxyDynamicKubeconfigName(r.rootShard, r.frontProxy) + secretName = r.names.FrontProxyDynamicKubeconfigName(r.rootShard, r.frontProxy) } else { - secretName = resources.GetRootShardProxyDynamicKubeconfigName(r.rootShard) + secretName = r.names.RootShardProxyDynamicKubeconfigName(r.rootShard) } // readonly=false because front-proxy updates the file to work with different shards @@ -168,7 +168,7 @@ func (r *reconciler) deploymentReconciler() reconciling.NamedDeploymentReconcile mountSecret(r.certName(operatorv1alpha1.RequestHeaderClientCertificate), frontProxyBasepath+"/requestheader-client", true) // kcp rootshard root ca - mountSecret(resources.GetRootShardCAName(r.rootShard, operatorv1alpha1.RootCA), kcpBasepath+"/tls/ca", true) + mountSecret(r.names.RootShardCAName(r.rootShard, operatorv1alpha1.RootCA), kcpBasepath+"/tls/ca", true) // If caBundleSecretRef is specified, mount the merged CA bundle secret. // This secret contains both kcp root CA and user-provided CA bundle merged together. @@ -216,7 +216,7 @@ func (r *reconciler) deploymentReconciler() reconciling.NamedDeploymentReconcile dep = utils.ApplyDeploymentTemplate(dep, template) if r.frontProxy != nil { - dep = utils.ApplyFrontProxyAuthConfiguration(dep, r.frontProxy.Spec.Auth, r.rootShard) + dep = utils.ApplyFrontProxyAuthConfiguration(dep, r.frontProxy.Spec.Auth, r.rootShard, r.names) // If frontproxy has bundle annotation, store desired replicas in annotation then scale deployment to 0 locally if r.frontProxy.Annotations != nil && r.frontProxy.Annotations[resources.BundleAnnotation] != "" { diff --git a/internal/resources/frontproxy/deployment_test.go b/internal/resources/frontproxy/deployment_test.go index 86f10c79..839cbe62 100644 --- a/internal/resources/frontproxy/deployment_test.go +++ b/internal/resources/frontproxy/deployment_test.go @@ -28,11 +28,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) func TestDeploymentReconciler(t *testing.T) { + version1 := naming.NewVersion1() tests := []struct { name string frontProxy *operatorv1alpha1.FrontProxy @@ -59,7 +60,7 @@ func TestDeploymentReconciler(t *testing.T) { Name: "test-root-shard", }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -77,13 +78,13 @@ func TestDeploymentReconciler(t *testing.T) { } expectedMounts := []string{ - resources.GetFrontProxyDynamicKubeconfigName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}), - resources.GetFrontProxyCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}, operatorv1alpha1.KubeconfigCertificate), - resources.GetFrontProxyCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}, operatorv1alpha1.ServerCertificate), - resources.GetFrontProxyCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}, operatorv1alpha1.RequestHeaderClientCertificate), - resources.GetFrontProxyConfigName(&operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}), - resources.GetMergedClientCAName("test-front-proxy"), - resources.GetRootShardCAName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.RootCA), + version1.FrontProxyDynamicKubeconfigName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}), + version1.FrontProxyCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}, operatorv1alpha1.KubeconfigCertificate), + version1.FrontProxyCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}, operatorv1alpha1.ServerCertificate), + version1.FrontProxyCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, &operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}, operatorv1alpha1.RequestHeaderClientCertificate), + version1.FrontProxyConfigName(&operatorv1alpha1.FrontProxy{ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}}), + version1.MergedClientCAName("test-front-proxy"), + version1.RootShardCAName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.RootCA), } for _, expectedMount := range expectedMounts { @@ -121,7 +122,7 @@ func TestDeploymentReconciler(t *testing.T) { Name: "test-root-shard", }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -151,7 +152,7 @@ func TestDeploymentReconciler(t *testing.T) { Name: "test-root-shard", }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -181,7 +182,7 @@ func TestDeploymentReconciler(t *testing.T) { Name: "test-root-shard", }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -228,7 +229,7 @@ func TestDeploymentReconciler(t *testing.T) { Name: "test-root-shard", }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -280,7 +281,7 @@ func TestDeploymentReconciler(t *testing.T) { Name: "test-root-shard", }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -337,7 +338,7 @@ func TestDeploymentReconciler(t *testing.T) { }, }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -369,10 +370,10 @@ func TestDeploymentReconciler(t *testing.T) { foundShard2Volume := false for _, volume := range dep.Spec.Template.Spec.Volumes { - if volume.Name == resources.GetRootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) { + if volume.Name == version1.RootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) { foundShard1Volume = true } - if volume.Name == resources.GetShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "test-shard-2"}}, operatorv1alpha1.ServiceAccountCertificate) { + if volume.Name == version1.ShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "test-shard-2"}}, operatorv1alpha1.ServiceAccountCertificate) { foundShard2Volume = true } } @@ -384,10 +385,10 @@ func TestDeploymentReconciler(t *testing.T) { foundShard2VolumeMount := false for _, volumeMount := range container.VolumeMounts { - if volumeMount.Name == resources.GetRootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) { + if volumeMount.Name == version1.RootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) { foundShard1VolumeMount = true } - if volumeMount.Name == resources.GetShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "test-shard-2"}}, operatorv1alpha1.ServiceAccountCertificate) { + if volumeMount.Name == version1.ShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "test-shard-2"}}, operatorv1alpha1.ServiceAccountCertificate) { foundShard2VolumeMount = true } } @@ -418,7 +419,7 @@ func TestDeploymentReconciler(t *testing.T) { Name: "test-root-shard", }, }, - expectedName: resources.GetFrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ + expectedName: version1.FrontProxyDeploymentName(&operatorv1alpha1.FrontProxy{ ObjectMeta: metav1.ObjectMeta{Name: "test-front-proxy"}, }), validateDeploy: func(t *testing.T, dep *appsv1.Deployment) { @@ -454,7 +455,7 @@ func TestDeploymentReconciler(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - fpReconciler := NewFrontProxy(tt.frontProxy, tt.rootShard) + fpReconciler := NewFrontProxy(tt.frontProxy, tt.rootShard, version1) name, reconcilerFunc := fpReconciler.deploymentReconciler()() assert.Equal(t, tt.expectedName, name) @@ -566,11 +567,14 @@ func TestGetArgs(t *testing.T) { }, } + version1 := naming.NewVersion1() + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { rec := NewFrontProxy( &operatorv1alpha1.FrontProxy{Spec: *tt.spec}, &operatorv1alpha1.RootShard{}, + version1, ) result := rec.getArgs() diff --git a/internal/resources/frontproxy/reconciler.go b/internal/resources/frontproxy/reconciler.go index 10dc0c44..a14cc561 100644 --- a/internal/resources/frontproxy/reconciler.go +++ b/internal/resources/frontproxy/reconciler.go @@ -29,7 +29,7 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/reconciling/modifier" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -37,9 +37,10 @@ type reconciler struct { frontProxy *operatorv1alpha1.FrontProxy rootShard *operatorv1alpha1.RootShard resourceLabels map[string]string + names naming.Scheme } -func NewFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShard *operatorv1alpha1.RootShard) *reconciler { +func NewFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) *reconciler { if frontProxy == nil { panic("Use NewRootShardProxy instead.") } @@ -47,14 +48,16 @@ func NewFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShard *operatorv return &reconciler{ frontProxy: frontProxy, rootShard: rootShard, - resourceLabels: resources.GetFrontProxyResourceLabels(frontProxy), + resourceLabels: names.FrontProxyResourceLabels(frontProxy), + names: names, } } -func NewRootShardProxy(rootShard *operatorv1alpha1.RootShard) *reconciler { +func NewRootShardProxy(rootShard *operatorv1alpha1.RootShard, namingScheme naming.Scheme) *reconciler { return &reconciler{ rootShard: rootShard, - resourceLabels: resources.GetRootShardProxyResourceLabels(rootShard), + resourceLabels: namingScheme.RootShardProxyResourceLabels(rootShard), + names: namingScheme, } } diff --git a/internal/resources/frontproxy/secrets.go b/internal/resources/frontproxy/secrets.go index 5d945ec0..af55f0b1 100644 --- a/internal/resources/frontproxy/secrets.go +++ b/internal/resources/frontproxy/secrets.go @@ -22,8 +22,6 @@ import ( corev1 "k8s.io/api/core/v1" clientcmdv1 "k8s.io/client-go/tools/clientcmd/api/v1" "sigs.k8s.io/yaml" - - "github.com/kcp-dev/kcp-operator/internal/resources" ) const ( @@ -36,9 +34,9 @@ const ( func (r *reconciler) dynamicKubeconfigSecretReconciler() reconciling.NamedSecretReconcilerFactory { var name string if r.frontProxy != nil { - name = resources.GetFrontProxyDynamicKubeconfigName(r.rootShard, r.frontProxy) + name = r.names.FrontProxyDynamicKubeconfigName(r.rootShard, r.frontProxy) } else { - name = resources.GetRootShardProxyDynamicKubeconfigName(r.rootShard) + name = r.names.RootShardProxyDynamicKubeconfigName(r.rootShard) } return func() (string, reconciling.SecretReconciler) { @@ -66,7 +64,7 @@ func (r *reconciler) dynamicKubeconfig() ([]byte, error) { Name: "system:admin", Cluster: clientcmdv1.Cluster{ CertificateAuthority: kubeconfigCAPath, - Server: resources.GetRootShardBaseURL(r.rootShard), + Server: r.names.RootShardBaseURL(r.rootShard), }, }, }, diff --git a/internal/resources/frontproxy/service.go b/internal/resources/frontproxy/service.go index b25fce47..2d36c966 100644 --- a/internal/resources/frontproxy/service.go +++ b/internal/resources/frontproxy/service.go @@ -23,16 +23,15 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" - "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) func (r *reconciler) serviceName() string { if r.frontProxy != nil { - return resources.GetFrontProxyServiceName(r.frontProxy) + return r.names.FrontProxyServiceName(r.frontProxy) } else { - return resources.GetRootShardProxyServiceName(r.rootShard) + return r.names.RootShardProxyServiceName(r.rootShard) } } diff --git a/internal/resources/kubeconfig/certificate.go b/internal/resources/kubeconfig/certificate.go index f8906bef..d64f0da0 100644 --- a/internal/resources/kubeconfig/certificate.go +++ b/internal/resources/kubeconfig/certificate.go @@ -23,12 +23,12 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "github.com/kcp-dev/kcp-operator/internal/reconciling" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func ClientCertificateReconciler(kubeConfig *operatorv1alpha1.Kubeconfig, issuerName string) reconciling.NamedCertificateReconcilerFactory { +func ClientCertificateReconciler(kubeConfig *operatorv1alpha1.Kubeconfig, issuerName string, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { orgs := sets.New(kubeConfig.Spec.Groups...) orgs.Insert(KubeconfigGroup(kubeConfig)) @@ -39,7 +39,7 @@ func ClientCertificateReconciler(kubeConfig *operatorv1alpha1.Kubeconfig, issuer SecretName: kubeConfig.GetCertificateName(), SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ Labels: map[string]string{ - resources.KubeconfigLabel: kubeConfig.Name, + "operator.kcp.io/kubeconfig": kubeConfig.Name, }, }, Duration: &kubeConfig.Spec.Validity, diff --git a/internal/resources/kubeconfig/secret.go b/internal/resources/kubeconfig/secret.go index cdb3c4ac..08ee2601 100644 --- a/internal/resources/kubeconfig/secret.go +++ b/internal/resources/kubeconfig/secret.go @@ -27,7 +27,7 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -46,6 +46,7 @@ func KubeconfigSecretReconciler( caSecret *corev1.Secret, certSecret *corev1.Secret, caBundle *corev1.Secret, // can be nil + names naming.Scheme, ) (reconciling.NamedSecretReconcilerFactory, error) { if caBundle != nil && caBundle.Data["tls.crt"] == nil { return nil, fmt.Errorf("the CA bundle secret %s/%s does not contain a `tls.crt` key", caBundle.Namespace, caBundle.Name) @@ -86,7 +87,7 @@ func KubeconfigSecretReconciler( panic("RootShard must be provided when kubeconfig targets one.") } - serverURL := resources.GetRootShardBaseURL(rootShard) + serverURL := names.RootShardBaseURL(rootShard) defaultURL, err := url.JoinPath(serverURL, "clusters", "root") if err != nil { return nil, err @@ -104,7 +105,7 @@ func KubeconfigSecretReconciler( panic("Shard must be provided when kubeconfig targets one.") } - serverURL := resources.GetShardBaseURL(shard) + serverURL := names.ShardBaseURL(shard) defaultURL, err := url.JoinPath(serverURL, "clusters", "root") if err != nil { return nil, err diff --git a/internal/resources/naming/scheme.go b/internal/resources/naming/scheme.go index fb0407b0..91597276 100644 --- a/internal/resources/naming/scheme.go +++ b/internal/resources/naming/scheme.go @@ -17,62 +17,82 @@ limitations under the License. package naming import ( + "fmt" + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) +const ( + appNameLabel = "app.kubernetes.io/name" + appInstanceLabel = "app.kubernetes.io/instance" + appManagedByLabel = "app.kubernetes.io/managed-by" + appComponentLabel = "app.kubernetes.io/component" + + defaultClusterDomain = "cluster.local" +) + type Scheme interface { // RootShard naming - GetRootShardDeploymentName(r *operatorv1alpha1.RootShard) string - GetRootShardProxyDeploymentName(r *operatorv1alpha1.RootShard) string - GetRootShardServiceName(r *operatorv1alpha1.RootShard) string - GetRootShardResourceLabels(r *operatorv1alpha1.RootShard) map[string]string - GetRootShardProxyResourceLabels(r *operatorv1alpha1.RootShard) map[string]string - GetRootShardBaseHost(r *operatorv1alpha1.RootShard) string - GetRootShardBaseURL(r *operatorv1alpha1.RootShard) string - GetRootShardCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string - GetRootShardProxyCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string - GetRootShardCAName(r *operatorv1alpha1.RootShard, caName operatorv1alpha1.CA) string - GetRootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string - GetRootShardProxyConfigName(r *operatorv1alpha1.RootShard) string - GetRootShardProxyServiceName(r *operatorv1alpha1.RootShard) string - GetRootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string + RootShardDeploymentName(r *operatorv1alpha1.RootShard) string + RootShardProxyDeploymentName(r *operatorv1alpha1.RootShard) string + RootShardServiceName(r *operatorv1alpha1.RootShard) string + RootShardResourceLabels(r *operatorv1alpha1.RootShard) map[string]string + RootShardProxyResourceLabels(r *operatorv1alpha1.RootShard) map[string]string + RootShardBaseHost(r *operatorv1alpha1.RootShard) string + RootShardBaseURL(r *operatorv1alpha1.RootShard) string + RootShardCertificateName(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string + RootShardProxyCertificateName(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string + RootShardCAName(r *operatorv1alpha1.RootShard, ca operatorv1alpha1.CA) string + RootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string + RootShardProxyConfigName(r *operatorv1alpha1.RootShard) string + RootShardProxyServiceName(r *operatorv1alpha1.RootShard) string + RootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string // Shard naming - GetShardDeploymentName(s *operatorv1alpha1.Shard) string - GetShardServiceName(s *operatorv1alpha1.Shard) string - GetShardResourceLabels(s *operatorv1alpha1.Shard) map[string]string - GetShardBaseHost(s *operatorv1alpha1.Shard) string - GetShardBaseURL(s *operatorv1alpha1.Shard) string - GetShardCertificateName(s *operatorv1alpha1.Shard, certName operatorv1alpha1.Certificate) string - GetShardKubeconfigSecret(shard *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string + ShardDeploymentName(s *operatorv1alpha1.Shard) string + ShardServiceName(s *operatorv1alpha1.Shard) string + ShardResourceLabels(s *operatorv1alpha1.Shard) map[string]string + ShardBaseHost(s *operatorv1alpha1.Shard) string + ShardBaseURL(s *operatorv1alpha1.Shard) string + ShardCertificateName(s *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string + ShardKubeconfigSecret(s *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string // CacheServer naming - GetCacheServerDeploymentName(s *operatorv1alpha1.CacheServer) string - GetCacheServerServiceName(s *operatorv1alpha1.CacheServer) string - GetCacheServerResourceLabels(s *operatorv1alpha1.CacheServer) map[string]string - GetCacheServerBaseHost(s *operatorv1alpha1.CacheServer) string - GetCacheServerBaseURL(s *operatorv1alpha1.CacheServer) string - GetCacheServerCertificateName(s *operatorv1alpha1.CacheServer, certName operatorv1alpha1.Certificate) string - GetCacheServerCAName(cacheServerName string, caName operatorv1alpha1.CA) string - GetCacheServerClientCertificateName(s *operatorv1alpha1.CacheServer) string - GetCacheServerKubeconfigName(cacheServerName string) string + CacheServerDeploymentName(c *operatorv1alpha1.CacheServer) string + CacheServerServiceName(c *operatorv1alpha1.CacheServer) string + CacheServerResourceLabels(c *operatorv1alpha1.CacheServer) map[string]string + CacheServerBaseHost(c *operatorv1alpha1.CacheServer) string + CacheServerBaseURL(c *operatorv1alpha1.CacheServer) string + CacheServerCertificateName(c *operatorv1alpha1.CacheServer, cert operatorv1alpha1.Certificate) string + CacheServerCAName(cacheServerName string, ca operatorv1alpha1.CA) string + CacheServerClientCertificateName(c *operatorv1alpha1.CacheServer) string + CacheServerKubeconfigName(cacheServerName string) string // VirtualWorkspace naming - GetVirtualWorkspaceDeploymentName(vw *operatorv1alpha1.VirtualWorkspace) string - GetVirtualWorkspaceResourceLabels(vw *operatorv1alpha1.VirtualWorkspace) map[string]string - GetVirtualWorkspaceBaseHost(s *operatorv1alpha1.VirtualWorkspace) string - GetVirtualWorkspaceBaseURL(s *operatorv1alpha1.VirtualWorkspace) string - GetVirtualWorkspaceCertificateName(vw *operatorv1alpha1.VirtualWorkspace, certName operatorv1alpha1.Certificate) string + VirtualWorkspaceDeploymentName(vw *operatorv1alpha1.VirtualWorkspace) string + VirtualWorkspaceServiceName(vw *operatorv1alpha1.VirtualWorkspace) string + VirtualWorkspaceResourceLabels(vw *operatorv1alpha1.VirtualWorkspace) map[string]string + VirtualWorkspaceBaseHost(vw *operatorv1alpha1.VirtualWorkspace) string + VirtualWorkspaceBaseURL(vw *operatorv1alpha1.VirtualWorkspace) string + VirtualWorkspaceCertificateName(vw *operatorv1alpha1.VirtualWorkspace, cert operatorv1alpha1.Certificate) string // FrontProxy naming - GetFrontProxyResourceLabels(f *operatorv1alpha1.FrontProxy) map[string]string - GetFrontProxyDeploymentName(f *operatorv1alpha1.FrontProxy) string - GetFrontProxyCertificateName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy, certName operatorv1alpha1.Certificate) string - GetFrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy) string - GetFrontProxyConfigName(f *operatorv1alpha1.FrontProxy) string - GetFrontProxyServiceName(f *operatorv1alpha1.FrontProxy) string + FrontProxyResourceLabels(fp *operatorv1alpha1.FrontProxy) map[string]string + FrontProxyDeploymentName(fp *operatorv1alpha1.FrontProxy) string + FrontProxyCertificateName(r *operatorv1alpha1.RootShard, fp *operatorv1alpha1.FrontProxy, cert operatorv1alpha1.Certificate) string + FrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, fp *operatorv1alpha1.FrontProxy) string + FrontProxyConfigName(fp *operatorv1alpha1.FrontProxy) string + FrontProxyServiceName(fp *operatorv1alpha1.FrontProxy) string // Bundle naming - GetBundleName(ownerName string) string - GetMergedClientCAName(ownerName string) string + BundleName(ownerName string) string + MergedClientCAName(ownerName string) string +} + +func fqService(svcName, namespace, clusterDomain string) string { + if clusterDomain == "" { + clusterDomain = defaultClusterDomain + } + + return fmt.Sprintf("%s.%s.svc.%s", svcName, namespace, clusterDomain) } diff --git a/internal/resources/naming/v1.go b/internal/resources/naming/v1.go index 22066cd7..43cf1651 100644 --- a/internal/resources/naming/v1.go +++ b/internal/resources/naming/v1.go @@ -22,15 +22,6 @@ import ( operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -const ( - appNameLabel = "app.kubernetes.io/name" - appInstanceLabel = "app.kubernetes.io/instance" - appManagedByLabel = "app.kubernetes.io/managed-by" - appComponentLabel = "app.kubernetes.io/component" - - defaultClusterDomain = "cluster.local" -) - type version1 struct{} func NewVersion1() Scheme { @@ -48,216 +39,200 @@ func (v *version1) getResourceLabels(instance, component string) map[string]stri // RootShard naming -func (v *version1) GetRootShardDeploymentName(r *operatorv1alpha1.RootShard) string { +func (v *version1) RootShardDeploymentName(r *operatorv1alpha1.RootShard) string { return fmt.Sprintf("%s-kcp", r.Name) } -func (v *version1) GetRootShardProxyDeploymentName(r *operatorv1alpha1.RootShard) string { +func (v *version1) RootShardProxyDeploymentName(r *operatorv1alpha1.RootShard) string { return fmt.Sprintf("%s-proxy", r.Name) } -func (v *version1) GetRootShardServiceName(r *operatorv1alpha1.RootShard) string { +func (v *version1) RootShardServiceName(r *operatorv1alpha1.RootShard) string { return fmt.Sprintf("%s-kcp", r.Name) } -func (v *version1) GetRootShardResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { +func (v *version1) RootShardResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { return v.getResourceLabels(r.Name, "rootshard") } -func (v *version1) GetRootShardProxyResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { +func (v *version1) RootShardProxyResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { return v.getResourceLabels(r.Name, "rootshard-proxy") } -func (v *version1) GetRootShardBaseHost(r *operatorv1alpha1.RootShard) string { - clusterDomain := r.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } - - return fmt.Sprintf("%s-kcp.%s.svc.%s", r.Name, r.Namespace, clusterDomain) +func (v *version1) RootShardBaseHost(r *operatorv1alpha1.RootShard) string { + return fqService(v.RootShardServiceName(r), r.Namespace, r.Spec.ClusterDomain) } -func (v *version1) GetRootShardBaseURL(r *operatorv1alpha1.RootShard) string { +func (v *version1) RootShardBaseURL(r *operatorv1alpha1.RootShard) string { if r.Spec.ShardBaseURL != "" { return r.Spec.ShardBaseURL } - return fmt.Sprintf("https://%s:6443", v.GetRootShardBaseHost(r)) + return fmt.Sprintf("https://%s:6443", v.RootShardBaseHost(r)) } -func (v *version1) GetRootShardCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", r.Name, certName) +func (v *version1) RootShardCertificateName(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", r.Name, cert) } -func (v *version1) GetRootShardProxyCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-proxy-%s", r.Name, certName) +func (v *version1) RootShardProxyCertificateName(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-proxy-%s", r.Name, cert) } -func (v *version1) GetRootShardCAName(r *operatorv1alpha1.RootShard, caName operatorv1alpha1.CA) string { - if caName == operatorv1alpha1.RootCA { +func (v *version1) RootShardCAName(r *operatorv1alpha1.RootShard, ca operatorv1alpha1.CA) string { + if ca == operatorv1alpha1.RootCA { return fmt.Sprintf("%s-ca", r.Name) } - return fmt.Sprintf("%s-%s-ca", r.Name, caName) + return fmt.Sprintf("%s-%s-ca", r.Name, ca) } -func (v *version1) GetRootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string { +func (v *version1) RootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string { return fmt.Sprintf("%s-proxy-dynamic-kubeconfig", r.Name) } -func (v *version1) GetRootShardProxyConfigName(r *operatorv1alpha1.RootShard) string { +func (v *version1) RootShardProxyConfigName(r *operatorv1alpha1.RootShard) string { return fmt.Sprintf("%s-proxy-config", r.Name) } -func (v *version1) GetRootShardProxyServiceName(r *operatorv1alpha1.RootShard) string { +func (v *version1) RootShardProxyServiceName(r *operatorv1alpha1.RootShard) string { return fmt.Sprintf("%s-proxy", r.Name) } -func (v *version1) GetRootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { +func (v *version1) RootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { return fmt.Sprintf("%s-%s-kubeconfig", r.Name, cert) } // Shard naming -func (v *version1) GetShardDeploymentName(s *operatorv1alpha1.Shard) string { +func (v *version1) ShardDeploymentName(s *operatorv1alpha1.Shard) string { return fmt.Sprintf("%s-shard-kcp", s.Name) } -func (v *version1) GetShardServiceName(s *operatorv1alpha1.Shard) string { +func (v *version1) ShardServiceName(s *operatorv1alpha1.Shard) string { return fmt.Sprintf("%s-shard-kcp", s.Name) } -func (v *version1) GetShardResourceLabels(s *operatorv1alpha1.Shard) map[string]string { +func (v *version1) ShardResourceLabels(s *operatorv1alpha1.Shard) map[string]string { return v.getResourceLabels(s.Name, "shard") } -func (v *version1) GetShardBaseHost(s *operatorv1alpha1.Shard) string { - clusterDomain := s.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } - - return fmt.Sprintf("%s-shard-kcp.%s.svc.%s", s.Name, s.Namespace, clusterDomain) +func (v *version1) ShardBaseHost(s *operatorv1alpha1.Shard) string { + return fqService(v.ShardServiceName(s), s.Namespace, s.Spec.ClusterDomain) } -func (v *version1) GetShardBaseURL(s *operatorv1alpha1.Shard) string { +func (v *version1) ShardBaseURL(s *operatorv1alpha1.Shard) string { if s.Spec.ShardBaseURL != "" { return s.Spec.ShardBaseURL } - return fmt.Sprintf("https://%s:6443", v.GetShardBaseHost(s)) + return fmt.Sprintf("https://%s:6443", v.ShardBaseHost(s)) } -func (v *version1) GetShardCertificateName(s *operatorv1alpha1.Shard, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", s.Name, certName) +func (v *version1) ShardCertificateName(s *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", s.Name, cert) } -func (v *version1) GetShardKubeconfigSecret(shard *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s-kubeconfig", shard.Name, cert) +func (v *version1) ShardKubeconfigSecret(s *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s-kubeconfig", s.Name, cert) } // CacheServer naming -func (v *version1) GetCacheServerDeploymentName(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("%s-cache-server", s.Name) +func (v *version1) CacheServerDeploymentName(c *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("%s-cache-server", c.Name) } -func (v *version1) GetCacheServerServiceName(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("%s-cache-server", s.Name) +func (v *version1) CacheServerServiceName(c *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("%s-cache-server", c.Name) } -func (v *version1) GetCacheServerResourceLabels(s *operatorv1alpha1.CacheServer) map[string]string { - return v.getResourceLabels(s.Name, "cache-server") +func (v *version1) CacheServerResourceLabels(c *operatorv1alpha1.CacheServer) map[string]string { + return v.getResourceLabels(c.Name, "cache-server") } -func (v *version1) GetCacheServerBaseHost(s *operatorv1alpha1.CacheServer) string { - clusterDomain := s.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } - - return fmt.Sprintf("%s-cache-server.%s.svc.%s", s.Name, s.Namespace, clusterDomain) +func (v *version1) CacheServerBaseHost(c *operatorv1alpha1.CacheServer) string { + return fqService(v.CacheServerServiceName(c), c.Namespace, c.Spec.ClusterDomain) } -func (v *version1) GetCacheServerBaseURL(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("https://%s:6443", v.GetCacheServerBaseHost(s)) +func (v *version1) CacheServerBaseURL(c *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("https://%s:6443", v.CacheServerBaseHost(c)) } -func (v *version1) GetCacheServerCertificateName(s *operatorv1alpha1.CacheServer, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", s.Name, certName) +func (v *version1) CacheServerCertificateName(c *operatorv1alpha1.CacheServer, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", c.Name, cert) } -func (v *version1) GetCacheServerCAName(cacheServerName string, caName operatorv1alpha1.CA) string { - if caName == operatorv1alpha1.RootCA { +func (v *version1) CacheServerCAName(cacheServerName string, ca operatorv1alpha1.CA) string { + if ca == operatorv1alpha1.RootCA { return fmt.Sprintf("%s-ca", cacheServerName) } - return fmt.Sprintf("%s-%s-ca", cacheServerName, caName) + return fmt.Sprintf("%s-%s-ca", cacheServerName, ca) } -func (v *version1) GetCacheServerClientCertificateName(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("%s-client-certificate", s.Name) +func (v *version1) CacheServerClientCertificateName(c *operatorv1alpha1.CacheServer) string { + return fmt.Sprintf("%s-client-certificate", c.Name) } -func (v *version1) GetCacheServerKubeconfigName(cacheServerName string) string { +func (v *version1) CacheServerKubeconfigName(cacheServerName string) string { return fmt.Sprintf("%s-kubeconfig", cacheServerName) } // VirtualWorkspace naming -func (v *version1) GetVirtualWorkspaceDeploymentName(vw *operatorv1alpha1.VirtualWorkspace) string { +func (v *version1) VirtualWorkspaceDeploymentName(vw *operatorv1alpha1.VirtualWorkspace) string { return fmt.Sprintf("%s-virtual-workspace", vw.Name) } -func (v *version1) GetVirtualWorkspaceResourceLabels(vw *operatorv1alpha1.VirtualWorkspace) map[string]string { - return v.getResourceLabels(vw.Name, "virtual-workspace") +func (v *version1) VirtualWorkspaceServiceName(vw *operatorv1alpha1.VirtualWorkspace) string { + return fmt.Sprintf("%s-virtual-workspace", vw.Name) } -func (v *version1) GetVirtualWorkspaceBaseHost(s *operatorv1alpha1.VirtualWorkspace) string { - clusterDomain := s.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } +func (v *version1) VirtualWorkspaceResourceLabels(vw *operatorv1alpha1.VirtualWorkspace) map[string]string { + return v.getResourceLabels(vw.Name, "virtual-workspace") +} - return fmt.Sprintf("%s-virtual-workspace.%s.svc.%s", s.Name, s.Namespace, clusterDomain) +func (v *version1) VirtualWorkspaceBaseHost(vw *operatorv1alpha1.VirtualWorkspace) string { + return fqService(v.VirtualWorkspaceServiceName(vw), vw.Namespace, vw.Spec.ClusterDomain) } -func (v *version1) GetVirtualWorkspaceBaseURL(s *operatorv1alpha1.VirtualWorkspace) string { - return fmt.Sprintf("https://%s:6443", v.GetVirtualWorkspaceBaseHost(s)) +func (v *version1) VirtualWorkspaceBaseURL(vw *operatorv1alpha1.VirtualWorkspace) string { + return fmt.Sprintf("https://%s:6443", v.VirtualWorkspaceBaseHost(vw)) } -func (v *version1) GetVirtualWorkspaceCertificateName(vw *operatorv1alpha1.VirtualWorkspace, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", vw.Name, certName) +func (v *version1) VirtualWorkspaceCertificateName(vw *operatorv1alpha1.VirtualWorkspace, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s", vw.Name, cert) } // FrontProxy naming -func (v *version1) GetFrontProxyResourceLabels(f *operatorv1alpha1.FrontProxy) map[string]string { - return v.getResourceLabels(f.Name, "front-proxy") +func (v *version1) FrontProxyResourceLabels(fp *operatorv1alpha1.FrontProxy) map[string]string { + return v.getResourceLabels(fp.Name, "front-proxy") } -func (v *version1) GetFrontProxyDeploymentName(f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-front-proxy", f.Name) +func (v *version1) FrontProxyDeploymentName(fp *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-front-proxy", fp.Name) } -func (v *version1) GetFrontProxyCertificateName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s-%s", r.Name, f.Name, certName) +func (v *version1) FrontProxyCertificateName(r *operatorv1alpha1.RootShard, fp *operatorv1alpha1.FrontProxy, cert operatorv1alpha1.Certificate) string { + return fmt.Sprintf("%s-%s-%s", r.Name, fp.Name, cert) } -func (v *version1) GetFrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-%s-dynamic-kubeconfig", r.Name, f.Name) +func (v *version1) FrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, fp *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-%s-dynamic-kubeconfig", r.Name, fp.Name) } -func (v *version1) GetFrontProxyConfigName(f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-config", f.Name) +func (v *version1) FrontProxyConfigName(fp *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-config", fp.Name) } -func (v *version1) GetFrontProxyServiceName(f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-front-proxy", f.Name) +func (v *version1) FrontProxyServiceName(fp *operatorv1alpha1.FrontProxy) string { + return fmt.Sprintf("%s-front-proxy", fp.Name) } // Bundle naming -func (v *version1) GetBundleName(ownerName string) string { +func (v *version1) BundleName(ownerName string) string { return fmt.Sprintf("%s-bundle", ownerName) } -func (v *version1) GetMergedClientCAName(ownerName string) string { +func (v *version1) MergedClientCAName(ownerName string) string { return fmt.Sprintf("%s-merged-client-ca", ownerName) } diff --git a/internal/resources/resources.go b/internal/resources/resources.go index 608ca930..65d6804c 100644 --- a/internal/resources/resources.go +++ b/internal/resources/resources.go @@ -41,11 +41,6 @@ const ( // the .prow.yaml accordingly and shift the jobs. ImageTag = "v0.31.0" - appNameLabel = "app.kubernetes.io/name" - appInstanceLabel = "app.kubernetes.io/instance" - appManagedByLabel = "app.kubernetes.io/managed-by" - appComponentLabel = "app.kubernetes.io/component" - // RootShardLabel is placed on Secrets created for Certificates so that // the Secrets can be more easily mapped to their RootShards. RootShardLabel = "operator.kcp.io/rootshard" @@ -66,8 +61,6 @@ const ( // the certificate also has system:masters as an organization, which is what ultimately // grants the operator its permissions. OperatorUsername = "system:kcp-operator" - - defaultClusterDomain = "cluster.local" ) func GetImageSettings(imageSpec *operatorv1alpha1.ImageSpec) (string, []corev1.LocalObjectReference, *semver.Version) { @@ -91,216 +84,3 @@ func GetImageSettings(imageSpec *operatorv1alpha1.ImageSpec) (string, []corev1.L return fmt.Sprintf("%s:%s", repository, tag), imagePullSecrets, version } - -func GetRootShardDeploymentName(r *operatorv1alpha1.RootShard) string { - return fmt.Sprintf("%s-kcp", r.Name) -} - -func GetRootShardProxyDeploymentName(r *operatorv1alpha1.RootShard) string { - return fmt.Sprintf("%s-proxy", r.Name) -} - -func GetShardDeploymentName(s *operatorv1alpha1.Shard) string { - return fmt.Sprintf("%s-shard-kcp", s.Name) -} - -func GetCacheServerDeploymentName(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("%s-cache-server", s.Name) -} - -func GetVirtualWorkspaceDeploymentName(vw *operatorv1alpha1.VirtualWorkspace) string { - return fmt.Sprintf("%s-virtual-workspace", vw.Name) -} - -func GetRootShardServiceName(r *operatorv1alpha1.RootShard) string { - return fmt.Sprintf("%s-kcp", r.Name) -} - -func GetShardServiceName(s *operatorv1alpha1.Shard) string { - return fmt.Sprintf("%s-shard-kcp", s.Name) -} - -func GetCacheServerServiceName(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("%s-cache-server", s.Name) -} - -func getResourceLabels(instance, component string) map[string]string { - return map[string]string{ - appManagedByLabel: "kcp-operator", - appNameLabel: "kcp", - appInstanceLabel: instance, - appComponentLabel: component, - } -} - -func GetRootShardResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { - return getResourceLabels(r.Name, "rootshard") -} - -func GetRootShardProxyResourceLabels(r *operatorv1alpha1.RootShard) map[string]string { - return getResourceLabels(r.Name, "rootshard-proxy") -} - -func GetShardResourceLabels(s *operatorv1alpha1.Shard) map[string]string { - return getResourceLabels(s.Name, "shard") -} - -func GetCacheServerResourceLabels(s *operatorv1alpha1.CacheServer) map[string]string { - return getResourceLabels(s.Name, "cache-server") -} - -func GetVirtualWorkspaceResourceLabels(vw *operatorv1alpha1.VirtualWorkspace) map[string]string { - return getResourceLabels(vw.Name, "virtual-workspace") -} - -func GetRootShardBaseHost(r *operatorv1alpha1.RootShard) string { - clusterDomain := r.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } - - return fmt.Sprintf("%s-kcp.%s.svc.%s", r.Name, r.Namespace, clusterDomain) -} - -func GetRootShardBaseURL(r *operatorv1alpha1.RootShard) string { - if r.Spec.ShardBaseURL != "" { - return r.Spec.ShardBaseURL - } - return fmt.Sprintf("https://%s:6443", GetRootShardBaseHost(r)) -} - -func GetShardBaseHost(s *operatorv1alpha1.Shard) string { - clusterDomain := s.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } - - return fmt.Sprintf("%s-shard-kcp.%s.svc.%s", s.Name, s.Namespace, clusterDomain) -} - -func GetShardBaseURL(s *operatorv1alpha1.Shard) string { - if s.Spec.ShardBaseURL != "" { - return s.Spec.ShardBaseURL - } - return fmt.Sprintf("https://%s:6443", GetShardBaseHost(s)) -} - -func GetCacheServerBaseHost(s *operatorv1alpha1.CacheServer) string { - clusterDomain := s.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } - - return fmt.Sprintf("%s-cache-server.%s.svc.%s", s.Name, s.Namespace, clusterDomain) -} - -func GetCacheServerBaseURL(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("https://%s:6443", GetCacheServerBaseHost(s)) -} - -func GetVirtualWorkspaceBaseHost(s *operatorv1alpha1.VirtualWorkspace) string { - clusterDomain := s.Spec.ClusterDomain - if clusterDomain == "" { - clusterDomain = defaultClusterDomain - } - - return fmt.Sprintf("%s-virtual-workspace.%s.svc.%s", s.Name, s.Namespace, clusterDomain) -} - -func GetVirtualWorkspaceBaseURL(s *operatorv1alpha1.VirtualWorkspace) string { - return fmt.Sprintf("https://%s:6443", GetVirtualWorkspaceBaseHost(s)) -} - -func GetRootShardCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", r.Name, certName) -} - -func GetRootShardProxyCertificateName(r *operatorv1alpha1.RootShard, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-proxy-%s", r.Name, certName) -} - -func GetShardCertificateName(s *operatorv1alpha1.Shard, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", s.Name, certName) -} - -func GetCacheServerCertificateName(s *operatorv1alpha1.CacheServer, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", s.Name, certName) -} - -func GetVirtualWorkspaceCertificateName(vw *operatorv1alpha1.VirtualWorkspace, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s", vw.Name, certName) -} - -func GetRootShardCAName(r *operatorv1alpha1.RootShard, caName operatorv1alpha1.CA) string { - if caName == operatorv1alpha1.RootCA { - return fmt.Sprintf("%s-ca", r.Name) - } - return fmt.Sprintf("%s-%s-ca", r.Name, caName) -} - -func GetCacheServerCAName(cacheServerName string, caName operatorv1alpha1.CA) string { - if caName == operatorv1alpha1.RootCA { - return fmt.Sprintf("%s-ca", cacheServerName) - } - return fmt.Sprintf("%s-%s-ca", cacheServerName, caName) -} - -func GetFrontProxyResourceLabels(f *operatorv1alpha1.FrontProxy) map[string]string { - return getResourceLabels(f.Name, "front-proxy") -} - -func GetFrontProxyDeploymentName(f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-front-proxy", f.Name) -} - -func GetFrontProxyCertificateName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy, certName operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s-%s", r.Name, f.Name, certName) -} - -func GetRootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string { - return fmt.Sprintf("%s-proxy-dynamic-kubeconfig", r.Name) -} - -func GetFrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-%s-dynamic-kubeconfig", r.Name, f.Name) -} - -func GetCacheServerClientCertificateName(s *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("%s-client-certificate", s.Name) -} - -func GetCacheServerKubeconfigName(cacheServerName string) string { - return fmt.Sprintf("%s-kubeconfig", cacheServerName) -} - -func GetRootShardProxyConfigName(r *operatorv1alpha1.RootShard) string { - return fmt.Sprintf("%s-proxy-config", r.Name) -} - -func GetFrontProxyConfigName(f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-config", f.Name) -} - -func GetFrontProxyServiceName(f *operatorv1alpha1.FrontProxy) string { - return fmt.Sprintf("%s-front-proxy", f.Name) -} - -func GetRootShardProxyServiceName(r *operatorv1alpha1.RootShard) string { - return fmt.Sprintf("%s-proxy", r.Name) -} - -func GetRootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s-kubeconfig", r.Name, cert) -} - -func GetShardKubeconfigSecret(shard *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s-kubeconfig", shard.Name, cert) -} - -func GetBundleName(ownerName string) string { - return fmt.Sprintf("%s-bundle", ownerName) -} - -func GetMergedClientCAName(ownerName string) string { - return fmt.Sprintf("%s-merged-client-ca", ownerName) -} diff --git a/internal/resources/rootshard/ca_bundle.go b/internal/resources/rootshard/ca_bundle.go index 18278fae..1dab5fbd 100644 --- a/internal/resources/rootshard/ca_bundle.go +++ b/internal/resources/rootshard/ca_bundle.go @@ -27,10 +27,11 @@ import ( ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func MergedCABundleSecretReconciler(ctx context.Context, rootShard *operatorv1alpha1.RootShard, kubeClient ctrlruntimeclient.Client) k8creconciling.NamedSecretReconcilerFactory { +func MergedCABundleSecretReconciler(ctx context.Context, rootShard *operatorv1alpha1.RootShard, kubeClient ctrlruntimeclient.Client, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { return func() (string, k8creconciling.SecretReconciler) { secretName := fmt.Sprintf("%s-merged-ca-bundle", rootShard.Name) return secretName, func(secret *corev1.Secret) (*corev1.Secret, error) { @@ -40,7 +41,7 @@ func MergedCABundleSecretReconciler(ctx context.Context, rootShard *operatorv1al // Get ServerCA certificate serverCASecret := &corev1.Secret{} - serverCASecretName := resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + serverCASecretName := names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA) err := kubeClient.Get(ctx, types.NamespacedName{ Name: serverCASecretName, Namespace: rootShard.Namespace, diff --git a/internal/resources/rootshard/ca_certificates.go b/internal/resources/rootshard/ca_certificates.go index 94d40496..1c09ccdb 100644 --- a/internal/resources/rootshard/ca_certificates.go +++ b/internal/resources/rootshard/ca_certificates.go @@ -22,13 +22,14 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) // RootCACertificateReconciler creates the central CA used for the kcp setup around a specific RootShard. This shouldn't be called if the RootShard is configured to use a BYO CA certificate. -func RootCACertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { - name := resources.GetRootShardCAName(rootShard, operatorv1alpha1.RootCA) +func RootCACertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { + name := names.RootShardCAName(rootShard, operatorv1alpha1.RootCA) template := rootShard.Spec.CertificateTemplates.CATemplate(operatorv1alpha1.RootCA) if rootShard.Spec.Certificates.IssuerRef == nil { @@ -37,7 +38,7 @@ func RootCACertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ IsCA: true, @@ -68,13 +69,13 @@ func RootCACertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil } } -func CACertificateReconciler(rootShard *operatorv1alpha1.RootShard, ca operatorv1alpha1.CA) reconciling.NamedCertificateReconcilerFactory { - name := resources.GetRootShardCAName(rootShard, ca) +func CACertificateReconciler(rootShard *operatorv1alpha1.RootShard, ca operatorv1alpha1.CA, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { + name := names.RootShardCAName(rootShard, ca) template := rootShard.Spec.CertificateTemplates.CATemplate(ca) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ IsCA: true, CommonName: name, @@ -93,7 +94,7 @@ func CACertificateReconciler(rootShard *operatorv1alpha1.RootShard, ca operatorv }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.RootCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), Kind: "Issuer", Group: "cert-manager.io", }, diff --git a/internal/resources/rootshard/certificates.go b/internal/resources/rootshard/certificates.go index 8cdb8c08..8d3fd8b0 100644 --- a/internal/resources/rootshard/certificates.go +++ b/internal/resources/rootshard/certificates.go @@ -24,19 +24,20 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func ServerCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ServerCertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ServerCertificate - name := resources.GetRootShardCertificateName(rootShard, certKind) + name := names.RootShardCertificateName(rootShard, certKind) template := rootShard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -58,10 +59,10 @@ func ServerCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil certmanagerv1.UsageDigitalSignature, }, - DNSNames: buildRootShardDNSNames(rootShard), + DNSNames: buildRootShardDNSNames(rootShard, names), IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -72,15 +73,15 @@ func ServerCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil } } -func VirtualWorkspacesCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func VirtualWorkspacesCertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.VirtualWorkspacesCertificate - name := resources.GetRootShardCertificateName(rootShard, certKind) + name := names.RootShardCertificateName(rootShard, certKind) template := rootShard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -105,7 +106,7 @@ func VirtualWorkspacesCertificateReconciler(rootShard *operatorv1alpha1.RootShar }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -116,15 +117,15 @@ func VirtualWorkspacesCertificateReconciler(rootShard *operatorv1alpha1.RootShar } } -func ServiceAccountCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ServiceAccountCertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ServiceAccountCertificate - name := resources.GetRootShardCertificateName(rootShard, certKind) + name := names.RootShardCertificateName(rootShard, certKind) template := rootShard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ CommonName: name, SecretName: name, @@ -147,7 +148,7 @@ func ServiceAccountCertificateReconciler(rootShard *operatorv1alpha1.RootShard) }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -158,15 +159,15 @@ func ServiceAccountCertificateReconciler(rootShard *operatorv1alpha1.RootShard) } } -func LogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func LogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.LogicalClusterAdminCertificate - name := resources.GetRootShardCertificateName(rootShard, certKind) + name := names.RootShardCertificateName(rootShard, certKind) template := rootShard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ CommonName: "logical-cluster-admin", SecretName: name, @@ -192,7 +193,7 @@ func LogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha1.RootSh }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -203,15 +204,15 @@ func LogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha1.RootSh } } -func ExternalLogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ExternalLogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ExternalLogicalClusterAdminCertificate - name := resources.GetRootShardCertificateName(rootShard, certKind) + name := names.RootShardCertificateName(rootShard, certKind) template := rootShard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ CommonName: "external-logical-cluster-admin", SecretName: name, @@ -237,7 +238,7 @@ func ExternalLogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -248,15 +249,15 @@ func ExternalLogicalClusterAdminCertificateReconciler(rootShard *operatorv1alpha } } -func OperatorClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func OperatorClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.OperatorCertificate - name := resources.GetRootShardCertificateName(rootShard, certKind) + name := names.RootShardCertificateName(rootShard, certKind) template := rootShard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ CommonName: resources.OperatorUsername, SecretName: name, @@ -286,7 +287,7 @@ func OperatorClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) // the internal root shard proxy (also cluster-local). All of these are configured // to use the regular client CA (not like "normal" front-proxies, which have their // own CA). - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -299,15 +300,15 @@ func OperatorClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) // ClientCertificateReconciler generates a client certificate that is used by the root shard to // connect to an external kcp-virtual-workspaces pod. -func ClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ClientCertificate - name := resources.GetRootShardCertificateName(rootShard, certKind) + name := names.RootShardCertificateName(rootShard, certKind) template := rootShard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + cert.SetLabels(names.RootShardResourceLabels(rootShard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -334,7 +335,7 @@ func ClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -348,9 +349,9 @@ func ClientCertificateReconciler(rootShard *operatorv1alpha1.RootShard) reconcil // buildRootShardDNSNames builds the list of DNS names for the root shard server certificate. // It includes the internal Kubernetes service host, the external hostname, and if shardBaseURL // is set, it also extracts and includes the hostname from that URL. -func buildRootShardDNSNames(rootShard *operatorv1alpha1.RootShard) []string { +func buildRootShardDNSNames(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) []string { dnsNames := sets.New( - resources.GetRootShardBaseHost(rootShard), + names.RootShardBaseHost(rootShard), rootShard.Spec.External.Hostname, ) diff --git a/internal/resources/rootshard/deployment.go b/internal/resources/rootshard/deployment.go index 0f279c79..271af2ea 100644 --- a/internal/resources/rootshard/deployment.go +++ b/internal/resources/rootshard/deployment.go @@ -29,6 +29,7 @@ import ( "k8s.io/utils/ptr" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -76,10 +77,10 @@ func getCacheServerClientCertMountPath() string { return "/etc/cache-server/tls/client-certificate" } -func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace) reconciling.NamedDeploymentReconcilerFactory { +func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace, names naming.Scheme) reconciling.NamedDeploymentReconcilerFactory { return func() (string, reconciling.DeploymentReconciler) { - return resources.GetRootShardDeploymentName(rootShard), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { - labels := resources.GetRootShardResourceLabels(rootShard) + return names.RootShardDeploymentName(rootShard), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { + labels := names.RootShardResourceLabels(rootShard) dep.SetLabels(labels) dep.Spec.Selector = &metav1.LabelSelector{ MatchLabels: labels, @@ -89,11 +90,11 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator secretMounts := []utils.SecretMount{{ VolumeName: "kcp-ca", - SecretName: resources.GetRootShardCAName(rootShard, operatorv1alpha1.RootCA), + SecretName: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), MountPath: getCAMountPath(operatorv1alpha1.RootCA), }} - args := getArgs(rootShard, kcpVW) + args := getArgs(rootShard, kcpVW, names) for _, cert := range []operatorv1alpha1.Certificate{ // requires server CA and the logical-cluster-admin cert to be mounted @@ -103,7 +104,7 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator } { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-kubeconfig", cert), - SecretName: resources.GetRootShardKubeconfigSecret(rootShard, cert), + SecretName: names.RootShardKubeconfigSecret(rootShard, cert), MountPath: getKubeconfigMountPath(cert), }) } @@ -116,7 +117,7 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator } { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-ca", ca), - SecretName: resources.GetRootShardCAName(rootShard, ca), + SecretName: names.RootShardCAName(rootShard, ca), MountPath: getCAMountPath(ca), }) } @@ -130,7 +131,7 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator } { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-cert", cert), - SecretName: resources.GetRootShardCertificateName(rootShard, cert), + SecretName: names.RootShardCertificateName(rootShard, cert), MountPath: getCertificateMountPath(cert), }) } @@ -152,13 +153,13 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator if ref := rootShard.Spec.Cache.Reference; ref != nil { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "cache-server-kubeconfig", - SecretName: resources.GetCacheServerKubeconfigName(ref.Name), + SecretName: names.CacheServerKubeconfigName(ref.Name), MountPath: getCacheServerKubeconfigMountPath(), }) secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "cache-server-ca", - SecretName: resources.GetCacheServerCAName(ref.Name, operatorv1alpha1.RootCA), + SecretName: names.CacheServerCAName(ref.Name, operatorv1alpha1.RootCA), MountPath: getCacheServerCAMountPath(operatorv1alpha1.RootCA), }) @@ -210,7 +211,7 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator } } -func getArgs(rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace) []string { +func getArgs(rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace, names naming.Scheme) []string { args := []string{ // CA configuration. fmt.Sprintf("--root-ca-file=%s/tls.crt", getCAMountPath(operatorv1alpha1.RootCA)), @@ -231,7 +232,7 @@ func getArgs(rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.Virt "--service-account-lookup=false", // General shard configuration. - fmt.Sprintf("--shard-base-url=%s", resources.GetRootShardBaseURL(rootShard)), + fmt.Sprintf("--shard-base-url=%s", names.RootShardBaseURL(rootShard)), fmt.Sprintf("--shard-external-url=https://%s:%d", rootShard.Spec.External.Hostname, rootShard.Spec.External.Port), fmt.Sprintf("--logical-cluster-admin-kubeconfig=%s/kubeconfig", getKubeconfigMountPath(operatorv1alpha1.LogicalClusterAdminCertificate)), fmt.Sprintf("--external-logical-cluster-admin-kubeconfig=%s/kubeconfig", getKubeconfigMountPath(operatorv1alpha1.ExternalLogicalClusterAdminCertificate)), diff --git a/internal/resources/rootshard/issuers.go b/internal/resources/rootshard/issuers.go index 26fc5f5c..c6da189a 100644 --- a/internal/resources/rootshard/issuers.go +++ b/internal/resources/rootshard/issuers.go @@ -20,12 +20,12 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/kcp-dev/kcp-operator/internal/reconciling" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func RootCAIssuerReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedIssuerReconcilerFactory { - name := resources.GetRootShardCAName(rootShard, operatorv1alpha1.RootCA) +func RootCAIssuerReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedIssuerReconcilerFactory { + name := names.RootShardCAName(rootShard, operatorv1alpha1.RootCA) secretName := name if rootShard.Spec.Certificates.CASecretRef != nil { @@ -34,7 +34,7 @@ func RootCAIssuerReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.N return func() (string, reconciling.IssuerReconciler) { return name, func(issuer *certmanagerv1.Issuer) (*certmanagerv1.Issuer, error) { - issuer.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + issuer.SetLabels(names.RootShardResourceLabels(rootShard)) issuer.Spec = certmanagerv1.IssuerSpec{ IssuerConfig: certmanagerv1.IssuerConfig{ CA: &certmanagerv1.CAIssuer{ @@ -48,12 +48,12 @@ func RootCAIssuerReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.N } } -func CAIssuerReconciler(rootShard *operatorv1alpha1.RootShard, ca operatorv1alpha1.CA) reconciling.NamedIssuerReconcilerFactory { - name := resources.GetRootShardCAName(rootShard, ca) +func CAIssuerReconciler(rootShard *operatorv1alpha1.RootShard, ca operatorv1alpha1.CA, names naming.Scheme) reconciling.NamedIssuerReconcilerFactory { + name := names.RootShardCAName(rootShard, ca) return func() (string, reconciling.IssuerReconciler) { return name, func(issuer *certmanagerv1.Issuer) (*certmanagerv1.Issuer, error) { - issuer.SetLabels(resources.GetRootShardResourceLabels(rootShard)) + issuer.SetLabels(names.RootShardResourceLabels(rootShard)) issuer.Spec = certmanagerv1.IssuerSpec{ IssuerConfig: certmanagerv1.IssuerConfig{ CA: &certmanagerv1.CAIssuer{ @@ -67,13 +67,13 @@ func CAIssuerReconciler(rootShard *operatorv1alpha1.RootShard, ca operatorv1alph } } -func ClientCAIssuerReconciler(rootshard *operatorv1alpha1.RootShard) reconciling.NamedIssuerReconcilerFactory { - name := resources.GetRootShardCAName(rootshard, operatorv1alpha1.ClientCA) +func ClientCAIssuerReconciler(rootshard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedIssuerReconcilerFactory { + name := names.RootShardCAName(rootshard, operatorv1alpha1.ClientCA) secretName := name return func() (string, reconciling.IssuerReconciler) { return name, func(issuer *certmanagerv1.Issuer) (*certmanagerv1.Issuer, error) { - issuer.SetLabels(resources.GetRootShardResourceLabels(rootshard)) + issuer.SetLabels(names.RootShardResourceLabels(rootshard)) issuer.Spec = certmanagerv1.IssuerSpec{ IssuerConfig: certmanagerv1.IssuerConfig{ CA: &certmanagerv1.CAIssuer{ @@ -87,13 +87,13 @@ func ClientCAIssuerReconciler(rootshard *operatorv1alpha1.RootShard) reconciling } } -func FrontProxyClientCAIssuerReconciler(rootshard *operatorv1alpha1.RootShard) reconciling.NamedIssuerReconcilerFactory { - name := resources.GetRootShardCAName(rootshard, operatorv1alpha1.FrontProxyClientCA) +func FrontProxyClientCAIssuerReconciler(rootshard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedIssuerReconcilerFactory { + name := names.RootShardCAName(rootshard, operatorv1alpha1.FrontProxyClientCA) secretName := name return func() (string, reconciling.IssuerReconciler) { return name, func(issuer *certmanagerv1.Issuer) (*certmanagerv1.Issuer, error) { - issuer.SetLabels(resources.GetRootShardResourceLabels(rootshard)) + issuer.SetLabels(names.RootShardResourceLabels(rootshard)) issuer.Spec = certmanagerv1.IssuerSpec{ IssuerConfig: certmanagerv1.IssuerConfig{ CA: &certmanagerv1.CAIssuer{ diff --git a/internal/resources/rootshard/kubeconfigs.go b/internal/resources/rootshard/kubeconfigs.go index f907780e..bbad282c 100644 --- a/internal/resources/rootshard/kubeconfigs.go +++ b/internal/resources/rootshard/kubeconfigs.go @@ -25,15 +25,11 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func kubeconfigSecret(rootShard *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s-kubeconfig", rootShard.Name, cert) -} - -func LogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1.RootShard) k8creconciling.NamedSecretReconcilerFactory { +func LogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { const ( serverName = "root-shard" contextName = "shard-base" // hardcoded in kcp @@ -41,7 +37,7 @@ func LogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1.RootSha ) return func() (string, k8creconciling.SecretReconciler) { - return kubeconfigSecret(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { + return names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { var config *clientcmdapi.Config if secret.Data == nil { @@ -51,7 +47,7 @@ func LogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1.RootSha config = &clientcmdapi.Config{ Clusters: map[string]*clientcmdapi.Cluster{ serverName: { - Server: resources.GetRootShardBaseURL(rootShard), + Server: names.RootShardBaseURL(rootShard), CertificateAuthority: getCAMountPath(operatorv1alpha1.ServerCA) + "/tls.crt", }, }, @@ -82,7 +78,7 @@ func LogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1.RootSha } } -func ExternalLogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1.RootShard) k8creconciling.NamedSecretReconcilerFactory { +func ExternalLogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { const ( serverName = "root-shard" contextName = "shard-base" // hardcoded in kcp @@ -90,7 +86,7 @@ func ExternalLogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1 ) return func() (string, k8creconciling.SecretReconciler) { - return kubeconfigSecret(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { + return names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { var config *clientcmdapi.Config if secret.Data == nil { diff --git a/internal/resources/rootshard/service.go b/internal/resources/rootshard/service.go index a458459b..396de47d 100644 --- a/internal/resources/rootshard/service.go +++ b/internal/resources/rootshard/service.go @@ -23,14 +23,14 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func ServiceReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedServiceReconcilerFactory { +func ServiceReconciler(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedServiceReconcilerFactory { return func() (string, reconciling.ServiceReconciler) { - return resources.GetRootShardServiceName(rootShard), func(svc *corev1.Service) (*corev1.Service, error) { + return names.RootShardServiceName(rootShard), func(svc *corev1.Service) (*corev1.Service, error) { ports := []corev1.ServicePort{{ Name: "https", Protocol: corev1.ProtocolTCP, @@ -49,7 +49,7 @@ func ServiceReconciler(rootShard *operatorv1alpha1.RootShard) reconciling.NamedS }) } - labels := resources.GetRootShardResourceLabels(rootShard) + labels := names.RootShardResourceLabels(rootShard) svc.SetLabels(labels) svc.Spec.Type = corev1.ServiceTypeClusterIP svc.Spec.Ports = ports diff --git a/internal/resources/shard/ca_bundle.go b/internal/resources/shard/ca_bundle.go index f6bc9df2..0228eabc 100644 --- a/internal/resources/shard/ca_bundle.go +++ b/internal/resources/shard/ca_bundle.go @@ -27,10 +27,11 @@ import ( ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func MergedCABundleSecretReconciler(ctx context.Context, shard *operatorv1alpha1.Shard, kubeClient ctrlruntimeclient.Client) k8creconciling.NamedSecretReconcilerFactory { +func MergedCABundleSecretReconciler(ctx context.Context, shard *operatorv1alpha1.Shard, kubeClient ctrlruntimeclient.Client, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { return func() (string, k8creconciling.SecretReconciler) { secretName := fmt.Sprintf("%s-merged-ca-bundle", shard.Name) return secretName, func(secret *corev1.Secret) (*corev1.Secret, error) { @@ -40,7 +41,7 @@ func MergedCABundleSecretReconciler(ctx context.Context, shard *operatorv1alpha1 // Get ServerCA certificate serverCASecret := &corev1.Secret{} - serverCASecretName := resources.GetShardCertificateName(shard, operatorv1alpha1.ServerCertificate) + serverCASecretName := names.ShardCertificateName(shard, operatorv1alpha1.ServerCertificate) err := kubeClient.Get(ctx, types.NamespacedName{ Name: serverCASecretName, Namespace: shard.Namespace, diff --git a/internal/resources/shard/certificates.go b/internal/resources/shard/certificates.go index 87093bec..6b579bca 100644 --- a/internal/resources/shard/certificates.go +++ b/internal/resources/shard/certificates.go @@ -26,19 +26,20 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func ServerCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ServerCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ServerCertificate - name := resources.GetShardCertificateName(shard, certKind) + name := names.ShardCertificateName(shard, certKind) template := shard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetShardResourceLabels(shard)) + cert.SetLabels(names.ShardResourceLabels(shard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -62,10 +63,10 @@ func ServerCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *opera certmanagerv1.UsageDigitalSignature, }, - DNSNames: buildShardDNSNames(shard), + DNSNames: buildShardDNSNames(shard, names), IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -76,15 +77,15 @@ func ServerCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *opera } } -func VirtualWorkspacesCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func VirtualWorkspacesCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.VirtualWorkspacesCertificate - name := resources.GetShardCertificateName(shard, certKind) + name := names.ShardCertificateName(shard, certKind) template := shard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetShardResourceLabels(shard)) + cert.SetLabels(names.ShardResourceLabels(shard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -107,11 +108,11 @@ func VirtualWorkspacesCertificateReconciler(shard *operatorv1alpha1.Shard, rootS }, DNSNames: []string{ - resources.GetShardBaseHost(shard), + names.ShardBaseHost(shard), }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -122,15 +123,15 @@ func VirtualWorkspacesCertificateReconciler(shard *operatorv1alpha1.Shard, rootS } } -func ServiceAccountCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ServiceAccountCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ServiceAccountCertificate - name := resources.GetShardCertificateName(shard, certKind) + name := names.ShardCertificateName(shard, certKind) template := shard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetShardResourceLabels(shard)) + cert.SetLabels(names.ShardResourceLabels(shard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -155,7 +156,7 @@ func ServiceAccountCertificateReconciler(shard *operatorv1alpha1.Shard, rootShar }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -166,15 +167,15 @@ func ServiceAccountCertificateReconciler(shard *operatorv1alpha1.Shard, rootShar } } -func RootShardClientCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func RootShardClientCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ClientCertificate - name := resources.GetShardCertificateName(shard, certKind) + name := names.ShardCertificateName(shard, certKind) template := shard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetShardResourceLabels(shard)) + cert.SetLabels(names.ShardResourceLabels(shard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -202,7 +203,7 @@ func RootShardClientCertificateReconciler(shard *operatorv1alpha1.Shard, rootSha }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -213,15 +214,15 @@ func RootShardClientCertificateReconciler(shard *operatorv1alpha1.Shard, rootSha } } -func LogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func LogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.LogicalClusterAdminCertificate - name := resources.GetShardCertificateName(shard, certKind) + name := names.ShardCertificateName(shard, certKind) template := shard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetShardResourceLabels(shard)) + cert.SetLabels(names.ShardResourceLabels(shard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -249,7 +250,7 @@ func LogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Shard, roo }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ClientCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -260,15 +261,15 @@ func LogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Shard, roo } } -func ExternalLogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ExternalLogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ExternalLogicalClusterAdminCertificate - name := resources.GetShardCertificateName(shard, certKind) + name := names.ShardCertificateName(shard, certKind) template := shard.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetShardResourceLabels(shard)) + cert.SetLabels(names.ShardResourceLabels(shard)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -296,7 +297,7 @@ func ExternalLogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Sh }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Kind: "Issuer", Group: "cert-manager.io", }, @@ -310,10 +311,10 @@ func ExternalLogicalClusterAdminCertificateReconciler(shard *operatorv1alpha1.Sh // buildShardDNSNames builds the list of DNS names for the shard server certificate. // It includes localhost, the internal Kubernetes service host, and if shardBaseURL // is set, it also extracts and includes the hostname from that URL. -func buildShardDNSNames(shard *operatorv1alpha1.Shard) []string { +func buildShardDNSNames(shard *operatorv1alpha1.Shard, names naming.Scheme) []string { dnsNames := sets.New( "localhost", - resources.GetShardBaseHost(shard), + names.ShardBaseHost(shard), ) // If shardBaseURL is set, extract and add its hostname diff --git a/internal/resources/shard/deployment.go b/internal/resources/shard/deployment.go index 1ce48d4b..b51de783 100644 --- a/internal/resources/shard/deployment.go +++ b/internal/resources/shard/deployment.go @@ -29,6 +29,7 @@ import ( "k8s.io/utils/ptr" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -88,10 +89,10 @@ func getEffectiveCacheRef(shard *operatorv1alpha1.Shard, rootShard *operatorv1al return "" } -func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace) reconciling.NamedDeploymentReconcilerFactory { +func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace, names naming.Scheme) reconciling.NamedDeploymentReconcilerFactory { return func() (string, reconciling.DeploymentReconciler) { - return resources.GetShardDeploymentName(shard), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { - labels := resources.GetShardResourceLabels(shard) + return names.ShardDeploymentName(shard), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { + labels := names.ShardResourceLabels(shard) dep.SetLabels(labels) dep.Spec.Selector = &metav1.LabelSelector{ MatchLabels: labels, @@ -101,11 +102,11 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al secretMounts := []utils.SecretMount{{ VolumeName: "kcp-ca", - SecretName: resources.GetRootShardCAName(rootShard, operatorv1alpha1.RootCA), + SecretName: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), MountPath: getCAMountPath(operatorv1alpha1.RootCA), }} - args := getArgs(shard, rootShard, kcpVW) + args := getArgs(shard, rootShard, kcpVW, names) for _, cert := range []operatorv1alpha1.Certificate{ // requires server CA and the shard client cert to be mounted @@ -115,7 +116,7 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al } { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-kubeconfig", cert), - SecretName: resources.GetShardKubeconfigSecret(shard, cert), + SecretName: names.ShardKubeconfigSecret(shard, cert), MountPath: getKubeconfigMountPath(cert), }) } @@ -129,7 +130,7 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al } { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-ca", ca), - SecretName: resources.GetRootShardCAName(rootShard, ca), + SecretName: names.RootShardCAName(rootShard, ca), MountPath: getCAMountPath(ca), }) } @@ -143,7 +144,7 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al } { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-cert", cert), - SecretName: resources.GetShardCertificateName(shard, cert), + SecretName: names.ShardCertificateName(shard, cert), MountPath: getCertificateMountPath(cert), }) } @@ -166,11 +167,11 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "cache-server-kubeconfig", - SecretName: resources.GetCacheServerKubeconfigName(cacheRef), + SecretName: names.CacheServerKubeconfigName(cacheRef), MountPath: getCacheServerKubeconfigMountPath(), }, utils.SecretMount{ VolumeName: "cache-server-ca", - SecretName: resources.GetCacheServerCAName(cacheRef, operatorv1alpha1.RootCA), + SecretName: names.CacheServerCAName(cacheRef, operatorv1alpha1.RootCA), MountPath: getCacheServerCAMountPath(operatorv1alpha1.RootCA), }, utils.SecretMount{ VolumeName: "cache-server-client-cert", @@ -221,7 +222,7 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al } } -func getArgs(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace) []string { +func getArgs(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, kcpVW *operatorv1alpha1.VirtualWorkspace, names naming.Scheme) []string { // Configure the cache kubeconfig to point either to an explicitly configured cache (maybe on the // shard, maybe on the root shard), or the root shard itself (in case no external cache is configured). var cacheKubeconfigMount string @@ -255,7 +256,7 @@ func getArgs(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShar // General shard configuration. fmt.Sprintf("--shard-name=%s", shard.Name), - fmt.Sprintf("--shard-base-url=%s", resources.GetShardBaseURL(shard)), + fmt.Sprintf("--shard-base-url=%s", names.ShardBaseURL(shard)), fmt.Sprintf("--shard-external-url=https://%s:%d", rootShard.Spec.External.Hostname, rootShard.Spec.External.Port), fmt.Sprintf("--external-hostname=%s", rootShard.Spec.External.Hostname), diff --git a/internal/resources/shard/kubeconfigs.go b/internal/resources/shard/kubeconfigs.go index 58037af7..6d265929 100644 --- a/internal/resources/shard/kubeconfigs.go +++ b/internal/resources/shard/kubeconfigs.go @@ -25,7 +25,7 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -33,7 +33,7 @@ func kubeconfigSecret(shard *operatorv1alpha1.Shard, cert operatorv1alpha1.Certi return fmt.Sprintf("%s-%s-kubeconfig", shard.Name, cert) } -func RootShardClientKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) k8creconciling.NamedSecretReconcilerFactory { +func RootShardClientKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { const ( serverName = "root-shard" contextName = "shard-base" // hardcoded in kcp @@ -50,7 +50,7 @@ func RootShardClientKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShar config = &clientcmdapi.Config{ Clusters: map[string]*clientcmdapi.Cluster{ serverName: { - Server: resources.GetRootShardBaseURL(rootShard), + Server: names.RootShardBaseURL(rootShard), CertificateAuthority: getCAMountPath(operatorv1alpha1.ServerCA) + "/tls.crt", }, }, @@ -81,7 +81,7 @@ func RootShardClientKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShar } } -func LogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) k8creconciling.NamedSecretReconcilerFactory { +func LogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { const ( serverName = "logical-cluster:admin" contextName = "logical-cluster" @@ -99,7 +99,7 @@ func LogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Shard, root config = &clientcmdapi.Config{ Clusters: map[string]*clientcmdapi.Cluster{ serverName: { - Server: resources.GetShardBaseURL(shard), + Server: names.ShardBaseURL(shard), CertificateAuthority: getCAMountPath(operatorv1alpha1.ServerCA) + "/tls.crt", }, }, @@ -130,7 +130,7 @@ func LogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Shard, root } } -func ExternalLogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard) k8creconciling.NamedSecretReconcilerFactory { +func ExternalLogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { const ( serverName = "external-logical-cluster:admin" contextName = "external-logical-cluster" diff --git a/internal/resources/shard/service.go b/internal/resources/shard/service.go index ea75ee8d..6a83e6c1 100644 --- a/internal/resources/shard/service.go +++ b/internal/resources/shard/service.go @@ -23,14 +23,14 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func ServiceReconciler(shard *operatorv1alpha1.Shard) reconciling.NamedServiceReconcilerFactory { +func ServiceReconciler(shard *operatorv1alpha1.Shard, names naming.Scheme) reconciling.NamedServiceReconcilerFactory { return func() (string, reconciling.ServiceReconciler) { - return resources.GetShardServiceName(shard), func(svc *corev1.Service) (*corev1.Service, error) { + return names.ShardServiceName(shard), func(svc *corev1.Service) (*corev1.Service, error) { ports := []corev1.ServicePort{{ Name: "https", Protocol: corev1.ProtocolTCP, @@ -49,7 +49,7 @@ func ServiceReconciler(shard *operatorv1alpha1.Shard) reconciling.NamedServiceRe }) } - labels := resources.GetShardResourceLabels(shard) + labels := names.ShardResourceLabels(shard) svc.SetLabels(labels) svc.Spec.Type = corev1.ServiceTypeClusterIP svc.Spec.Ports = ports diff --git a/internal/resources/utils/authentication.go b/internal/resources/utils/authentication.go index b25987a8..988d7a63 100644 --- a/internal/resources/utils/authentication.go +++ b/internal/resources/utils/authentication.go @@ -23,7 +23,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -81,7 +81,7 @@ func applyOIDCConfiguration(deployment *appsv1.Deployment, config operatorv1alph return deployment } -func applyServiceAccountAuthentication(deployment *appsv1.Deployment, rootShard *operatorv1alpha1.RootShard) *appsv1.Deployment { +func applyServiceAccountAuthentication(deployment *appsv1.Deployment, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) *appsv1.Deployment { // Secrets and volumes volumes := []corev1.Volume{} @@ -89,31 +89,31 @@ func applyServiceAccountAuthentication(deployment *appsv1.Deployment, rootShard // Root shard is not on the list, so we add it manually volumes = append(volumes, corev1.Volume{ - Name: resources.GetRootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), + Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: resources.GetRootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), + SecretName: names.RootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), }, }, }) volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: resources.GetRootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), + Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), ReadOnly: true, MountPath: fmt.Sprintf("/etc/kcp/tls/%s/%s", rootShard.Name, string(operatorv1alpha1.ServiceAccountCertificate)), }) for _, shard := range rootShard.Status.Shards { volumes = append(volumes, corev1.Volume{ - Name: resources.GetShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: shard.Name}}, operatorv1alpha1.ServiceAccountCertificate), + Name: names.ShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: shard.Name}}, operatorv1alpha1.ServiceAccountCertificate), VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: resources.GetShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: shard.Name}}, operatorv1alpha1.ServiceAccountCertificate), + SecretName: names.ShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: shard.Name}}, operatorv1alpha1.ServiceAccountCertificate), }, }, }) volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: resources.GetShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: shard.Name}}, operatorv1alpha1.ServiceAccountCertificate), + Name: names.ShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: shard.Name}}, operatorv1alpha1.ServiceAccountCertificate), ReadOnly: true, MountPath: fmt.Sprintf("/etc/kcp/tls/%s/%s", shard.Name, string(operatorv1alpha1.ServiceAccountCertificate)), }) diff --git a/internal/resources/utils/authentication_test.go b/internal/resources/utils/authentication_test.go index ea37532f..5d51a5d7 100644 --- a/internal/resources/utils/authentication_test.go +++ b/internal/resources/utils/authentication_test.go @@ -26,11 +26,12 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) func TestApplyServiceAccountAuthentication(t *testing.T) { + version1 := naming.NewVersion1() tests := []struct { name string rootShard *operatorv1alpha1.RootShard @@ -71,7 +72,7 @@ func TestApplyServiceAccountAuthentication(t *testing.T) { // Check volumes assert.Len(t, dep.Spec.Template.Spec.Volumes, 1) rootShardVolume := dep.Spec.Template.Spec.Volumes[0] - expectedVolumeName := resources.GetRootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) + expectedVolumeName := version1.RootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) assert.Equal(t, expectedVolumeName, rootShardVolume.Name) assert.NotNil(t, rootShardVolume.Secret) assert.Equal(t, expectedVolumeName, rootShardVolume.Secret.SecretName) @@ -135,9 +136,9 @@ func TestApplyServiceAccountAuthentication(t *testing.T) { assert.Equal(t, volume.Name, volume.Secret.SecretName) } - expectedRootVolume := resources.GetRootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) - expectedShard1Volume := resources.GetShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "shard-1"}}, operatorv1alpha1.ServiceAccountCertificate) - expectedShard2Volume := resources.GetShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "shard-2"}}, operatorv1alpha1.ServiceAccountCertificate) + expectedRootVolume := version1.RootShardCertificateName(&operatorv1alpha1.RootShard{ObjectMeta: metav1.ObjectMeta{Name: "test-root-shard"}}, operatorv1alpha1.ServiceAccountCertificate) + expectedShard1Volume := version1.ShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "shard-1"}}, operatorv1alpha1.ServiceAccountCertificate) + expectedShard2Volume := version1.ShardCertificateName(&operatorv1alpha1.Shard{ObjectMeta: metav1.ObjectMeta{Name: "shard-2"}}, operatorv1alpha1.ServiceAccountCertificate) assert.True(t, volumeNames[expectedRootVolume], "Root shard volume not found") assert.True(t, volumeNames[expectedShard1Volume], "Shard-1 volume not found") @@ -289,7 +290,7 @@ func TestApplyServiceAccountAuthentication(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := applyServiceAccountAuthentication(tt.initialDeploy, tt.rootShard) + result := applyServiceAccountAuthentication(tt.initialDeploy, tt.rootShard, version1) require.NotNil(t, result) assert.Equal(t, tt.initialDeploy, result, "Function should return the same deployment instance") diff --git a/internal/resources/utils/deployments.go b/internal/resources/utils/deployments.go index 7ec0b096..1ca0cd3c 100644 --- a/internal/resources/utils/deployments.go +++ b/internal/resources/utils/deployments.go @@ -22,6 +22,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -104,14 +105,14 @@ func ApplyAuthConfiguration(deployment *appsv1.Deployment, config *operatorv1alp return deployment } -func ApplyFrontProxyAuthConfiguration(deployment *appsv1.Deployment, config *operatorv1alpha1.AuthSpec, rootShard *operatorv1alpha1.RootShard) *appsv1.Deployment { +func ApplyFrontProxyAuthConfiguration(deployment *appsv1.Deployment, config *operatorv1alpha1.AuthSpec, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) *appsv1.Deployment { if config == nil { return deployment } deployment = ApplyAuthConfiguration(deployment, config) if config.ServiceAccount != nil && config.ServiceAccount.Enabled { - deployment = applyServiceAccountAuthentication(deployment, rootShard) + deployment = applyServiceAccountAuthentication(deployment, rootShard, names) } return deployment diff --git a/internal/resources/virtualworkspace/certificate.go b/internal/resources/virtualworkspace/certificate.go index e0b4e4e1..3678bf8d 100644 --- a/internal/resources/virtualworkspace/certificate.go +++ b/internal/resources/virtualworkspace/certificate.go @@ -24,6 +24,7 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -32,11 +33,11 @@ func commonName(vw *operatorv1alpha1.VirtualWorkspace) string { return fmt.Sprintf("%s-virtual-workspace", vw.Name) } -func ClientCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, issuerName string) reconciling.NamedCertificateReconcilerFactory { +func ClientCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, issuerName string, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ClientCertificate template := vw.Spec.CertificateTemplates.CertificateTemplate(certKind) - name := resources.GetVirtualWorkspaceCertificateName(vw, certKind) + name := names.VirtualWorkspaceCertificateName(vw, certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { @@ -80,15 +81,15 @@ func ClientCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, issuerNa } } -func ServerCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *operatorv1alpha1.RootShard) reconciling.NamedCertificateReconcilerFactory { +func ServerCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { const certKind = operatorv1alpha1.ServerCertificate - name := resources.GetVirtualWorkspaceCertificateName(vw, certKind) + name := names.VirtualWorkspaceCertificateName(vw, certKind) template := vw.Spec.CertificateTemplates.CertificateTemplate(certKind) return func() (string, reconciling.CertificateReconciler) { return name, func(cert *certmanagerv1.Certificate) (*certmanagerv1.Certificate, error) { - cert.SetLabels(resources.GetVirtualWorkspaceResourceLabels(vw)) + cert.SetLabels(names.VirtualWorkspaceResourceLabels(vw)) cert.Spec = certmanagerv1.CertificateSpec{ SecretName: name, SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ @@ -113,11 +114,11 @@ func ServerCertificateReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShar DNSNames: []string{ "localhost", - resources.GetVirtualWorkspaceBaseHost(vw), + names.VirtualWorkspaceBaseHost(vw), }, IssuerRef: certmanagermetav1.IssuerReference{ - Name: resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA), + Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Kind: "Issuer", Group: "cert-manager.io", }, diff --git a/internal/resources/virtualworkspace/deployment.go b/internal/resources/virtualworkspace/deployment.go index 8293ec42..9bfb6c46 100644 --- a/internal/resources/virtualworkspace/deployment.go +++ b/internal/resources/virtualworkspace/deployment.go @@ -28,6 +28,7 @@ import ( "k8s.io/utils/ptr" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -88,18 +89,18 @@ func getEffectiveCacheRef(rootShard *operatorv1alpha1.RootShard, shard *operator return "" } -func kubeconfigSecret(rootShard *operatorv1alpha1.RootShard, shard *operatorv1alpha1.Shard, certName operatorv1alpha1.Certificate) string { +func kubeconfigSecret(rootShard *operatorv1alpha1.RootShard, shard *operatorv1alpha1.Shard, certName operatorv1alpha1.Certificate, names naming.Scheme) string { if shard != nil { - return resources.GetShardKubeconfigSecret(shard, certName) + return names.ShardKubeconfigSecret(shard, certName) } else { - return resources.GetRootShardKubeconfigSecret(rootShard, certName) + return names.RootShardKubeconfigSecret(rootShard, certName) } } -func DeploymentReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *operatorv1alpha1.RootShard, shard *operatorv1alpha1.Shard) reconciling.NamedDeploymentReconcilerFactory { +func DeploymentReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *operatorv1alpha1.RootShard, shard *operatorv1alpha1.Shard, names naming.Scheme) reconciling.NamedDeploymentReconcilerFactory { return func() (string, reconciling.DeploymentReconciler) { - return resources.GetVirtualWorkspaceDeploymentName(vw), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { - labels := resources.GetVirtualWorkspaceResourceLabels(vw) + return names.VirtualWorkspaceDeploymentName(vw), func(dep *appsv1.Deployment) (*appsv1.Deployment, error) { + labels := names.VirtualWorkspaceResourceLabels(vw) dep.SetLabels(labels) dep.Spec.Selector = &metav1.LabelSelector{ MatchLabels: labels, @@ -109,7 +110,7 @@ func DeploymentReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *oper secretMounts := []utils.SecretMount{{ VolumeName: "kcp-ca", - SecretName: resources.GetRootShardCAName(rootShard, operatorv1alpha1.RootCA), + SecretName: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), MountPath: getCAMountPath(operatorv1alpha1.RootCA), }} @@ -124,14 +125,14 @@ func DeploymentReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *oper } { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-ca", ca), - SecretName: resources.GetRootShardCAName(rootShard, ca), + SecretName: names.RootShardCAName(rootShard, ca), MountPath: getCAMountPath(ca), }) } secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-cert", operatorv1alpha1.ServerCertificate), - SecretName: resources.GetVirtualWorkspaceCertificateName(vw, operatorv1alpha1.ServerCertificate), + SecretName: names.VirtualWorkspaceCertificateName(vw, operatorv1alpha1.ServerCertificate), MountPath: getCertificateMountPath(operatorv1alpha1.ServerCertificate), }) @@ -141,13 +142,13 @@ func DeploymentReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *oper secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-kubeconfig", operatorv1alpha1.LogicalClusterAdminCertificate), - SecretName: kubeconfigSecret(rootShard, shard, operatorv1alpha1.LogicalClusterAdminCertificate), + SecretName: kubeconfigSecret(rootShard, shard, operatorv1alpha1.LogicalClusterAdminCertificate, names), MountPath: getKubeconfigMountPath(operatorv1alpha1.LogicalClusterAdminCertificate), }) secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: fmt.Sprintf("%s-cert", operatorv1alpha1.ClientCertificate), - SecretName: resources.GetVirtualWorkspaceCertificateName(vw, operatorv1alpha1.ClientCertificate), + SecretName: names.VirtualWorkspaceCertificateName(vw, operatorv1alpha1.ClientCertificate), MountPath: getCertificateMountPath(operatorv1alpha1.LogicalClusterAdminCertificate), }) @@ -157,12 +158,12 @@ func DeploymentReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *oper secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "cache-server-kubeconfig", - SecretName: resources.GetCacheServerKubeconfigName(cacheRef), + SecretName: names.CacheServerKubeconfigName(cacheRef), MountPath: getCacheServerKubeconfigMountPath(), }, utils.SecretMount{ VolumeName: "cache-server-ca", - SecretName: resources.GetCacheServerCAName(cacheRef, operatorv1alpha1.RootCA), + SecretName: names.CacheServerCAName(cacheRef, operatorv1alpha1.RootCA), MountPath: getCacheServerCAMountPath(operatorv1alpha1.RootCA), }, utils.SecretMount{ diff --git a/internal/resources/virtualworkspace/service.go b/internal/resources/virtualworkspace/service.go index a4515fe8..9e632586 100644 --- a/internal/resources/virtualworkspace/service.go +++ b/internal/resources/virtualworkspace/service.go @@ -23,19 +23,15 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func GetVirtualWorkspaceServiceName(vw *operatorv1alpha1.VirtualWorkspace) string { - return resources.GetVirtualWorkspaceDeploymentName(vw) -} - -func ServiceReconciler(vw *operatorv1alpha1.VirtualWorkspace) reconciling.NamedServiceReconcilerFactory { +func ServiceReconciler(vw *operatorv1alpha1.VirtualWorkspace, names naming.Scheme) reconciling.NamedServiceReconcilerFactory { return func() (string, reconciling.ServiceReconciler) { - return GetVirtualWorkspaceServiceName(vw), func(svc *corev1.Service) (*corev1.Service, error) { - labels := resources.GetVirtualWorkspaceResourceLabels(vw) + return names.VirtualWorkspaceServiceName(vw), func(svc *corev1.Service) (*corev1.Service, error) { + labels := names.VirtualWorkspaceResourceLabels(vw) svc.SetLabels(labels) svc.Spec.Type = corev1.ServiceTypeClusterIP svc.Spec.Ports = []corev1.ServicePort{ diff --git a/test/e2e/cacheserver/cacheserver_test.go b/test/e2e/cacheserver/cacheserver_test.go index c1e439e6..ddfc7fce 100644 --- a/test/e2e/cacheserver/cacheserver_test.go +++ b/test/e2e/cacheserver/cacheserver_test.go @@ -33,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/types" ctrlruntime "sigs.k8s.io/controller-runtime" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" "github.com/kcp-dev/kcp-operator/test/utils" ) @@ -42,6 +43,7 @@ func TestCacheWithRootShard(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() // create namespace namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "cache-rootshard") @@ -50,7 +52,7 @@ func TestCacheWithRootShard(t *testing.T) { cacheServer := utils.DeployCacheServer(ctx, t, client, namespace.Name) // deploy a root shard that uses our cache - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { rs.Spec.Cache.Reference = &corev1.LocalObjectReference{ Name: cacheServer.Name, } @@ -104,6 +106,7 @@ func TestCacheWithExternalEtcdAndRootShard(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() // create namespace namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "cache-with-etcd-rootshard") @@ -112,7 +115,7 @@ func TestCacheWithExternalEtcdAndRootShard(t *testing.T) { cacheServer := utils.DeployCacheServerWithExternalEtcd(ctx, t, client, namespace.Name, 2) // deploy a root shard that uses our cache - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { rs.Spec.Cache.Reference = &corev1.LocalObjectReference{ Name: cacheServer.Name, } @@ -161,6 +164,7 @@ func TestCacheWithMultipleExplicitShards(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() // create namespace namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "cache-sharded-explicit") @@ -169,7 +173,7 @@ func TestCacheWithMultipleExplicitShards(t *testing.T) { cacheServer := utils.DeployCacheServer(ctx, t, client, namespace.Name) // deploy a root shard that uses our cache - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { rs.Spec.Cache.Reference = &corev1.LocalObjectReference{ Name: cacheServer.Name, } @@ -228,6 +232,7 @@ func TestCacheWithMultipleShardsInheritingConfig(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() // create namespace namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "cache-sharded-inherit") @@ -236,7 +241,7 @@ func TestCacheWithMultipleShardsInheritingConfig(t *testing.T) { cacheServer := utils.DeployCacheServer(ctx, t, client, namespace.Name) // deploy a root shard that uses our cache - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, "", func(rs *operatorv1alpha1.RootShard) { rs.Spec.Cache.Reference = &corev1.LocalObjectReference{ Name: cacheServer.Name, } diff --git a/test/e2e/frontproxies/frontproxies_test.go b/test/e2e/frontproxies/frontproxies_test.go index 36af7e4b..1fd8e10f 100644 --- a/test/e2e/frontproxies/frontproxies_test.go +++ b/test/e2e/frontproxies/frontproxies_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/types" ctrlruntime "sigs.k8s.io/controller-runtime" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" "github.com/kcp-dev/kcp-operator/test/utils" ) @@ -41,6 +42,7 @@ func TestCreateFrontProxy(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "create-frontproxy") @@ -48,7 +50,7 @@ func TestCreateFrontProxy(t *testing.T) { externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) // deploy rootshard - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, externalHostname) + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname) // deploy front-proxy frontProxy := utils.DeployFrontProxy(ctx, t, client, namespace.Name, rootShard.Name, externalHostname) diff --git a/test/e2e/kubeconfig-rbac/frontproxies_test.go b/test/e2e/kubeconfig-rbac/frontproxies_test.go index 32f50053..68b1a8b4 100644 --- a/test/e2e/kubeconfig-rbac/frontproxies_test.go +++ b/test/e2e/kubeconfig-rbac/frontproxies_test.go @@ -35,6 +35,7 @@ import ( ctrlruntime "sigs.k8s.io/controller-runtime" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" "github.com/kcp-dev/kcp-operator/test/utils" ) @@ -44,6 +45,7 @@ func TestProvisionFrontProxyRBAC(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() rootCluster := logicalcluster.NewPath("root") namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "provision-frontproxy-rbac") @@ -52,7 +54,7 @@ func TestProvisionFrontProxyRBAC(t *testing.T) { externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) // deploy rootshard - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, externalHostname) + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname) // deploy front-proxy frontProxy := utils.DeployFrontProxy(ctx, t, client, namespace.Name, rootShard.Name, externalHostname) diff --git a/test/e2e/rootshards/proxy_test.go b/test/e2e/rootshards/proxy_test.go index 30fd44ff..c5b76ad5 100644 --- a/test/e2e/rootshards/proxy_test.go +++ b/test/e2e/rootshards/proxy_test.go @@ -36,6 +36,7 @@ import ( ctrlruntime "sigs.k8s.io/controller-runtime" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" "github.com/kcp-dev/kcp-operator/test/utils" ) @@ -45,6 +46,7 @@ func TestRootShardProxy(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "rootshard-proxy") @@ -52,7 +54,7 @@ func TestRootShardProxy(t *testing.T) { externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) // deploy a root shard incl. etcd - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, externalHostname) + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname) // deploy a 2nd shard incl. etcd shardName := "aadvark" diff --git a/test/e2e/rootshards/rootshards_test.go b/test/e2e/rootshards/rootshards_test.go index 3b761a17..111a0e60 100644 --- a/test/e2e/rootshards/rootshards_test.go +++ b/test/e2e/rootshards/rootshards_test.go @@ -31,6 +31,7 @@ import ( "k8s.io/apimachinery/pkg/types" ctrlruntime "sigs.k8s.io/controller-runtime" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" "github.com/kcp-dev/kcp-operator/test/utils" ) @@ -40,9 +41,10 @@ func TestCreateRootShard(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "create-rootshard") - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, "") + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, "") configSecretName := "kubeconfig" diff --git a/test/e2e/shards/shards_test.go b/test/e2e/shards/shards_test.go index 4977be6b..3cd7eb6a 100644 --- a/test/e2e/shards/shards_test.go +++ b/test/e2e/shards/shards_test.go @@ -34,6 +34,7 @@ import ( ctrlruntime "sigs.k8s.io/controller-runtime" resources "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" "github.com/kcp-dev/kcp-operator/test/utils" ) @@ -43,12 +44,13 @@ func TestCreateShard(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() // create namespace namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "create-shard") // deploy a root shard incl. etcd - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, "") + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, "") // deploy a 2nd shard incl. etcd shardName := "aadvark" @@ -149,12 +151,13 @@ func TestShardBundleAnnotation(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() // create namespace namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "shard-bundle-annotation") // deploy a root shard incl. etcd - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, "") + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, "") // deploy a shard without bundle annotation first shardName := "annotated-shard" diff --git a/test/e2e/virtualworkspaces/virtualworkspaces_test.go b/test/e2e/virtualworkspaces/virtualworkspaces_test.go index 9ed9aa37..6319d7b0 100644 --- a/test/e2e/virtualworkspaces/virtualworkspaces_test.go +++ b/test/e2e/virtualworkspaces/virtualworkspaces_test.go @@ -42,6 +42,7 @@ import ( ctrlruntime "sigs.k8s.io/controller-runtime" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" "github.com/kcp-dev/kcp-operator/test/conformance" "github.com/kcp-dev/kcp-operator/test/utils" @@ -63,12 +64,13 @@ func TestExternalVirtualWorkspace(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "external-vw") // Deploy the standalone, external kcp virtual-workspace (do not wait for readiness since both // the root shard and the VW will need to have a little dance before both are ready). - vw := utils.DeployVirtualWorkspace(ctx, t, client, namespace.Name, "kcp-vw", false, func(vw *operatorv1alpha1.VirtualWorkspace) { + vw := utils.DeployVirtualWorkspace(ctx, t, client, namingScheme, namespace.Name, "kcp-vw", false, func(vw *operatorv1alpha1.VirtualWorkspace) { vw.Spec.Target.RootShardRef = &corev1.LocalObjectReference{ Name: "r00t", // Must match the rootshard name } @@ -79,7 +81,7 @@ func TestExternalVirtualWorkspace(t *testing.T) { externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) // Deploy a root shard that uses the external VW (in-process VW is disabled). - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, externalHostname, func(rs *operatorv1alpha1.RootShard) { + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname, func(rs *operatorv1alpha1.RootShard) { // Point the root shard to use our external VW instead of the in-process one. rs.Spec.KCPVirtualWorkspace = &corev1.LocalObjectReference{ Name: vw.Name, @@ -251,6 +253,7 @@ func TestMultipleShardsWithExternalVirtualWorkspacesAndExtCache(t *testing.T) { client := utils.GetKubeClient(t) ctx := context.Background() + namingScheme := naming.NewVersion1() namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "multi-shard-extcache-vw") @@ -258,7 +261,7 @@ func TestMultipleShardsWithExternalVirtualWorkspacesAndExtCache(t *testing.T) { cacheServer := utils.DeployCacheServer(ctx, t, client, namespace.Name) // Deploy external VirtualWorkspace for root shard - rootVW := utils.DeployVirtualWorkspace(ctx, t, client, namespace.Name, "root-vw", false, func(vw *operatorv1alpha1.VirtualWorkspace) { + rootVW := utils.DeployVirtualWorkspace(ctx, t, client, namingScheme, namespace.Name, "root-vw", false, func(vw *operatorv1alpha1.VirtualWorkspace) { vw.Spec.Target.RootShardRef = &corev1.LocalObjectReference{ Name: "r00t", } @@ -269,7 +272,7 @@ func TestMultipleShardsWithExternalVirtualWorkspacesAndExtCache(t *testing.T) { externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) // Deploy root shard with external VW - rootShard := utils.DeployRootShard(ctx, t, client, namespace.Name, externalHostname, func(rs *operatorv1alpha1.RootShard) { + rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname, func(rs *operatorv1alpha1.RootShard) { rs.Spec.KCPVirtualWorkspace = &corev1.LocalObjectReference{ Name: rootVW.Name, } @@ -283,7 +286,7 @@ func TestMultipleShardsWithExternalVirtualWorkspacesAndExtCache(t *testing.T) { }) // Deploy external VirtualWorkspace for regular shard1 - shard1VW := utils.DeployVirtualWorkspace(ctx, t, client, namespace.Name, "shard1-vw", false, func(vw *operatorv1alpha1.VirtualWorkspace) { + shard1VW := utils.DeployVirtualWorkspace(ctx, t, client, namingScheme, namespace.Name, "shard1-vw", false, func(vw *operatorv1alpha1.VirtualWorkspace) { vw.Spec.Target.ShardRef = &corev1.LocalObjectReference{ Name: "shard1", } diff --git a/test/utils/deploy.go b/test/utils/deploy.go index ba980b1b..0531d8e9 100644 --- a/test/utils/deploy.go +++ b/test/utils/deploy.go @@ -26,7 +26,7 @@ import ( corev1 "k8s.io/api/core/v1" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -126,7 +126,7 @@ func DeployShard(ctx context.Context, t *testing.T, client ctrlruntimeclient.Cli return shard } -func DeployRootShard(ctx context.Context, t *testing.T, client ctrlruntimeclient.Client, namespace string, externalHostname string, patches ...func(*operatorv1alpha1.RootShard)) operatorv1alpha1.RootShard { +func DeployRootShard(ctx context.Context, t *testing.T, client ctrlruntimeclient.Client, names naming.Scheme, namespace string, externalHostname string, patches ...func(*operatorv1alpha1.RootShard)) operatorv1alpha1.RootShard { t.Helper() etcd := DeployEtcd(t, "etcd-r00t", namespace) @@ -136,7 +136,7 @@ func DeployRootShard(ctx context.Context, t *testing.T, client ctrlruntimeclient rootShard.Namespace = namespace if externalHostname == "" { - externalHostname = resources.GetRootShardBaseHost(&rootShard) + externalHostname = names.RootShardBaseHost(&rootShard) } rootShard.Spec = operatorv1alpha1.RootShardSpec{ @@ -303,7 +303,7 @@ func DeployCacheServerWithExternalEtcd(ctx context.Context, t *testing.T, client })...) } -func DeployVirtualWorkspace(ctx context.Context, t *testing.T, client ctrlruntimeclient.Client, namespace, name string, waitForReady bool, patches ...func(*operatorv1alpha1.VirtualWorkspace)) operatorv1alpha1.VirtualWorkspace { +func DeployVirtualWorkspace(ctx context.Context, t *testing.T, client ctrlruntimeclient.Client, names naming.Scheme, namespace, name string, waitForReady bool, patches ...func(*operatorv1alpha1.VirtualWorkspace)) operatorv1alpha1.VirtualWorkspace { t.Helper() vw := operatorv1alpha1.VirtualWorkspace{} @@ -311,7 +311,7 @@ func DeployVirtualWorkspace(ctx context.Context, t *testing.T, client ctrlruntim vw.Namespace = namespace vw.Spec = operatorv1alpha1.VirtualWorkspaceSpec{ External: operatorv1alpha1.ExternalConfig{ - Hostname: resources.GetVirtualWorkspaceBaseHost(&vw), + Hostname: names.VirtualWorkspaceBaseHost(&vw), Port: 6443, }, } diff --git a/test/utils/utils.go b/test/utils/utils.go index 791b4eb4..a1f9f5e6 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -43,7 +43,7 @@ import ( ctrlruntime "sigs.k8s.io/controller-runtime" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -297,10 +297,12 @@ func ConnectWithRootShardProxy( ) ctrlruntimeclient.Client { t.Helper() + namingScheme := naming.NewVersion1() + // get the secret for the kcp-operator client cert key := types.NamespacedName{ Namespace: rootShard.Namespace, - Name: resources.GetRootShardCertificateName(rootShard, operatorv1alpha1.OperatorCertificate), + Name: namingScheme.RootShardCertificateName(rootShard, operatorv1alpha1.OperatorCertificate), } certSecret := &corev1.Secret{} @@ -311,7 +313,7 @@ func ConnectWithRootShardProxy( // start a port forwarding localPort := getPort(t) servicePort := 6443 - serviceName := resources.GetRootShardProxyServiceName(rootShard) + serviceName := namingScheme.RootShardProxyServiceName(rootShard) SelfDestuctingPortForward(t, ctx, rootShard.Namespace, "svc/"+serviceName, servicePort, localPort) From 1506086ed2d376870b6b996848fc1f2634dc6879 Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Tue, 14 Apr 2026 14:39:29 +0200 Subject: [PATCH 11/13] fix all the other places that implicitly had the naming scheme hardcoded On-behalf-of: @SAP christoph.mewes@sap.com --- internal/controller/bundle/controller.go | 8 +- internal/controller/bundle/objects.go | 137 ++++++++---------- .../resources/cacheserver/certificates.go | 2 +- internal/resources/frontproxy/ca_bundle.go | 13 +- internal/resources/frontproxy/certificates.go | 7 +- internal/resources/frontproxy/service_test.go | 7 +- internal/resources/naming/scheme.go | 5 +- internal/resources/naming/v1.go | 13 +- internal/resources/rootshard/ca_bundle.go | 2 +- .../resources/rootshard/certificates_test.go | 5 +- internal/resources/rootshard/deployment.go | 4 +- internal/resources/shard/ca_bundle.go | 2 +- internal/resources/shard/certificates_test.go | 5 +- internal/resources/shard/deployment.go | 4 +- internal/resources/shard/kubeconfigs.go | 10 +- .../resources/virtualworkspace/deployment.go | 2 +- test/e2e/frontproxies/frontproxies_test.go | 4 +- test/e2e/kubeconfig-rbac/frontproxies_test.go | 3 +- test/e2e/rootshards/proxy_test.go | 3 +- test/e2e/shards/shards_test.go | 36 ++--- .../virtualworkspaces_test.go | 29 ++-- test/utils/utils.go | 13 ++ 22 files changed, 163 insertions(+), 151 deletions(-) diff --git a/internal/controller/bundle/controller.go b/internal/controller/bundle/controller.go index fae2f6e4..c6d0f88c 100644 --- a/internal/controller/bundle/controller.go +++ b/internal/controller/bundle/controller.go @@ -42,6 +42,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/kcp-dev/kcp-operator/internal/resources" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -159,6 +160,7 @@ func (r *BundleReconciler) reconcile(ctx context.Context, bundle *operatorv1alph // Determine which target the bundle is for and get the list of required objects target := bundle.Spec.Target + names := naming.NewVersion1() var ( targetExists bool targetName string @@ -178,7 +180,7 @@ func (r *BundleReconciler) reconcile(ctx context.Context, bundle *operatorv1alph }, rootShard) if err == nil { targetExists = true - requiredObjects = getBundleObjectsForRootShard(rootShard) + requiredObjects = getBundleObjectsForRootShard(rootShard, names) } else if ctrlruntimeclient.IgnoreNotFound(err) != nil { errs = append(errs, fmt.Errorf("failed to get RootShard %s: %w", targetName, err)) } @@ -200,7 +202,7 @@ func (r *BundleReconciler) reconcile(ctx context.Context, bundle *operatorv1alph Namespace: bundle.Namespace, }, rootShard) if err == nil { - requiredObjects = getBundleObjectsForShard(shard, rootShard.Name) + requiredObjects = getBundleObjectsForShard(shard, rootShard.Name, names) } else { errs = append(errs, fmt.Errorf("failed to get RootShard for Shard %s: %w", targetName, err)) } @@ -226,7 +228,7 @@ func (r *BundleReconciler) reconcile(ctx context.Context, bundle *operatorv1alph Namespace: bundle.Namespace, }, rootShard) if err == nil { - requiredObjects = getBundleObjectsForFrontProxy(frontProxy, rootShard.Name) + requiredObjects = getBundleObjectsForFrontProxy(frontProxy, rootShard.Name, names) } else { errs = append(errs, fmt.Errorf("failed to get RootShard for FrontProxy %s: %w", targetName, err)) } diff --git a/internal/controller/bundle/objects.go b/internal/controller/bundle/objects.go index 3f086848..5e3c41da 100644 --- a/internal/controller/bundle/objects.go +++ b/internal/controller/bundle/objects.go @@ -17,11 +17,10 @@ limitations under the License. package bundle import ( - "fmt" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -64,36 +63,39 @@ var ( ) // getBundleObjectsForShard returns the list of objects required for a Shard bundle -func getBundleObjectsForShard(shard *operatorv1alpha1.Shard, rootShardName string) []operatorv1alpha1.BundleObject { - shardName := shard.Name +func getBundleObjectsForShard(shard *operatorv1alpha1.Shard, rootShardName string, names naming.Scheme) []operatorv1alpha1.BundleObject { namespace := shard.Namespace + rootShard := &operatorv1alpha1.RootShard{} + rootShard.Name = rootShardName + rootShard.Namespace = namespace + objects := []operatorv1alpha1.BundleObject{ // CA certificates from RootShard (shared) - {GVR: secretGVR, Name: fmt.Sprintf("%s-front-proxy-client-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-requestheader-client-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-server-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-client-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-service-account-ca", rootShardName), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Namespace: namespace}, // Shard-specific certificates and secrets - {GVR: secretGVR, Name: fmt.Sprintf("%s-logical-cluster-admin", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-logical-cluster-admin-kubeconfig", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-client-kubeconfig", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-external-logical-cluster-admin", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-external-logical-cluster-admin-kubeconfig", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-virtual-workspaces", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-client", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-server", shardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-service-account", shardName), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardKubeconfigSecret(shard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ClientCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardKubeconfigSecret(shard, operatorv1alpha1.ClientCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardKubeconfigSecret(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ServerCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.VirtualWorkspacesCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ServiceAccountCertificate), Namespace: namespace}, } // Add merged CA bundle only if CABundleSecretRef is configured if shard.Spec.CABundleSecretRef != nil { objects = append(objects, operatorv1alpha1.BundleObject{ GVR: secretGVR, - Name: fmt.Sprintf("%s-merged-ca-bundle", shardName), + Name: names.MergedCABundleName(shard.Name), Namespace: namespace, }) } @@ -101,14 +103,14 @@ func getBundleObjectsForShard(shard *operatorv1alpha1.Shard, rootShardName strin // Deployment objects = append(objects, operatorv1alpha1.BundleObject{ GVR: deploymentGVR, - Name: fmt.Sprintf("%s-shard-kcp", shardName), + Name: names.ShardDeploymentName(shard), Namespace: namespace, }) // Service objects = append(objects, operatorv1alpha1.BundleObject{ GVR: serviceGVR, - Name: fmt.Sprintf("%s-shard-kcp", shardName), + Name: names.ShardServiceName(shard), Namespace: namespace, }) @@ -117,56 +119,55 @@ func getBundleObjectsForShard(shard *operatorv1alpha1.Shard, rootShardName strin // getBundleObjectsForRootShard returns the list of objects required for a RootShard bundle // TODO(mjudeikis): These are not yet tested. Need to double check if its full list. -func getBundleObjectsForRootShard(rootShard *operatorv1alpha1.RootShard) []operatorv1alpha1.BundleObject { - rootShardName := rootShard.Name +func getBundleObjectsForRootShard(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) []operatorv1alpha1.BundleObject { namespace := rootShard.Namespace objects := []operatorv1alpha1.BundleObject{ // Root CA and intermediate CAs - {GVR: secretGVR, Name: fmt.Sprintf("%s-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-server-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-requestheader-client-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-client-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-service-account-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-front-proxy-client-ca", rootShardName), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Namespace: namespace}, // RootShard certificates - {GVR: secretGVR, Name: fmt.Sprintf("%s-server", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-service-account", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-virtual-workspaces", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-logical-cluster-admin", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-external-logical-cluster-admin", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-operator-client", rootShardName), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ServerCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.VirtualWorkspacesCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.OperatorCertificate), Namespace: namespace}, // Kubeconfig secrets - {GVR: secretGVR, Name: fmt.Sprintf("%s-logical-cluster-admin-kubeconfig", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-external-logical-cluster-admin-kubeconfig", rootShardName), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, // Service - {GVR: serviceGVR, Name: fmt.Sprintf("%s-kcp", rootShardName), Namespace: namespace}, + {GVR: serviceGVR, Name: names.RootShardServiceName(rootShard), Namespace: namespace}, } // Add merged CA bundle if configured if rootShard.Spec.CABundleSecretRef != nil { objects = append(objects, operatorv1alpha1.BundleObject{ GVR: secretGVR, - Name: fmt.Sprintf("%s-merged-ca-bundle", rootShardName), + Name: names.MergedCABundleName(rootShard.Name), Namespace: namespace, }) } // Add proxy-related objects objects = append(objects, []operatorv1alpha1.BundleObject{ - {GVR: secretGVR, Name: fmt.Sprintf("%s-proxy-dynamic-kubeconfig", rootShardName), Namespace: namespace}, - {GVR: configMapGVR, Name: fmt.Sprintf("%s-proxy-config", rootShardName), Namespace: namespace}, - {GVR: serviceGVR, Name: fmt.Sprintf("%s-proxy", rootShardName), Namespace: namespace}, - {GVR: deploymentGVR, Name: fmt.Sprintf("%s-proxy", rootShardName), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardProxyDynamicKubeconfigName(rootShard), Namespace: namespace}, + {GVR: configMapGVR, Name: names.RootShardProxyConfigName(rootShard), Namespace: namespace}, + {GVR: serviceGVR, Name: names.RootShardProxyServiceName(rootShard), Namespace: namespace}, + {GVR: deploymentGVR, Name: names.RootShardProxyDeploymentName(rootShard), Namespace: namespace}, }...) // Add rootshard deployment objects = append(objects, operatorv1alpha1.BundleObject{ GVR: deploymentGVR, - Name: fmt.Sprintf("%s-kcp", rootShardName), + Name: names.RootShardDeploymentName(rootShard), Namespace: namespace, }) @@ -175,44 +176,30 @@ func getBundleObjectsForRootShard(rootShard *operatorv1alpha1.RootShard) []opera // getBundleObjectsForFrontProxy returns the list of objects required for a FrontProxy bundle // TODO(mjudeikis): These are not yet tested. Need to double check if its full list. -func getBundleObjectsForFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShardName string) []operatorv1alpha1.BundleObject { - frontProxyName := frontProxy.Name +func getBundleObjectsForFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShardName string, names naming.Scheme) []operatorv1alpha1.BundleObject { namespace := frontProxy.Namespace + rootShard := &operatorv1alpha1.RootShard{} + rootShard.Name = rootShardName + rootShard.Namespace = namespace + return []operatorv1alpha1.BundleObject{ - // CA certificates from RootShard (shared) - {GVR: secretGVR, Name: fmt.Sprintf("%s-front-proxy-client-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-requestheader-client-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-server-ca", rootShardName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-ca", rootShardName), Namespace: namespace}, + // CA certificates from RootShard (shared) (Secret names are identical to Cert names) + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Namespace: namespace}, + {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), Namespace: namespace}, // FrontProxy-specific certificates - {GVR: secretGVR, Name: fmt.Sprintf("%s-%s-server", rootShardName, frontProxyName), Namespace: namespace}, - {GVR: secretGVR, Name: fmt.Sprintf("%s-%s-client", rootShardName, frontProxyName), Namespace: namespace}, + {GVR: secretGVR, Name: names.FrontProxyCertificateName(rootShard, frontProxy, operatorv1alpha1.ServerCertificate), Namespace: namespace}, + {GVR: secretGVR, Name: names.FrontProxyCertificateName(rootShard, frontProxy, operatorv1alpha1.ClientCertificate), Namespace: namespace}, // FrontProxy configuration and service - {GVR: secretGVR, Name: fmt.Sprintf("%s-%s-dynamic-kubeconfig", rootShardName, frontProxyName), Namespace: namespace}, - {GVR: configMapGVR, Name: fmt.Sprintf("%s-config", frontProxyName), Namespace: namespace}, - {GVR: serviceGVR, Name: fmt.Sprintf("%s-front-proxy", frontProxyName), Namespace: namespace}, + {GVR: secretGVR, Name: names.FrontProxyDynamicKubeconfigName(rootShard, frontProxy), Namespace: namespace}, + {GVR: configMapGVR, Name: names.FrontProxyConfigName(frontProxy), Namespace: namespace}, + {GVR: serviceGVR, Name: names.FrontProxyServiceName(frontProxy), Namespace: namespace}, // FrontProxy deployment - {GVR: deploymentGVR, Name: fmt.Sprintf("%s-front-proxy", frontProxyName), Namespace: namespace}, - } -} - -// GetBundleObjectsForTarget returns the list of objects required for a Bundle based on the target -func GetBundleObjectsForTarget(target operatorv1alpha1.BundleTarget, namespace string, shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, frontProxy *operatorv1alpha1.FrontProxy) []operatorv1alpha1.BundleObject { - switch { - case target.RootShardRef != nil && rootShard != nil: - return getBundleObjectsForRootShard(rootShard) - - case target.ShardRef != nil && shard != nil && rootShard != nil: - return getBundleObjectsForShard(shard, rootShard.Name) - - case target.FrontProxyRef != nil && frontProxy != nil && rootShard != nil: - return getBundleObjectsForFrontProxy(frontProxy, rootShard.Name) - - default: - return []operatorv1alpha1.BundleObject{} + {GVR: deploymentGVR, Name: names.FrontProxyDeploymentName(frontProxy), Namespace: namespace}, } } diff --git a/internal/resources/cacheserver/certificates.go b/internal/resources/cacheserver/certificates.go index 892a5844..41237b74 100644 --- a/internal/resources/cacheserver/certificates.go +++ b/internal/resources/cacheserver/certificates.go @@ -72,7 +72,7 @@ func RootCACertificateReconciler(server *operatorv1alpha1.CacheServer, names nam // ClientCertificateReconciler creates a client certificate for authenticating to the cache server. // This certificate is mounted by shards that connect to the cache server. func ClientCertificateReconciler(server *operatorv1alpha1.CacheServer, names naming.Scheme) reconciling.NamedCertificateReconcilerFactory { - name := names.CacheServerClientCertificateName(server) + name := names.CacheServerClientCertificateName(server.Name) template := server.Spec.CertificateTemplates.CertificateTemplate(operatorv1alpha1.ClientCertificate) return func() (string, reconciling.CertificateReconciler) { diff --git a/internal/resources/frontproxy/ca_bundle.go b/internal/resources/frontproxy/ca_bundle.go index ec4d9b97..b60cb75a 100644 --- a/internal/resources/frontproxy/ca_bundle.go +++ b/internal/resources/frontproxy/ca_bundle.go @@ -32,10 +32,12 @@ import ( ) func (r *reconciler) mergedClientCASecretName() string { + owner := r.names.RootShardProxyDeploymentName(r.rootShard) if r.frontProxy != nil { - return fmt.Sprintf("%s-merged-client-ca", r.frontProxy.Name) + owner = r.frontProxy.Name } - return fmt.Sprintf("%s-proxy-merged-client-ca", r.rootShard.Name) + + return r.names.MergedClientCAName(owner) } // mergedClientCASecretReconciler creates a single secret with the @@ -92,11 +94,12 @@ func (r *reconciler) mergedClientCASecretReconciler(ctx context.Context, kubeCli } func (r *reconciler) mergedCABundleSecretName() string { - // Validate whether called for frontProxy or rootShardFrontProxy + owner := r.names.RootShardProxyDeploymentName(r.rootShard) if r.frontProxy != nil { - return fmt.Sprintf("%s-merged-ca-bundle", r.frontProxy.Name) + owner = r.frontProxy.Name } - return fmt.Sprintf("%s-proxy-merged-ca-bundle", r.rootShard.Name) + + return r.names.MergedCABundleName(owner) } func (r *reconciler) mergedCABundleSecretReconciler(ctx context.Context, kubeClient ctrlruntimeclient.Client) k8creconciling.NamedSecretReconcilerFactory { diff --git a/internal/resources/frontproxy/certificates.go b/internal/resources/frontproxy/certificates.go index a3bf2fd7..616b8172 100644 --- a/internal/resources/frontproxy/certificates.go +++ b/internal/resources/frontproxy/certificates.go @@ -74,10 +74,15 @@ func (r *reconciler) serverCertificateReconciler() reconciling.NamedCertificateR template := r.certTemplateMap().CertificateTemplate(certKind) fpService := r.serviceName() + clusterDomain := "cluster.local" + if cd := r.rootShard.Spec.ClusterDomain; cd != "" { + clusterDomain = cd + } + dnsNames := []string{ fpService, fmt.Sprintf("%s.%s", fpService, r.rootShard.Namespace), - fmt.Sprintf("%s.%s.svc.cluster.local", fpService, r.rootShard.Namespace), + fmt.Sprintf("%s.%s.svc.%s", fpService, r.rootShard.Namespace, clusterDomain), } if r.frontProxy != nil { diff --git a/internal/resources/frontproxy/service_test.go b/internal/resources/frontproxy/service_test.go index 8cdabb19..65bb9f0d 100644 --- a/internal/resources/frontproxy/service_test.go +++ b/internal/resources/frontproxy/service_test.go @@ -24,6 +24,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -207,13 +208,15 @@ func TestGetExternalPort(t *testing.T) { }, } + namingScheme := naming.NewVersion1() + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var rec *reconciler if tt.frontProxy != nil { - rec = NewFrontProxy(tt.frontProxy, tt.rootShard) + rec = NewFrontProxy(tt.frontProxy, tt.rootShard, namingScheme) } else { - rec = NewRootShardProxy(tt.rootShard) + rec = NewRootShardProxy(tt.rootShard, namingScheme) } actualPort := rec.getExternalPort() diff --git a/internal/resources/naming/scheme.go b/internal/resources/naming/scheme.go index 91597276..e904db28 100644 --- a/internal/resources/naming/scheme.go +++ b/internal/resources/naming/scheme.go @@ -65,7 +65,8 @@ type Scheme interface { CacheServerBaseURL(c *operatorv1alpha1.CacheServer) string CacheServerCertificateName(c *operatorv1alpha1.CacheServer, cert operatorv1alpha1.Certificate) string CacheServerCAName(cacheServerName string, ca operatorv1alpha1.CA) string - CacheServerClientCertificateName(c *operatorv1alpha1.CacheServer) string + // deprecated, use CacheServerCertificateName instead + CacheServerClientCertificateName(cacheServerName string) string CacheServerKubeconfigName(cacheServerName string) string // VirtualWorkspace naming @@ -83,9 +84,11 @@ type Scheme interface { FrontProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard, fp *operatorv1alpha1.FrontProxy) string FrontProxyConfigName(fp *operatorv1alpha1.FrontProxy) string FrontProxyServiceName(fp *operatorv1alpha1.FrontProxy) string + FrontProxyBaseHost(fp *operatorv1alpha1.FrontProxy, r *operatorv1alpha1.RootShard) string // Bundle naming BundleName(ownerName string) string + MergedCABundleName(ownerName string) string MergedClientCAName(ownerName string) string } diff --git a/internal/resources/naming/v1.go b/internal/resources/naming/v1.go index 43cf1651..3da0e572 100644 --- a/internal/resources/naming/v1.go +++ b/internal/resources/naming/v1.go @@ -167,8 +167,9 @@ func (v *version1) CacheServerCAName(cacheServerName string, ca operatorv1alpha1 return fmt.Sprintf("%s-%s-ca", cacheServerName, ca) } -func (v *version1) CacheServerClientCertificateName(c *operatorv1alpha1.CacheServer) string { - return fmt.Sprintf("%s-client-certificate", c.Name) +func (v *version1) CacheServerClientCertificateName(cacheServerName string) string { + // This being a different naming scheme than CacheServerCertificateName() is fixed in v2. + return fmt.Sprintf("%s-client-certificate", cacheServerName) } func (v *version1) CacheServerKubeconfigName(cacheServerName string) string { @@ -227,12 +228,20 @@ func (v *version1) FrontProxyServiceName(fp *operatorv1alpha1.FrontProxy) string return fmt.Sprintf("%s-front-proxy", fp.Name) } +func (v *version1) FrontProxyBaseHost(fp *operatorv1alpha1.FrontProxy, r *operatorv1alpha1.RootShard) string { + return fqService(v.FrontProxyServiceName(fp), fp.Namespace, r.Spec.ClusterDomain) +} + // Bundle naming func (v *version1) BundleName(ownerName string) string { return fmt.Sprintf("%s-bundle", ownerName) } +func (v *version1) MergedCABundleName(ownerName string) string { + return fmt.Sprintf("%s-merged-ca-bundle", ownerName) +} + func (v *version1) MergedClientCAName(ownerName string) string { return fmt.Sprintf("%s-merged-client-ca", ownerName) } diff --git a/internal/resources/rootshard/ca_bundle.go b/internal/resources/rootshard/ca_bundle.go index 1dab5fbd..e1a51eb2 100644 --- a/internal/resources/rootshard/ca_bundle.go +++ b/internal/resources/rootshard/ca_bundle.go @@ -33,7 +33,7 @@ import ( func MergedCABundleSecretReconciler(ctx context.Context, rootShard *operatorv1alpha1.RootShard, kubeClient ctrlruntimeclient.Client, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { return func() (string, k8creconciling.SecretReconciler) { - secretName := fmt.Sprintf("%s-merged-ca-bundle", rootShard.Name) + secretName := names.MergedCABundleName(rootShard.Name) return secretName, func(secret *corev1.Secret) (*corev1.Secret, error) { if secret.Data == nil { secret.Data = make(map[string][]byte) diff --git a/internal/resources/rootshard/certificates_test.go b/internal/resources/rootshard/certificates_test.go index 900b369a..7e5ad4b4 100644 --- a/internal/resources/rootshard/certificates_test.go +++ b/internal/resources/rootshard/certificates_test.go @@ -23,6 +23,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -144,9 +145,11 @@ func TestBuildRootShardDNSNames(t *testing.T) { }, } + namingScheme := naming.NewVersion1() + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := buildRootShardDNSNames(tt.rootShard) + result := buildRootShardDNSNames(tt.rootShard, namingScheme) assert.ElementsMatch(t, tt.expected, result) }) } diff --git a/internal/resources/rootshard/deployment.go b/internal/resources/rootshard/deployment.go index 271af2ea..31799213 100644 --- a/internal/resources/rootshard/deployment.go +++ b/internal/resources/rootshard/deployment.go @@ -143,7 +143,7 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator if rootShard.Spec.CABundleSecretRef != nil { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "ca-bundle", - SecretName: fmt.Sprintf("%s-merged-ca-bundle", rootShard.Name), + SecretName: names.MergedCABundleName(rootShard.Name), MountPath: getCAMountPath(operatorv1alpha1.CABundleCA), }) } @@ -165,7 +165,7 @@ func DeploymentReconciler(rootShard *operatorv1alpha1.RootShard, kcpVW *operator secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "cache-server-client-cert", - SecretName: fmt.Sprintf("%s-client-certificate", ref.Name), + SecretName: names.CacheServerClientCertificateName(ref.Name), MountPath: getCacheServerClientCertMountPath(), }) } diff --git a/internal/resources/shard/ca_bundle.go b/internal/resources/shard/ca_bundle.go index 0228eabc..3b09d1fd 100644 --- a/internal/resources/shard/ca_bundle.go +++ b/internal/resources/shard/ca_bundle.go @@ -33,7 +33,7 @@ import ( func MergedCABundleSecretReconciler(ctx context.Context, shard *operatorv1alpha1.Shard, kubeClient ctrlruntimeclient.Client, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { return func() (string, k8creconciling.SecretReconciler) { - secretName := fmt.Sprintf("%s-merged-ca-bundle", shard.Name) + secretName := names.MergedCABundleName(shard.Name) return secretName, func(secret *corev1.Secret) (*corev1.Secret, error) { if secret.Data == nil { secret.Data = make(map[string][]byte) diff --git a/internal/resources/shard/certificates_test.go b/internal/resources/shard/certificates_test.go index 8b238b64..2edfebba 100644 --- a/internal/resources/shard/certificates_test.go +++ b/internal/resources/shard/certificates_test.go @@ -23,6 +23,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -108,9 +109,11 @@ func TestBuildShardDNSNames(t *testing.T) { }, } + namingScheme := naming.NewVersion1() + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := buildShardDNSNames(tt.shard) + result := buildShardDNSNames(tt.shard, namingScheme) assert.ElementsMatch(t, tt.expected, result) }) } diff --git a/internal/resources/shard/deployment.go b/internal/resources/shard/deployment.go index b51de783..72206466 100644 --- a/internal/resources/shard/deployment.go +++ b/internal/resources/shard/deployment.go @@ -156,7 +156,7 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al if shard.Spec.CABundleSecretRef != nil { secretMounts = append(secretMounts, utils.SecretMount{ VolumeName: "ca-bundle", - SecretName: fmt.Sprintf("%s-merged-ca-bundle", shard.Name), + SecretName: names.MergedCABundleName(shard.Name), MountPath: getCAMountPath(operatorv1alpha1.CABundleCA), }) } @@ -175,7 +175,7 @@ func DeploymentReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1al MountPath: getCacheServerCAMountPath(operatorv1alpha1.RootCA), }, utils.SecretMount{ VolumeName: "cache-server-client-cert", - SecretName: fmt.Sprintf("%s-client-certificate", cacheRef), + SecretName: names.CacheServerClientCertificateName(cacheRef), MountPath: getCacheServerClientCertMountPath(), }, ) diff --git a/internal/resources/shard/kubeconfigs.go b/internal/resources/shard/kubeconfigs.go index 6d265929..02c1200b 100644 --- a/internal/resources/shard/kubeconfigs.go +++ b/internal/resources/shard/kubeconfigs.go @@ -29,10 +29,6 @@ import ( operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) -func kubeconfigSecret(shard *operatorv1alpha1.Shard, cert operatorv1alpha1.Certificate) string { - return fmt.Sprintf("%s-%s-kubeconfig", shard.Name, cert) -} - func RootShardClientKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) k8creconciling.NamedSecretReconcilerFactory { const ( serverName = "root-shard" @@ -41,7 +37,7 @@ func RootShardClientKubeconfigReconciler(shard *operatorv1alpha1.Shard, rootShar ) return func() (string, k8creconciling.SecretReconciler) { - return kubeconfigSecret(shard, operatorv1alpha1.ClientCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { + return names.ShardKubeconfigSecret(shard, operatorv1alpha1.ClientCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { var config *clientcmdapi.Config if secret.Data == nil { secret.Data = make(map[string][]byte) @@ -89,7 +85,7 @@ func LogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Shard, root ) return func() (string, k8creconciling.SecretReconciler) { - return kubeconfigSecret(shard, operatorv1alpha1.LogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { + return names.ShardKubeconfigSecret(shard, operatorv1alpha1.LogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { var config *clientcmdapi.Config if secret.Data == nil { @@ -138,7 +134,7 @@ func ExternalLogicalClusterAdminKubeconfigReconciler(shard *operatorv1alpha1.Sha ) return func() (string, k8creconciling.SecretReconciler) { - return kubeconfigSecret(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { + return names.ShardKubeconfigSecret(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), func(secret *corev1.Secret) (*corev1.Secret, error) { var config *clientcmdapi.Config if secret.Data == nil { diff --git a/internal/resources/virtualworkspace/deployment.go b/internal/resources/virtualworkspace/deployment.go index 9bfb6c46..485535fd 100644 --- a/internal/resources/virtualworkspace/deployment.go +++ b/internal/resources/virtualworkspace/deployment.go @@ -168,7 +168,7 @@ func DeploymentReconciler(vw *operatorv1alpha1.VirtualWorkspace, rootShard *oper }, utils.SecretMount{ VolumeName: "cache-server-client-cert", - SecretName: fmt.Sprintf("%s-client-certificate", cacheRef), + SecretName: names.CacheServerClientCertificateName(cacheRef), MountPath: getCacheServerClientCertMountPath(), }, ) diff --git a/test/e2e/frontproxies/frontproxies_test.go b/test/e2e/frontproxies/frontproxies_test.go index 1fd8e10f..3bdfd87b 100644 --- a/test/e2e/frontproxies/frontproxies_test.go +++ b/test/e2e/frontproxies/frontproxies_test.go @@ -20,7 +20,6 @@ package frontproxies import ( "context" - "fmt" "testing" "time" @@ -46,8 +45,7 @@ func TestCreateFrontProxy(t *testing.T) { namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "create-frontproxy") - // externalHostname must match whatever DeployFrontProxy chooses as the name for the FrontProxy - externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) + externalHostname := utils.FrontProxyExternalHostname(namespace.Name, namingScheme) // deploy rootshard rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname) diff --git a/test/e2e/kubeconfig-rbac/frontproxies_test.go b/test/e2e/kubeconfig-rbac/frontproxies_test.go index 68b1a8b4..20161b1a 100644 --- a/test/e2e/kubeconfig-rbac/frontproxies_test.go +++ b/test/e2e/kubeconfig-rbac/frontproxies_test.go @@ -20,7 +20,6 @@ package kubeconfigrbac import ( "context" - "fmt" "testing" "time" @@ -51,7 +50,7 @@ func TestProvisionFrontProxyRBAC(t *testing.T) { namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "provision-frontproxy-rbac") // externalHostname must match whatever DeployFrontProxy chooses as the name for the FrontProxy - externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) + externalHostname := utils.FrontProxyExternalHostname(namespace.Name, namingScheme) // deploy rootshard rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname) diff --git a/test/e2e/rootshards/proxy_test.go b/test/e2e/rootshards/proxy_test.go index c5b76ad5..6292fc92 100644 --- a/test/e2e/rootshards/proxy_test.go +++ b/test/e2e/rootshards/proxy_test.go @@ -20,7 +20,6 @@ package rootshards import ( "context" - "fmt" "testing" "time" @@ -51,7 +50,7 @@ func TestRootShardProxy(t *testing.T) { namespace := utils.CreateSelfDestructingNamespace(t, ctx, client, "rootshard-proxy") // externalHostname must match whatever DeployFrontProxy chooses as the name for the FrontProxy - externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) + externalHostname := utils.FrontProxyExternalHostname(namespace.Name, namingScheme) // deploy a root shard incl. etcd rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname) diff --git a/test/e2e/shards/shards_test.go b/test/e2e/shards/shards_test.go index 3cd7eb6a..6eb1729f 100644 --- a/test/e2e/shards/shards_test.go +++ b/test/e2e/shards/shards_test.go @@ -165,7 +165,7 @@ func TestShardBundleAnnotation(t *testing.T) { shard := utils.DeployShard(ctx, t, client, namespace.Name, shardName, rootShard.Name) // verify no bundle exists yet - bundleName := fmt.Sprintf("%s-bundle", shard.Name) + bundleName := namingScheme.BundleName(shard.Name) bundle := &operatorv1alpha1.Bundle{} err := client.Get(ctx, types.NamespacedName{ Namespace: namespace.Name, @@ -280,29 +280,29 @@ bundleReady: // verify specific expected objects exist expectedObjectsList := []string{ // CA certificates from RootShard (6 objects) - fmt.Sprintf("secrets.core.v1:%s/%s-front-proxy-client-ca", namespace.Name, rootShard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-requestheader-client-ca", namespace.Name, rootShard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-server-ca", namespace.Name, rootShard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-ca", namespace.Name, rootShard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-client-ca", namespace.Name, rootShard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-service-account-ca", namespace.Name, rootShard.Name), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.RootShardCAName(&rootShard, operatorv1alpha1.RootCA)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.RootShardCAName(&rootShard, operatorv1alpha1.ServerCA)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.RootShardCAName(&rootShard, operatorv1alpha1.RequestHeaderClientCA)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.RootShardCAName(&rootShard, operatorv1alpha1.ClientCA)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.RootShardCAName(&rootShard, operatorv1alpha1.ServiceAccountCA)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.RootShardCAName(&rootShard, operatorv1alpha1.FrontProxyClientCA)), // Shard-specific certificates and secrets (9 objects) - fmt.Sprintf("secrets.core.v1:%s/%s-logical-cluster-admin", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-logical-cluster-admin-kubeconfig", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-client-kubeconfig", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-external-logical-cluster-admin", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-external-logical-cluster-admin-kubeconfig", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-virtual-workspaces", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-client", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-server", namespace.Name, shard.Name), - fmt.Sprintf("secrets.core.v1:%s/%s-service-account", namespace.Name, shard.Name), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardCertificateName(&shard, operatorv1alpha1.LogicalClusterAdminCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardKubeconfigSecret(&shard, operatorv1alpha1.LogicalClusterAdminCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardCertificateName(&shard, operatorv1alpha1.ClientCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardKubeconfigSecret(&shard, operatorv1alpha1.ClientCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardCertificateName(&shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardKubeconfigSecret(&shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardCertificateName(&shard, operatorv1alpha1.ServerCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardCertificateName(&shard, operatorv1alpha1.VirtualWorkspacesCertificate)), + fmt.Sprintf("secrets.core.v1:%s/%s", namespace.Name, namingScheme.ShardCertificateName(&shard, operatorv1alpha1.ServiceAccountCertificate)), // Deployment (1 object) - fmt.Sprintf("deployments.apps.v1:%s/%s-shard-kcp", namespace.Name, shard.Name), + fmt.Sprintf("deployments.apps.v1:%s/%s", namespace.Name, namingScheme.ShardDeploymentName(&shard)), // Service (1 object) - fmt.Sprintf("services.core.v1:%s/%s-shard-kcp", namespace.Name, shard.Name), + fmt.Sprintf("services.core.v1:%s/%s", namespace.Name, namingScheme.ShardServiceName(&shard)), } t.Log("Verifying all expected objects are present in bundle...") diff --git a/test/e2e/virtualworkspaces/virtualworkspaces_test.go b/test/e2e/virtualworkspaces/virtualworkspaces_test.go index 6319d7b0..695eba94 100644 --- a/test/e2e/virtualworkspaces/virtualworkspaces_test.go +++ b/test/e2e/virtualworkspaces/virtualworkspaces_test.go @@ -78,7 +78,7 @@ func TestExternalVirtualWorkspace(t *testing.T) { }) // externalHostname must match whatever DeployFrontProxy chooses as the name for the FrontProxy - externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) + externalHostname := utils.FrontProxyExternalHostname(namespace.Name, namingScheme) // Deploy a root shard that uses the external VW (in-process VW is disabled). rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname, func(rs *operatorv1alpha1.RootShard) { @@ -97,16 +97,8 @@ func TestExternalVirtualWorkspace(t *testing.T) { fp.Spec.Resources = lowResourceRequirements() }) - // Wait for the VirtualWorkspace pods to be ready. t.Log("Waiting for VirtualWorkspace pods to be ready...") - vwPodOpts := []ctrlruntimeclient.ListOption{ - ctrlruntimeclient.InNamespace(vw.Namespace), - ctrlruntimeclient.MatchingLabels{ - "app.kubernetes.io/component": "virtual-workspace", - "app.kubernetes.io/instance": vw.Name, - }, - } - utils.WaitForPods(t, ctx, client, vwPodOpts...) + waitForVirtualWorkspacePods(t, ctx, client, namingScheme, &vw) // Create a kubeconfig to access the root shard. configSecretName := "kubeconfig" @@ -195,7 +187,7 @@ func TestExternalVirtualWorkspace(t *testing.T) { } // Set up port forwarding to the VirtualWorkspace service - vwServiceName := fmt.Sprintf("%s-virtual-workspace", vw.Name) + vwServiceName := namingScheme.VirtualWorkspaceServiceName(&vw) vwLocalPortStr, err := server.GetFreePort(t) if err != nil { t.Fatalf("Failed to get free port: %v", err) @@ -269,7 +261,7 @@ func TestMultipleShardsWithExternalVirtualWorkspacesAndExtCache(t *testing.T) { }) // externalHostname must match whatever DeployFrontProxy chooses as the name for the FrontProxy - externalHostname := fmt.Sprintf("front-proxy-front-proxy.%s.svc.cluster.local", namespace.Name) + externalHostname := utils.FrontProxyExternalHostname(namespace.Name, namingScheme) // Deploy root shard with external VW rootShard := utils.DeployRootShard(ctx, t, client, namingScheme, namespace.Name, externalHostname, func(rs *operatorv1alpha1.RootShard) { @@ -313,10 +305,10 @@ func TestMultipleShardsWithExternalVirtualWorkspacesAndExtCache(t *testing.T) { // Wait for both VirtualWorkspace pods to be ready t.Log("Waiting for root VirtualWorkspace pods to be ready...") - waitForVirtualWorkspacePods(t, ctx, client, rootVW.Namespace, rootVW.Name) + waitForVirtualWorkspacePods(t, ctx, client, namingScheme, &rootVW) t.Log("Waiting for shard VirtualWorkspace pods to be ready...") - waitForVirtualWorkspacePods(t, ctx, client, shard1VW.Namespace, shard1VW.Name) + waitForVirtualWorkspacePods(t, ctx, client, namingScheme, &shard1VW) // verify the setup test := conformance.NewWorkspaceSchedulingTest(frontProxy.Name, client, namespace.Name) @@ -330,15 +322,12 @@ func TestMultipleShardsWithExternalVirtualWorkspacesAndExtCache(t *testing.T) { } // waitForVirtualWorkspacePods waits for VirtualWorkspace pods to become ready. -func waitForVirtualWorkspacePods(t *testing.T, ctx context.Context, client ctrlruntimeclient.Client, namespace, name string) { +func waitForVirtualWorkspacePods(t *testing.T, ctx context.Context, client ctrlruntimeclient.Client, names naming.Scheme, vw *operatorv1alpha1.VirtualWorkspace) { t.Helper() opts := []ctrlruntimeclient.ListOption{ - ctrlruntimeclient.InNamespace(namespace), - ctrlruntimeclient.MatchingLabels{ - "app.kubernetes.io/component": "virtual-workspace", - "app.kubernetes.io/instance": name, - }, + ctrlruntimeclient.InNamespace(vw.Namespace), + ctrlruntimeclient.MatchingLabels(names.VirtualWorkspaceResourceLabels(vw)), } utils.WaitForPods(t, ctx, client, opts...) } diff --git a/test/utils/utils.go b/test/utils/utils.go index a1f9f5e6..7129bc50 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -43,6 +43,7 @@ import ( ctrlruntime "sigs.k8s.io/controller-runtime" ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -371,3 +372,15 @@ func GetKcpRelease() *semver.Version { return parsed } + +func FrontProxyExternalHostname(namespace string, names naming.Scheme) string { + fp := &operatorv1alpha1.FrontProxy{} + fp.Name = "front-proxy" // has to match what is used in DeployFrontProxy() + fp.Namespace = namespace + + rs := &operatorv1alpha1.RootShard{} + rs.Name = "r00t" // has to match what is used in DeployRootShard() + rs.Namespace = namespace + + return names.FrontProxyBaseHost(fp, rs) +} From 6fc9003edb2f9d270da7a7b36ee6ebae586bffea Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Tue, 14 Apr 2026 20:23:39 +0200 Subject: [PATCH 12/13] AI review comments On-behalf-of: @SAP christoph.mewes@sap.com --- internal/client/clients.go | 6 +++--- internal/controller/frontproxy/controller.go | 3 +-- internal/controller/virtualworkspace/controller.go | 2 +- internal/resources/kubeconfig/certificate.go | 3 ++- internal/resources/kubeconfig/rbac.go | 3 ++- internal/resources/naming/scheme.go | 1 + internal/resources/naming/v1.go | 4 ++++ internal/resources/resources.go | 4 ++++ 8 files changed, 18 insertions(+), 8 deletions(-) diff --git a/internal/client/clients.go b/internal/client/clients.go index b3099ce1..67a447f6 100644 --- a/internal/client/clients.go +++ b/internal/client/clients.go @@ -34,7 +34,7 @@ import ( // NewRootShardClient returns a new client for talking to the kcp root shard service directly. func NewRootShardClient(ctx context.Context, names naming.Scheme, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { - baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", names.RootShardServiceName(rootShard), rootShard.Namespace) + baseUrl := fmt.Sprintf("https://%s:6443", names.RootShardBaseHost(rootShard)) if !cluster.Empty() { baseUrl = fmt.Sprintf("%s/clusters/%s", baseUrl, cluster.String()) @@ -45,7 +45,7 @@ func NewRootShardClient(ctx context.Context, names naming.Scheme, c ctrlruntimec // NewRootShardClient returns a new client that connects to the operator's internal front-proxy. func NewRootShardProxyClient(ctx context.Context, names naming.Scheme, c ctrlruntimeclient.Client, rootShard *operatorv1alpha1.RootShard, cluster logicalcluster.Name, scheme *runtime.Scheme) (ctrlruntimeclient.Client, error) { - baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", names.RootShardProxyServiceName(rootShard), rootShard.Namespace) + baseUrl := fmt.Sprintf("https://%s:6443", names.RootShardProxyBaseHost(rootShard)) if !cluster.Empty() { baseUrl = fmt.Sprintf("%s/clusters/%s", baseUrl, cluster.String()) @@ -61,7 +61,7 @@ func NewShardClient(ctx context.Context, names naming.Scheme, c ctrlruntimeclien return nil, fmt.Errorf("failed to determine effective RootShard: %w", err) } - baseUrl := fmt.Sprintf("https://%s.%s.svc.cluster.local:6443", names.ShardServiceName(shard), shard.Namespace) + baseUrl := fmt.Sprintf("https://%s:6443", names.ShardBaseHost(shard)) if !cluster.Empty() { baseUrl = fmt.Sprintf("%s/clusters/%s", baseUrl, cluster.String()) diff --git a/internal/controller/frontproxy/controller.go b/internal/controller/frontproxy/controller.go index 43587010..7484f3d0 100644 --- a/internal/controller/frontproxy/controller.go +++ b/internal/controller/frontproxy/controller.go @@ -169,8 +169,7 @@ func (r *FrontProxyReconciler) reconcileStatus(ctx context.Context, oldFrontProx // Only check deployment status if not bundled if !isBundled { - namingScheme := naming.NewVersion1() - depKey := types.NamespacedName{Namespace: frontProxy.Namespace, Name: namingScheme.FrontProxyDeploymentName(frontProxy)} + depKey := types.NamespacedName{Namespace: frontProxy.Namespace, Name: names.FrontProxyDeploymentName(frontProxy)} cond, err := util.GetDeploymentAvailableCondition(ctx, r.Client, depKey) if err != nil { errs = append(errs, err) diff --git a/internal/controller/virtualworkspace/controller.go b/internal/controller/virtualworkspace/controller.go index ef724ff6..53d7d94d 100644 --- a/internal/controller/virtualworkspace/controller.go +++ b/internal/controller/virtualworkspace/controller.go @@ -142,7 +142,7 @@ func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.Virtual } clientCertIssuer = names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA) - // serverCA = namingScheme.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + // serverCA = names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA) case vw.Spec.Target.ShardRef != nil: shard = &operatorv1alpha1.Shard{} diff --git a/internal/resources/kubeconfig/certificate.go b/internal/resources/kubeconfig/certificate.go index d64f0da0..d0ec6ed8 100644 --- a/internal/resources/kubeconfig/certificate.go +++ b/internal/resources/kubeconfig/certificate.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "github.com/kcp-dev/kcp-operator/internal/reconciling" + "github.com/kcp-dev/kcp-operator/internal/resources" "github.com/kcp-dev/kcp-operator/internal/resources/naming" "github.com/kcp-dev/kcp-operator/internal/resources/utils" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" @@ -39,7 +40,7 @@ func ClientCertificateReconciler(kubeConfig *operatorv1alpha1.Kubeconfig, issuer SecretName: kubeConfig.GetCertificateName(), SecretTemplate: &certmanagerv1.CertificateSecretTemplate{ Labels: map[string]string{ - "operator.kcp.io/kubeconfig": kubeConfig.Name, + resources.KubeconfigLabel: kubeConfig.Name, }, }, Duration: &kubeConfig.Spec.Validity, diff --git a/internal/resources/kubeconfig/rbac.go b/internal/resources/kubeconfig/rbac.go index e957de6c..f3f3e2d3 100644 --- a/internal/resources/kubeconfig/rbac.go +++ b/internal/resources/kubeconfig/rbac.go @@ -24,12 +24,13 @@ import ( rbacv1 "k8s.io/api/rbac/v1" "github.com/kcp-dev/kcp-operator/internal/kubernetes" + "github.com/kcp-dev/kcp-operator/internal/resources" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) func OwnerLabels(owner *operatorv1alpha1.Kubeconfig) map[string]string { return map[string]string{ - "operator.kcp.io/kubeconfig": string(owner.UID), + resources.KubeconfigUIDLabel: string(owner.UID), } } diff --git a/internal/resources/naming/scheme.go b/internal/resources/naming/scheme.go index e904db28..e1c5dad3 100644 --- a/internal/resources/naming/scheme.go +++ b/internal/resources/naming/scheme.go @@ -46,6 +46,7 @@ type Scheme interface { RootShardProxyDynamicKubeconfigName(r *operatorv1alpha1.RootShard) string RootShardProxyConfigName(r *operatorv1alpha1.RootShard) string RootShardProxyServiceName(r *operatorv1alpha1.RootShard) string + RootShardProxyBaseHost(r *operatorv1alpha1.RootShard) string RootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string // Shard naming diff --git a/internal/resources/naming/v1.go b/internal/resources/naming/v1.go index 3da0e572..32088334 100644 --- a/internal/resources/naming/v1.go +++ b/internal/resources/naming/v1.go @@ -97,6 +97,10 @@ func (v *version1) RootShardProxyServiceName(r *operatorv1alpha1.RootShard) stri return fmt.Sprintf("%s-proxy", r.Name) } +func (v *version1) RootShardProxyBaseHost(r *operatorv1alpha1.RootShard) string { + return fqService(v.RootShardProxyServiceName(r), r.Namespace, r.Spec.ClusterDomain) +} + func (v *version1) RootShardKubeconfigSecret(r *operatorv1alpha1.RootShard, cert operatorv1alpha1.Certificate) string { return fmt.Sprintf("%s-%s-kubeconfig", r.Name, cert) } diff --git a/internal/resources/resources.go b/internal/resources/resources.go index 65d6804c..9e18f6a8 100644 --- a/internal/resources/resources.go +++ b/internal/resources/resources.go @@ -50,6 +50,10 @@ const ( CacheServerLabel = "operator.kcp.io/cache-server" VirtualWorkspaceLabel = "operator.kcp.io/virtual-workspace" + // KubeconfigUIDLabel is used inside kcp workspaces to link RBAC resources + // to their owning Kubeconfig object on the kcp operator cluster. + KubeconfigUIDLabel = "operator.kcp.io/kubeconfig" + // BundleAnnotation is placed on RootShard, Shard, or FrontProxy objects to trigger automatic Bundle creation BundleAnnotation = "operator.kcp.io/bundle" From b9d3ee9fa14bf625e3bdfe13e63f7ed77afc819b Mon Sep 17 00:00:00 2001 From: Christoph Mewes Date: Wed, 15 Apr 2026 15:48:54 +0200 Subject: [PATCH 13/13] move front-proxy bundling code into the frontproxy reconciler, fix wrong certs in the FP bundle On-behalf-of: @SAP christoph.mewes@sap.com --- internal/controller/bundle/controller.go | 2 +- internal/controller/bundle/objects.go | 161 +++++------------- .../controller/virtualworkspace/controller.go | 2 +- internal/resources/bundling/objects.go | 78 +++++++++ internal/resources/frontproxy/reconciler.go | 35 +++- internal/resources/frontproxy/secrets.go | 11 +- 6 files changed, 161 insertions(+), 128 deletions(-) create mode 100644 internal/resources/bundling/objects.go diff --git a/internal/controller/bundle/controller.go b/internal/controller/bundle/controller.go index c6d0f88c..edb913bf 100644 --- a/internal/controller/bundle/controller.go +++ b/internal/controller/bundle/controller.go @@ -228,7 +228,7 @@ func (r *BundleReconciler) reconcile(ctx context.Context, bundle *operatorv1alph Namespace: bundle.Namespace, }, rootShard) if err == nil { - requiredObjects = getBundleObjectsForFrontProxy(frontProxy, rootShard.Name, names) + requiredObjects = getBundleObjectsForFrontProxy(frontProxy, rootShard, names) } else { errs = append(errs, fmt.Errorf("failed to get RootShard for FrontProxy %s: %w", targetName, err)) } diff --git a/internal/controller/bundle/objects.go b/internal/controller/bundle/objects.go index 5e3c41da..56e6aa3a 100644 --- a/internal/controller/bundle/objects.go +++ b/internal/controller/bundle/objects.go @@ -17,9 +17,8 @@ limitations under the License. package bundle import ( - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - + "github.com/kcp-dev/kcp-operator/internal/resources/bundling" + "github.com/kcp-dev/kcp-operator/internal/resources/frontproxy" "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -32,36 +31,6 @@ type BundleObjectSpec struct { Objects []operatorv1alpha1.BundleObject } -var ( - // secretGVR is the GVR for Secret resources - secretGVR = schema.GroupVersionResource{ - Group: corev1.GroupName, - Version: "v1", - Resource: "secrets", - } - - // serviceGVR is the GVR for Service resources - serviceGVR = schema.GroupVersionResource{ - Group: corev1.GroupName, - Version: "v1", - Resource: "services", - } - - // configMapGVR is the GVR for ConfigMap resources - configMapGVR = schema.GroupVersionResource{ - Group: corev1.GroupName, - Version: "v1", - Resource: "configmaps", - } - - // deploymentGVR is the GVR for Deployment resources - deploymentGVR = schema.GroupVersionResource{ - Group: "apps", - Version: "v1", - Resource: "deployments", - } -) - // getBundleObjectsForShard returns the list of objects required for a Shard bundle func getBundleObjectsForShard(shard *operatorv1alpha1.Shard, rootShardName string, names naming.Scheme) []operatorv1alpha1.BundleObject { namespace := shard.Namespace @@ -72,47 +41,35 @@ func getBundleObjectsForShard(shard *operatorv1alpha1.Shard, rootShardName strin objects := []operatorv1alpha1.BundleObject{ // CA certificates from RootShard (shared) - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Namespace: namespace}, + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), namespace), // Shard-specific certificates and secrets - {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardKubeconfigSecret(shard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ClientCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardKubeconfigSecret(shard, operatorv1alpha1.ClientCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardKubeconfigSecret(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ServerCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.VirtualWorkspacesCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.ShardCertificateName(shard, operatorv1alpha1.ServiceAccountCertificate), Namespace: namespace}, + bundling.NewSecret(names.ShardCertificateName(shard, operatorv1alpha1.LogicalClusterAdminCertificate), namespace), + bundling.NewSecret(names.ShardKubeconfigSecret(shard, operatorv1alpha1.LogicalClusterAdminCertificate), namespace), + bundling.NewSecret(names.ShardCertificateName(shard, operatorv1alpha1.ClientCertificate), namespace), + bundling.NewSecret(names.ShardKubeconfigSecret(shard, operatorv1alpha1.ClientCertificate), namespace), + bundling.NewSecret(names.ShardCertificateName(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), namespace), + bundling.NewSecret(names.ShardKubeconfigSecret(shard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), namespace), + bundling.NewSecret(names.ShardCertificateName(shard, operatorv1alpha1.ServerCertificate), namespace), + bundling.NewSecret(names.ShardCertificateName(shard, operatorv1alpha1.VirtualWorkspacesCertificate), namespace), + bundling.NewSecret(names.ShardCertificateName(shard, operatorv1alpha1.ServiceAccountCertificate), namespace), } // Add merged CA bundle only if CABundleSecretRef is configured if shard.Spec.CABundleSecretRef != nil { - objects = append(objects, operatorv1alpha1.BundleObject{ - GVR: secretGVR, - Name: names.MergedCABundleName(shard.Name), - Namespace: namespace, - }) + objects = append(objects, bundling.NewSecret(names.MergedCABundleName(shard.Name), namespace)) } // Deployment - objects = append(objects, operatorv1alpha1.BundleObject{ - GVR: deploymentGVR, - Name: names.ShardDeploymentName(shard), - Namespace: namespace, - }) + objects = append(objects, bundling.NewDeployment(names.ShardDeploymentName(shard), namespace)) // Service - objects = append(objects, operatorv1alpha1.BundleObject{ - GVR: serviceGVR, - Name: names.ShardServiceName(shard), - Namespace: namespace, - }) + objects = append(objects, bundling.NewService(names.ShardServiceName(shard), namespace)) return objects } @@ -124,82 +81,50 @@ func getBundleObjectsForRootShard(rootShard *operatorv1alpha1.RootShard, names n objects := []operatorv1alpha1.BundleObject{ // Root CA and intermediate CAs - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Namespace: namespace}, + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.ServiceAccountCA), namespace), + bundling.NewSecret(names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), namespace), // RootShard certificates - {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ServerCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.VirtualWorkspacesCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCertificateName(rootShard, operatorv1alpha1.OperatorCertificate), Namespace: namespace}, + bundling.NewSecret(names.RootShardCertificateName(rootShard, operatorv1alpha1.ServerCertificate), namespace), + bundling.NewSecret(names.RootShardCertificateName(rootShard, operatorv1alpha1.ServiceAccountCertificate), namespace), + bundling.NewSecret(names.RootShardCertificateName(rootShard, operatorv1alpha1.VirtualWorkspacesCertificate), namespace), + bundling.NewSecret(names.RootShardCertificateName(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), namespace), + bundling.NewSecret(names.RootShardCertificateName(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), namespace), + bundling.NewSecret(names.RootShardCertificateName(rootShard, operatorv1alpha1.OperatorCertificate), namespace), // Kubeconfig secrets - {GVR: secretGVR, Name: names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), Namespace: namespace}, + bundling.NewSecret(names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.LogicalClusterAdminCertificate), namespace), + bundling.NewSecret(names.RootShardKubeconfigSecret(rootShard, operatorv1alpha1.ExternalLogicalClusterAdminCertificate), namespace), // Service - {GVR: serviceGVR, Name: names.RootShardServiceName(rootShard), Namespace: namespace}, + bundling.NewService(names.RootShardServiceName(rootShard), namespace), } // Add merged CA bundle if configured if rootShard.Spec.CABundleSecretRef != nil { - objects = append(objects, operatorv1alpha1.BundleObject{ - GVR: secretGVR, - Name: names.MergedCABundleName(rootShard.Name), - Namespace: namespace, - }) + objects = append(objects, bundling.NewSecret(names.MergedCABundleName(rootShard.Name), namespace)) } // Add proxy-related objects objects = append(objects, []operatorv1alpha1.BundleObject{ - {GVR: secretGVR, Name: names.RootShardProxyDynamicKubeconfigName(rootShard), Namespace: namespace}, - {GVR: configMapGVR, Name: names.RootShardProxyConfigName(rootShard), Namespace: namespace}, - {GVR: serviceGVR, Name: names.RootShardProxyServiceName(rootShard), Namespace: namespace}, - {GVR: deploymentGVR, Name: names.RootShardProxyDeploymentName(rootShard), Namespace: namespace}, + bundling.NewSecret(names.RootShardProxyDynamicKubeconfigName(rootShard), namespace), + bundling.NewConfigMap(names.RootShardProxyConfigName(rootShard), namespace), + bundling.NewService(names.RootShardProxyServiceName(rootShard), namespace), + bundling.NewDeployment(names.RootShardProxyDeploymentName(rootShard), namespace), }...) // Add rootshard deployment - objects = append(objects, operatorv1alpha1.BundleObject{ - GVR: deploymentGVR, - Name: names.RootShardDeploymentName(rootShard), - Namespace: namespace, - }) + objects = append(objects, bundling.NewDeployment(names.RootShardDeploymentName(rootShard), namespace)) return objects } // getBundleObjectsForFrontProxy returns the list of objects required for a FrontProxy bundle // TODO(mjudeikis): These are not yet tested. Need to double check if its full list. -func getBundleObjectsForFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShardName string, names naming.Scheme) []operatorv1alpha1.BundleObject { - namespace := frontProxy.Namespace - - rootShard := &operatorv1alpha1.RootShard{} - rootShard.Name = rootShardName - rootShard.Namespace = namespace - - return []operatorv1alpha1.BundleObject{ - // CA certificates from RootShard (shared) (Secret names are identical to Cert names) - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.FrontProxyClientCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RequestHeaderClientCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.ServerCA), Namespace: namespace}, - {GVR: secretGVR, Name: names.RootShardCAName(rootShard, operatorv1alpha1.RootCA), Namespace: namespace}, - - // FrontProxy-specific certificates - {GVR: secretGVR, Name: names.FrontProxyCertificateName(rootShard, frontProxy, operatorv1alpha1.ServerCertificate), Namespace: namespace}, - {GVR: secretGVR, Name: names.FrontProxyCertificateName(rootShard, frontProxy, operatorv1alpha1.ClientCertificate), Namespace: namespace}, - - // FrontProxy configuration and service - {GVR: secretGVR, Name: names.FrontProxyDynamicKubeconfigName(rootShard, frontProxy), Namespace: namespace}, - {GVR: configMapGVR, Name: names.FrontProxyConfigName(frontProxy), Namespace: namespace}, - {GVR: serviceGVR, Name: names.FrontProxyServiceName(frontProxy), Namespace: namespace}, - - // FrontProxy deployment - {GVR: deploymentGVR, Name: names.FrontProxyDeploymentName(frontProxy), Namespace: namespace}, - } +func getBundleObjectsForFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShard *operatorv1alpha1.RootShard, names naming.Scheme) []operatorv1alpha1.BundleObject { + return frontproxy.NewFrontProxy(frontProxy, rootShard, names).Bundle() } diff --git a/internal/controller/virtualworkspace/controller.go b/internal/controller/virtualworkspace/controller.go index 53d7d94d..354c92db 100644 --- a/internal/controller/virtualworkspace/controller.go +++ b/internal/controller/virtualworkspace/controller.go @@ -184,7 +184,7 @@ func (r *Reconciler) reconcile(ctx context.Context, vw *operatorv1alpha1.Virtual // The client CA is shared among all shards and owned by the root shard. clientCertIssuer = names.RootShardCAName(rootShard, operatorv1alpha1.ClientCA) - // serverCA = namingScheme.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) + // serverCA = names.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA) default: err := errors.New("no valid target for VirtualWorkspace found") diff --git a/internal/resources/bundling/objects.go b/internal/resources/bundling/objects.go new file mode 100644 index 00000000..6a2d712d --- /dev/null +++ b/internal/resources/bundling/objects.go @@ -0,0 +1,78 @@ +/* +Copyright 2026 The kcp Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package bundling + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + + operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" +) + +var ( + // SecretGVR is the GVR for Secret resources + SecretGVR = schema.GroupVersionResource{ + Group: corev1.GroupName, + Version: "v1", + Resource: "secrets", + } + + // ServiceGVR is the GVR for Service resources + ServiceGVR = schema.GroupVersionResource{ + Group: corev1.GroupName, + Version: "v1", + Resource: "services", + } + + // ConfigMapGVR is the GVR for ConfigMap resources + ConfigMapGVR = schema.GroupVersionResource{ + Group: corev1.GroupName, + Version: "v1", + Resource: "configmaps", + } + + // DeploymentGVR is the GVR for Deployment resources + DeploymentGVR = schema.GroupVersionResource{ + Group: "apps", + Version: "v1", + Resource: "deployments", + } +) + +func NewObject(gvr schema.GroupVersionResource, name, namespace string) operatorv1alpha1.BundleObject { + return operatorv1alpha1.BundleObject{ + GVR: gvr, + Name: name, + Namespace: namespace, + } +} + +func NewSecret(name, namespace string) operatorv1alpha1.BundleObject { + return NewObject(SecretGVR, name, namespace) +} + +func NewService(name, namespace string) operatorv1alpha1.BundleObject { + return NewObject(ServiceGVR, name, namespace) +} + +func NewConfigMap(name, namespace string) operatorv1alpha1.BundleObject { + return NewObject(ConfigMapGVR, name, namespace) +} + +func NewDeployment(name, namespace string) operatorv1alpha1.BundleObject { + return NewObject(DeploymentGVR, name, namespace) +} diff --git a/internal/resources/frontproxy/reconciler.go b/internal/resources/frontproxy/reconciler.go index a14cc561..65072698 100644 --- a/internal/resources/frontproxy/reconciler.go +++ b/internal/resources/frontproxy/reconciler.go @@ -29,6 +29,7 @@ import ( "github.com/kcp-dev/kcp-operator/internal/reconciling" "github.com/kcp-dev/kcp-operator/internal/reconciling/modifier" + "github.com/kcp-dev/kcp-operator/internal/resources/bundling" "github.com/kcp-dev/kcp-operator/internal/resources/naming" operatorv1alpha1 "github.com/kcp-dev/kcp-operator/sdk/apis/operator/v1alpha1" ) @@ -53,11 +54,11 @@ func NewFrontProxy(frontProxy *operatorv1alpha1.FrontProxy, rootShard *operatorv } } -func NewRootShardProxy(rootShard *operatorv1alpha1.RootShard, namingScheme naming.Scheme) *reconciler { +func NewRootShardProxy(rootShard *operatorv1alpha1.RootShard, names naming.Scheme) *reconciler { return &reconciler{ rootShard: rootShard, - resourceLabels: namingScheme.RootShardProxyResourceLabels(rootShard), - names: namingScheme, + resourceLabels: names.RootShardProxyResourceLabels(rootShard), + names: names, } } @@ -142,3 +143,31 @@ func (r *reconciler) Reconcile(ctx context.Context, client ctrlruntimeclient.Cli return kerrors.NewAggregate(errs) } + +func (r *reconciler) Bundle() []operatorv1alpha1.BundleObject { + namespace := r.frontProxy.Namespace + + objects := []operatorv1alpha1.BundleObject{ + // CA certificates from RootShard (shared) (Secret names are identical to Cert names) + bundling.NewSecret(r.names.RootShardCAName(r.rootShard, operatorv1alpha1.FrontProxyClientCA), namespace), + bundling.NewSecret(r.names.RootShardCAName(r.rootShard, operatorv1alpha1.RequestHeaderClientCA), namespace), + bundling.NewSecret(r.names.RootShardCAName(r.rootShard, operatorv1alpha1.ServerCA), namespace), + bundling.NewSecret(r.names.RootShardCAName(r.rootShard, operatorv1alpha1.RootCA), namespace), + + // FrontProxy-specific certificates + bundling.NewSecret(r.certName(operatorv1alpha1.ServerCertificate), namespace), + bundling.NewSecret(r.certName(operatorv1alpha1.AdminKubeconfigClientCertificate), namespace), + bundling.NewSecret(r.certName(operatorv1alpha1.KubeconfigCertificate), namespace), + bundling.NewSecret(r.certName(operatorv1alpha1.RequestHeaderClientCertificate), namespace), + + // FrontProxy configuration and service + bundling.NewSecret(r.names.FrontProxyDynamicKubeconfigName(r.rootShard, r.frontProxy), namespace), + bundling.NewConfigMap(r.pathMappingConfigMapName(), namespace), + bundling.NewService(r.names.FrontProxyServiceName(r.frontProxy), namespace), + + // FrontProxy deployment + bundling.NewDeployment(r.names.FrontProxyDeploymentName(r.frontProxy), namespace), + } + + return objects +} diff --git a/internal/resources/frontproxy/secrets.go b/internal/resources/frontproxy/secrets.go index af55f0b1..2828501f 100644 --- a/internal/resources/frontproxy/secrets.go +++ b/internal/resources/frontproxy/secrets.go @@ -31,16 +31,17 @@ const ( kubeconfigCAPath = "/etc/kcp/tls/ca/tls.crt" ) -func (r *reconciler) dynamicKubeconfigSecretReconciler() reconciling.NamedSecretReconcilerFactory { - var name string +func (r *reconciler) dynamicKubeconfigSecretName() string { if r.frontProxy != nil { - name = r.names.FrontProxyDynamicKubeconfigName(r.rootShard, r.frontProxy) + return r.names.FrontProxyDynamicKubeconfigName(r.rootShard, r.frontProxy) } else { - name = r.names.RootShardProxyDynamicKubeconfigName(r.rootShard) + return r.names.RootShardProxyDynamicKubeconfigName(r.rootShard) } +} +func (r *reconciler) dynamicKubeconfigSecretReconciler() reconciling.NamedSecretReconcilerFactory { return func() (string, reconciling.SecretReconciler) { - return name, func(obj *corev1.Secret) (*corev1.Secret, error) { + return r.dynamicKubeconfigSecretName(), func(obj *corev1.Secret) (*corev1.Secret, error) { obj.SetLabels(r.resourceLabels) kubeconfig, err := r.dynamicKubeconfig()