mirror of https://github.com/grafana/grafana.git
				
				
				
			
							parent
							
								
									aadd5bacfa
								
							
						
					
					
						commit
						0f398e940d
					
				|  | @ -67,6 +67,7 @@ | |||
| /scripts/modowners/ @grafana/backend-platform | ||||
| 
 | ||||
| /pkg/api/ @grafana/backend-platform | ||||
| /pkg/apis/ @grafana/grafana-app-platform-squad | ||||
| /pkg/bus/ @grafana/backend-platform | ||||
| /pkg/cmd/ @grafana/backend-platform | ||||
| /pkg/components/apikeygen/ @grafana/grafana-authnz-team | ||||
|  |  | |||
|  | @ -0,0 +1,14 @@ | |||
| package install | ||||
| 
 | ||||
| import ( | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	utilruntime "k8s.io/apimachinery/pkg/util/runtime" | ||||
| 
 | ||||
| 	playlistv1 "github.com/grafana/grafana/pkg/apis/playlist/v1" | ||||
| ) | ||||
| 
 | ||||
| // Install registers the API group and adds types to a scheme
 | ||||
| func Install(scheme *runtime.Scheme) { | ||||
| 	utilruntime.Must(playlistv1.AddToScheme(scheme)) | ||||
| 	utilruntime.Must(scheme.SetVersionPriority(playlistv1.SchemeGroupVersion)) | ||||
| } | ||||
|  | @ -0,0 +1,5 @@ | |||
| // +k8s:deepcopy-gen=package
 | ||||
| // +k8s:openapi-gen=true
 | ||||
| // +groupName=playlist.grafana.io
 | ||||
| 
 | ||||
| package v1 // import "github.com/grafana/grafana/pkg/apis/playlist/v1"
 | ||||
|  | @ -0,0 +1,76 @@ | |||
| package v1 | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	"k8s.io/apimachinery/pkg/apis/meta/internalversion" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apiserver/pkg/registry/rest" | ||||
| ) | ||||
| 
 | ||||
| var _ rest.Scoper = (*Handler)(nil) | ||||
| var _ rest.SingularNameProvider = (*Handler)(nil) | ||||
| var _ rest.Getter = (*Handler)(nil) | ||||
| var _ rest.Lister = (*Handler)(nil) | ||||
| var _ rest.Storage = (*Handler)(nil) | ||||
| 
 | ||||
| type Handler struct{} | ||||
| 
 | ||||
| func (r *Handler) New() runtime.Object { | ||||
| 	return &Playlist{} | ||||
| } | ||||
| 
 | ||||
| func (r *Handler) Destroy() {} | ||||
| 
 | ||||
