K8s: Move the namespace mapper to the same package that resolves them (#77101)

This commit is contained in:
Ryan McKinley 2023-10-25 11:13:46 -07:00 committed by GitHub
parent 89f63dcddb
commit 7e069f9d91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 74 deletions

View File

@ -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,

View File

@ -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))
})
}
}

View File

@ -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
}

View File

@ -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)

View File

@ -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 {

View File

@ -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))
})
}
}