From 652b4f2fab422288314bb7595d114ff38415ae19 Mon Sep 17 00:00:00 2001 From: Andres Torres Date: Thu, 11 Dec 2025 15:12:25 -0500 Subject: [PATCH] fix(setting): Add default scheme to handle k8s api errors (#115177) --- pkg/services/setting/service.go | 6 ++- pkg/services/setting/service_test.go | 76 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/pkg/services/setting/service.go b/pkg/services/setting/service.go index 6b49abcb24f..0a249ef65ac 100644 --- a/pkg/services/setting/service.go +++ b/pkg/services/setting/service.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/otel/trace" "gopkg.in/ini.v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apiserver/pkg/endpoints/request" @@ -397,6 +398,9 @@ func getRestClient(config Config, log logging.Logger) (*rest.RESTClient, error) burst = config.Burst } + // Add a default scheme to handle K8s API error responses + scheme := runtime.NewScheme() + restConfig := &rest.Config{ Host: config.URL, TLSClientConfig: config.TLSClientConfig, @@ -407,7 +411,7 @@ func getRestClient(config Config, log logging.Logger) (*rest.RESTClient, error) APIPath: "/apis", ContentConfig: rest.ContentConfig{ GroupVersion: &settingGroupVersion, - NegotiatedSerializer: serializer.NewCodecFactory(nil).WithoutConversion(), + NegotiatedSerializer: serializer.NewCodecFactory(scheme).WithoutConversion(), }, } diff --git a/pkg/services/setting/service_test.go b/pkg/services/setting/service_test.go index 5d9a2565551..9b007fb1dc9 100644 --- a/pkg/services/setting/service_test.go +++ b/pkg/services/setting/service_test.go @@ -148,6 +148,82 @@ func TestRemoteSettingService_List(t *testing.T) { require.Error(t, err) assert.Nil(t, result) }) + + t.Run("should handle API errors", func(t *testing.T) { + statusResponse := `{ + "apiVersion": "v1", + "kind": "Status", + "metadata": {}, + "status": "Failure", + "message": "settings.setting.grafana.app \"test\" not found", + "reason": "NotFound", + "details": { + "name": "test", + "group": "setting.grafana.app", + "kind": "settings" + }, + "code": 404 + }` + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(statusResponse)) + })) + defer server.Close() + + client := newTestClient(t, server.URL, 500) + ctx := request.WithNamespace(context.Background(), "test-namespace") + + result, err := client.List(ctx, metav1.LabelSelector{}) + + require.Error(t, err) + assert.Nil(t, result) + assert.Contains(t, err.Error(), "could not find the requested resource") + }) + + t.Run("should handle 500 internal server error", func(t *testing.T) { + statusResponse := `{ + "apiVersion": "v1", + "kind": "Status", + "metadata": {}, + "status": "Failure", + "message": "Internal error occurred: database connection failed", + "reason": "InternalError", + "code": 500 + }` + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(statusResponse)) + })) + defer server.Close() + + client := newTestClient(t, server.URL, 500) + ctx := request.WithNamespace(context.Background(), "test-namespace") + + result, err := client.List(ctx, metav1.LabelSelector{}) + + require.Error(t, err) + assert.Nil(t, result) + assert.Contains(t, err.Error(), "error on the server") + }) + + t.Run("should handle connection errors", func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + serverURL := server.URL + server.Close() + + client := newTestClient(t, serverURL, 500) + ctx := request.WithNamespace(context.Background(), "test-namespace") + + result, err := client.List(ctx, metav1.LabelSelector{}) + + require.Error(t, err) + assert.Nil(t, result) + assert.Contains(t, err.Error(), "connection refused") + }) } func TestParseSettingList(t *testing.T) {