From f1826c6f3fe22a15b8a63db5b38d7ed661368f1d Mon Sep 17 00:00:00 2001 From: Shirly Radco Date: Wed, 24 Jun 2026 11:52:14 +0300 Subject: [PATCH] fix: prefer KUBECONFIG over in-cluster config for k8s client The server previously used rest.InClusterConfig() exclusively, which fails in CI where the test step pod runs on the build cluster while KUBECONFIG points to the provisioned test cluster. This caused the e2e-management-api tests to get 404 errors because the management routes could not be registered without a working k8s connection. Introduce loadKubeConfig() that prefers KUBECONFIG when set (for CI and local development) and falls back to in-cluster config (for production deployments). Signed-off-by: Shirly Radco Co-authored-by: Cursor --- pkg/server.go | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/pkg/server.go b/pkg/server.go index 323c83656..4af77a24c 100644 --- a/pkg/server.go +++ b/pkg/server.go @@ -19,6 +19,7 @@ import ( "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/record" "github.com/openshift/monitoring-plugin/internal/managementrouter" @@ -127,18 +128,11 @@ func createHTTPServer(ctx context.Context, cfg *Config) (*http.Server, error) { var k8sconfig *rest.Config var err error - // Uncomment the following line for local development: - // k8sconfig, err = clientcmd.BuildConfigFromFlags("", os.Getenv("KUBECONFIG")) - // if err != nil { - // return nil, fmt.Errorf("cannot get kubeconfig from file: %w", err) - // } - - // Comment the following line for local development: var k8sclient *dynamic.DynamicClient if acmMode || alertManagementAPIMode { - k8sconfig, err = rest.InClusterConfig() + k8sconfig, err = loadKubeConfig() if err != nil { - return nil, fmt.Errorf("cannot get in cluster config: %w", err) + return nil, fmt.Errorf("cannot load kubernetes config: %w", err) } k8sclient, err = dynamic.NewForConfig(k8sconfig) @@ -402,6 +396,23 @@ func configHandler(cfg *Config) (http.HandlerFunc, *PluginConfig) { }), &pluginConfig } +// loadKubeConfig returns a *rest.Config by preferring KUBECONFIG (useful for +// local development and CI) and falling back to in-cluster service-account config. +func loadKubeConfig() (*rest.Config, error) { + if kubeconfig := os.Getenv("KUBECONFIG"); kubeconfig != "" { + cfg, err := clientcmd.BuildConfigFromFlags("", kubeconfig) + if err != nil { + return nil, fmt.Errorf("cannot build config from KUBECONFIG: %w", err) + } + return cfg, nil + } + cfg, err := rest.InClusterConfig() + if err != nil { + return nil, fmt.Errorf("cannot get in-cluster config: %w", err) + } + return cfg, nil +} + func startProxy(cfg *Config, k8sclient *dynamic.DynamicClient, tlsConfig *tls.Config, timeout time.Duration, kind proxy.KindType, port proxy.ProxyPort) { proxyRouter := setupProxyRoutes(cfg, k8sclient, kind) proxyRouter.Use(corsHeaderMiddleware())