diff --git a/go/core/internal/httpserver/handlers/substrate.go b/go/core/internal/httpserver/handlers/substrate.go index 3bdc1ff6c..53f57ab3a 100644 --- a/go/core/internal/httpserver/handlers/substrate.go +++ b/go/core/internal/httpserver/handlers/substrate.go @@ -13,6 +13,7 @@ import ( "github.com/kagent-dev/kagent/go/core/internal/httpserver/errors" "github.com/kagent-dev/kagent/go/core/pkg/auth" "github.com/kagent-dev/kagent/go/core/pkg/sandboxbackend/substrate" + "k8s.io/apimachinery/pkg/api/meta" utilvalidation "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/controller-runtime/pkg/client" ctrllog "sigs.k8s.io/controller-runtime/pkg/log" @@ -110,11 +111,19 @@ func (h *SubstrateHandler) listSubstrateCRs(ctx context.Context, namespace strin wpList := &atev1alpha1.WorkerPoolList{} if err := h.KubeClient.List(ctx, wpList, listOpts...); err != nil { - return nil, nil, err + if meta.IsNoMatchError(err) { + ctrllog.FromContext(ctx).V(1).Info("WorkerPool CRD not found, returning empty list", "namespace", namespace) + } else { + return nil, nil, err + } } tmplList := &atev1alpha1.ActorTemplateList{} if err := h.KubeClient.List(ctx, tmplList, listOpts...); err != nil { - return nil, nil, err + if meta.IsNoMatchError(err) { + ctrllog.FromContext(ctx).V(1).Info("ActorTemplate CRD not found, returning empty list", "namespace", namespace) + } else { + return nil, nil, err + } } workerPools := make([]api.SubstrateWorkerPoolEntry, 0, len(wpList.Items)) diff --git a/go/core/internal/httpserver/handlers/substrate_test.go b/go/core/internal/httpserver/handlers/substrate_test.go index 279ac6401..27b4ab4e5 100644 --- a/go/core/internal/httpserver/handlers/substrate_test.go +++ b/go/core/internal/httpserver/handlers/substrate_test.go @@ -139,3 +139,26 @@ func TestHandleGetSubstrateStatus(t *testing.T) { require.Equal(t, "Running", wrapped.Data.Actors[0].Status) require.Len(t, wrapped.Data.Workers, 1) } + +func TestHandleGetSubstrateStatus_MissingCRDs(t *testing.T) { + t.Parallel() + + // Use a client that returns NoKindMatchError for all List calls, + // simulating a cluster where the ate.dev CRDs are not installed. + base := &handlers.Base{KubeClient: noMatchKubeClient{}, Authorizer: &auth.NoopAuthorizer{}} + ate := &substrate.Client{ControlClient: &stubAteControl{}} + h := handlers.NewSubstrateHandler(base, ate) + + req := httptest.NewRequest(http.MethodGet, "/api/substrate/status?namespace=kagent", nil) + req = setUser(req, "test-user") + rec := httptest.NewRecorder() + h.HandleGetSubstrateStatus(&testErrorResponseWriter{ResponseWriter: rec}, req) + + require.Equal(t, http.StatusOK, rec.Code) + + var wrapped api.StandardResponse[api.SubstrateStatusResponse] + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &wrapped)) + require.True(t, wrapped.Data.Enabled) + require.Empty(t, wrapped.Data.WorkerPools) + require.Empty(t, wrapped.Data.ActorTemplates) +}