diff --git a/pkg/apis/playlist/v0alpha1/conversions.go b/pkg/apis/playlist/v0alpha1/conversions.go index 0994cd55ea6..b512f207294 100644 --- a/pkg/apis/playlist/v0alpha1/conversions.go +++ b/pkg/apis/playlist/v0alpha1/conversions.go @@ -7,27 +7,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" "github.com/grafana/grafana/pkg/services/playlist" - "github.com/grafana/grafana/pkg/setting" ) -type namespaceMapper = func(orgId int64) string - -func orgNamespaceMapper(orgId int64) string { - if orgId == 1 { - return "default" - } - return fmt.Sprintf("org-%d", orgId) -} - -func getNamespaceMapper(cfg *setting.Cfg) namespaceMapper { - if cfg.StackID != "" { - return func(orgId int64) string { return "stack-" + cfg.StackID } - } - return orgNamespaceMapper -} - -func convertToK8sResource(v *playlist.PlaylistDTO, namespacer namespaceMapper) *Playlist { +func convertToK8sResource(v *playlist.PlaylistDTO, namespacer request.NamespaceMapper) *Playlist { spec := Spec{ Title: v.Name, Interval: v.Interval, diff --git a/pkg/apis/playlist/v0alpha1/conversions_test.go b/pkg/apis/playlist/v0alpha1/conversions_test.go index 17c458b6cad..ce13fdd2ea0 100644 --- a/pkg/apis/playlist/v0alpha1/conversions_test.go +++ b/pkg/apis/playlist/v0alpha1/conversions_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" "github.com/grafana/grafana/pkg/services/playlist" - "github.com/grafana/grafana/pkg/setting" ) func TestPlaylistConversion(t *testing.T) { @@ -24,7 +24,7 @@ func TestPlaylistConversion(t *testing.T) { {Type: "dashboard_by_id", Value: "123"}, // deprecated }, } - dst := convertToK8sResource(src, orgNamespaceMapper) + dst := convertToK8sResource(src, request.GetNamespaceMapper(nil)) require.Equal(t, "abc", src.Uid) require.Equal(t, "abc", dst.Name) @@ -61,36 +61,3 @@ func TestPlaylistConversion(t *testing.T) { } }`, string(out)) } - -func TestNamespaceMapper(t *testing.T) { - tests := []struct { - name string - cfg string - orgId int64 - expected string - }{ - { - name: "default namespace", - orgId: 1, - expected: "default", - }, - { - name: "with org", - orgId: 123, - expected: "org-123", - }, - { - name: "with stackId", - cfg: "abc", - orgId: 123, // ignored - expected: "stack-abc", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - mapper := getNamespaceMapper(&setting.Cfg{StackID: tt.cfg}) - require.Equal(t, tt.expected, mapper(tt.orgId)) - }) - } -} diff --git a/pkg/apis/playlist/v0alpha1/legacy_storage.go b/pkg/apis/playlist/v0alpha1/legacy_storage.go index 6537b1535ff..460d87fb128 100644 --- a/pkg/apis/playlist/v0alpha1/legacy_storage.go +++ b/pkg/apis/playlist/v0alpha1/legacy_storage.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/rest" - grafanarequest "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" + "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" "github.com/grafana/grafana/pkg/services/playlist" ) @@ -23,7 +23,7 @@ var ( type legacyStorage struct { service playlist.Service - namespacer namespaceMapper + namespacer request.NamespaceMapper tableConverter rest.TableConvertor } @@ -52,7 +52,7 @@ func (s *legacyStorage) ConvertToTable(ctx context.Context, object runtime.Objec func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) { // TODO: handle fetching all available orgs when no namespace is specified // To test: kubectl get playlists --all-namespaces - info, err := grafanarequest.NamespaceInfoFrom(ctx, true) + info, err := request.NamespaceInfoFrom(ctx, true) if err != nil { return nil, err } @@ -87,7 +87,7 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO } func (s *legacyStorage) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { - info, err := grafanarequest.NamespaceInfoFrom(ctx, true) + info, err := request.NamespaceInfoFrom(ctx, true) if err != nil { return nil, err } diff --git a/pkg/apis/playlist/v0alpha1/register.go b/pkg/apis/playlist/v0alpha1/register.go index 758027f8772..67d9d994d2e 100644 --- a/pkg/apis/playlist/v0alpha1/register.go +++ b/pkg/apis/playlist/v0alpha1/register.go @@ -14,6 +14,7 @@ import ( common "k8s.io/kube-openapi/pkg/common" grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver" + "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" grafanarest "github.com/grafana/grafana/pkg/services/grafana-apiserver/rest" "github.com/grafana/grafana/pkg/services/grafana-apiserver/utils" "github.com/grafana/grafana/pkg/services/playlist" @@ -29,7 +30,7 @@ var _ grafanaapiserver.APIGroupBuilder = (*PlaylistAPIBuilder)(nil) // This is used just so wire has something unique to return type PlaylistAPIBuilder struct { service playlist.Service - namespacer namespaceMapper + namespacer request.NamespaceMapper gv schema.GroupVersion } @@ -39,7 +40,7 @@ func RegisterAPIService(p playlist.Service, ) *PlaylistAPIBuilder { builder := &PlaylistAPIBuilder{ service: p, - namespacer: getNamespaceMapper(cfg), + namespacer: request.GetNamespaceMapper(cfg), gv: schema.GroupVersion{Group: GroupName, Version: VersionID}, } apiregistration.RegisterAPI(builder) diff --git a/pkg/services/grafana-apiserver/endpoints/request/request.go b/pkg/services/grafana-apiserver/endpoints/request/namespace.go similarity index 70% rename from pkg/services/grafana-apiserver/endpoints/request/request.go rename to pkg/services/grafana-apiserver/endpoints/request/namespace.go index 1c12b0f7893..4848c24386c 100644 --- a/pkg/services/grafana-apiserver/endpoints/request/request.go +++ b/pkg/services/grafana-apiserver/endpoints/request/namespace.go @@ -7,6 +7,8 @@ import ( "strings" "k8s.io/apiserver/pkg/endpoints/request" + + "github.com/grafana/grafana/pkg/setting" ) type NamespaceInfo struct { @@ -20,6 +22,22 @@ type NamespaceInfo struct { Value string } +// NamespaceMapper converts an orgID into a namespace +type NamespaceMapper = func(orgId int64) string + +// GetNamespaceMapper returns a function that will convert orgIds into a consistent namespace +func GetNamespaceMapper(cfg *setting.Cfg) NamespaceMapper { + if cfg != nil && cfg.StackID != "" { + return func(orgId int64) string { return "stack-" + cfg.StackID } + } + return func(orgId int64) string { + if orgId == 1 { + return "default" + } + return fmt.Sprintf("org-%d", orgId) + } +} + func NamespaceInfoFrom(ctx context.Context, requireOrgID bool) (NamespaceInfo, error) { info, err := ParseNamespace(request.NamespaceValue(ctx)) if err == nil && requireOrgID && info.OrgID < 1 { diff --git a/pkg/services/grafana-apiserver/endpoints/request/request_test.go b/pkg/services/grafana-apiserver/endpoints/request/namespace_test.go similarity index 61% rename from pkg/services/grafana-apiserver/endpoints/request/request_test.go rename to pkg/services/grafana-apiserver/endpoints/request/namespace_test.go index d38f9bd6b5f..4f9dc7e9281 100644 --- a/pkg/services/grafana-apiserver/endpoints/request/request_test.go +++ b/pkg/services/grafana-apiserver/endpoints/request/namespace_test.go @@ -3,19 +3,22 @@ package request_test import ( "testing" - grafanarequest "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" + "github.com/stretchr/testify/require" + + "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" + "github.com/grafana/grafana/pkg/setting" ) func TestParseNamespace(t *testing.T) { tests := []struct { name string namespace string - expected grafanarequest.NamespaceInfo + expected request.NamespaceInfo expectErr bool }{ { name: "empty namespace", - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, }, }, @@ -23,7 +26,7 @@ func TestParseNamespace(t *testing.T) { name: "incorrect number of parts", namespace: "org-123-a", expectErr: true, - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, }, }, @@ -31,14 +34,14 @@ func TestParseNamespace(t *testing.T) { name: "org id not a number", namespace: "org-invalid", expectErr: true, - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, }, }, { name: "valid org id", namespace: "org-123", - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: 123, }, }, @@ -46,7 +49,7 @@ func TestParseNamespace(t *testing.T) { name: "org should not be 1 in the namespace", namespace: "org-1", expectErr: true, - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, }, }, @@ -54,7 +57,7 @@ func TestParseNamespace(t *testing.T) { name: "can not be negative", namespace: "org--5", expectErr: true, - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, }, }, @@ -62,21 +65,21 @@ func TestParseNamespace(t *testing.T) { name: "can not be zero", namespace: "org-0", expectErr: true, - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, }, }, { name: "default is org 1", namespace: "default", - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: 1, }, }, { name: "valid stack", namespace: "stack-abcdef", - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: 1, StackID: "abcdef", }, @@ -85,7 +88,7 @@ func TestParseNamespace(t *testing.T) { name: "invalid stack id", namespace: "stack-", expectErr: true, - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, }, }, @@ -93,7 +96,7 @@ func TestParseNamespace(t *testing.T) { name: "invalid stack id (too short)", namespace: "stack-1", expectErr: true, - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, StackID: "1", }, @@ -101,7 +104,7 @@ func TestParseNamespace(t *testing.T) { { name: "other namespace", namespace: "anything", - expected: grafanarequest.NamespaceInfo{ + expected: request.NamespaceInfo{ OrgID: -1, Value: "anything", }, @@ -110,7 +113,7 @@ func TestParseNamespace(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - info, err := grafanarequest.ParseNamespace(tt.namespace) + info, err := request.ParseNamespace(tt.namespace) if tt.expectErr != (err != nil) { t.Errorf("ParseNamespace() returned %+v, expected an error", info) } @@ -126,3 +129,36 @@ func TestParseNamespace(t *testing.T) { }) } } + +func TestNamespaceMapper(t *testing.T) { + tests := []struct { + name string + cfg string + orgId int64 + expected string + }{ + { + name: "default namespace", + orgId: 1, + expected: "default", + }, + { + name: "with org", + orgId: 123, + expected: "org-123", + }, + { + name: "with stackId", + cfg: "abc", + orgId: 123, // ignored + expected: "stack-abc", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mapper := request.GetNamespaceMapper(&setting.Cfg{StackID: tt.cfg}) + require.Equal(t, tt.expected, mapper(tt.orgId)) + }) + } +}