mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
K8s: Register apiserver as background service, and list real playlists (#75338)
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
parent
60922e5f77
commit
440f9a6ffb
4
go.mod
4
go.mod
@ -282,6 +282,7 @@ require (
|
||||
k8s.io/apiserver v0.27.1 // @grafana/grafana-app-platform-squad
|
||||
k8s.io/client-go v0.27.1 // @grafana/grafana-app-platform-squad
|
||||
k8s.io/klog/v2 v2.90.1 // @grafana/grafana-app-platform-squad
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // @grafana/grafana-app-platform-squad
|
||||
)
|
||||
|
||||
require (
|
||||
@ -300,7 +301,6 @@ require (
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/bmatcuk/doublestar v1.1.1 // indirect
|
||||
github.com/buildkite/yaml v2.1.0+incompatible // indirect
|
||||
github.com/bwmarrin/snowflake v0.3.0 // indirect
|
||||
github.com/centrifugal/protocol v0.10.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/cockroachdb/errors v1.9.1 // indirect
|
||||
@ -412,8 +412,6 @@ require (
|
||||
k8s.io/api v0.27.1 // indirect
|
||||
k8s.io/component-base v0.27.1 // indirect
|
||||
k8s.io/kms v0.27.1 // indirect
|
||||
k8s.io/kube-aggregator v0.27.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.40.0 // indirect
|
||||
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||
|
6
go.sum
6
go.sum
@ -847,8 +847,6 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
|
||||
github.com/buildkite/yaml v2.1.0+incompatible h1:xirI+ql5GzfikVNDmt+yeiXpf/v1Gt03qXTtT5WXdr8=
|
||||
github.com/buildkite/yaml v2.1.0+incompatible/go.mod h1:UoU8vbcwu1+vjZq01+KrpSeLBgQQIjL/H7Y6KwikUrI=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
|
||||
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
|
||||
github.com/caio/go-tdigest v3.1.0+incompatible h1:uoVMJ3Q5lXmVLCCqaMGHLBWnbGoN6Lpu7OAUPR60cds=
|
||||
github.com/caio/go-tdigest v3.1.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
@ -1805,8 +1803,6 @@ github.com/grafana/grafana-google-sdk-go v0.1.0 h1:LKGY8z2DSxKjYfr2flZsWgTRTZ6HG
|
||||
github.com/grafana/grafana-google-sdk-go v0.1.0/go.mod h1:Vo2TKWfDVmNTELBUM+3lkrZvFtBws0qSZdXhQxRdJrE=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.94.0/go.mod h1:3VXz4nCv6wH5SfgB3mlW39s+c+LetqSCjFj7xxPC5+M=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.176.0 h1:dayiqGR6uJyJBO8rRTp/E7oKsnEjNSS0p7vVkXy/Brw=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.176.0/go.mod h1:9crAQqSzxvPe0VKC/T23cd+2I9TZb43yoOcUL/qZ5FU=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.177.0 h1:ERJ38b91Zw8tkz8MgHio5pVeK7ySaf5+i1I4F28YgWs=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.177.0/go.mod h1:9crAQqSzxvPe0VKC/T23cd+2I9TZb43yoOcUL/qZ5FU=
|
||||
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482 h1:1YNoeIhii4UIIQpCPU+EXidnqf449d0C3ZntAEt4KSo=
|
||||
@ -4087,8 +4083,6 @@ k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
|
||||
k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kms v0.27.1 h1:JTSQbJb+mcobScQwF0bOmZhIwP17k8GvBsiLlA6SQqw=
|
||||
k8s.io/kms v0.27.1/go.mod h1:VuTsw0uHlSycKLCkypCGxfFCjLfzf/5YMeATECd/zJA=
|
||||
k8s.io/kube-aggregator v0.27.1 h1:NYgl5PDV/oX1yqAZIkRnb+KtW+eLykzc6hHg81ECgiI=
|
||||
k8s.io/kube-aggregator v0.27.1/go.mod h1:S1YUIr4mU0MjKm6kg2fUyIKK5fWgwoHFMgNjlI5JFpM=
|
||||
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
|
||||
k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY=
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
|
||||
|
@ -4,13 +4,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
)
|
||||
|
||||
var _ rest.Scoper = (*handler)(nil)
|
||||
@ -47,54 +48,83 @@ func (r *handler) ConvertToTable(ctx context.Context, object runtime.Object, tab
|
||||
|
||||
func (r *handler) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
|
||||
ns, ok := request.NamespaceFrom(ctx)
|
||||
if ok && ns != "" {
|
||||
orgId, err := apis.NamespaceToOrgID(ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("OrgID: %d\n", orgId)
|
||||
if !ok || ns == "" {
|
||||
return nil, fmt.Errorf("namespace required")
|
||||
}
|
||||
|
||||
// TODO: replace
|
||||
return &PlaylistList{
|
||||
orgId, err := grafanaapiserver.NamespaceToOrgID(ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limit := 100
|
||||
if options.Limit > 0 {
|
||||
limit = int(options.Limit)
|
||||
}
|
||||
res, err := r.service.Search(ctx, &playlist.GetPlaylistsQuery{
|
||||
OrgId: orgId,
|
||||
Limit: limit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := &PlaylistList{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "PlaylistList",
|
||||
APIVersion: APIVersion,
|
||||
},
|
||||
Items: []Playlist{
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Playlist",
|
||||
APIVersion: APIVersion,
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test",
|
||||
},
|
||||
Name: "test",
|
||||
}
|
||||
for _, v := range res {
|
||||
p := Playlist{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Playlist",
|
||||
APIVersion: APIVersion,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: v.UID,
|
||||
},
|
||||
}
|
||||
p.Name = v.Name + " // " + v.Interval
|
||||
list.Items = append(list.Items, p)
|
||||
// TODO?? if table... we don't need the body of each, otherwise full lookup!
|
||||
}
|
||||
if len(list.Items) == limit {
|
||||
list.Continue = "<more>" // TODO?
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (r *handler) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
||||
ns, ok := request.NamespaceFrom(ctx)
|
||||
if ok && ns != "" {
|
||||
orgId, err := apis.NamespaceToOrgID(ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("OrgID: %d\n", orgId)
|
||||
if !ok || ns == "" {
|
||||
return nil, fmt.Errorf("namespace required")
|
||||
}
|
||||
|
||||
orgId, err := grafanaapiserver.NamespaceToOrgID(ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p, err := r.service.Get(ctx, &playlist.GetPlaylistByUidQuery{
|
||||
UID: name,
|
||||
OrgId: orgId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p == nil {
|
||||
return nil, fmt.Errorf("not found?")
|
||||
}
|
||||
|
||||
// TODO: replace
|
||||
return &Playlist{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Playlist",
|
||||
APIVersion: APIVersion,
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Name: p.Uid,
|
||||
},
|
||||
Name: "test",
|
||||
Name: p.Name + "//" + p.Interval,
|
||||
}, nil
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/apis"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@ -10,6 +9,9 @@ import (
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
common "k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/playlist"
|
||||
)
|
||||
|
||||
// GroupName is the group name for this API.
|
||||
@ -17,14 +19,22 @@ const GroupName = "playlist.x.grafana.com"
|
||||
const VersionID = "v0-alpha" //
|
||||
const APIVersion = GroupName + "/" + VersionID
|
||||
|
||||
type builder struct{}
|
||||
var _ grafanaapiserver.APIGroupBuilder = (*PlaylistAPIBuilder)(nil)
|
||||
|
||||
// TODO.. this will have wire dependencies
|
||||
func GetAPIGroupBuilder() apis.APIGroupBuilder {
|
||||
return &builder{}
|
||||
// This is used just so wire has something unique to return
|
||||
type PlaylistAPIBuilder struct {
|
||||
service playlist.Service
|
||||
}
|
||||
|
||||
func (b *builder) InstallSchema(scheme *runtime.Scheme) error {
|
||||
func RegisterAPIService(p playlist.Service, apiregistration grafanaapiserver.APIRegistrar) *PlaylistAPIBuilder {
|
||||
builder := &PlaylistAPIBuilder{
|
||||
service: p,
|
||||
}
|
||||
apiregistration.RegisterAPI(builder)
|
||||
return builder
|
||||
}
|
||||
|
||||
func (b *PlaylistAPIBuilder) InstallSchema(scheme *runtime.Scheme) error {
|
||||
err := AddToScheme(scheme)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -32,26 +42,26 @@ func (b *builder) InstallSchema(scheme *runtime.Scheme) error {
|
||||
return scheme.SetVersionPriority(SchemeGroupVersion)
|
||||
}
|
||||
|
||||
func (b *builder) GetAPIGroupInfo(
|
||||
func (b *PlaylistAPIBuilder) GetAPIGroupInfo(
|
||||
scheme *runtime.Scheme,
|
||||
codecs serializer.CodecFactory, // pointer?
|
||||
) *genericapiserver.APIGroupInfo {
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(GroupName, scheme, metav1.ParameterCodec, codecs)
|
||||
storage := map[string]rest.Storage{}
|
||||
storage["playlists"] = &handler{
|
||||
service: nil, // TODO!!!!!
|
||||
service: b.service,
|
||||
}
|
||||
|
||||
apiGroupInfo.VersionedResourcesStorageMap[VersionID] = storage
|
||||
return &apiGroupInfo
|
||||
}
|
||||
|
||||
func (b *builder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions {
|
||||
func (b *PlaylistAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefinitions {
|
||||
return getOpenAPIDefinitions
|
||||
}
|
||||
|
||||
// Register additional routes with the server
|
||||
func (b *builder) GetOpenAPIPostProcessor() func(*spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
func (b *PlaylistAPIBuilder) GetOpenAPIPostProcessor() func(*spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,8 @@ type Playlist struct {
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type PlaylistList 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"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []Playlist `json:"playlists,omitempty"`
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func (in *Playlist) DeepCopyObject() runtime.Object {
|
||||
func (in *PlaylistList) DeepCopyInto(out *PlaylistList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]Playlist, len(*in))
|
||||
|
10
pkg/apis/wireset.go
Normal file
10
pkg/apis/wireset.go
Normal file
@ -0,0 +1,10 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
playlistv1 "github.com/grafana/grafana/pkg/apis/playlist/v1"
|
||||
)
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
playlistv1.RegisterAPIService,
|
||||
)
|
25
pkg/registry/apis/apis.go
Normal file
25
pkg/registry/apis/apis.go
Normal file
@ -0,0 +1,25 @@
|
||||
package apiregistry
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
playlistsv1 "github.com/grafana/grafana/pkg/apis/playlist/v1"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
)
|
||||
|
||||
var (
|
||||
_ registry.BackgroundService = (*Service)(nil)
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
|
||||
func ProvideService(
|
||||
_ *playlistsv1.PlaylistAPIBuilder,
|
||||
) *Service {
|
||||
return &Service{}
|
||||
}
|
||||
|
||||
func (s *Service) Run(ctx context.Context) error {
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
12
pkg/registry/apis/wireset.go
Normal file
12
pkg/registry/apis/wireset.go
Normal file
@ -0,0 +1,12 @@
|
||||
package apiregistry
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis"
|
||||
)
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideService,
|
||||
apis.WireSet,
|
||||
)
|
@ -8,11 +8,13 @@ import (
|
||||
uss "github.com/grafana/grafana/pkg/infra/usagestats/service"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats/statscollector"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
apiregistry "github.com/grafana/grafana/pkg/registry/apis"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/anonymous/anonimpl"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/services/cleanup"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardsnapshots"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
ldapapi "github.com/grafana/grafana/pkg/services/ldap/api"
|
||||
@ -51,16 +53,16 @@ func ProvideBackgroundServiceRegistry(
|
||||
secretsService *secretsManager.SecretsService, remoteCache *remotecache.RemoteCache, StorageService store.StorageService, searchService searchV2.SearchService, entityEventsService store.EntityEventsService,
|
||||
saService *samanager.ServiceAccountsService, authInfoService *authinfoservice.Implementation,
|
||||
grpcServerProvider grpcserver.Provider, secretMigrationProvider secretsMigrations.SecretMigrationProvider, loginAttemptService *loginattemptimpl.Service,
|
||||
bundleService *supportbundlesimpl.Service,
|
||||
publicDashboardsMetric *publicdashboardsmetric.Service,
|
||||
keyRetriever *dynamic.KeyRetriever,
|
||||
dynamicAngularDetectorsProvider *angulardetectorsprovider.Dynamic,
|
||||
bundleService *supportbundlesimpl.Service, publicDashboardsMetric *publicdashboardsmetric.Service,
|
||||
keyRetriever *dynamic.KeyRetriever, dynamicAngularDetectorsProvider *angulardetectorsprovider.Dynamic,
|
||||
grafanaAPIServer grafanaapiserver.Service,
|
||||
anon *anonimpl.AnonDeviceService,
|
||||
// Need to make sure these are initialized, is there a better place to put them?
|
||||
_ dashboardsnapshots.Service, _ *alerting.AlertNotificationService,
|
||||
_ serviceaccounts.Service, _ *guardian.Provider,
|
||||
_ *plugindashboardsservice.DashboardUpdater, _ *sanitizer.Provider,
|
||||
_ *grpcserver.HealthService, _ entity.EntityStoreServer, _ *grpcserver.ReflectionService, _ *ldapapi.Service,
|
||||
_ *apiregistry.Service,
|
||||
) *BackgroundServiceRegistry {
|
||||
return NewBackgroundServiceRegistry(
|
||||
httpServer,
|
||||
@ -94,6 +96,7 @@ func ProvideBackgroundServiceRegistry(
|
||||
publicDashboardsMetric,
|
||||
keyRetriever,
|
||||
dynamicAngularDetectorsProvider,
|
||||
grafanaAPIServer,
|
||||
anon,
|
||||
)
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
@ -16,7 +15,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@ -122,13 +120,14 @@ func (s *ModuleServer) Run() error {
|
||||
return NewService(s.cfg, s.opts, s.apiOpts)
|
||||
})
|
||||
|
||||
if s.features.IsEnabled(featuremgmt.FlagGrafanaAPIServer) {
|
||||
m.RegisterModule(modules.GrafanaAPIServer, func() (services.Service, error) {
|
||||
return grafanaapiserver.New(path.Join(s.cfg.DataPath, "k8s"))
|
||||
})
|
||||
} else {
|
||||
s.log.Debug("apiserver feature is disabled")
|
||||
}
|
||||
// TODO: uncomment this once the apiserver is ready to be run as a standalone target
|
||||
//if s.features.IsEnabled(featuremgmt.FlagGrafanaAPIServer) {
|
||||
// m.RegisterModule(modules.GrafanaAPIServer, func() (services.Service, error) {
|
||||
// return grafanaapiserver.New(path.Join(s.cfg.DataPath, "k8s"))
|
||||
// })
|
||||
//} else {
|
||||
// s.log.Debug("apiserver feature is disabled")
|
||||
//}
|
||||
|
||||
m.RegisterModule(modules.All, nil)
|
||||
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/middleware/csrf"
|
||||
"github.com/grafana/grafana/pkg/middleware/loggermw"
|
||||
apiregistry "github.com/grafana/grafana/pkg/registry/apis"
|
||||
"github.com/grafana/grafana/pkg/registry/corekind"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
@ -63,6 +64,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/grafana-apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
grpccontext "github.com/grafana/grafana/pkg/services/grpcserver/context"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver/interceptors"
|
||||
@ -359,6 +361,8 @@ var wireBasicSet = wire.NewSet(
|
||||
loggermw.Provide,
|
||||
signingkeysimpl.ProvideEmbeddedSigningKeysService,
|
||||
wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)),
|
||||
grafanaapiserver.WireSet,
|
||||
apiregistry.WireSet,
|
||||
)
|
||||
|
||||
var wireSet = wire.NewSet(
|
||||
|
@ -1,4 +1,4 @@
|
||||
package apis
|
||||
package grafanaapiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,7 +1,6 @@
|
||||
package grafanaapiserver
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/apis"
|
||||
"golang.org/x/exp/maps"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
common "k8s.io/kube-openapi/pkg/common"
|
||||
@ -9,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// This should eventually live in grafana-app-sdk
|
||||
func getOpenAPIDefinitions(builders []apis.APIGroupBuilder) common.GetOpenAPIDefinitions {
|
||||
func getOpenAPIDefinitions(builders []APIGroupBuilder) common.GetOpenAPIDefinitions {
|
||||
return func(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
|
||||
defs := getStandardOpenAPIDefinitions(ref)
|
||||
for _, builder := range builders {
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"crypto/x509"
|
||||
"net"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/grafana/dskit/services"
|
||||
@ -18,6 +20,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/authentication/request/headerrequest"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||
"k8s.io/apiserver/pkg/endpoints/responsewriter"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/apiserver/pkg/util/openapi"
|
||||
@ -27,9 +30,15 @@ import (
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis"
|
||||
playlistv1 "github.com/grafana/grafana/pkg/apis/playlist/v1"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -37,15 +46,16 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
_ Service = (*service)(nil)
|
||||
_ RestConfigProvider = (*service)(nil)
|
||||
_ Service = (*service)(nil)
|
||||
_ RestConfigProvider = (*service)(nil)
|
||||
_ registry.BackgroundService = (*service)(nil)
|
||||
_ registry.CanBeDisabled = (*service)(nil)
|
||||
)
|
||||
|
||||
var (
|
||||
Scheme = runtime.NewScheme()
|
||||
Codecs = serializer.NewCodecFactory(Scheme)
|
||||
|
||||
// if you modify this, make sure you update the crEncoder
|
||||
unversionedVersion = schema.GroupVersion{Group: "", Version: "v1"}
|
||||
unversionedTypes = []runtime.Object{
|
||||
&metav1.Status{},
|
||||
@ -65,6 +75,12 @@ func init() {
|
||||
|
||||
type Service interface {
|
||||
services.NamedService
|
||||
registry.BackgroundService
|
||||
registry.CanBeDisabled
|
||||
}
|
||||
|
||||
type APIRegistrar interface {
|
||||
RegisterAPI(builder APIGroupBuilder)
|
||||
}
|
||||
|
||||
type RestConfigProvider interface {
|
||||
@ -76,19 +92,50 @@ type service struct {
|
||||
|
||||
restConfig *clientrest.Config
|
||||
|
||||
enabled bool
|
||||
dataPath string
|
||||
stopCh chan struct{}
|
||||
stoppedCh chan error
|
||||
|
||||
rr routing.RouteRegister
|
||||
handler web.Handler
|
||||
builders []APIGroupBuilder
|
||||
}
|
||||
|
||||
func New(dataPath string) (*service, error) {
|
||||
func ProvideService(cfg *setting.Cfg,
|
||||
rr routing.RouteRegister,
|
||||
) (*service, error) {
|
||||
s := &service{
|
||||
dataPath: dataPath,
|
||||
enabled: cfg.IsFeatureToggleEnabled(featuremgmt.FlagGrafanaAPIServer),
|
||||
rr: rr,
|
||||
dataPath: path.Join(cfg.DataPath, "k8s"),
|
||||
stopCh: make(chan struct{}),
|
||||
builders: []APIGroupBuilder{},
|
||||
}
|
||||
|
||||
// This will be used when running as a dskit service
|
||||
s.BasicService = services.NewBasicService(s.start, s.running, nil).WithName(modules.GrafanaAPIServer)
|
||||
|
||||
// TODO: this is very hacky
|
||||
// We need to register the routes in ProvideService to make sure
|
||||
// the routes are registered before the Grafana HTTP server starts.
|
||||
s.rr.Group("/k8s", func(k8sRoute routing.RouteRegister) {
|
||||
handler := func(c *contextmodel.ReqContext) {
|
||||
if s.handler == nil {
|
||||
c.Resp.WriteHeader(404)
|
||||
_, _ = c.Resp.Write([]byte("Not found"))
|
||||
return
|
||||
}
|
||||
|
||||
if handle, ok := s.handler.(func(c *contextmodel.ReqContext)); ok {
|
||||
handle(c)
|
||||
return
|
||||
}
|
||||
}
|
||||
k8sRoute.Any("/", middleware.ReqSignedIn, handler)
|
||||
k8sRoute.Any("/*", middleware.ReqSignedIn, handler)
|
||||
})
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@ -96,6 +143,22 @@ func (s *service) GetRestConfig() *clientrest.Config {
|
||||
return s.restConfig
|
||||
}
|
||||
|
||||
func (s *service) IsDisabled() bool {
|
||||
return !s.enabled
|
||||
}
|
||||
|
||||
// Run is an adapter for the BackgroundService interface.
|
||||
func (s *service) Run(ctx context.Context) error {
|
||||
if err := s.start(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.running(ctx)
|
||||
}
|
||||
|
||||
func (s *service) RegisterAPI(builder APIGroupBuilder) {
|
||||
s.builders = append(s.builders, builder)
|
||||
}
|
||||
|
||||
func (s *service) start(ctx context.Context) error {
|
||||
logger := logr.New(newLogAdapter())
|
||||
logger.V(9)
|
||||
@ -153,9 +216,7 @@ func (s *service) start(ctx context.Context) error {
|
||||
serverConfig.Authentication.Authenticator = authenticator
|
||||
|
||||
// Get the list of groups the server will support
|
||||
builders := []apis.APIGroupBuilder{
|
||||
playlistv1.GetAPIGroupBuilder(),
|
||||
}
|
||||
builders := s.builders
|
||||
|
||||
// Install schemas
|
||||
for _, b := range builders {
|
||||
@ -199,10 +260,8 @@ func (s *service) start(ctx context.Context) error {
|
||||
|
||||
prepared := server.PrepareRun()
|
||||
|
||||
// TODO: not sure if we can still inject RouteRegister with the new module server setup
|
||||
// Disabling the /k8s endpoint until we have a solution
|
||||
|
||||
/* handler := func(c *contextmodel.ReqContext) {
|
||||
// TODO: this is a hack. see note in ProvideService
|
||||
s.handler = func(c *contextmodel.ReqContext) {
|
||||
req := c.Req
|
||||
req.URL.Path = strings.TrimPrefix(req.URL.Path, "/k8s")
|
||||
if req.URL.Path == "" {
|
||||
@ -221,10 +280,6 @@ func (s *service) start(ctx context.Context) error {
|
||||
resp := responsewriter.WrapForHTTP1Or2(c.Resp)
|
||||
prepared.GenericAPIServer.Handler.ServeHTTP(resp, req)
|
||||
}
|
||||
/* s.rr.Group("/k8s", func(k8sRoute routing.RouteRegister) {
|
||||
k8sRoute.Any("/", middleware.ReqSignedIn, handler)
|
||||
k8sRoute.Any("/*", middleware.ReqSignedIn, handler)
|
||||
}) */
|
||||
|
||||
go func() {
|
||||
s.stoppedCh <- prepared.Run(s.stopCh)
|
||||
|
12
pkg/services/grafana-apiserver/wireset.go
Normal file
12
pkg/services/grafana-apiserver/wireset.go
Normal file
@ -0,0 +1,12 @@
|
||||
package grafanaapiserver
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideService,
|
||||
wire.Bind(new(RestConfigProvider), new(*service)),
|
||||
wire.Bind(new(Service), new(*service)),
|
||||
wire.Bind(new(APIRegistrar), new(*service)),
|
||||
)
|
Loading…
Reference in New Issue
Block a user