now with routes for testdata
This commit is contained in:
@@ -5,7 +5,7 @@ import (
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
)
|
||||
|
||||
// Optional extensions for an explict datasource type
|
||||
// Optional extensions for an explicit datasource type
|
||||
type DataSourceOpenAPIExtension struct {
|
||||
// When specified, this will replace the default spec
|
||||
DataSourceSpec *spec.Schema `json:"spec,omitempty"`
|
||||
@@ -17,10 +17,10 @@ type DataSourceOpenAPIExtension struct {
|
||||
Schemas map[string]*spec.Schema `json:"schemas,omitempty"`
|
||||
|
||||
// Resource routes
|
||||
Routes *spec3.Paths `json:"routes,omitempty"`
|
||||
Routes map[string]*spec3.Path `json:"routes,omitempty"`
|
||||
|
||||
// Proxy routes
|
||||
Proxy *spec3.Paths `json:"proxy,omitempty"`
|
||||
Proxy map[string]*spec3.Path `json:"proxy,omitempty"`
|
||||
}
|
||||
|
||||
type SecureValueInfo struct {
|
||||
|
||||
@@ -3,6 +3,7 @@ package datasource
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
datasourceV0 "github.com/grafana/grafana/pkg/apis/datasource/v0alpha1"
|
||||
secretsV0 "github.com/grafana/grafana/pkg/apis/secret/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/query/queryschema"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/builder"
|
||||
)
|
||||
|
||||
func (b *DataSourceAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
@@ -20,14 +22,16 @@ func (b *DataSourceAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.Op
|
||||
root := "/apis/" + b.datasourceResourceInfo.GroupVersion().String() + "/"
|
||||
|
||||
// Add queries to the request properties
|
||||
err := queryschema.AddQueriesToOpenAPI(queryschema.OASQueryOptions{
|
||||
if err := queryschema.AddQueriesToOpenAPI(queryschema.OASQueryOptions{
|
||||
Swagger: oas,
|
||||
PluginJSON: &b.pluginJSON,
|
||||
QueryTypes: b.queryTypes,
|
||||
Root: root,
|
||||
QueryPath: "namespaces/{namespace}/datasources/{name}/query",
|
||||
QueryDescription: fmt.Sprintf("Query the %s datasources", b.pluginJSON.Name),
|
||||
})
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set explicit apiVersion and kind on the datasource
|
||||
ds, ok := oas.Components.Schemas["com.github.grafana.grafana.pkg.apis.datasource.v0alpha1.DataSource"]
|
||||
@@ -93,6 +97,33 @@ func (b *DataSourceAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.Op
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if len(custom.Routes) > 0 {
|
||||
ds := oas.Paths.Paths[root+"namespaces/{namespace}/datasources/{name}"]
|
||||
if ds == nil || len(ds.Parameters) < 2 {
|
||||
return nil, fmt.Errorf("missing parmeters")
|
||||
}
|
||||
|
||||
prefix := root + "namespaces/{namespace}/datasources/{name}/resource"
|
||||
for k := range oas.Paths.Paths {
|
||||
if strings.HasPrefix(k, prefix) {
|
||||
delete(oas.Paths.Paths, k)
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range custom.Routes {
|
||||
if k != "" && !strings.HasPrefix(k, "/") {
|
||||
return nil, fmt.Errorf("path must have slash prefix")
|
||||
}
|
||||
v.Parameters = append(v.Parameters, ds.Parameters[0:2]...)
|
||||
for _, op := range builder.GetPathOperations(v) {
|
||||
if op != nil {
|
||||
op.Tags = append(op.Tags, "Route") // Custom resource?
|
||||
}
|
||||
}
|
||||
oas.Paths.Paths[prefix+k] = v // TODO add namepsace + name parameters
|
||||
}
|
||||
}
|
||||
return oas, err
|
||||
}
|
||||
|
||||
@@ -125,6 +156,205 @@ func getCustomOpenAPI(plugin string) (*datasourceV0.DataSourceOpenAPIExtension,
|
||||
}
|
||||
oas.DataSourceSpec = p
|
||||
|
||||
// Resource routes
|
||||
// https://github.com/grafana/grafana/blob/main/pkg/tsdb/grafana-testdata-datasource/resource_handler.go#L20
|
||||
unstructured := spec.RefProperty("#/components/schemas/com.github.grafana.grafana.pkg.apimachinery.apis.common.v0alpha1.Unstructured")
|
||||
unstructuredResponse := &spec3.Responses{
|
||||
ResponsesProps: spec3.ResponsesProps{
|
||||
Default: &spec3.Response{
|
||||
ResponseProps: spec3.ResponseProps{
|
||||
Content: map[string]*spec3.MediaType{
|
||||
"application/json": {
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: unstructured,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
unstructuredRequest := &spec3.RequestBody{
|
||||
RequestBodyProps: spec3.RequestBodyProps{
|
||||
Content: map[string]*spec3.MediaType{
|
||||
"applicaiton/json": {
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: unstructured,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
oas.Routes = map[string]*spec3.Path{
|
||||
"": {
|
||||
PathProps: spec3.PathProps{
|
||||
Summary: "hello world",
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Responses: &spec3.Responses{
|
||||
ResponsesProps: spec3.ResponsesProps{
|
||||
Default: &spec3.Response{
|
||||
ResponseProps: spec3.ResponseProps{
|
||||
Content: map[string]*spec3.MediaType{
|
||||
"text/plain": {
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: spec.StringProperty(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/scenarios": {
|
||||
PathProps: spec3.PathProps{
|
||||
Summary: "hello world",
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/stream": {
|
||||
PathProps: spec3.PathProps{
|
||||
Summary: "Get streaming response",
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Parameters: []*spec3.Parameter{
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "count",
|
||||
In: "query",
|
||||
Schema: spec.Int64Property(),
|
||||
Description: "number of points that will be returned",
|
||||
Example: 10,
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "start",
|
||||
In: "query",
|
||||
Schema: spec.Int64Property(),
|
||||
Description: "the start value",
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "flush",
|
||||
In: "query",
|
||||
Schema: spec.Int64Property(),
|
||||
Description: "How often the result is flushed (1-100%)",
|
||||
Example: 100,
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "speed",
|
||||
In: "query",
|
||||
Schema: spec.StringProperty(),
|
||||
Description: "the clock cycle",
|
||||
Example: "100ms",
|
||||
},
|
||||
},
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "format",
|
||||
In: "query",
|
||||
Schema: spec.StringProperty().WithEnum("json", "influx"),
|
||||
Description: "the response format",
|
||||
},
|
||||
},
|
||||
},
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/boom": {
|
||||
PathProps: spec3.PathProps{
|
||||
Summary: "force a panic",
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
Post: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/test": {
|
||||
PathProps: spec3.PathProps{
|
||||
Summary: "Echo any request",
|
||||
Post: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
RequestBody: unstructuredRequest,
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/sims": {
|
||||
PathProps: spec3.PathProps{
|
||||
Description: "Get list of simulations",
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/sim/{key}": {
|
||||
PathProps: spec3.PathProps{
|
||||
Description: "Get list of simulations",
|
||||
Get: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Parameters: []*spec3.Parameter{
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "key",
|
||||
In: "path",
|
||||
Description: "simulation key (should include hz)",
|
||||
},
|
||||
},
|
||||
},
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
Post: &spec3.Operation{
|
||||
OperationProps: spec3.OperationProps{
|
||||
Parameters: []*spec3.Parameter{
|
||||
{
|
||||
ParameterProps: spec3.ParameterProps{
|
||||
Name: "key",
|
||||
In: "path",
|
||||
Description: "simulation key (should include hz)",
|
||||
},
|
||||
},
|
||||
},
|
||||
RequestBody: unstructuredRequest,
|
||||
Responses: unstructuredResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// mux.HandleFunc("/sims", s.sims.GetSimulationHandler)
|
||||
// mux.HandleFunc("/sim/", s.sims.GetSimulationHandler)
|
||||
|
||||
// Duplicate the test route (but with a new path)
|
||||
testcopy := *oas.Routes["/test"]
|
||||
oas.Routes["/test/json"] = &testcopy
|
||||
|
||||
return oas, nil
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
Reference in New Issue
Block a user