From c66f5316640f84c3441b6e1a16e07c7323388d62 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Fri, 26 Jun 2026 13:59:54 +0300 Subject: [PATCH 1/8] Improve platform detection to reduce unknown telemetry values Replace CRD-based detection (which relied on optional addons being installed) with discovery API group checks and API server URL patterns. Add detection for AKS, DOKS, OKE, ACK, NKP, Platform9, Tanzu, and Rancher alongside the existing GKE, EKS, and OpenShift detections. --- cmd/postgres-operator/main.go | 149 ++++++++++++++++++++++++---------- 1 file changed, 104 insertions(+), 45 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index f61123c4b..cdc811709 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -358,69 +358,112 @@ func initManager(ctx context.Context) (runtime.Options, error) { return options, nil } -func isGKE(ctx context.Context, cfg *rest.Config) bool { - log := logging.FromContext(ctx) - - const groupName, kind = "cloud.google.com", "BackendConfig" - +// hasAPIGroup returns true if the cluster exposes the given API group name. +// Uses the discovery API which is available to all authenticated users with no extra RBAC. +func hasAPIGroup(ctx context.Context, cfg *rest.Config, groupName string) bool { client, err := discovery.NewDiscoveryClientForConfig(cfg) - assertNoError(err) - + if err != nil { + return false + } groups, err := client.ServerGroups() if err != nil { - assertNoError(err) + return false } for _, g := range groups.Groups { - if g.Name != groupName { - continue - } - for _, v := range g.Versions { - resourceList, err := client.ServerResourcesForGroupVersion(v.GroupVersion) - if err != nil { - assertNoError(err) - } - for _, r := range resourceList.APIResources { - if r.Kind == kind { - log.Info("detected GKE environment") - return true - } - } + if g.Name == groupName { + return true } } + return false +} +func isGKE(ctx context.Context, cfg *rest.Config) bool { + // networking.gke.io is registered on all GKE clusters by the built-in network controller. + if hasAPIGroup(ctx, cfg, "networking.gke.io") { + logging.FromContext(ctx).Info("detected GKE environment") + return true + } return false } func isEKS(ctx context.Context, cfg *rest.Config) bool { - log := logging.FromContext(ctx) + // EKS API server hostnames always end with .eks.amazonaws.com. + if strings.Contains(cfg.Host, ".eks.amazonaws.com") { + logging.FromContext(ctx).Info("detected EKS environment") + return true + } + return false +} - const groupName, kind = "vpcresources.k8s.aws", "SecurityGroupPolicy" +func isAKS(ctx context.Context, cfg *rest.Config) bool { + // AKS API server hostnames always end with .azmk8s.io. + if strings.Contains(cfg.Host, ".azmk8s.io") { + logging.FromContext(ctx).Info("detected AKS environment") + return true + } + return false +} - client, err := discovery.NewDiscoveryClientForConfig(cfg) - assertNoError(err) +func isDOKS(ctx context.Context, cfg *rest.Config) bool { + // DOKS API server hostnames always end with .k8s.ondigitalocean.com. + if strings.Contains(cfg.Host, ".k8s.ondigitalocean.com") { + logging.FromContext(ctx).Info("detected DOKS environment") + return true + } + return false +} - groups, err := client.ServerGroups() - if err != nil { - assertNoError(err) +func isOKE(ctx context.Context, cfg *rest.Config) bool { + // OKE API server hostnames always end with .oraclecloud.com. + if strings.Contains(cfg.Host, ".oraclecloud.com") { + logging.FromContext(ctx).Info("detected OKE environment") + return true } - for _, g := range groups.Groups { - if g.Name != groupName { - continue - } - for _, v := range g.Versions { - resourceList, err := client.ServerResourcesForGroupVersion(v.GroupVersion) - if err != nil { - assertNoError(err) - } - for _, r := range resourceList.APIResources { - if r.Kind == kind { - log.Info("detected EKS environment") - return true - } - } - } + return false +} + +func isACK(ctx context.Context, cfg *rest.Config) bool { + // ACK API server hostnames always end with .aliyuncs.com. + if strings.Contains(cfg.Host, ".aliyuncs.com") { + logging.FromContext(ctx).Info("detected ACK environment") + return true } + return false +} +func isNKP(ctx context.Context, cfg *rest.Config) bool { + // NKP registers nkp.nutanix.com; legacy D2iQ/Konvoy used kommander.mesosphere.io. + if hasAPIGroup(ctx, cfg, "nkp.nutanix.com") || hasAPIGroup(ctx, cfg, "kommander.mesosphere.io") { + logging.FromContext(ctx).Info("detected NKP environment") + return true + } + return false +} + +func isPlatform9(ctx context.Context, cfg *rest.Config) bool { + // Platform9 API server hostnames contain .platform9.io or .platform9.net. + if strings.Contains(cfg.Host, ".platform9.io") || strings.Contains(cfg.Host, ".platform9.net") { + logging.FromContext(ctx).Info("detected Platform9 environment") + return true + } + return false +} + +func isTanzu(ctx context.Context, cfg *rest.Config) bool { + // Tanzu registers run.tanzu.vmware.com on all TKG clusters. + if hasAPIGroup(ctx, cfg, "run.tanzu.vmware.com") { + logging.FromContext(ctx).Info("detected Tanzu environment") + return true + } + return false +} + +func isRancher(ctx context.Context, cfg *rest.Config) bool { + // Rancher registers management.cattle.io on all managed clusters. + if hasAPIGroup(ctx, cfg, "management.cattle.io") { + logging.FromContext(ctx).Info("detected Rancher environment") + return true + } return false } @@ -432,6 +475,22 @@ func detectPlatform(ctx context.Context, cfg *rest.Config) string { return "gke" case isEKS(ctx, cfg): return "eks" + case isAKS(ctx, cfg): + return "aks" + case isDOKS(ctx, cfg): + return "doks" + case isOKE(ctx, cfg): + return "oke" + case isACK(ctx, cfg): + return "ack" + case isNKP(ctx, cfg): + return "nkp" + case isPlatform9(ctx, cfg): + return "platform9" + case isTanzu(ctx, cfg): + return "tanzu" + case isRancher(ctx, cfg): + return "rancher" default: return "unknown" } From ef3911315a244d91435b7be75983ce0c793fa492 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Fri, 26 Jun 2026 16:39:30 +0300 Subject: [PATCH 2/8] fix platforms --- cmd/postgres-operator/main.go | 93 ++++++++++++++++------------------- 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index cdc811709..422d4afc2 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -6,6 +6,7 @@ package main import ( "context" + "crypto/tls" "os" goruntime "runtime" "strconv" @@ -157,13 +158,15 @@ func main() { func addControllersToManager(ctx context.Context, mgr manager.Manager) error { os.Setenv("REGISTRATION_REQUIRED", "false") + openShift := isOpenshift(ctx, mgr.GetConfig()) + r := &postgrescluster.Reconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), Owner: postgrescluster.ControllerName, Recorder: mgr.GetEventRecorderFor(postgrescluster.ControllerName), Tracer: otel.Tracer(postgrescluster.ControllerName), - IsOpenShift: isOpenshift(ctx, mgr.GetConfig()), + IsOpenShift: openShift, CertManagerCtrlFunc: certmanager.NewController, RestConfig: mgr.GetConfig(), } @@ -193,10 +196,10 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { Owner: pgcluster.PGClusterControllerName, Recorder: mgr.GetEventRecorderFor(pgcluster.PGClusterControllerName), Tracer: otel.Tracer(pgcluster.PGClusterControllerName), - Platform: detectPlatform(ctx, mgr.GetConfig()), + Platform: detectPlatform(ctx, mgr.GetConfig(), openShift), KubeVersion: getServerVersion(ctx, mgr.GetConfig()), CrunchyController: cm.Controller(), - IsOpenShift: isOpenshift(ctx, mgr.GetConfig()), + IsOpenShift: openShift, Cron: pgcluster.NewCronRegistry(), ExternalChan: externalEvents, StopExternalWatchers: stopChan, @@ -272,7 +275,7 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { Client: mgr.GetClient(), Owner: "pgadmin-controller", Recorder: mgr.GetEventRecorderFor(naming.ControllerPGAdmin), - IsOpenShift: isOpenshift(ctx, mgr.GetConfig()), + IsOpenShift: openShift, } if err := pgAdminReconciler.SetupWithManager(mgr); err != nil { @@ -359,14 +362,17 @@ func initManager(ctx context.Context) (runtime.Options, error) { } // hasAPIGroup returns true if the cluster exposes the given API group name. -// Uses the discovery API which is available to all authenticated users with no extra RBAC. +// Uses the discovery API; note that hardened clusters may restrict discovery access. func hasAPIGroup(ctx context.Context, cfg *rest.Config, groupName string) bool { + log := logging.FromContext(ctx) client, err := discovery.NewDiscoveryClientForConfig(cfg) if err != nil { + log.V(1).Info("platform detection: could not create discovery client", "error", err.Error()) return false } groups, err := client.ServerGroups() if err != nil { + log.V(1).Info("platform detection: could not list API groups", "error", err.Error()) return false } for _, g := range groups.Groups { @@ -378,7 +384,6 @@ func hasAPIGroup(ctx context.Context, cfg *rest.Config, groupName string) bool { } func isGKE(ctx context.Context, cfg *rest.Config) bool { - // networking.gke.io is registered on all GKE clusters by the built-in network controller. if hasAPIGroup(ctx, cfg, "networking.gke.io") { logging.FromContext(ctx).Info("detected GKE environment") return true @@ -387,8 +392,9 @@ func isGKE(ctx context.Context, cfg *rest.Config) bool { } func isEKS(ctx context.Context, cfg *rest.Config) bool { - // EKS API server hostnames always end with .eks.amazonaws.com. - if strings.Contains(cfg.Host, ".eks.amazonaws.com") { + // crd.k8s.amazonaws.com (VPC CNI) and metrics.eks.amazonaws.com (control plane metrics) + // are independent EKS signals; either is sufficient. + if hasAPIGroup(ctx, cfg, "crd.k8s.amazonaws.com") || hasAPIGroup(ctx, cfg, "metrics.eks.amazonaws.com") { logging.FromContext(ctx).Info("detected EKS environment") return true } @@ -396,17 +402,34 @@ func isEKS(ctx context.Context, cfg *rest.Config) bool { } func isAKS(ctx context.Context, cfg *rest.Config) bool { - // AKS API server hostnames always end with .azmk8s.io. - if strings.Contains(cfg.Host, ".azmk8s.io") { - logging.FromContext(ctx).Info("detected AKS environment") - return true + // AKS exposes no unique API groups, so we inspect the API server TLS certificate: + // its SAN always contains a hostname ending in .azmk8s.io regardless of network plugin. + tlsCfg, err := rest.TLSConfigFor(cfg) + if err != nil { + logging.FromContext(ctx).V(1).Info("platform detection: could not build TLS config", "error", err.Error()) + return false + } + host := strings.TrimPrefix(cfg.Host, "https://") + host = strings.TrimPrefix(host, "http://") + conn, err := tls.Dial("tcp", host, tlsCfg) + if err != nil { + logging.FromContext(ctx).V(1).Info("platform detection: could not dial API server", "error", err.Error()) + return false + } + defer conn.Close() + for _, cert := range conn.ConnectionState().PeerCertificates { + for _, san := range cert.DNSNames { + if strings.HasSuffix(san, ".azmk8s.io") { + logging.FromContext(ctx).Info("detected AKS environment") + return true + } + } } return false } func isDOKS(ctx context.Context, cfg *rest.Config) bool { - // DOKS API server hostnames always end with .k8s.ondigitalocean.com. - if strings.Contains(cfg.Host, ".k8s.ondigitalocean.com") { + if hasAPIGroup(ctx, cfg, "dataplane-operator.doks.digitalocean.com") { logging.FromContext(ctx).Info("detected DOKS environment") return true } @@ -414,7 +437,6 @@ func isDOKS(ctx context.Context, cfg *rest.Config) bool { } func isOKE(ctx context.Context, cfg *rest.Config) bool { - // OKE API server hostnames always end with .oraclecloud.com. if strings.Contains(cfg.Host, ".oraclecloud.com") { logging.FromContext(ctx).Info("detected OKE environment") return true @@ -423,7 +445,6 @@ func isOKE(ctx context.Context, cfg *rest.Config) bool { } func isACK(ctx context.Context, cfg *rest.Config) bool { - // ACK API server hostnames always end with .aliyuncs.com. if strings.Contains(cfg.Host, ".aliyuncs.com") { logging.FromContext(ctx).Info("detected ACK environment") return true @@ -432,7 +453,7 @@ func isACK(ctx context.Context, cfg *rest.Config) bool { } func isNKP(ctx context.Context, cfg *rest.Config) bool { - // NKP registers nkp.nutanix.com; legacy D2iQ/Konvoy used kommander.mesosphere.io. + // kommander.mesosphere.io is the legacy D2iQ/Konvoy group name. if hasAPIGroup(ctx, cfg, "nkp.nutanix.com") || hasAPIGroup(ctx, cfg, "kommander.mesosphere.io") { logging.FromContext(ctx).Info("detected NKP environment") return true @@ -441,7 +462,6 @@ func isNKP(ctx context.Context, cfg *rest.Config) bool { } func isPlatform9(ctx context.Context, cfg *rest.Config) bool { - // Platform9 API server hostnames contain .platform9.io or .platform9.net. if strings.Contains(cfg.Host, ".platform9.io") || strings.Contains(cfg.Host, ".platform9.net") { logging.FromContext(ctx).Info("detected Platform9 environment") return true @@ -450,7 +470,6 @@ func isPlatform9(ctx context.Context, cfg *rest.Config) bool { } func isTanzu(ctx context.Context, cfg *rest.Config) bool { - // Tanzu registers run.tanzu.vmware.com on all TKG clusters. if hasAPIGroup(ctx, cfg, "run.tanzu.vmware.com") { logging.FromContext(ctx).Info("detected Tanzu environment") return true @@ -459,7 +478,6 @@ func isTanzu(ctx context.Context, cfg *rest.Config) bool { } func isRancher(ctx context.Context, cfg *rest.Config) bool { - // Rancher registers management.cattle.io on all managed clusters. if hasAPIGroup(ctx, cfg, "management.cattle.io") { logging.FromContext(ctx).Info("detected Rancher environment") return true @@ -467,9 +485,9 @@ func isRancher(ctx context.Context, cfg *rest.Config) bool { return false } -func detectPlatform(ctx context.Context, cfg *rest.Config) string { +func detectPlatform(ctx context.Context, cfg *rest.Config, openShift bool) string { switch { - case isOpenshift(ctx, cfg): + case openShift: return "openshift" case isGKE(ctx, cfg): return "gke" @@ -555,35 +573,10 @@ func getLogLevel() zapcore.LevelEnabler { } func isOpenshift(ctx context.Context, cfg *rest.Config) bool { - log := logging.FromContext(ctx) - - const sccGroupName, sccKind = "security.openshift.io", "SecurityContextConstraints" - - client, err := discovery.NewDiscoveryClientForConfig(cfg) - assertNoError(err) - - groups, err := client.ServerGroups() - if err != nil { - assertNoError(err) - } - for _, g := range groups.Groups { - if g.Name != sccGroupName { - continue - } - for _, v := range g.Versions { - resourceList, err := client.ServerResourcesForGroupVersion(v.GroupVersion) - if err != nil { - assertNoError(err) - } - for _, r := range resourceList.APIResources { - if r.Kind == sccKind { - log.Info("detected Openshift environment") - return true - } - } - } + if hasAPIGroup(ctx, cfg, "security.openshift.io") { + logging.FromContext(ctx).Info("detected Openshift environment") + return true } - return false } From 2c321a756c327053868944a27a3db3588755deec Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Tue, 7 Jul 2026 18:39:48 +0300 Subject: [PATCH 3/8] fix ACK --- cmd/postgres-operator/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 422d4afc2..215f63afd 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -445,7 +445,7 @@ func isOKE(ctx context.Context, cfg *rest.Config) bool { } func isACK(ctx context.Context, cfg *rest.Config) bool { - if strings.Contains(cfg.Host, ".aliyuncs.com") { + if strings.Contains(cfg.Host, ".aliyuncs.com") || hasAPIGroup(ctx, cfg, "alibabacloud.com") { logging.FromContext(ctx).Info("detected ACK environment") return true } From 3507d94b0b98588e1715824f7a8f51f81d34b452 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Tue, 7 Jul 2026 18:49:19 +0300 Subject: [PATCH 4/8] fix comments --- cmd/postgres-operator/main.go | 141 +++++++++++----------------------- 1 file changed, 44 insertions(+), 97 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 215f63afd..77abf14e2 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -383,27 +383,48 @@ func hasAPIGroup(ctx context.Context, cfg *rest.Config, groupName string) bool { return false } -func isGKE(ctx context.Context, cfg *rest.Config) bool { - if hasAPIGroup(ctx, cfg, "networking.gke.io") { - logging.FromContext(ctx).Info("detected GKE environment") - return true - } - return false +type platformProbe struct { + name string + label string + apiGroups []string + hosts []string + custom func(ctx context.Context, cfg *rest.Config) bool } -func isEKS(ctx context.Context, cfg *rest.Config) bool { - // crd.k8s.amazonaws.com (VPC CNI) and metrics.eks.amazonaws.com (control plane metrics) - // are independent EKS signals; either is sufficient. - if hasAPIGroup(ctx, cfg, "crd.k8s.amazonaws.com") || hasAPIGroup(ctx, cfg, "metrics.eks.amazonaws.com") { - logging.FromContext(ctx).Info("detected EKS environment") - return true +func (p platformProbe) detect(ctx context.Context, cfg *rest.Config) bool { + if p.custom != nil { + return p.custom(ctx, cfg) + } + for _, g := range p.apiGroups { + if hasAPIGroup(ctx, cfg, g) { + return true + } + } + for _, h := range p.hosts { + if strings.Contains(cfg.Host, h) { + return true + } } return false } -func isAKS(ctx context.Context, cfg *rest.Config) bool { - // AKS exposes no unique API groups, so we inspect the API server TLS certificate: - // its SAN always contains a hostname ending in .azmk8s.io regardless of network plugin. +var platformProbes = []platformProbe{ + {name: "gke", label: "GKE", apiGroups: []string{"networking.gke.io"}}, + // crd.k8s.amazonaws.com (VPC CNI) and metrics.eks.amazonaws.com are independent EKS signals. + {name: "eks", label: "EKS", apiGroups: []string{"crd.k8s.amazonaws.com", "metrics.eks.amazonaws.com"}}, + // AKS exposes no unique API groups; inspect the API server TLS cert SAN instead. + {name: "aks", label: "AKS", custom: detectAKS}, + {name: "doks", label: "DOKS", apiGroups: []string{"dataplane-operator.doks.digitalocean.com"}}, + {name: "oke", label: "OKE", hosts: []string{".oraclecloud.com"}}, + {name: "ack", label: "ACK", apiGroups: []string{"alibabacloud.com"}, hosts: []string{".aliyuncs.com"}}, + // kommander.mesosphere.io is the legacy D2iQ/Konvoy group name for NKP. + {name: "nkp", label: "NKP", apiGroups: []string{"nkp.nutanix.com", "kommander.mesosphere.io"}}, + {name: "platform9", label: "Platform9", hosts: []string{".platform9.io", ".platform9.net"}}, + {name: "tanzu", label: "Tanzu", apiGroups: []string{"run.tanzu.vmware.com"}}, + {name: "rancher", label: "Rancher", apiGroups: []string{"management.cattle.io"}}, +} + +func detectAKS(ctx context.Context, cfg *rest.Config) bool { tlsCfg, err := rest.TLSConfigFor(cfg) if err != nil { logging.FromContext(ctx).V(1).Info("platform detection: could not build TLS config", "error", err.Error()) @@ -420,7 +441,6 @@ func isAKS(ctx context.Context, cfg *rest.Config) bool { for _, cert := range conn.ConnectionState().PeerCertificates { for _, san := range cert.DNSNames { if strings.HasSuffix(san, ".azmk8s.io") { - logging.FromContext(ctx).Info("detected AKS environment") return true } } @@ -428,90 +448,17 @@ func isAKS(ctx context.Context, cfg *rest.Config) bool { return false } -func isDOKS(ctx context.Context, cfg *rest.Config) bool { - if hasAPIGroup(ctx, cfg, "dataplane-operator.doks.digitalocean.com") { - logging.FromContext(ctx).Info("detected DOKS environment") - return true - } - return false -} - -func isOKE(ctx context.Context, cfg *rest.Config) bool { - if strings.Contains(cfg.Host, ".oraclecloud.com") { - logging.FromContext(ctx).Info("detected OKE environment") - return true - } - return false -} - -func isACK(ctx context.Context, cfg *rest.Config) bool { - if strings.Contains(cfg.Host, ".aliyuncs.com") || hasAPIGroup(ctx, cfg, "alibabacloud.com") { - logging.FromContext(ctx).Info("detected ACK environment") - return true - } - return false -} - -func isNKP(ctx context.Context, cfg *rest.Config) bool { - // kommander.mesosphere.io is the legacy D2iQ/Konvoy group name. - if hasAPIGroup(ctx, cfg, "nkp.nutanix.com") || hasAPIGroup(ctx, cfg, "kommander.mesosphere.io") { - logging.FromContext(ctx).Info("detected NKP environment") - return true - } - return false -} - -func isPlatform9(ctx context.Context, cfg *rest.Config) bool { - if strings.Contains(cfg.Host, ".platform9.io") || strings.Contains(cfg.Host, ".platform9.net") { - logging.FromContext(ctx).Info("detected Platform9 environment") - return true - } - return false -} - -func isTanzu(ctx context.Context, cfg *rest.Config) bool { - if hasAPIGroup(ctx, cfg, "run.tanzu.vmware.com") { - logging.FromContext(ctx).Info("detected Tanzu environment") - return true - } - return false -} - -func isRancher(ctx context.Context, cfg *rest.Config) bool { - if hasAPIGroup(ctx, cfg, "management.cattle.io") { - logging.FromContext(ctx).Info("detected Rancher environment") - return true - } - return false -} - func detectPlatform(ctx context.Context, cfg *rest.Config, openShift bool) string { - switch { - case openShift: + if openShift { return "openshift" - case isGKE(ctx, cfg): - return "gke" - case isEKS(ctx, cfg): - return "eks" - case isAKS(ctx, cfg): - return "aks" - case isDOKS(ctx, cfg): - return "doks" - case isOKE(ctx, cfg): - return "oke" - case isACK(ctx, cfg): - return "ack" - case isNKP(ctx, cfg): - return "nkp" - case isPlatform9(ctx, cfg): - return "platform9" - case isTanzu(ctx, cfg): - return "tanzu" - case isRancher(ctx, cfg): - return "rancher" - default: - return "unknown" } + for _, probe := range platformProbes { + if probe.detect(ctx, cfg) { + logging.FromContext(ctx).Info("detected "+probe.label+" environment") + return probe.name + } + } + return "unknown" } // getServerVersion returns the stringified server version (i.e., the same info `kubectl version` From 813ad19ede6d08df467b8b5d2601a135b8bdc1ba Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Wed, 8 Jul 2026 13:40:26 +0300 Subject: [PATCH 5/8] fix OKE --- cmd/postgres-operator/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 77abf14e2..dcbe6aa6c 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -415,7 +415,7 @@ var platformProbes = []platformProbe{ // AKS exposes no unique API groups; inspect the API server TLS cert SAN instead. {name: "aks", label: "AKS", custom: detectAKS}, {name: "doks", label: "DOKS", apiGroups: []string{"dataplane-operator.doks.digitalocean.com"}}, - {name: "oke", label: "OKE", hosts: []string{".oraclecloud.com"}}, + {name: "oke", label: "OKE", apiGroups: []string{"oci.oraclecloud.com"}, hosts: []string{".oraclecloud.com"}}, {name: "ack", label: "ACK", apiGroups: []string{"alibabacloud.com"}, hosts: []string{".aliyuncs.com"}}, // kommander.mesosphere.io is the legacy D2iQ/Konvoy group name for NKP. {name: "nkp", label: "NKP", apiGroups: []string{"nkp.nutanix.com", "kommander.mesosphere.io"}}, From 610fbfe47f4a86551956d08315ea309baac3bb4c Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Wed, 8 Jul 2026 23:20:36 +0300 Subject: [PATCH 6/8] fix cpmment --- cmd/postgres-operator/main.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index dcbe6aa6c..a2058f8a5 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -432,12 +432,13 @@ func detectAKS(ctx context.Context, cfg *rest.Config) bool { } host := strings.TrimPrefix(cfg.Host, "https://") host = strings.TrimPrefix(host, "http://") - conn, err := tls.Dial("tcp", host, tlsCfg) + netConn, err := (&tls.Dialer{Config: tlsCfg}).DialContext(ctx, "tcp", host) if err != nil { logging.FromContext(ctx).V(1).Info("platform detection: could not dial API server", "error", err.Error()) return false } - defer conn.Close() + defer netConn.Close() + conn := netConn.(*tls.Conn) for _, cert := range conn.ConnectionState().PeerCertificates { for _, san := range cert.DNSNames { if strings.HasSuffix(san, ".azmk8s.io") { @@ -454,7 +455,7 @@ func detectPlatform(ctx context.Context, cfg *rest.Config, openShift bool) strin } for _, probe := range platformProbes { if probe.detect(ctx, cfg) { - logging.FromContext(ctx).Info("detected "+probe.label+" environment") + logging.FromContext(ctx).Info("detected " + probe.label + " environment") return probe.name } } From 63eb16d482e78fccace7ecddf80a0487fb2ae107 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Sat, 18 Jul 2026 13:57:51 +0300 Subject: [PATCH 7/8] fix comment --- cmd/postgres-operator/main.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index a2058f8a5..f2ce7e6e5 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -146,7 +146,7 @@ func main() { log.Info("upgrade checking enabled") // get the URL for the check for upgrades endpoint if set in the env assertNoError(upgradecheck.ManagedScheduler(mgr, - isOpenshift(ctx, mgr.GetConfig()), os.Getenv("CHECK_FOR_UPGRADES_URL"), versionString, nil)) + false, os.Getenv("CHECK_FOR_UPGRADES_URL"), versionString, nil)) } assertNoError(mgr.Start(ctx)) @@ -158,7 +158,8 @@ func main() { func addControllersToManager(ctx context.Context, mgr manager.Manager) error { os.Setenv("REGISTRATION_REQUIRED", "false") - openShift := isOpenshift(ctx, mgr.GetConfig()) + platform := detectPlatform(ctx, mgr.GetConfig()) + openShift := platform == "openshift" r := &postgrescluster.Reconciler{ Client: mgr.GetClient(), @@ -196,7 +197,7 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { Owner: pgcluster.PGClusterControllerName, Recorder: mgr.GetEventRecorderFor(pgcluster.PGClusterControllerName), Tracer: otel.Tracer(pgcluster.PGClusterControllerName), - Platform: detectPlatform(ctx, mgr.GetConfig(), openShift), + Platform: platform, KubeVersion: getServerVersion(ctx, mgr.GetConfig()), CrunchyController: cm.Controller(), IsOpenShift: openShift, @@ -409,6 +410,7 @@ func (p platformProbe) detect(ctx context.Context, cfg *rest.Config) bool { } var platformProbes = []platformProbe{ + {name: "openshift", label: "Openshift", apiGroups: []string{"security.openshift.io"}}, {name: "gke", label: "GKE", apiGroups: []string{"networking.gke.io"}}, // crd.k8s.amazonaws.com (VPC CNI) and metrics.eks.amazonaws.com are independent EKS signals. {name: "eks", label: "EKS", apiGroups: []string{"crd.k8s.amazonaws.com", "metrics.eks.amazonaws.com"}}, @@ -449,10 +451,7 @@ func detectAKS(ctx context.Context, cfg *rest.Config) bool { return false } -func detectPlatform(ctx context.Context, cfg *rest.Config, openShift bool) string { - if openShift { - return "openshift" - } +func detectPlatform(ctx context.Context, cfg *rest.Config) string { for _, probe := range platformProbes { if probe.detect(ctx, cfg) { logging.FromContext(ctx).Info("detected " + probe.label + " environment") @@ -520,13 +519,6 @@ func getLogLevel() zapcore.LevelEnabler { } } -func isOpenshift(ctx context.Context, cfg *rest.Config) bool { - if hasAPIGroup(ctx, cfg, "security.openshift.io") { - logging.FromContext(ctx).Info("detected Openshift environment") - return true - } - return false -} type envConfig struct { LeaderElection bool `default:"true" envconfig:"PGO_CONTROLLER_LEADER_ELECTION_ENABLED"` From 3accde1df7d10c15c9b12a936b9188b24f2288c3 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Wed, 22 Jul 2026 13:19:03 +0300 Subject: [PATCH 8/8] move API group discovery into k8s.GroupExists helper --- cmd/postgres-operator/main.go | 16 ++++++---------- percona/k8s/util.go | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index e7605f371..bf7ce2dfe 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -371,25 +371,19 @@ func initManager(ctx context.Context) (runtime.Options, error) { } // hasAPIGroup returns true if the cluster exposes the given API group name. -// Uses the discovery API; note that hardened clusters may restrict discovery access. func hasAPIGroup(ctx context.Context, cfg *rest.Config, groupName string) bool { log := logging.FromContext(ctx) - client, err := discovery.NewDiscoveryClientForConfig(cfg) + dc, err := discovery.NewDiscoveryClientForConfig(cfg) if err != nil { log.V(1).Info("platform detection: could not create discovery client", "error", err.Error()) return false } - groups, err := client.ServerGroups() + ok, err := k8s.GroupExists(dc, groupName) if err != nil { log.V(1).Info("platform detection: could not list API groups", "error", err.Error()) return false } - for _, g := range groups.Groups { - if g.Name == groupName { - return true - } - } - return false + return ok } type platformProbe struct { @@ -442,7 +436,9 @@ func detectAKS(ctx context.Context, cfg *rest.Config) bool { } host := strings.TrimPrefix(cfg.Host, "https://") host = strings.TrimPrefix(host, "http://") - netConn, err := (&tls.Dialer{Config: tlsCfg}).DialContext(ctx, "tcp", host) + dialCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + netConn, err := (&tls.Dialer{Config: tlsCfg}).DialContext(dialCtx, "tcp", host) if err != nil { logging.FromContext(ctx).V(1).Info("platform detection: could not dial API server", "error", err.Error()) return false diff --git a/percona/k8s/util.go b/percona/k8s/util.go index 89e554762..8c6d0d2ff 100644 --- a/percona/k8s/util.go +++ b/percona/k8s/util.go @@ -214,3 +214,26 @@ func GroupVersionKindExists(dc *discovery.DiscoveryClient, groupVersion, kind st return false, nil } + +// GroupExists checks whether a given API group exists in the Kubernetes API Server. +func GroupExists(dc *discovery.DiscoveryClient, group string) (bool, error) { + if dc == nil { + return false, errors.New("discovery client is nil") + } + if group == "" { + return false, errors.New("group must not be empty") + } + + groups, err := dc.ServerGroups() + if err != nil { + return false, errors.Wrap(err, "get server groups") + } + + for _, g := range groups.Groups { + if g.Name == group { + return true, nil + } + } + + return false, nil +}