From 2fc1210b38e94574790fae1a9ac94abd186a710a Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Thu, 11 Dec 2025 09:36:09 +0300 Subject: [PATCH] Stars: Enable the collections apiserver (#115076) --- .../pkg/apis/collections/v1alpha1/stars.go | 16 +++++++++++----- .../pkg/apis/collections/v1alpha1/stars_test.go | 2 +- pkg/registry/apis/collections/legacy/stars.go | 5 ++++- pkg/registry/apis/collections/register.go | 6 ------ pkg/tests/apis/collections/stars_test.go | 9 +++++++-- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/apps/collections/pkg/apis/collections/v1alpha1/stars.go b/apps/collections/pkg/apis/collections/v1alpha1/stars.go index e203e6b560e..79bff8a6513 100644 --- a/apps/collections/pkg/apis/collections/v1alpha1/stars.go +++ b/apps/collections/pkg/apis/collections/v1alpha1/stars.go @@ -8,9 +8,8 @@ import ( func (stars *StarsSpec) Add(group, kind, name string) { for i, r := range stars.Resource { if r.Group == group && r.Kind == kind { - r.Names = append(r.Names, name) - slices.Sort(r.Names) - stars.Resource[i].Names = slices.Compact(r.Names) + stars.Resource[i].Names = append(r.Names, name) + stars.Normalize() return } } @@ -46,8 +45,15 @@ func (stars *StarsSpec) Normalize() { resources := make([]StarsResource, 0, len(stars.Resource)) for _, r := range stars.Resource { if len(r.Names) > 0 { - slices.Sort(r.Names) - r.Names = slices.Compact(r.Names) // removes any duplicates + unique := make([]string, 0, len(r.Names)) + found := make(map[string]bool, len(r.Names)) + for _, name := range r.Names { + if !found[name] { + unique = append(unique, name) + found[name] = true + } + } + r.Names = unique resources = append(resources, r) } } diff --git a/apps/collections/pkg/apis/collections/v1alpha1/stars_test.go b/apps/collections/pkg/apis/collections/v1alpha1/stars_test.go index 5713b07a751..d4421fae614 100644 --- a/apps/collections/pkg/apis/collections/v1alpha1/stars_test.go +++ b/apps/collections/pkg/apis/collections/v1alpha1/stars_test.go @@ -39,7 +39,7 @@ func TestStarsWrite(t *testing.T) { Resource: []StarsResource{{ Group: "g", Kind: "k", - Names: []string{"a", "b", "c", "x"}, // added "b" (and sorted) + Names: []string{"a", "b", "x", "c"}, // added c to the end }}, }, }, { diff --git a/pkg/registry/apis/collections/legacy/stars.go b/pkg/registry/apis/collections/legacy/stars.go index 8c7d9e711ea..39f7a9c088f 100644 --- a/pkg/registry/apis/collections/legacy/stars.go +++ b/pkg/registry/apis/collections/legacy/stars.go @@ -204,11 +204,14 @@ func (s *DashboardStarsStorage) write(ctx context.Context, obj *collections.Star previous[v] = true } } - for _, dashboard := range stars { + for idx, dashboard := range stars { if previous[dashboard] { delete(previous, dashboard) continue // nothing needed } + if idx > 0 { + time.Sleep(75 * time.Millisecond) // values are ordered by update time; this keeps the order predictable + } err = s.stars.Add(ctx, &star.StarDashboardCommand{ UserID: user.ID, OrgID: user.OrgID, diff --git a/pkg/registry/apis/collections/register.go b/pkg/registry/apis/collections/register.go index 9be4412c377..699d3bbe672 100644 --- a/pkg/registry/apis/collections/register.go +++ b/pkg/registry/apis/collections/register.go @@ -46,12 +46,6 @@ func RegisterAPIService( users user.Service, apiregistration builder.APIRegistrar, ) *APIBuilder { - // Requires development settings and clearly experimental - //nolint:staticcheck // not yet migrated to OpenFeature - if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { - return nil - } - sql := legacy.NewLegacySQL(legacysql.NewDatabaseProvider(db)) builder := &APIBuilder{ authorizer: &utils.AuthorizeFromName{ diff --git a/pkg/tests/apis/collections/stars_test.go b/pkg/tests/apis/collections/stars_test.go index fe841fb4851..573da05a00b 100644 --- a/pkg/tests/apis/collections/stars_test.go +++ b/pkg/tests/apis/collections/stars_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net/http" + "slices" "testing" "github.com/stretchr/testify/require" @@ -160,7 +161,7 @@ func TestIntegrationStars(t *testing.T) { { "group": "dashboard.grafana.app", "kind": "Dashboard", - "names": []string{"test-2", "aaa", "bbb"}, + "names": []string{"test-2", "aaa", "aaa", "bbb"}, }, }, }, @@ -174,13 +175,17 @@ func TestIntegrationStars(t *testing.T) { require.Equal(t, "dashboard.grafana.app", resources[0].Group) require.Equal(t, "Dashboard", resources[0].Kind) require.ElementsMatch(t, - []string{"aaa", "bbb", "test-2"}, // NOTE 2 stays, 3 removed, added aaa+bbb (and sorted!) + []string{"test-2", "aaa", "bbb"}, // keeps the requested order, removing duplicates resources[0].Names) rspObj, err = starsClient.Resource.Get(ctx, "user-"+starsClient.Args.User.Identity.GetIdentifier(), metav1.GetOptions{}) require.NoError(t, err) after = typed(t, rspObj, &collections.Stars{}) + + // FIXME: when we remove legacy support this should not sort! + slices.Sort(after.Spec.Resource[0].Names) + jj, err := json.MarshalIndent(after.Spec, "", " ") require.NoError(t, err) require.JSONEq(t, `{