| func (r *Handler) NamespaceScoped() bool { | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (r *Handler) GetSingularName() string { | ||||
| 	return "playlist" | ||||
| } | ||||
| 
 | ||||
| func (r *Handler) NewList() runtime.Object { | ||||
| 	return &PlaylistList{} | ||||
| } | ||||
| 
 | ||||
| func (r *Handler) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { | ||||
| 	return rest.NewDefaultTableConvertor(Resource("playlists")).ConvertToTable(ctx, object, tableOptions) | ||||
| } | ||||
| 
 | ||||
| func (r *Handler) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) { | ||||
| 	// TODO: replace
 | ||||
| 	return &PlaylistList{ | ||||
| 		TypeMeta: metav1.TypeMeta{ | ||||
| 			Kind:       "PlaylistList", | ||||
| 			APIVersion: "playlist.grafana.io/v1", | ||||
| 		}, | ||||
| 		Items: []Playlist{ | ||||
| 			{ | ||||
| 				TypeMeta: metav1.TypeMeta{ | ||||
| 					Kind:       "Playlist", | ||||
| 					APIVersion: "playlist.grafana.io/v1", | ||||
| 				}, | ||||
| 				ObjectMeta: metav1.ObjectMeta{ | ||||
| 					Name: "test", | ||||
| 				}, | ||||
| 				Name: "test", | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func (r *Handler) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { | ||||
| 	// TODO: replace
 | ||||
| 	return &Playlist{ | ||||
| 		TypeMeta: metav1.TypeMeta{ | ||||
| 			Kind:       "Playlist", | ||||
| 			APIVersion: "playlist.grafana.io/v1", | ||||
| 		}, | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Name: name, | ||||
| 		}, | ||||
| 		Name: "test", | ||||
| 	}, nil | ||||
| } | ||||
|  | @ -0,0 +1,36 @@ | |||
| package v1 | ||||
| 
 | ||||
| import ( | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| ) | ||||
| 
 | ||||
| // GroupName is the group name for this API.
 | ||||
| const GroupName = "playlist.grafana.io" | ||||
| 
 | ||||
| // SchemeGroupVersion is group version used to register these objects
 | ||||
| var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} | ||||
| 
 | ||||
| // Resource takes an unqualified resource and returns a Group qualified GroupResource
 | ||||
| func Resource(resource string) schema.GroupResource { | ||||
| 	return SchemeGroupVersion.WithResource(resource).GroupResource() | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	// SchemeBuilder points to a list of functions added to Scheme.
 | ||||
| 	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes) | ||||
| 	localSchemeBuilder = &SchemeBuilder | ||||
| 	// AddToScheme is a common registration function for mapping packaged scoped group & version keys to a scheme.
 | ||||
| 	AddToScheme = localSchemeBuilder.AddToScheme | ||||
| ) | ||||
| 
 | ||||
| // Adds the list of known types to the given scheme.
 | ||||
| func addKnownTypes(scheme *runtime.Scheme) error { | ||||
| 	scheme.AddKnownTypes(SchemeGroupVersion, | ||||
| 		&Playlist{}, | ||||
| 		&PlaylistList{}, | ||||
| 	) | ||||
| 	metav1.AddToGroupVersion(scheme, SchemeGroupVersion) | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,27 @@ | |||
| package v1 | ||||
| 
 | ||||
| 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"` | ||||
| 
 | ||||
| 	Name string `json:"name,omitempty"` | ||||
| } | ||||
| 
 | ||||
| // +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"` | ||||
| 
 | ||||
| 	Items []Playlist `json:"playlists,omitempty"` | ||||
| } | ||||
|  | @ -0,0 +1,87 @@ | |||
| //go:build !ignore_autogenerated
 | ||||
| // +build !ignore_autogenerated
 | ||||
| 
 | ||||
| // generated by scripts/k8s/update-codegen.sh
 | ||||
| 
 | ||||
| // Code generated by deepcopy-gen. DO NOT EDIT.
 | ||||
| 
 | ||||
| package v1 | ||||
| 
 | ||||
