mirror of https://github.com/grafana/grafana.git
				
				
				
			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
 | ||||
|  |  | |||
|  | @ -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