mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
K8s: Add resource type helper to avoid so many hardcoded names (#79344)
This commit is contained in:
parent
5147bdeb4b
commit
f69516bf47
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/apis/playlist/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
internalplaylist "github.com/grafana/grafana/pkg/registry/apis/playlist"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
@ -329,11 +330,7 @@ type playlistK8sHandler struct {
|
||||
|
||||
func newPlaylistK8sHandler(hs *HTTPServer) *playlistK8sHandler {
|
||||
return &playlistK8sHandler{
|
||||
gvr: schema.GroupVersionResource{
|
||||
Group: internalplaylist.GroupName,
|
||||
Version: "v0alpha1",
|
||||
Resource: "playlists",
|
||||
},
|
||||
gvr: v0alpha1.PlaylistResourceInfo.GroupVersionResource(),
|
||||
namespacer: request.GetNamespaceMapper(hs.Cfg),
|
||||
clientConfigProvider: hs.clientConfigProvider,
|
||||
}
|
||||
|
@ -2,6 +2,26 @@ package v0alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
GROUP = "example.grafana.app"
|
||||
VERSION = "v0alpha1"
|
||||
APIVERSION = GROUP + "/" + VERSION
|
||||
)
|
||||
|
||||
var RuntimeResourceInfo = apis.NewResourceInfo(GROUP, VERSION,
|
||||
"runtime", "runtime", "RuntimeInfo",
|
||||
func() runtime.Object { return &RuntimeInfo{} },
|
||||
func() runtime.Object { return &RuntimeInfo{} },
|
||||
)
|
||||
var DummyResourceInfo = apis.NewResourceInfo(GROUP, VERSION,
|
||||
"dummy", "dummy", "DummyResource",
|
||||
func() runtime.Object { return &DummyResource{} },
|
||||
func() runtime.Object { return &DummyResourceList{} },
|
||||
)
|
||||
|
||||
// Mirrors the info exposed in "github.com/grafana/grafana/pkg/setting"
|
||||
|
@ -2,6 +2,21 @@ package v0alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
GROUP = "playlist.grafana.app"
|
||||
VERSION = "v0alpha1"
|
||||
APIVERSION = GROUP + "/" + VERSION
|
||||
)
|
||||
|
||||
var PlaylistResourceInfo = apis.NewResourceInfo(GROUP, VERSION,
|
||||
"playlists", "playlist", "Playlist",
|
||||
func() runtime.Object { return &Playlist{} },
|
||||
func() runtime.Object { return &PlaylistList{} },
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
87
pkg/apis/types.go
Normal file
87
pkg/apis/types.go
Normal file
@ -0,0 +1,87 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// ResourceInfo helps define a k8s resource
|
||||
type ResourceInfo struct {
|
||||
group string
|
||||
version string
|
||||
resourceName string
|
||||
singularName string
|
||||
kind string
|
||||
newObj func() runtime.Object
|
||||
newList func() runtime.Object
|
||||
}
|
||||
|
||||
func NewResourceInfo(group, version, resourceName, singularName, kind string,
|
||||
newObj func() runtime.Object, newList func() runtime.Object) ResourceInfo {
|
||||
return ResourceInfo{group, version, resourceName, singularName, kind, newObj, newList}
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) GetSingularName() string {
|
||||
return info.singularName
|
||||
}
|
||||
|
||||
// TypeMeta returns k8s type
|
||||
func (info *ResourceInfo) TypeMeta() metav1.TypeMeta {
|
||||
return metav1.TypeMeta{
|
||||
Kind: info.kind,
|
||||
APIVersion: info.group + "/" + info.version,
|
||||
}
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) GroupVersion() schema.GroupVersion {
|
||||
return schema.GroupVersion{
|
||||
Group: info.group,
|
||||
Version: info.version,
|
||||
}
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) GroupResource() schema.GroupResource {
|
||||
return schema.GroupResource{
|
||||
Group: info.group,
|
||||
Resource: info.resourceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) SingularGroupResource() schema.GroupResource {
|
||||
return schema.GroupResource{
|
||||
Group: info.group,
|
||||
Resource: info.singularName,
|
||||
}
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) GroupVersionResource() schema.GroupVersionResource {
|
||||
return schema.GroupVersionResource{
|
||||
Group: info.group,
|
||||
Version: info.version,
|
||||
Resource: info.resourceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) StoragePath(sub ...string) string {
|
||||
switch len(sub) {
|
||||
case 0:
|
||||
return info.resourceName
|
||||
case 1:
|
||||
return info.resourceName + "/" + sub[0]
|
||||
}
|
||||
panic("invalid subresource path")
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) NewFunc() runtime.Object {
|
||||
return info.newObj()
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) NewListFunc() runtime.Object {
|
||||
return info.newList()
|
||||
}
|
||||
|
||||
func (info *ResourceInfo) NewNotFound(name string) *errors.StatusError {
|
||||
return errors.NewNotFound(info.SingularGroupResource(), name)
|
||||
}
|
@ -32,18 +32,19 @@ type dummyStorage struct {
|
||||
}
|
||||
|
||||
func newDummyStorage(gv schema.GroupVersion, scheme *runtime.Scheme, names ...string) *dummyStorage {
|
||||
var resourceInfo = example.DummyResourceInfo
|
||||
strategy := grafanaregistry.NewStrategy(scheme)
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &example.DummyResource{} }, // getter not supported
|
||||
NewListFunc: func() runtime.Object { return &example.DummyResourceList{} }, // both list and get return the same thing
|
||||
NewFunc: resourceInfo.NewFunc,
|
||||
NewListFunc: resourceInfo.NewListFunc,
|
||||
PredicateFunc: grafanaregistry.Matcher,
|
||||
DefaultQualifiedResource: gv.WithResource("dummy").GroupResource(),
|
||||
SingularQualifiedResource: gv.WithResource("dummy").GroupResource(),
|
||||
DefaultQualifiedResource: resourceInfo.GroupResource(),
|
||||
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
||||
TableConvertor: rest.NewDefaultTableConvertor(resourceInfo.GroupResource()),
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
DeleteStrategy: strategy,
|
||||
}
|
||||
store.TableConvertor = rest.NewDefaultTableConvertor(store.DefaultQualifiedResource)
|
||||
|
||||
return &dummyStorage{
|
||||
store: store,
|
||||
@ -63,7 +64,7 @@ func (s *dummyStorage) NamespaceScoped() bool {
|
||||
}
|
||||
|
||||
func (s *dummyStorage) GetSingularName() string {
|
||||
return "dummy"
|
||||
return example.DummyResourceInfo.GetSingularName()
|
||||
}
|
||||
|
||||
func (s *dummyStorage) NewList() runtime.Object {
|
||||
|
@ -23,11 +23,6 @@ import (
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
)
|
||||
|
||||
// GroupName is the group name for this API.
|
||||
const GroupName = "example.grafana.app"
|
||||
const VersionID = "v0alpha1" //
|
||||
const APIVersion = GroupName + "/" + VersionID
|
||||
|
||||
var _ grafanaapiserver.APIGroupBuilder = (*TestingAPIBuilder)(nil)
|
||||
|
||||
// This is used just so wire has something unique to return
|
||||
@ -38,7 +33,7 @@ type TestingAPIBuilder struct {
|
||||
|
||||
func NewTestingAPIBuilder() *TestingAPIBuilder {
|
||||
return &TestingAPIBuilder{
|
||||
gv: schema.GroupVersion{Group: GroupName, Version: VersionID},
|
||||
gv: schema.GroupVersion{Group: example.GROUP, Version: example.VERSION},
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,13 +84,13 @@ func (b *TestingAPIBuilder) GetAPIGroupInfo(
|
||||
optsGetter generic.RESTOptionsGetter,
|
||||
) (*genericapiserver.APIGroupInfo, error) {
|
||||
b.codecs = codecs
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(GroupName, scheme, metav1.ParameterCodec, codecs)
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(b.gv.Group, scheme, metav1.ParameterCodec, codecs)
|
||||
|
||||
storage := map[string]rest.Storage{}
|
||||
storage["runtime"] = newDeploymentInfoStorage(b.gv, scheme)
|
||||
storage["dummy"] = newDummyStorage(b.gv, scheme, "test1", "test2", "test3")
|
||||
storage["dummy/sub"] = &dummySubresourceREST{}
|
||||
apiGroupInfo.VersionedResourcesStorageMap[VersionID] = storage
|
||||
storage[example.RuntimeResourceInfo.StoragePath()] = newDeploymentInfoStorage(b.gv, scheme)
|
||||
storage[example.DummyResourceInfo.StoragePath()] = newDummyStorage(b.gv, scheme, "test1", "test2", "test3")
|
||||
storage[example.DummyResourceInfo.StoragePath("sub")] = &dummySubresourceREST{}
|
||||
apiGroupInfo.VersionedResourcesStorageMap[b.gv.Version] = storage
|
||||
return &apiGroupInfo, nil
|
||||
}
|
||||
|
||||
|
@ -29,26 +29,24 @@ type staticStorage struct {
|
||||
}
|
||||
|
||||
func newDeploymentInfoStorage(gv schema.GroupVersion, scheme *runtime.Scheme) *staticStorage {
|
||||
var resourceInfo = example.RuntimeResourceInfo
|
||||
strategy := grafanaregistry.NewStrategy(scheme)
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &example.RuntimeInfo{} }, // getter not supported
|
||||
NewListFunc: func() runtime.Object { return &example.RuntimeInfo{} }, // both list and get return the same thing
|
||||
NewFunc: resourceInfo.NewFunc,
|
||||
NewListFunc: resourceInfo.NewListFunc,
|
||||
PredicateFunc: grafanaregistry.Matcher,
|
||||
DefaultQualifiedResource: gv.WithResource("runtime").GroupResource(),
|
||||
SingularQualifiedResource: gv.WithResource("runtime").GroupResource(),
|
||||
DefaultQualifiedResource: resourceInfo.GroupResource(),
|
||||
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
||||
TableConvertor: rest.NewDefaultTableConvertor(resourceInfo.GroupResource()),
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
DeleteStrategy: strategy,
|
||||
}
|
||||
store.TableConvertor = rest.NewDefaultTableConvertor(store.DefaultQualifiedResource)
|
||||
|
||||
return &staticStorage{
|
||||
Store: store,
|
||||
info: example.RuntimeInfo{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: APIVersion,
|
||||
Kind: "DeploymentInfo",
|
||||
},
|
||||
TypeMeta: example.RuntimeResourceInfo.TypeMeta(),
|
||||
BuildVersion: setting.BuildVersion,
|
||||
BuildCommit: setting.BuildCommit,
|
||||
BuildBranch: setting.BuildBranch,
|
||||
@ -72,7 +70,7 @@ func (s *staticStorage) NamespaceScoped() bool {
|
||||
}
|
||||
|
||||
func (s *staticStorage) GetSingularName() string {
|
||||
return "runtime"
|
||||
return example.RuntimeResourceInfo.GetSingularName()
|
||||
}
|
||||
|
||||
func (s *staticStorage) NewList() runtime.Object {
|
||||
|
@ -5,11 +5,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1"
|
||||
@ -28,17 +26,16 @@ var (
|
||||
_ rest.GracefulDeleter = (*legacyStorage)(nil)
|
||||
)
|
||||
|
||||
var resourceInfo = playlist.PlaylistResourceInfo
|
||||
|
||||
type legacyStorage struct {
|
||||
service playlistsvc.Service
|
||||
namespacer request.NamespaceMapper
|
||||
tableConverter rest.TableConvertor
|
||||
|
||||
DefaultQualifiedResource schema.GroupResource
|
||||
SingularQualifiedResource schema.GroupResource
|
||||
}
|
||||
|
||||
func (s *legacyStorage) New() runtime.Object {
|
||||
return &playlist.Playlist{}
|
||||
return resourceInfo.NewFunc()
|
||||
}
|
||||
|
||||
func (s *legacyStorage) Destroy() {}
|
||||
@ -48,11 +45,11 @@ func (s *legacyStorage) NamespaceScoped() bool {
|
||||
}
|
||||
|
||||
func (s *legacyStorage) GetSingularName() string {
|
||||
return "playlist"
|
||||
return resourceInfo.GetSingularName()
|
||||
}
|
||||
|
||||
func (s *legacyStorage) NewList() runtime.Object {
|
||||
return &playlist.PlaylistList{}
|
||||
return resourceInfo.NewListFunc()
|
||||
}
|
||||
|
||||
func (s *legacyStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
|
||||
@ -60,9 +57,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 := request.NamespaceInfoFrom(ctx, true)
|
||||
orgId, err := request.OrgIDForList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -72,7 +67,7 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO
|
||||
limit = int(options.Limit)
|
||||
}
|
||||
res, err := s.service.Search(ctx, &playlistsvc.GetPlaylistsQuery{
|
||||
OrgId: info.OrgID,
|
||||
OrgId: orgId,
|
||||
Limit: limit,
|
||||
})
|
||||
if err != nil {
|
||||
@ -83,7 +78,7 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO
|
||||
for _, v := range res {
|
||||
p, err := s.service.Get(ctx, &playlistsvc.GetPlaylistByUidQuery{
|
||||
UID: v.UID,
|
||||
OrgId: info.OrgID,
|
||||
OrgId: orgId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -108,7 +103,7 @@ func (s *legacyStorage) Get(ctx context.Context, name string, options *metav1.Ge
|
||||
})
|
||||
if err != nil || dto == nil {
|
||||
if errors.Is(err, playlistsvc.ErrPlaylistNotFound) || err == nil {
|
||||
err = k8serrors.NewNotFound(s.SingularQualifiedResource, name)
|
||||
err = resourceInfo.NewNotFound(name)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
@ -22,10 +22,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
// GroupName is the group name for this API.
|
||||
const GroupName = "playlist.grafana.app"
|
||||
const VersionID = "v0alpha1"
|
||||
|
||||
var _ grafanaapiserver.APIGroupBuilder = (*PlaylistAPIBuilder)(nil)
|
||||
|
||||
// This is used just so wire has something unique to return
|
||||
@ -42,7 +38,7 @@ func RegisterAPIService(p playlistsvc.Service,
|
||||
builder := &PlaylistAPIBuilder{
|
||||
service: p,
|
||||
namespacer: request.GetNamespaceMapper(cfg),
|
||||
gv: schema.GroupVersion{Group: GroupName, Version: VersionID},
|
||||
gv: playlist.PlaylistResourceInfo.GroupVersion(),
|
||||
}
|
||||
apiregistration.RegisterAPI(builder)
|
||||
return builder
|
||||
@ -52,22 +48,23 @@ func (b *PlaylistAPIBuilder) GetGroupVersion() schema.GroupVersion {
|
||||
return b.gv
|
||||
}
|
||||
|
||||
func (b *PlaylistAPIBuilder) InstallSchema(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(b.gv,
|
||||
func addKnownTypes(scheme *runtime.Scheme, gv schema.GroupVersion) {
|
||||
scheme.AddKnownTypes(gv,
|
||||
&playlist.Playlist{},
|
||||
&playlist.PlaylistList{},
|
||||
)
|
||||
}
|
||||
|
||||
func (b *PlaylistAPIBuilder) InstallSchema(scheme *runtime.Scheme) error {
|
||||
addKnownTypes(scheme, b.gv)
|
||||
|
||||
// Link this version to the internal representation.
|
||||
// This is used for server-side-apply (PATCH), and avoids the error:
|
||||
// "no kind is registered for the type"
|
||||
scheme.AddKnownTypes(schema.GroupVersion{
|
||||
addKnownTypes(scheme, schema.GroupVersion{
|
||||
Group: b.gv.Group,
|
||||
Version: runtime.APIVersionInternal,
|
||||
},
|
||||
&playlist.Playlist{},
|
||||
&playlist.PlaylistList{},
|
||||
)
|
||||
})
|
||||
|
||||
// If multiple versions exist, then register conversions from zz_generated.conversion.go
|
||||
// if err := playlist.RegisterConversions(scheme); err != nil {
|
||||
@ -82,17 +79,16 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
|
||||
codecs serializer.CodecFactory, // pointer?
|
||||
optsGetter generic.RESTOptionsGetter,
|
||||
) (*genericapiserver.APIGroupInfo, error) {
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(GroupName, scheme, metav1.ParameterCodec, codecs)
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(playlist.GROUP, scheme, metav1.ParameterCodec, codecs)
|
||||
storage := map[string]rest.Storage{}
|
||||
|
||||
resource := playlist.PlaylistResourceInfo
|
||||
legacyStore := &legacyStorage{
|
||||
service: b.service,
|
||||
namespacer: b.namespacer,
|
||||
DefaultQualifiedResource: b.gv.WithResource("playlists").GroupResource(),
|
||||
SingularQualifiedResource: b.gv.WithResource("playlist").GroupResource(),
|
||||
service: b.service,
|
||||
namespacer: b.namespacer,
|
||||
}
|
||||
legacyStore.tableConverter = utils.NewTableConverter(
|
||||
legacyStore.DefaultQualifiedResource,
|
||||
resource.GroupResource(),
|
||||
[]metav1.TableColumnDefinition{
|
||||
{Name: "Name", Type: "string", Format: "name"},
|
||||
{Name: "Title", Type: "string", Format: "string", Description: "The playlist name"},
|
||||
@ -112,7 +108,7 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
storage["playlists"] = legacyStore
|
||||
storage[resource.StoragePath()] = legacyStore
|
||||
|
||||
// enable dual writes if a RESTOptionsGetter is provided
|
||||
if optsGetter != nil {
|
||||
@ -120,10 +116,10 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storage["playlists"] = grafanarest.NewDualWriter(legacyStore, store)
|
||||
storage[resource.StoragePath()] = grafanarest.NewDualWriter(legacyStore, store)
|
||||
}
|
||||
|
||||
apiGroupInfo.VersionedResourcesStorageMap[VersionID] = storage
|
||||
apiGroupInfo.VersionedResourcesStorageMap[playlist.VERSION] = storage
|
||||
return &apiGroupInfo, nil
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,13 @@ type storage struct {
|
||||
func newStorage(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter, legacy *legacyStorage) (*storage, error) {
|
||||
strategy := grafanaregistry.NewStrategy(scheme)
|
||||
|
||||
resource := playlist.PlaylistResourceInfo
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &playlist.Playlist{} },
|
||||
NewListFunc: func() runtime.Object { return &playlist.PlaylistList{} },
|
||||
NewFunc: resource.NewFunc,
|
||||
NewListFunc: resource.NewListFunc,
|
||||
PredicateFunc: grafanaregistry.Matcher,
|
||||
DefaultQualifiedResource: legacy.DefaultQualifiedResource,
|
||||
SingularQualifiedResource: legacy.SingularQualifiedResource,
|
||||
DefaultQualifiedResource: resource.GroupResource(),
|
||||
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
||||
TableConvertor: legacy.tableConverter,
|
||||
|
||||
CreateStrategy: strategy,
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@ -75,3 +76,16 @@ func ParseNamespace(ns string) (NamespaceInfo, error) {
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func OrgIDForList(ctx context.Context) (int64, error) {
|
||||
ns := request.NamespaceValue(ctx)
|
||||
if ns == "" {
|
||||
user, err := appcontext.User(ctx)
|
||||
if user != nil {
|
||||
return user.OrgID, err
|
||||
}
|
||||
return -1, err
|
||||
}
|
||||
info, err := ParseNamespace(ns)
|
||||
return info.OrgID, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user