| 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 *Playlist) DeepCopyInto(out *Playlist) { | ||||
| 	*out = *in | ||||
| 	out.TypeMeta = in.TypeMeta | ||||
| 	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) | ||||
| 	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.ObjectMeta.DeepCopyInto(&out.ObjectMeta) | ||||
| 	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 *Handler) DeepCopyInto(out *Handler) { | ||||
| 	*out = *in | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Storage.
 | ||||
| func (in *Handler) DeepCopy() *Handler { | ||||
| 	if in == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	out := new(Handler) | ||||
| 	in.DeepCopyInto(out) | ||||
| 	return out | ||||
| } | ||||
|  | @ -4,27 +4,29 @@ import ( | |||
| 	"context" | ||||
| 	"crypto/x509" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 
 | ||||
| 	"github.com/go-logr/logr" | ||||
| 	"github.com/grafana/dskit/services" | ||||
| 	kindsv1 "github.com/grafana/grafana-apiserver/pkg/apis/kinds/v1" | ||||
| 	grafanaapiserver "github.com/grafana/grafana-apiserver/pkg/apiserver" | ||||
| 	"github.com/grafana/grafana-apiserver/pkg/certgenerator" | ||||
| 	grafanaapiserveroptions "github.com/grafana/grafana-apiserver/pkg/cmd/server/options" | ||||
| 	"github.com/grafana/grafana-apiserver/pkg/storage/filepath" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer" | ||||
| 	"k8s.io/apiserver/pkg/authentication/authenticator" | ||||
| 	"k8s.io/apiserver/pkg/authentication/request/headerrequest" | ||||
| 	"k8s.io/apiserver/pkg/authentication/user" | ||||
| 	"k8s.io/apiserver/pkg/registry/rest" | ||||
| 	genericapiserver "k8s.io/apiserver/pkg/server" | ||||
| 	"k8s.io/apiserver/pkg/server/options" | ||||
| 	"k8s.io/client-go/rest" | ||||
| 	clientrest "k8s.io/client-go/rest" | ||||
| 	"k8s.io/client-go/tools/clientcmd" | ||||
| 	clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | ||||
| 	"k8s.io/klog/v2" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/apis/install" | ||||
| 	playlistv1 "github.com/grafana/grafana/pkg/apis/playlist/v1" | ||||
| 	"github.com/grafana/grafana/pkg/modules" | ||||
| ) | ||||
| 
 | ||||
|  | @ -37,18 +39,41 @@ var ( | |||
| 	_ RestConfigProvider = (*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{}, | ||||
| 		&metav1.WatchEvent{}, | ||||
| 		&metav1.APIVersions{}, | ||||
| 		&metav1.APIGroupList{}, | ||||
| 		&metav1.APIGroup{}, | ||||
| 		&metav1.APIResourceList{}, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	install.Install(Scheme) | ||||
| 	// we need to add the options to empty v1
 | ||||
| 	metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Group: "", Version: "v1"}) | ||||
| 	Scheme.AddUnversionedTypes(unversionedVersion, unversionedTypes...) | ||||
| } | ||||
| 
 | ||||
| type Service interface { | ||||
| 	services.NamedService | ||||
| } | ||||
| 
 | ||||
| type RestConfigProvider interface { | ||||
| 	GetRestConfig() *rest.Config | ||||
| 	GetRestConfig() *clientrest.Config | ||||
| } | ||||
| 
 | ||||
