K8s: improve openapi generation (#83796)
This commit is contained in:
@@ -14,12 +14,13 @@ import (
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
openapi "k8s.io/kube-openapi/pkg/common"
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1"
|
||||
datasource "github.com/grafana/grafana/pkg/apis/datasource/v0alpha1"
|
||||
query "github.com/grafana/grafana/pkg/apis/query/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/apiserver/builder"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
@@ -117,9 +118,9 @@ func (b *DataSourceAPIBuilder) GetGroupVersion() schema.GroupVersion {
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme, gv schema.GroupVersion) {
|
||||
scheme.AddKnownTypes(gv,
|
||||
&v0alpha1.DataSourceConnection{},
|
||||
&v0alpha1.DataSourceConnectionList{},
|
||||
&v0alpha1.HealthCheckResult{},
|
||||
&datasource.DataSourceConnection{},
|
||||
&datasource.DataSourceConnectionList{},
|
||||
&datasource.HealthCheckResult{},
|
||||
&unstructured.Unstructured{},
|
||||
// Query handler
|
||||
&query.QueryDataResponse{},
|
||||
@@ -152,7 +153,7 @@ func resourceFromPluginID(pluginID string) (common.ResourceInfo, error) {
|
||||
if err != nil {
|
||||
return common.ResourceInfo{}, err
|
||||
}
|
||||
return v0alpha1.GenericConnectionResourceInfo.WithGroupAndShortName(group, pluginID+"-connection"), nil
|
||||
return datasource.GenericConnectionResourceInfo.WithGroupAndShortName(group, pluginID+"-connection"), nil
|
||||
}
|
||||
|
||||
func (b *DataSourceAPIBuilder) GetAPIGroupInfo(
|
||||
@@ -177,7 +178,7 @@ func (b *DataSourceAPIBuilder) GetAPIGroupInfo(
|
||||
{Name: "Created At", Type: "date"},
|
||||
},
|
||||
func(obj any) ([]interface{}, error) {
|
||||
m, ok := obj.(*v0alpha1.DataSourceConnection)
|
||||
m, ok := obj.(*datasource.DataSourceConnection)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected connection")
|
||||
}
|
||||
@@ -220,13 +221,31 @@ func (b *DataSourceAPIBuilder) getPluginContext(ctx context.Context, uid string)
|
||||
func (b *DataSourceAPIBuilder) GetOpenAPIDefinitions() openapi.GetOpenAPIDefinitions {
|
||||
return func(ref openapi.ReferenceCallback) map[string]openapi.OpenAPIDefinition {
|
||||
defs := query.GetOpenAPIDefinitions(ref) // required when running standalone
|
||||
for k, v := range v0alpha1.GetOpenAPIDefinitions(ref) {
|
||||
for k, v := range datasource.GetOpenAPIDefinitions(ref) {
|
||||
defs[k] = v
|
||||
}
|
||||
return defs
|
||||
}
|
||||
}
|
||||
|
||||
func (b *DataSourceAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
// The plugin description
|
||||
oas.Info.Description = b.pluginJSON.Info.Description
|
||||
|
||||
// The root api URL
|
||||
root := "/apis/" + b.connectionResourceInfo.GroupVersion().String() + "/"
|
||||
|
||||
// Hide the ability to list all connections across tenants
|
||||
delete(oas.Paths.Paths, root+b.connectionResourceInfo.GroupResource().Resource)
|
||||
|
||||
// The root API discovery list
|
||||
sub := oas.Paths.Paths[root]
|
||||
if sub != nil && sub.Get != nil {
|
||||
sub.Get.Tags = []string{"API Discovery"} // sorts first in the list
|
||||
}
|
||||
return oas, nil
|
||||
}
|
||||
|
||||
// Register additional routes with the server
|
||||
func (b *DataSourceAPIBuilder) GetAPIRoutes() *builder.APIRoutes {
|
||||
return nil
|
||||
|
||||
@@ -9,17 +9,20 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis/datasource/v0alpha1"
|
||||
datasource "github.com/grafana/grafana/pkg/apis/datasource/v0alpha1"
|
||||
)
|
||||
|
||||
type subHealthREST struct {
|
||||
builder *DataSourceAPIBuilder
|
||||
}
|
||||
|
||||
var _ = rest.Connecter(&subHealthREST{})
|
||||
var (
|
||||
_ = rest.Connecter(&subHealthREST{})
|
||||
_ = rest.StorageMetadata(&subHealthREST{})
|
||||
)
|
||||
|
||||
func (r *subHealthREST) New() runtime.Object {
|
||||
return &v0alpha1.HealthCheckResult{}
|
||||
return &datasource.HealthCheckResult{}
|
||||
}
|
||||
|
||||
func (r *subHealthREST) Destroy() {
|
||||
@@ -29,28 +32,34 @@ func (r *subHealthREST) ConnectMethods() []string {
|
||||
return []string{"GET"}
|
||||
}
|
||||
|
||||
func (r *subHealthREST) ProducesMIMETypes(verb string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *subHealthREST) ProducesObject(verb string) interface{} {
|
||||
return &datasource.HealthCheckResult{}
|
||||
}
|
||||
|
||||
func (r *subHealthREST) NewConnectOptions() (runtime.Object, bool, string) {
|
||||
return nil, false, ""
|
||||
}
|
||||
|
||||
func (r *subHealthREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) {
|
||||
pluginCtx, err := r.builder.getPluginContext(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx = backend.WithGrafanaConfig(ctx, pluginCtx.GrafanaConfig)
|
||||
|
||||
healthResponse, err := r.builder.client.CheckHealth(ctx, &backend.CheckHealthRequest{
|
||||
PluginContext: pluginCtx,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
pluginCtx, err := r.builder.getPluginContext(ctx, name)
|
||||
if err != nil {
|
||||
responder.Error(err)
|
||||
return
|
||||
}
|
||||
ctx = backend.WithGrafanaConfig(ctx, pluginCtx.GrafanaConfig)
|
||||
|
||||
healthResponse, err := r.builder.client.CheckHealth(ctx, &backend.CheckHealthRequest{
|
||||
PluginContext: pluginCtx,
|
||||
})
|
||||
if err != nil {
|
||||
responder.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
rsp := &v0alpha1.HealthCheckResult{}
|
||||
rsp := &datasource.HealthCheckResult{}
|
||||
rsp.Code = int(healthResponse.Status)
|
||||
rsp.Status = healthResponse.Status.String()
|
||||
rsp.Message = healthResponse.Message
|
||||
|
||||
@@ -5,13 +5,12 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis/query/v0alpha1"
|
||||
query "github.com/grafana/grafana/pkg/apis/query/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/middleware/requestmeta"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@@ -24,51 +23,24 @@ type subQueryREST struct {
|
||||
var _ = rest.Connecter(&subQueryREST{})
|
||||
|
||||
func (r *subQueryREST) New() runtime.Object {
|
||||
return &v0alpha1.QueryDataResponse{}
|
||||
return &query.QueryDataResponse{}
|
||||
}
|
||||
|
||||
func (r *subQueryREST) Destroy() {}
|
||||
|
||||
func (r *subQueryREST) ConnectMethods() []string {
|
||||
return []string{"POST", "GET"}
|
||||
return []string{"POST"}
|
||||
}
|
||||
|
||||
func (r *subQueryREST) NewConnectOptions() (runtime.Object, bool, string) {
|
||||
return nil, false, ""
|
||||
}
|
||||
|
||||
func (r *subQueryREST) readQueries(req *http.Request) ([]backend.DataQuery, *v0alpha1.DataSourceRef, error) {
|
||||
reqDTO := v0alpha1.GenericQueryRequest{}
|
||||
// Simple URL to JSON mapping
|
||||
if req.Method == http.MethodGet {
|
||||
query := v0alpha1.GenericDataQuery{
|
||||
RefID: "A",
|
||||
MaxDataPoints: 1000,
|
||||
IntervalMS: 10,
|
||||
}
|
||||
params := req.URL.Query()
|
||||
for k := range params {
|
||||
v := params.Get(k) // the singular value
|
||||
switch k {
|
||||
case "to":
|
||||
reqDTO.To = v
|
||||
case "from":
|
||||
reqDTO.From = v
|
||||
case "maxDataPoints":
|
||||
query.MaxDataPoints, _ = strconv.ParseInt(v, 10, 64)
|
||||
case "intervalMs":
|
||||
query.IntervalMS, _ = strconv.ParseFloat(v, 64)
|
||||
case "queryType":
|
||||
query.QueryType = v
|
||||
default:
|
||||
query.AdditionalProperties()[k] = v
|
||||
}
|
||||
}
|
||||
reqDTO.Queries = []v0alpha1.GenericDataQuery{query}
|
||||
} else if err := web.Bind(req, &reqDTO); err != nil {
|
||||
func (r *subQueryREST) readQueries(req *http.Request) ([]backend.DataQuery, *query.DataSourceRef, error) {
|
||||
reqDTO := query.GenericQueryRequest{}
|
||||
if err := web.Bind(req, &reqDTO); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return legacydata.ToDataSourceQueries(reqDTO)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user