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/dtos"
|
||||||
"github.com/grafana/grafana/pkg/api/response"
|
"github.com/grafana/grafana/pkg/api/response"
|
||||||
"github.com/grafana/grafana/pkg/api/routing"
|
"github.com/grafana/grafana/pkg/api/routing"
|
||||||
|
"github.com/grafana/grafana/pkg/apis/playlist/v0alpha1"
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
internalplaylist "github.com/grafana/grafana/pkg/registry/apis/playlist"
|
internalplaylist "github.com/grafana/grafana/pkg/registry/apis/playlist"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
@ -329,11 +330,7 @@ type playlistK8sHandler struct {
|
|||||||
|
|
||||||
func newPlaylistK8sHandler(hs *HTTPServer) *playlistK8sHandler {
|
func newPlaylistK8sHandler(hs *HTTPServer) *playlistK8sHandler {
|
||||||
return &playlistK8sHandler{
|
return &playlistK8sHandler{
|
||||||
gvr: schema.GroupVersionResource{
|
gvr: v0alpha1.PlaylistResourceInfo.GroupVersionResource(),
|
||||||
Group: internalplaylist.GroupName,
|
|
||||||
Version: "v0alpha1",
|
|
||||||
Resource: "playlists",
|
|
||||||
},
|
|
||||||
namespacer: request.GetNamespaceMapper(hs.Cfg),
|
namespacer: request.GetNamespaceMapper(hs.Cfg),
|
||||||
clientConfigProvider: hs.clientConfigProvider,
|
clientConfigProvider: hs.clientConfigProvider,
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,26 @@ package v0alpha1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
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"
|
// Mirrors the info exposed in "github.com/grafana/grafana/pkg/setting"
|
||||||
|
@ -2,6 +2,21 @@ package v0alpha1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
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
|
// +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 {
|
func newDummyStorage(gv schema.GroupVersion, scheme *runtime.Scheme, names ...string) *dummyStorage {
|
||||||
|
var resourceInfo = example.DummyResourceInfo
|
||||||
strategy := grafanaregistry.NewStrategy(scheme)
|
strategy := grafanaregistry.NewStrategy(scheme)
|
||||||
store := &genericregistry.Store{
|
store := &genericregistry.Store{
|
||||||
NewFunc: func() runtime.Object { return &example.DummyResource{} }, // getter not supported
|
NewFunc: resourceInfo.NewFunc,
|
||||||
NewListFunc: func() runtime.Object { return &example.DummyResourceList{} }, // both list and get return the same thing
|
NewListFunc: resourceInfo.NewListFunc,
|
||||||
PredicateFunc: grafanaregistry.Matcher,
|
PredicateFunc: grafanaregistry.Matcher,
|
||||||
DefaultQualifiedResource: gv.WithResource("dummy").GroupResource(),
|
DefaultQualifiedResource: resourceInfo.GroupResource(),
|
||||||
SingularQualifiedResource: gv.WithResource("dummy").GroupResource(),
|
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
||||||
|
TableConvertor: rest.NewDefaultTableConvertor(resourceInfo.GroupResource()),
|
||||||
CreateStrategy: strategy,
|
CreateStrategy: strategy,
|
||||||
UpdateStrategy: strategy,
|
UpdateStrategy: strategy,
|
||||||
DeleteStrategy: strategy,
|
DeleteStrategy: strategy,
|
||||||
}
|
}
|
||||||
store.TableConvertor = rest.NewDefaultTableConvertor(store.DefaultQualifiedResource)
|
|
||||||
|
|
||||||
return &dummyStorage{
|
return &dummyStorage{
|
||||||
store: store,
|
store: store,
|
||||||
@ -63,7 +64,7 @@ func (s *dummyStorage) NamespaceScoped() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *dummyStorage) GetSingularName() string {
|
func (s *dummyStorage) GetSingularName() string {
|
||||||
return "dummy"
|
return example.DummyResourceInfo.GetSingularName()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *dummyStorage) NewList() runtime.Object {
|
func (s *dummyStorage) NewList() runtime.Object {
|
||||||
|
@ -23,11 +23,6 @@ import (
|
|||||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
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)
|
var _ grafanaapiserver.APIGroupBuilder = (*TestingAPIBuilder)(nil)
|
||||||
|
|
||||||
// This is used just so wire has something unique to return
|
// This is used just so wire has something unique to return
|
||||||
@ -38,7 +33,7 @@ type TestingAPIBuilder struct {
|
|||||||
|
|
||||||
func NewTestingAPIBuilder() *TestingAPIBuilder {
|
func NewTestingAPIBuilder() *TestingAPIBuilder {
|
||||||
return &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,
|
optsGetter generic.RESTOptionsGetter,
|
||||||
) (*genericapiserver.APIGroupInfo, error) {
|
) (*genericapiserver.APIGroupInfo, error) {
|
||||||
b.codecs = codecs
|
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 := map[string]rest.Storage{}
|
||||||
storage["runtime"] = newDeploymentInfoStorage(b.gv, scheme)
|
storage[example.RuntimeResourceInfo.StoragePath()] = newDeploymentInfoStorage(b.gv, scheme)
|
||||||
storage["dummy"] = newDummyStorage(b.gv, scheme, "test1", "test2", "test3")
|
storage[example.DummyResourceInfo.StoragePath()] = newDummyStorage(b.gv, scheme, "test1", "test2", "test3")
|
||||||
storage["dummy/sub"] = &dummySubresourceREST{}
|
storage[example.DummyResourceInfo.StoragePath("sub")] = &dummySubresourceREST{}
|
||||||
apiGroupInfo.VersionedResourcesStorageMap[VersionID] = storage
|
apiGroupInfo.VersionedResourcesStorageMap[b.gv.Version] = storage
|
||||||
return &apiGroupInfo, nil
|
return &apiGroupInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,26 +29,24 @@ type staticStorage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newDeploymentInfoStorage(gv schema.GroupVersion, scheme *runtime.Scheme) *staticStorage {
|
func newDeploymentInfoStorage(gv schema.GroupVersion, scheme *runtime.Scheme) *staticStorage {
|
||||||
|
var resourceInfo = example.RuntimeResourceInfo
|
||||||
strategy := grafanaregistry.NewStrategy(scheme)
|
strategy := grafanaregistry.NewStrategy(scheme)
|
||||||
store := &genericregistry.Store{
|
store := &genericregistry.Store{
|
||||||
NewFunc: func() runtime.Object { return &example.RuntimeInfo{} }, // getter not supported
|
NewFunc: resourceInfo.NewFunc,
|
||||||
NewListFunc: func() runtime.Object { return &example.RuntimeInfo{} }, // both list and get return the same thing
|
NewListFunc: resourceInfo.NewListFunc,
|
||||||
PredicateFunc: grafanaregistry.Matcher,
|
PredicateFunc: grafanaregistry.Matcher,
|
||||||
DefaultQualifiedResource: gv.WithResource("runtime").GroupResource(),
|
DefaultQualifiedResource: resourceInfo.GroupResource(),
|
||||||
SingularQualifiedResource: gv.WithResource("runtime").GroupResource(),
|
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
||||||
|
TableConvertor: rest.NewDefaultTableConvertor(resourceInfo.GroupResource()),
|
||||||
CreateStrategy: strategy,
|
CreateStrategy: strategy,
|
||||||
UpdateStrategy: strategy,
|
UpdateStrategy: strategy,
|
||||||
DeleteStrategy: strategy,
|
DeleteStrategy: strategy,
|
||||||
}
|
}
|
||||||
store.TableConvertor = rest.NewDefaultTableConvertor(store.DefaultQualifiedResource)
|
|
||||||
|
|
||||||
return &staticStorage{
|
return &staticStorage{
|
||||||
Store: store,
|
Store: store,
|
||||||
info: example.RuntimeInfo{
|
info: example.RuntimeInfo{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: example.RuntimeResourceInfo.TypeMeta(),
|
||||||
APIVersion: APIVersion,
|
|
||||||
Kind: "DeploymentInfo",
|
|
||||||
},
|
|
||||||
BuildVersion: setting.BuildVersion,
|
BuildVersion: setting.BuildVersion,
|
||||||
BuildCommit: setting.BuildCommit,
|
BuildCommit: setting.BuildCommit,
|
||||||
BuildBranch: setting.BuildBranch,
|
BuildBranch: setting.BuildBranch,
|
||||||
@ -72,7 +70,7 @@ func (s *staticStorage) NamespaceScoped() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *staticStorage) GetSingularName() string {
|
func (s *staticStorage) GetSingularName() string {
|
||||||
return "runtime"
|
return example.RuntimeResourceInfo.GetSingularName()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *staticStorage) NewList() runtime.Object {
|
func (s *staticStorage) NewList() runtime.Object {
|
||||||
|
@ -5,11 +5,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
|
||||||
playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1"
|
playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1"
|
||||||
@ -28,17 +26,16 @@ var (
|
|||||||
_ rest.GracefulDeleter = (*legacyStorage)(nil)
|
_ rest.GracefulDeleter = (*legacyStorage)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var resourceInfo = playlist.PlaylistResourceInfo
|
||||||
|
|
||||||
type legacyStorage struct {
|
type legacyStorage struct {
|
||||||
service playlistsvc.Service
|
service playlistsvc.Service
|
||||||
namespacer request.NamespaceMapper
|
namespacer request.NamespaceMapper
|
||||||
tableConverter rest.TableConvertor
|
tableConverter rest.TableConvertor
|
||||||
|
|
||||||
DefaultQualifiedResource schema.GroupResource
|
|
||||||
SingularQualifiedResource schema.GroupResource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *legacyStorage) New() runtime.Object {
|
func (s *legacyStorage) New() runtime.Object {
|
||||||
return &playlist.Playlist{}
|
return resourceInfo.NewFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *legacyStorage) Destroy() {}
|
func (s *legacyStorage) Destroy() {}
|
||||||
@ -48,11 +45,11 @@ func (s *legacyStorage) NamespaceScoped() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *legacyStorage) GetSingularName() string {
|
func (s *legacyStorage) GetSingularName() string {
|
||||||
return "playlist"
|
return resourceInfo.GetSingularName()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *legacyStorage) NewList() runtime.Object {
|
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) {
|
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) {
|
func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
|
||||||
// TODO: handle fetching all available orgs when no namespace is specified
|
orgId, err := request.OrgIDForList(ctx)
|
||||||
// To test: kubectl get playlists --all-namespaces
|
|
||||||
info, err := request.NamespaceInfoFrom(ctx, true)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -72,7 +67,7 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO
|
|||||||
limit = int(options.Limit)
|
limit = int(options.Limit)
|
||||||
}
|
}
|
||||||
res, err := s.service.Search(ctx, &playlistsvc.GetPlaylistsQuery{
|
res, err := s.service.Search(ctx, &playlistsvc.GetPlaylistsQuery{
|
||||||
OrgId: info.OrgID,
|
OrgId: orgId,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -83,7 +78,7 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO
|
|||||||
for _, v := range res {
|
for _, v := range res {
|
||||||
p, err := s.service.Get(ctx, &playlistsvc.GetPlaylistByUidQuery{
|
p, err := s.service.Get(ctx, &playlistsvc.GetPlaylistByUidQuery{
|
||||||
UID: v.UID,
|
UID: v.UID,
|
||||||
OrgId: info.OrgID,
|
OrgId: orgId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 err != nil || dto == nil {
|
||||||
if errors.Is(err, playlistsvc.ErrPlaylistNotFound) || err == nil {
|
if errors.Is(err, playlistsvc.ErrPlaylistNotFound) || err == nil {
|
||||||
err = k8serrors.NewNotFound(s.SingularQualifiedResource, name)
|
err = resourceInfo.NewNotFound(name)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/setting"
|
"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)
|
var _ grafanaapiserver.APIGroupBuilder = (*PlaylistAPIBuilder)(nil)
|
||||||
|
|
||||||
// This is used just so wire has something unique to return
|
// This is used just so wire has something unique to return
|
||||||
@ -42,7 +38,7 @@ func RegisterAPIService(p playlistsvc.Service,
|
|||||||
builder := &PlaylistAPIBuilder{
|
builder := &PlaylistAPIBuilder{
|
||||||
service: p,
|
service: p,
|
||||||
namespacer: request.GetNamespaceMapper(cfg),
|
namespacer: request.GetNamespaceMapper(cfg),
|
||||||
gv: schema.GroupVersion{Group: GroupName, Version: VersionID},
|
gv: playlist.PlaylistResourceInfo.GroupVersion(),
|
||||||
}
|
}
|
||||||
apiregistration.RegisterAPI(builder)
|
apiregistration.RegisterAPI(builder)
|
||||||
return builder
|
return builder
|
||||||
@ -52,22 +48,23 @@ func (b *PlaylistAPIBuilder) GetGroupVersion() schema.GroupVersion {
|
|||||||
return b.gv
|
return b.gv
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PlaylistAPIBuilder) InstallSchema(scheme *runtime.Scheme) error {
|
func addKnownTypes(scheme *runtime.Scheme, gv schema.GroupVersion) {
|
||||||
scheme.AddKnownTypes(b.gv,
|
scheme.AddKnownTypes(gv,
|
||||||
&playlist.Playlist{},
|
&playlist.Playlist{},
|
||||||
&playlist.PlaylistList{},
|
&playlist.PlaylistList{},
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PlaylistAPIBuilder) InstallSchema(scheme *runtime.Scheme) error {
|
||||||
|
addKnownTypes(scheme, b.gv)
|
||||||
|
|
||||||
// Link this version to the internal representation.
|
// Link this version to the internal representation.
|
||||||
// This is used for server-side-apply (PATCH), and avoids the error:
|
// This is used for server-side-apply (PATCH), and avoids the error:
|
||||||
// "no kind is registered for the type"
|
// "no kind is registered for the type"
|
||||||
scheme.AddKnownTypes(schema.GroupVersion{
|
addKnownTypes(scheme, schema.GroupVersion{
|
||||||
Group: b.gv.Group,
|
Group: b.gv.Group,
|
||||||
Version: runtime.APIVersionInternal,
|
Version: runtime.APIVersionInternal,
|
||||||
},
|
})
|
||||||
&playlist.Playlist{},
|
|
||||||
&playlist.PlaylistList{},
|
|
||||||
)
|
|
||||||
|
|
||||||
// If multiple versions exist, then register conversions from zz_generated.conversion.go
|
// If multiple versions exist, then register conversions from zz_generated.conversion.go
|
||||||
// if err := playlist.RegisterConversions(scheme); err != nil {
|
// if err := playlist.RegisterConversions(scheme); err != nil {
|
||||||
@ -82,17 +79,16 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
|
|||||||
codecs serializer.CodecFactory, // pointer?
|
codecs serializer.CodecFactory, // pointer?
|
||||||
optsGetter generic.RESTOptionsGetter,
|
optsGetter generic.RESTOptionsGetter,
|
||||||
) (*genericapiserver.APIGroupInfo, error) {
|
) (*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{}
|
storage := map[string]rest.Storage{}
|
||||||
|
|
||||||
|
resource := playlist.PlaylistResourceInfo
|
||||||
legacyStore := &legacyStorage{
|
legacyStore := &legacyStorage{
|
||||||
service: b.service,
|
service: b.service,
|
||||||
namespacer: b.namespacer,
|
namespacer: b.namespacer,
|
||||||
DefaultQualifiedResource: b.gv.WithResource("playlists").GroupResource(),
|
|
||||||
SingularQualifiedResource: b.gv.WithResource("playlist").GroupResource(),
|
|
||||||
}
|
}
|
||||||
legacyStore.tableConverter = utils.NewTableConverter(
|
legacyStore.tableConverter = utils.NewTableConverter(
|
||||||
legacyStore.DefaultQualifiedResource,
|
resource.GroupResource(),
|
||||||
[]metav1.TableColumnDefinition{
|
[]metav1.TableColumnDefinition{
|
||||||
{Name: "Name", Type: "string", Format: "name"},
|
{Name: "Name", Type: "string", Format: "name"},
|
||||||
{Name: "Title", Type: "string", Format: "string", Description: "The playlist name"},
|
{Name: "Title", Type: "string", Format: "string", Description: "The playlist name"},
|
||||||
@ -112,7 +108,7 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
|
|||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
storage["playlists"] = legacyStore
|
storage[resource.StoragePath()] = legacyStore
|
||||||
|
|
||||||
// enable dual writes if a RESTOptionsGetter is provided
|
// enable dual writes if a RESTOptionsGetter is provided
|
||||||
if optsGetter != nil {
|
if optsGetter != nil {
|
||||||
@ -120,10 +116,10 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return &apiGroupInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,12 +19,13 @@ type storage struct {
|
|||||||
func newStorage(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter, legacy *legacyStorage) (*storage, error) {
|
func newStorage(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter, legacy *legacyStorage) (*storage, error) {
|
||||||
strategy := grafanaregistry.NewStrategy(scheme)
|
strategy := grafanaregistry.NewStrategy(scheme)
|
||||||
|
|
||||||
|
resource := playlist.PlaylistResourceInfo
|
||||||
store := &genericregistry.Store{
|
store := &genericregistry.Store{
|
||||||
NewFunc: func() runtime.Object { return &playlist.Playlist{} },
|
NewFunc: resource.NewFunc,
|
||||||
NewListFunc: func() runtime.Object { return &playlist.PlaylistList{} },
|
NewListFunc: resource.NewListFunc,
|
||||||
PredicateFunc: grafanaregistry.Matcher,
|
PredicateFunc: grafanaregistry.Matcher,
|
||||||
DefaultQualifiedResource: legacy.DefaultQualifiedResource,
|
DefaultQualifiedResource: resource.GroupResource(),
|
||||||
SingularQualifiedResource: legacy.SingularQualifiedResource,
|
SingularQualifiedResource: resourceInfo.SingularGroupResource(),
|
||||||
TableConvertor: legacy.tableConverter,
|
TableConvertor: legacy.tableConverter,
|
||||||
|
|
||||||
CreateStrategy: strategy,
|
CreateStrategy: strategy,
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -75,3 +76,16 @@ func ParseNamespace(ns string) (NamespaceInfo, error) {
|
|||||||
}
|
}
|
||||||
return info, nil
|
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