K8s: Namespace parsing updates (default + stack-id) (#76310)

Co-authored-by: Todd Treece <360020+toddtreece@users.noreply.github.com>
This commit is contained in:
Ryan McKinley
2023-10-12 21:34:50 +03:00
committed by GitHub
co-authored by Todd Treece
parent be7fe761a3
commit 2a527aa33b
13 changed files with 325 additions and 78 deletions
@@ -8,6 +8,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"github.com/grafana/grafana/pkg/services/playlist"
"github.com/grafana/grafana/pkg/setting"
)
type namespaceMapper = func(orgId int64) string
@@ -19,6 +20,13 @@ func orgNamespaceMapper(orgId int64) string {
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 {
spec := Spec{
Title: v.Name,
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/playlist"
"github.com/grafana/grafana/pkg/setting"
)
func TestPlaylistConversion(t *testing.T) {
@@ -62,3 +63,36 @@ 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))
})
}
}
+13 -18
View File
@@ -22,13 +22,8 @@ var (
)
type legacyStorage struct {
service playlist.Service
}
func newLegacyStorage(s playlist.Service) *legacyStorage {
return &legacyStorage{
service: s,
}
service playlist.Service
namespacer namespaceMapper
}
func (s *legacyStorage) New() runtime.Object {
@@ -56,9 +51,9 @@ 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
orgId, ok := grafanarequest.OrgIDFrom(ctx)
if !ok {
orgId = 1 // TODO: default org ID 1 for now
info, err := grafanarequest.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
}
limit := 100
@@ -66,7 +61,7 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO
limit = int(options.Limit)
}
res, err := s.service.Search(ctx, &playlist.GetPlaylistsQuery{
OrgId: orgId,
OrgId: info.OrgID,
Limit: limit,
})
if err != nil {
@@ -82,12 +77,12 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO
for _, v := range res {
p, err := s.service.Get(ctx, &playlist.GetPlaylistByUidQuery{
UID: v.UID,
OrgId: orgId, // required
OrgId: info.OrgID,
})
if err != nil {
return nil, err
}
list.Items = append(list.Items, *convertToK8sResource(p, orgNamespaceMapper))
list.Items = append(list.Items, *convertToK8sResource(p, s.namespacer))
}
if len(list.Items) == limit {
list.Continue = "<more>" // TODO?
@@ -96,14 +91,14 @@ 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) {
orgId, ok := grafanarequest.OrgIDFrom(ctx)
if !ok {
orgId = 1 // TODO: default org ID 1 for now
info, err := grafanarequest.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
}
dto, err := s.service.Get(ctx, &playlist.GetPlaylistByUidQuery{
UID: name,
OrgId: orgId,
OrgId: info.OrgID,
})
if err != nil {
return nil, err
@@ -112,5 +107,5 @@ func (s *legacyStorage) Get(ctx context.Context, name string, options *metav1.Ge
return nil, fmt.Errorf("not found?")
}
return convertToK8sResource(dto, orgNamespaceMapper), nil
return convertToK8sResource(dto, s.namespacer), nil
}
+13 -4
View File
@@ -13,18 +13,24 @@ import (
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
grafanarest "github.com/grafana/grafana/pkg/services/grafana-apiserver/rest"
"github.com/grafana/grafana/pkg/services/playlist"
"github.com/grafana/grafana/pkg/setting"
)
var _ grafanaapiserver.APIGroupBuilder = (*PlaylistAPIBuilder)(nil)
// This is used just so wire has something unique to return
type PlaylistAPIBuilder struct {
service playlist.Service
service playlist.Service
namespacer namespaceMapper
}
func RegisterAPIService(p playlist.Service, apiregistration grafanaapiserver.APIRegistrar) *PlaylistAPIBuilder {
func RegisterAPIService(p playlist.Service,
apiregistration grafanaapiserver.APIRegistrar,
cfg *setting.Cfg,
) *PlaylistAPIBuilder {
builder := &PlaylistAPIBuilder{
service: p,
service: p,
namespacer: getNamespaceMapper(cfg),
}
apiregistration.RegisterAPI(builder)
return builder
@@ -50,7 +56,10 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(GroupName, scheme, metav1.ParameterCodec, codecs)
storage := map[string]rest.Storage{}
legacyStore := newLegacyStorage(b.service)
legacyStore := &legacyStorage{
service: b.service,
namespacer: b.namespacer,
}
storage["playlists"] = legacyStore
// enable dual writes if a RESTOptionsGetter is provided