diff --git a/pkg/api/playlist.go b/pkg/api/playlist.go index 30be0e3b550..3f1b95dc29f 100644 --- a/pkg/api/playlist.go +++ b/pkg/api/playlist.go @@ -12,8 +12,8 @@ import ( "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/routing" - internalplaylist "github.com/grafana/grafana/pkg/apis/playlist" "github.com/grafana/grafana/pkg/middleware" + internalplaylist "github.com/grafana/grafana/pkg/registry/apis/playlist" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" diff --git a/pkg/apis/example/v0alpha1/openapi.go b/pkg/apis/example/v0alpha1/zz_generated.openapi..go similarity index 97% rename from pkg/apis/example/v0alpha1/openapi.go rename to pkg/apis/example/v0alpha1/zz_generated.openapi..go index 7d10f829ae0..dc68decf0ef 100644 --- a/pkg/apis/example/v0alpha1/openapi.go +++ b/pkg/apis/example/v0alpha1/zz_generated.openapi..go @@ -8,7 +8,7 @@ import ( // NOTE: this must match the golang fully qualified name! const kindKey = "github.com/grafana/grafana/pkg/apis/example/v0alpha1.RuntimeInfo" -func getOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { +func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ kindKey: schema_pkg_apis_example_v0alpha1_RuntimeInfo(ref), } diff --git a/pkg/apis/playlist/doc.go b/pkg/apis/playlist/doc.go deleted file mode 100644 index f4eff4cd63a..00000000000 --- a/pkg/apis/playlist/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// +k8s:deepcopy-gen=package -// +groupName=playlist.grafana.app - -package playlist // import "github.com/grafana/grafana/pkg/apis/playlist" diff --git a/pkg/apis/playlist/types.go b/pkg/apis/playlist/types.go deleted file mode 100644 index c7c8647086a..00000000000 --- a/pkg/apis/playlist/types.go +++ /dev/null @@ -1,65 +0,0 @@ -package playlist - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type Playlist struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - // +optional - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec Spec `json:"spec,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type PlaylistList struct { - metav1.TypeMeta `json:",inline"` - // +optional - metav1.ListMeta `json:"metadata,omitempty"` - - Items []Playlist `json:"items,omitempty"` -} - -// Spec defines model for Spec. -type Spec struct { - // Name of the playlist. - Title string `json:"title"` - - // Interval sets the time between switching views in a playlist. - Interval string `json:"interval"` - - // The ordered list of items that the playlist will iterate over. - Items []Item `json:"items,omitempty"` -} - -// Defines values for ItemType. -const ( - ItemTypeDashboardByTag ItemType = "dashboard_by_tag" - ItemTypeDashboardByUid ItemType = "dashboard_by_uid" - - // deprecated -- should use UID - ItemTypeDashboardById ItemType = "dashboard_by_id" -) - -// Item defines model for Item. -type Item struct { - // Type of the item. - Type ItemType `json:"type"` - - // Value depends on type and describes the playlist item. - // - // - dashboard_by_id: The value is an internal numerical identifier set by Grafana. This - // is not portable as the numerical identifier is non-deterministic between different instances. - // Will be replaced by dashboard_by_uid in the future. (deprecated) - // - dashboard_by_tag: The value is a tag which is set on any number of dashboards. All - // dashboards behind the tag will be added to the playlist. - // - dashboard_by_uid: The value is the dashboard UID - Value string `json:"value"` -} - -// Type of the item. -type ItemType string diff --git a/pkg/apis/playlist/v0alpha1/register.go b/pkg/apis/playlist/v0alpha1/register.go deleted file mode 100644 index cc803ce8fbe..00000000000 --- a/pkg/apis/playlist/v0alpha1/register.go +++ /dev/null @@ -1,74 +0,0 @@ -package v0alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/apiserver/pkg/registry/generic" - genericapiserver "k8s.io/apiserver/pkg/server" - 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" - "github.com/grafana/grafana/pkg/services/playlist" - "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 -type PlaylistAPIBuilder struct { - service playlist.Service - namespacer request.NamespaceMapper - gv schema.GroupVersion -} - -func RegisterAPIService(p playlist.Service, - apiregistration grafanaapiserver.APIRegistrar, - cfg *setting.Cfg, -) *PlaylistAPIBuilder { - builder := &PlaylistAPIBuilder{ - service: p, - namespacer: request.GetNamespaceMapper(cfg), - gv: schema.GroupVersion{Group: GroupName, Version: VersionID}, - } - apiregistration.RegisterAPI(builder) - return builder -} - -func (b *PlaylistAPIBuilder) GetGroupVersion() schema.GroupVersion { - return b.gv -} - -func (b *PlaylistAPIBuilder) InstallSchema(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(b.gv, - &Playlist{}, - &PlaylistList{}, - ) - if err := RegisterConversions(scheme); err != nil { - return err - } - metav1.AddToGroupVersion(scheme, b.gv) - return scheme.SetVersionPriority(b.gv) -} - -func (b *PlaylistAPIBuilder) GetAPIGroupInfo( - scheme *runtime.Scheme, - codecs serializer.CodecFactory, // pointer? - optsGetter generic.RESTOptionsGetter, -) (*genericapiserver.APIGroupInfo, error) { - return nil, nil -} - -func (b *PlaylistAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions { - return getOpenAPIDefinitions -} - -func (b *PlaylistAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes { - return nil // no custom API routes -} diff --git a/pkg/apis/playlist/v0alpha1/zz_generated.conversion.go b/pkg/apis/playlist/v0alpha1/zz_generated.conversion.go deleted file mode 100644 index d89fef079e0..00000000000 --- a/pkg/apis/playlist/v0alpha1/zz_generated.conversion.go +++ /dev/null @@ -1,170 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by conversion-gen. DO NOT EDIT. - -package v0alpha1 - -import ( - unsafe "unsafe" - - playlist "github.com/grafana/grafana/pkg/apis/playlist" - conversion "k8s.io/apimachinery/pkg/conversion" - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// RegisterConversions adds conversion functions to the given scheme. -// Public to allow building arbitrary schemes. -func RegisterConversions(s *runtime.Scheme) error { - if err := s.AddGeneratedConversionFunc((*Item)(nil), (*playlist.Item)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v0alpha1_Item_To_playlist_Item(a.(*Item), b.(*playlist.Item), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*playlist.Item)(nil), (*Item)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_playlist_Item_To_v0alpha1_Item(a.(*playlist.Item), b.(*Item), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*Playlist)(nil), (*playlist.Playlist)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v0alpha1_Playlist_To_playlist_Playlist(a.(*Playlist), b.(*playlist.Playlist), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*playlist.Playlist)(nil), (*Playlist)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_playlist_Playlist_To_v0alpha1_Playlist(a.(*playlist.Playlist), b.(*Playlist), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*PlaylistList)(nil), (*playlist.PlaylistList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v0alpha1_PlaylistList_To_playlist_PlaylistList(a.(*PlaylistList), b.(*playlist.PlaylistList), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*playlist.PlaylistList)(nil), (*PlaylistList)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_playlist_PlaylistList_To_v0alpha1_PlaylistList(a.(*playlist.PlaylistList), b.(*PlaylistList), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*Spec)(nil), (*playlist.Spec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v0alpha1_Spec_To_playlist_Spec(a.(*Spec), b.(*playlist.Spec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*playlist.Spec)(nil), (*Spec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_playlist_Spec_To_v0alpha1_Spec(a.(*playlist.Spec), b.(*Spec), scope) - }); err != nil { - return err - } - return nil -} - -func autoConvert_v0alpha1_Item_To_playlist_Item(in *Item, out *playlist.Item, s conversion.Scope) error { - out.Type = playlist.ItemType(in.Type) - out.Value = in.Value - return nil -} - -// Convert_v0alpha1_Item_To_playlist_Item is an autogenerated conversion function. -func Convert_v0alpha1_Item_To_playlist_Item(in *Item, out *playlist.Item, s conversion.Scope) error { - return autoConvert_v0alpha1_Item_To_playlist_Item(in, out, s) -} - -func autoConvert_playlist_Item_To_v0alpha1_Item(in *playlist.Item, out *Item, s conversion.Scope) error { - out.Type = ItemType(in.Type) - out.Value = in.Value - return nil -} - -// Convert_playlist_Item_To_v0alpha1_Item is an autogenerated conversion function. -func Convert_playlist_Item_To_v0alpha1_Item(in *playlist.Item, out *Item, s conversion.Scope) error { - return autoConvert_playlist_Item_To_v0alpha1_Item(in, out, s) -} - -func autoConvert_v0alpha1_Playlist_To_playlist_Playlist(in *Playlist, out *playlist.Playlist, s conversion.Scope) error { - out.ObjectMeta = in.ObjectMeta - if err := Convert_v0alpha1_Spec_To_playlist_Spec(&in.Spec, &out.Spec, s); err != nil { - return err - } - return nil -} - -// Convert_v0alpha1_Playlist_To_playlist_Playlist is an autogenerated conversion function. -func Convert_v0alpha1_Playlist_To_playlist_Playlist(in *Playlist, out *playlist.Playlist, s conversion.Scope) error { - return autoConvert_v0alpha1_Playlist_To_playlist_Playlist(in, out, s) -} - -func autoConvert_playlist_Playlist_To_v0alpha1_Playlist(in *playlist.Playlist, out *Playlist, s conversion.Scope) error { - out.ObjectMeta = in.ObjectMeta - if err := Convert_playlist_Spec_To_v0alpha1_Spec(&in.Spec, &out.Spec, s); err != nil { - return err - } - return nil -} - -// Convert_playlist_Playlist_To_v0alpha1_Playlist is an autogenerated conversion function. -func Convert_playlist_Playlist_To_v0alpha1_Playlist(in *playlist.Playlist, out *Playlist, s conversion.Scope) error { - return autoConvert_playlist_Playlist_To_v0alpha1_Playlist(in, out, s) -} - -func autoConvert_v0alpha1_PlaylistList_To_playlist_PlaylistList(in *PlaylistList, out *playlist.PlaylistList, s conversion.Scope) error { - out.ListMeta = in.ListMeta - out.Items = *(*[]playlist.Playlist)(unsafe.Pointer(&in.Items)) - return nil -} - -// Convert_v0alpha1_PlaylistList_To_playlist_PlaylistList is an autogenerated conversion function. -func Convert_v0alpha1_PlaylistList_To_playlist_PlaylistList(in *PlaylistList, out *playlist.PlaylistList, s conversion.Scope) error { - return autoConvert_v0alpha1_PlaylistList_To_playlist_PlaylistList(in, out, s) -} - -func autoConvert_playlist_PlaylistList_To_v0alpha1_PlaylistList(in *playlist.PlaylistList, out *PlaylistList, s conversion.Scope) error { - out.ListMeta = in.ListMeta - out.Items = *(*[]Playlist)(unsafe.Pointer(&in.Items)) - return nil -} - -// Convert_playlist_PlaylistList_To_v0alpha1_PlaylistList is an autogenerated conversion function. -func Convert_playlist_PlaylistList_To_v0alpha1_PlaylistList(in *playlist.PlaylistList, out *PlaylistList, s conversion.Scope) error { - return autoConvert_playlist_PlaylistList_To_v0alpha1_PlaylistList(in, out, s) -} - -func autoConvert_v0alpha1_Spec_To_playlist_Spec(in *Spec, out *playlist.Spec, s conversion.Scope) error { - out.Title = in.Title - out.Interval = in.Interval - out.Items = *(*[]playlist.Item)(unsafe.Pointer(&in.Items)) - return nil -} - -// Convert_v0alpha1_Spec_To_playlist_Spec is an autogenerated conversion function. -func Convert_v0alpha1_Spec_To_playlist_Spec(in *Spec, out *playlist.Spec, s conversion.Scope) error { - return autoConvert_v0alpha1_Spec_To_playlist_Spec(in, out, s) -} - -func autoConvert_playlist_Spec_To_v0alpha1_Spec(in *playlist.Spec, out *Spec, s conversion.Scope) error { - out.Title = in.Title - out.Interval = in.Interval - out.Items = *(*[]Item)(unsafe.Pointer(&in.Items)) - return nil -} - -// Convert_playlist_Spec_To_v0alpha1_Spec is an autogenerated conversion function. -func Convert_playlist_Spec_To_v0alpha1_Spec(in *playlist.Spec, out *Spec, s conversion.Scope) error { - return autoConvert_playlist_Spec_To_v0alpha1_Spec(in, out, s) -} diff --git a/pkg/apis/playlist/v0alpha1/zz_generated.openapi.go b/pkg/apis/playlist/v0alpha1/zz_generated.openapi.go index 4be50c3a8f7..0e9be61c3bf 100644 --- a/pkg/apis/playlist/v0alpha1/zz_generated.openapi.go +++ b/pkg/apis/playlist/v0alpha1/zz_generated.openapi.go @@ -14,7 +14,7 @@ import ( spec "k8s.io/kube-openapi/pkg/validation/spec" ) -func getOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { +func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1.Item": schema_pkg_apis_playlist_v0alpha1_Item(ref), "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1.Playlist": schema_pkg_apis_playlist_v0alpha1_Playlist(ref), diff --git a/pkg/apis/playlist/zz_generated.deepcopy.go b/pkg/apis/playlist/zz_generated.deepcopy.go deleted file mode 100644 index 87997bf7079..00000000000 --- a/pkg/apis/playlist/zz_generated.deepcopy.go +++ /dev/null @@ -1,123 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by deepcopy-gen. DO NOT EDIT. - -package playlist - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Item) DeepCopyInto(out *Item) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Item. -func (in *Item) DeepCopy() *Item { - if in == nil { - return nil - } - out := new(Item) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Playlist) DeepCopyInto(out *Playlist) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Playlist. -func (in *Playlist) DeepCopy() *Playlist { - if in == nil { - return nil - } - out := new(Playlist) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Playlist) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PlaylistList) DeepCopyInto(out *PlaylistList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Playlist, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlaylistList. -func (in *PlaylistList) DeepCopy() *PlaylistList { - if in == nil { - return nil - } - out := new(PlaylistList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *PlaylistList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Spec) DeepCopyInto(out *Spec) { - *out = *in - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Item, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. -func (in *Spec) DeepCopy() *Spec { - if in == nil { - return nil - } - out := new(Spec) - in.DeepCopyInto(out) - return out -} diff --git a/pkg/apis/wireset.go b/pkg/apis/wireset.go deleted file mode 100644 index dd7465bf7e5..00000000000 --- a/pkg/apis/wireset.go +++ /dev/null @@ -1,17 +0,0 @@ -package apis - -import ( - "github.com/google/wire" - - examplev0alpha1 "github.com/grafana/grafana/pkg/apis/example/v0alpha1" - "github.com/grafana/grafana/pkg/apis/playlist" - playlistsv0alpha1 "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" -) - -// WireSet is the list of all services -// NOTE: you must also register the service in: pkg/registry/apis/apis.go -var WireSet = wire.NewSet( - playlist.RegisterAPIService, - playlistsv0alpha1.RegisterAPIService, - examplev0alpha1.RegisterAPIService, -) diff --git a/pkg/registry/apis/apis.go b/pkg/registry/apis/apis.go index 300d6778f9c..302e4b8908e 100644 --- a/pkg/registry/apis/apis.go +++ b/pkg/registry/apis/apis.go @@ -3,10 +3,9 @@ package apiregistry import ( "context" - examplev0alpha1 "github.com/grafana/grafana/pkg/apis/example/v0alpha1" - "github.com/grafana/grafana/pkg/apis/playlist" - playlistsv0alpha1 "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" "github.com/grafana/grafana/pkg/registry" + "github.com/grafana/grafana/pkg/registry/apis/example" + "github.com/grafana/grafana/pkg/registry/apis/playlist" ) var ( @@ -15,12 +14,11 @@ var ( type Service struct{} -// ProvideService is an entry point for each service that will force initialization +// ProvideRegistryServiceSink is an entry point for each service that will force initialization // and give each builder the chance to register itself with the main server -func ProvideService( +func ProvideRegistryServiceSink( _ *playlist.PlaylistAPIBuilder, - _ *playlistsv0alpha1.PlaylistAPIBuilder, - _ *examplev0alpha1.TestingAPIBuilder, + _ *example.TestingAPIBuilder, ) *Service { return &Service{} } diff --git a/pkg/apis/example/v0alpha1/register.go b/pkg/registry/apis/example/register.go similarity index 97% rename from pkg/apis/example/v0alpha1/register.go rename to pkg/registry/apis/example/register.go index 7dfca278ae6..7222d993d34 100644 --- a/pkg/apis/example/v0alpha1/register.go +++ b/pkg/registry/apis/example/register.go @@ -1,11 +1,9 @@ -package v0alpha1 +package example import ( "fmt" "net/http" - "github.com/grafana/grafana/pkg/services/featuremgmt" - grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -19,6 +17,10 @@ import ( common "k8s.io/kube-openapi/pkg/common" "k8s.io/kube-openapi/pkg/spec3" "k8s.io/kube-openapi/pkg/validation/spec" + + example "github.com/grafana/grafana/pkg/apis/example/v0alpha1" + "github.com/grafana/grafana/pkg/services/featuremgmt" + grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver" ) // GroupName is the group name for this API. @@ -68,7 +70,7 @@ func (b *TestingAPIBuilder) GetAPIGroupInfo( } func (b *TestingAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions { - return getOpenAPIDefinitions + return example.GetOpenAPIDefinitions } // Register additional routes with the server @@ -188,7 +190,7 @@ var ( // Adds the list of known types to the given scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &RuntimeInfo{}, + &example.RuntimeInfo{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/pkg/apis/example/v0alpha1/storage.go b/pkg/registry/apis/example/storage.go similarity index 89% rename from pkg/apis/example/v0alpha1/storage.go rename to pkg/registry/apis/example/storage.go index 33322f9581b..b1abd27ab18 100644 --- a/pkg/apis/example/v0alpha1/storage.go +++ b/pkg/registry/apis/example/storage.go @@ -1,4 +1,4 @@ -package v0alpha1 +package example import ( "context" @@ -9,6 +9,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/rest" + example "github.com/grafana/grafana/pkg/apis/example/v0alpha1" "github.com/grafana/grafana/pkg/setting" ) @@ -20,12 +21,12 @@ var ( ) type staticStorage struct { - info RuntimeInfo + info example.RuntimeInfo } func newDeploymentInfoStorage() *staticStorage { return &staticStorage{ - info: RuntimeInfo{ + info: example.RuntimeInfo{ TypeMeta: metav1.TypeMeta{ APIVersion: APIVersion, Kind: "DeploymentInfo", @@ -43,7 +44,7 @@ func newDeploymentInfoStorage() *staticStorage { } func (s *staticStorage) New() runtime.Object { - return &RuntimeInfo{} + return &example.RuntimeInfo{} } func (s *staticStorage) Destroy() {} @@ -57,7 +58,7 @@ func (s *staticStorage) GetSingularName() string { } func (s *staticStorage) NewList() runtime.Object { - return &RuntimeInfo{} + return &example.RuntimeInfo{} } func (s *staticStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { diff --git a/pkg/apis/playlist/conversions.go b/pkg/registry/apis/playlist/conversions.go similarity index 75% rename from pkg/apis/playlist/conversions.go rename to pkg/registry/apis/playlist/conversions.go index adffda00343..60f785a8a60 100644 --- a/pkg/apis/playlist/conversions.go +++ b/pkg/registry/apis/playlist/conversions.go @@ -10,14 +10,15 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" + playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" "github.com/grafana/grafana/pkg/kinds" "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" - "github.com/grafana/grafana/pkg/services/playlist" + playlistsvc "github.com/grafana/grafana/pkg/services/playlist" ) -func UnstructuredToLegacyPlaylist(item unstructured.Unstructured) *playlist.Playlist { +func UnstructuredToLegacyPlaylist(item unstructured.Unstructured) *playlistsvc.Playlist { spec := item.Object["spec"].(map[string]any) - return &playlist.Playlist{ + return &playlistsvc.Playlist{ UID: item.GetName(), Name: spec["title"].(string), Interval: spec["interval"].(string), @@ -25,9 +26,9 @@ func UnstructuredToLegacyPlaylist(item unstructured.Unstructured) *playlist.Play } } -func UnstructuredToLegacyPlaylistDTO(item unstructured.Unstructured) *playlist.PlaylistDTO { +func UnstructuredToLegacyPlaylistDTO(item unstructured.Unstructured) *playlistsvc.PlaylistDTO { spec := item.Object["spec"].(map[string]any) - dto := &playlist.PlaylistDTO{ + dto := &playlistsvc.PlaylistDTO{ Uid: item.GetName(), Name: spec["title"].(string), Interval: spec["interval"].(string), @@ -43,14 +44,14 @@ func UnstructuredToLegacyPlaylistDTO(item unstructured.Unstructured) *playlist.P return dto } -func convertToK8sResource(v *playlist.PlaylistDTO, namespacer request.NamespaceMapper) *Playlist { - spec := Spec{ +func convertToK8sResource(v *playlistsvc.PlaylistDTO, namespacer request.NamespaceMapper) *playlist.Playlist { + spec := playlist.Spec{ Title: v.Name, Interval: v.Interval, } for _, item := range v.Items { - spec.Items = append(spec.Items, Item{ - Type: ItemType(item.Type), + spec.Items = append(spec.Items, playlist.Item{ + Type: playlist.ItemType(item.Type), Value: item.Value, }) } @@ -63,7 +64,7 @@ func convertToK8sResource(v *playlist.PlaylistDTO, namespacer request.NamespaceM Key: fmt.Sprintf("%d", v.Id), }) } - return &Playlist{ + return &playlist.Playlist{ ObjectMeta: metav1.ObjectMeta{ Name: v.Uid, UID: types.UID(v.Uid), @@ -76,19 +77,19 @@ func convertToK8sResource(v *playlist.PlaylistDTO, namespacer request.NamespaceM } } -func convertToLegacyUpdateCommand(p *Playlist, orgId int64) (*playlist.UpdatePlaylistCommand, error) { +func convertToLegacyUpdateCommand(p *playlist.Playlist, orgId int64) (*playlistsvc.UpdatePlaylistCommand, error) { spec := p.Spec - cmd := &playlist.UpdatePlaylistCommand{ + cmd := &playlistsvc.UpdatePlaylistCommand{ UID: p.Name, Name: spec.Title, Interval: spec.Interval, OrgId: orgId, } for _, item := range spec.Items { - if item.Type == ItemTypeDashboardById { + if item.Type == playlist.ItemTypeDashboardById { return nil, fmt.Errorf("unsupported item type: %s", item.Type) } - cmd.Items = append(cmd.Items, playlist.PlaylistItem{ + cmd.Items = append(cmd.Items, playlistsvc.PlaylistItem{ Type: string(item.Type), Value: item.Value, }) diff --git a/pkg/apis/playlist/conversions_test.go b/pkg/registry/apis/playlist/conversions_test.go similarity index 100% rename from pkg/apis/playlist/conversions_test.go rename to pkg/registry/apis/playlist/conversions_test.go diff --git a/pkg/apis/playlist/legacy_storage.go b/pkg/registry/apis/playlist/legacy_storage.go similarity index 86% rename from pkg/apis/playlist/legacy_storage.go rename to pkg/registry/apis/playlist/legacy_storage.go index 7bad9013a47..d5c962343ec 100644 --- a/pkg/apis/playlist/legacy_storage.go +++ b/pkg/registry/apis/playlist/legacy_storage.go @@ -12,8 +12,9 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/registry/rest" + playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" "github.com/grafana/grafana/pkg/services/grafana-apiserver/endpoints/request" - "github.com/grafana/grafana/pkg/services/playlist" + playlistsvc "github.com/grafana/grafana/pkg/services/playlist" ) var ( @@ -28,7 +29,7 @@ var ( ) type legacyStorage struct { - service playlist.Service + service playlistsvc.Service namespacer request.NamespaceMapper tableConverter rest.TableConvertor @@ -37,7 +38,7 @@ type legacyStorage struct { } func (s *legacyStorage) New() runtime.Object { - return &Playlist{} + return &playlist.Playlist{} } func (s *legacyStorage) Destroy() {} @@ -51,7 +52,7 @@ func (s *legacyStorage) GetSingularName() string { } func (s *legacyStorage) NewList() runtime.Object { - return &PlaylistList{} + return &playlist.PlaylistList{} } func (s *legacyStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { @@ -70,7 +71,7 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO if options.Limit > 0 { limit = int(options.Limit) } - res, err := s.service.Search(ctx, &playlist.GetPlaylistsQuery{ + res, err := s.service.Search(ctx, &playlistsvc.GetPlaylistsQuery{ OrgId: info.OrgID, Limit: limit, }) @@ -78,9 +79,9 @@ func (s *legacyStorage) List(ctx context.Context, options *internalversion.ListO return nil, err } - list := &PlaylistList{} + list := &playlist.PlaylistList{} for _, v := range res { - p, err := s.service.Get(ctx, &playlist.GetPlaylistByUidQuery{ + p, err := s.service.Get(ctx, &playlistsvc.GetPlaylistByUidQuery{ UID: v.UID, OrgId: info.OrgID, }) @@ -101,12 +102,12 @@ func (s *legacyStorage) Get(ctx context.Context, name string, options *metav1.Ge return nil, err } - dto, err := s.service.Get(ctx, &playlist.GetPlaylistByUidQuery{ + dto, err := s.service.Get(ctx, &playlistsvc.GetPlaylistByUidQuery{ UID: name, OrgId: info.OrgID, }) if err != nil || dto == nil { - if errors.Is(err, playlist.ErrPlaylistNotFound) || err == nil { + if errors.Is(err, playlistsvc.ErrPlaylistNotFound) || err == nil { err = k8serrors.NewNotFound(s.SingularQualifiedResource, name) } return nil, err @@ -125,7 +126,7 @@ func (s *legacyStorage) Create(ctx context.Context, return nil, err } - p, ok := obj.(*Playlist) + p, ok := obj.(*playlist.Playlist) if !ok { return nil, fmt.Errorf("expected playlist?") } @@ -133,7 +134,7 @@ func (s *legacyStorage) Create(ctx context.Context, if err != nil { return nil, err } - out, err := s.service.Create(ctx, &playlist.CreatePlaylistCommand{ + out, err := s.service.Create(ctx, &playlistsvc.CreatePlaylistCommand{ UID: p.Name, Name: cmd.Name, Interval: cmd.Interval, @@ -169,7 +170,7 @@ func (s *legacyStorage) Update(ctx context.Context, if err != nil { return old, created, err } - p, ok := obj.(*Playlist) + p, ok := obj.(*playlist.Playlist) if !ok { return nil, created, fmt.Errorf("expected playlist after update") } @@ -197,11 +198,11 @@ func (s *legacyStorage) Delete(ctx context.Context, name string, deleteValidatio if err != nil { return nil, false, err } - p, ok := v.(*Playlist) + p, ok := v.(*playlist.Playlist) if !ok { return v, false, fmt.Errorf("expected a playlist response from Get") } - err = s.service.Delete(ctx, &playlist.DeletePlaylistCommand{ + err = s.service.Delete(ctx, &playlistsvc.DeletePlaylistCommand{ UID: name, OrgId: info.OrgID, }) diff --git a/pkg/apis/playlist/register.go b/pkg/registry/apis/playlist/register.go similarity index 76% rename from pkg/apis/playlist/register.go rename to pkg/registry/apis/playlist/register.go index 1658447dec2..0934c796237 100644 --- a/pkg/apis/playlist/register.go +++ b/pkg/registry/apis/playlist/register.go @@ -13,28 +13,29 @@ import ( genericapiserver "k8s.io/apiserver/pkg/server" common "k8s.io/kube-openapi/pkg/common" + playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" 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" + playlistsvc "github.com/grafana/grafana/pkg/services/playlist" "github.com/grafana/grafana/pkg/setting" ) // GroupName is the group name for this API. const GroupName = "playlist.grafana.app" -const VersionID = runtime.APIVersionInternal +const VersionID = "v0alpha1" var _ grafanaapiserver.APIGroupBuilder = (*PlaylistAPIBuilder)(nil) // This is used just so wire has something unique to return type PlaylistAPIBuilder struct { - service playlist.Service + service playlistsvc.Service namespacer request.NamespaceMapper gv schema.GroupVersion } -func RegisterAPIService(p playlist.Service, +func RegisterAPIService(p playlistsvc.Service, apiregistration grafanaapiserver.APIRegistrar, cfg *setting.Cfg, ) *PlaylistAPIBuilder { @@ -53,10 +54,27 @@ func (b *PlaylistAPIBuilder) GetGroupVersion() schema.GroupVersion { func (b *PlaylistAPIBuilder) InstallSchema(scheme *runtime.Scheme) error { scheme.AddKnownTypes(b.gv, - &Playlist{}, - &PlaylistList{}, + &playlist.Playlist{}, + &playlist.PlaylistList{}, ) - return nil + + // 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{ + 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 { + // return err + // } + metav1.AddToGroupVersion(scheme, b.gv) + return scheme.SetVersionPriority(b.gv) } func (b *PlaylistAPIBuilder) GetAPIGroupInfo( @@ -82,7 +100,7 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo( {Name: "Created At", Type: "date"}, }, func(obj runtime.Object) ([]interface{}, error) { - m, ok := obj.(*Playlist) + m, ok := obj.(*playlist.Playlist) if !ok { return nil, fmt.Errorf("expected playlist") } @@ -105,12 +123,12 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo( storage["playlists"] = grafanarest.NewDualWriter(legacyStore, store) } - apiGroupInfo.VersionedResourcesStorageMap["v0alpha1"] = storage + apiGroupInfo.VersionedResourcesStorageMap[VersionID] = storage return &apiGroupInfo, nil } func (b *PlaylistAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions { - return nil // no custom OpenAPI definitions + return playlist.GetOpenAPIDefinitions } func (b *PlaylistAPIBuilder) GetAPIRoutes() *grafanaapiserver.APIRoutes { diff --git a/pkg/apis/playlist/storage.go b/pkg/registry/apis/playlist/storage.go similarity index 83% rename from pkg/apis/playlist/storage.go rename to pkg/registry/apis/playlist/storage.go index d5d80e18b55..bd723d34b2f 100644 --- a/pkg/apis/playlist/storage.go +++ b/pkg/registry/apis/playlist/storage.go @@ -5,6 +5,7 @@ import ( "k8s.io/apiserver/pkg/registry/generic" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" + playlist "github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" grafanaregistry "github.com/grafana/grafana/pkg/services/grafana-apiserver/registry/generic" grafanarest "github.com/grafana/grafana/pkg/services/grafana-apiserver/rest" ) @@ -19,8 +20,8 @@ func newStorage(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter, le strategy := grafanaregistry.NewStrategy(scheme) store := &genericregistry.Store{ - NewFunc: func() runtime.Object { return &Playlist{} }, - NewListFunc: func() runtime.Object { return &PlaylistList{} }, + NewFunc: func() runtime.Object { return &playlist.Playlist{} }, + NewListFunc: func() runtime.Object { return &playlist.PlaylistList{} }, PredicateFunc: grafanaregistry.Matcher, DefaultQualifiedResource: legacy.DefaultQualifiedResource, SingularQualifiedResource: legacy.SingularQualifiedResource, diff --git a/pkg/registry/apis/wireset.go b/pkg/registry/apis/wireset.go index d96125ebc42..7338136a182 100644 --- a/pkg/registry/apis/wireset.go +++ b/pkg/registry/apis/wireset.go @@ -3,10 +3,15 @@ package apiregistry import ( "github.com/google/wire" - "github.com/grafana/grafana/pkg/apis" + "github.com/grafana/grafana/pkg/registry/apis/example" + "github.com/grafana/grafana/pkg/registry/apis/playlist" ) var WireSet = wire.NewSet( - ProvideService, - apis.WireSet, + ProvideRegistryServiceSink, // dummy background service that forces registration + + // Each must be added here *and* in the ServiceSink above + // playlistV0.RegisterAPIService, + playlist.RegisterAPIService, + example.RegisterAPIService, ) diff --git a/pkg/services/grafana-apiserver/service.go b/pkg/services/grafana-apiserver/service.go index 21eec399f8c..aa7e6ed241c 100644 --- a/pkg/services/grafana-apiserver/service.go +++ b/pkg/services/grafana-apiserver/service.go @@ -307,7 +307,7 @@ func (s *service) start(ctx context.Context) error { if err != nil { return err } - if g == nil { + if g == nil || len(g.PrioritizedVersions) < 1 { continue } err = server.InstallAPIGroup(g)