diff --git a/pkg/project/apiserver/registry/project/proxy/proxy.go b/pkg/project/apiserver/registry/project/proxy/proxy.go index 76c239d6e5..8b9c669de9 100644 --- a/pkg/project/apiserver/registry/project/proxy/proxy.go +++ b/pkg/project/apiserver/registry/project/proxy/proxy.go @@ -109,6 +109,15 @@ func (s *REST) Watch(ctx context.Context, options *metainternal.ListOptions) (wa if ctx == nil { return nil, fmt.Errorf("Context is nil") } + + // Reject WatchList (sendInitialEvents) requests. The Project resource is a + // virtual/proxy type backed by filtered Namespaces and cannot properly serve + // the WatchList protocol. Returning an error here causes client-go's + // reflector to fall back to the standard LIST+WATCH semantics. + if options != nil && options.SendInitialEvents != nil && *options.SendInitialEvents { + return nil, kerrors.NewMethodNotSupported(project.Resource("project"), "watch-list") + } + userInfo, exists := apirequest.UserFrom(ctx) if !exists { return nil, fmt.Errorf("no user") diff --git a/pkg/project/apiserver/registry/project/proxy/proxy_test.go b/pkg/project/apiserver/registry/project/proxy/proxy_test.go index 9197f6330e..b1a3e2cdb2 100644 --- a/pkg/project/apiserver/registry/project/proxy/proxy_test.go +++ b/pkg/project/apiserver/registry/project/proxy/proxy_test.go @@ -24,6 +24,7 @@ import ( "github.com/openshift/api/project" oapi "github.com/openshift/openshift-apiserver/pkg/api" projectapi "github.com/openshift/openshift-apiserver/pkg/project/apis/project" + metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion" ) // mockLister returns the namespaces in the list @@ -68,6 +69,24 @@ func TestListProjects(t *testing.T) { } } +func TestWatchRejectsSendInitialEvents(t *testing.T) { + storage := &REST{} + userInfo := &user.DefaultInfo{ + Name: "test-user", + } + ctx := apirequest.WithUser(apirequest.NewContext(), userInfo) + + _, err := storage.Watch(ctx, &metainternal.ListOptions{ + SendInitialEvents: ptr.To(true), + }) + if err == nil { + t.Fatal("expected an error but got nil") + } + if !kerrors.IsMethodNotSupported(err) { + t.Errorf("expected MethodNotSupported error, got: %v", err) + } +} + func TestCreateProjectBadObject(t *testing.T) { storage := REST{}