| type service struct { | ||||
| 	*services.BasicService | ||||
| 
 | ||||
| 	restConfig *rest.Config | ||||
| 	restConfig *clientrest.Config | ||||
| 
 | ||||
| 	dataPath  string | ||||
| 	stopCh    chan struct{} | ||||
|  | @ -66,7 +91,7 @@ func New(dataPath string) (*service, error) { | |||
| 	return s, nil | ||||
| } | ||||
| 
 | ||||
| func (s *service) GetRestConfig() *rest.Config { | ||||
| func (s *service) GetRestConfig() *clientrest.Config { | ||||
| 	return s.restConfig | ||||
| } | ||||
| 
 | ||||
|  | @ -75,15 +100,15 @@ func (s *service) start(ctx context.Context) error { | |||
| 	logger.V(9) | ||||
| 	klog.SetLoggerWithOptions(logger, klog.ContextualLogger(true)) | ||||
| 
 | ||||
| 	o := grafanaapiserveroptions.NewGrafanaAPIServerOptions(os.Stdout, os.Stderr) | ||||
| 	o.RecommendedOptions.SecureServing.BindPort = 6443 | ||||
| 	o.RecommendedOptions.Authentication.RemoteKubeConfigFileOptional = true | ||||
| 	o.RecommendedOptions.Authorization.RemoteKubeConfigFileOptional = true | ||||
| 	o.RecommendedOptions.Authorization.AlwaysAllowPaths = []string{"*"} | ||||
| 	o.RecommendedOptions.Authorization.AlwaysAllowGroups = []string{user.SystemPrivilegedGroup, "grafana"} | ||||
| 	o.RecommendedOptions.Etcd = nil | ||||
| 	o.RecommendedOptions.Admission = nil | ||||
| 	o.RecommendedOptions.CoreAPI = nil | ||||
| 	o := options.NewRecommendedOptions("", unstructured.UnstructuredJSONScheme) | ||||
| 	o.SecureServing.BindPort = 6443 | ||||
| 	o.Authentication.RemoteKubeConfigFileOptional = true | ||||
| 	o.Authorization.RemoteKubeConfigFileOptional = true | ||||
| 	o.Authorization.AlwaysAllowPaths = []string{"*"} | ||||
| 	o.Authorization.AlwaysAllowGroups = []string{user.SystemPrivilegedGroup, "grafana"} | ||||
| 	o.Etcd = nil | ||||
| 	o.Admission = nil | ||||
| 	o.CoreAPI = nil | ||||
| 
 | ||||
| 	// Get the util to get the paths to pre-generated certs
 | ||||
| 	certUtil := certgenerator.CertUtil{ | ||||
|  | @ -98,21 +123,18 @@ func (s *service) start(ctx context.Context) error { | |||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	o.RecommendedOptions.SecureServing.BindAddress = net.ParseIP(certgenerator.DefaultAPIServerIp) | ||||
| 	o.RecommendedOptions.SecureServing.ServerCert.CertKey = options.CertKey{ | ||||
| 	o.SecureServing.BindAddress = net.ParseIP(certgenerator.DefaultAPIServerIp) | ||||
| 	o.SecureServing.ServerCert.CertKey = options.CertKey{ | ||||
| 		CertFile: certUtil.APIServerCertFile(), | ||||
| 		KeyFile:  certUtil.APIServerKeyFile(), | ||||
| 	} | ||||
| 
 | ||||
| 	if err := o.Complete(); err != nil { | ||||
| 		return err | ||||
| 	if err := o.Validate(); len(err) > 0 { | ||||
| 		return err[0] | ||||
| 	} | ||||
| 
 | ||||
| 	if err := o.Validate(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	serverConfig, err := o.Config() | ||||
| 	serverConfig := genericapiserver.NewRecommendedConfig(Codecs) | ||||
| 	err := o.ApplyTo(serverConfig) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | @ -122,29 +144,34 @@ func (s *service) start(ctx context.Context) error { | |||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	serverConfig.ExtraConfig.RESTOptionsGetter = filepath.NewRESTOptionsGetter(s.dataPath, unstructured.UnstructuredJSONScheme) | ||||
| 	serverConfig.GenericConfig.RESTOptionsGetter = filepath.NewRESTOptionsGetter(s.dataPath, grafanaapiserver.Codecs.LegacyCodec(kindsv1.SchemeGroupVersion)) | ||||
| 	serverConfig.GenericConfig.Config.RESTOptionsGetter = filepath.NewRESTOptionsGetter(s.dataPath, grafanaapiserver.Codecs.LegacyCodec(kindsv1.SchemeGroupVersion)) | ||||
| 
 | ||||
| 	authenticator, err := newAuthenticator(rootCert) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	serverConfig.GenericConfig.Authentication.Authenticator = authenticator | ||||
| 	serverConfig.Authentication.Authenticator = authenticator | ||||
| 
 | ||||
| 	server, err := serverConfig.Complete().New(genericapiserver.NewEmptyDelegate()) | ||||
| 	server, err := serverConfig.Complete().New("grafana-apiserver", genericapiserver.NewEmptyDelegate()) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	s.restConfig = server.GenericAPIServer.LoopbackClientConfig | ||||
| 	apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(playlistv1.GroupName, Scheme, metav1.ParameterCodec, Codecs) | ||||
| 	playlistv1storage := map[string]rest.Storage{} | ||||
| 	playlistv1storage["playlists"] = &playlistv1.Handler{} | ||||
| 
 | ||||
| 	apiGroupInfo.VersionedResourcesStorageMap["v1"] = playlistv1storage | ||||
| 	if err := server.InstallAPIGroup(&apiGroupInfo); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	s.restConfig = server.LoopbackClientConfig | ||||
| 	err = s.writeKubeConfiguration(s.restConfig) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	prepared := server.GenericAPIServer.PrepareRun() | ||||
| 	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
 | ||||
|  | @ -192,7 +219,7 @@ func (s *service) running(ctx context.Context) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *service) writeKubeConfiguration(restConfig *rest.Config) error { | ||||
| func (s *service) writeKubeConfiguration(restConfig *clientrest.Config) error { | ||||
| 	clusters := make(map[string]*clientcmdapi.Cluster) | ||||
| 	clusters["default-cluster"] = &clientcmdapi.Cluster{ | ||||
| 		Server:                restConfig.Host, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue