mirror of
https://github.com/grafana/grafana.git
synced 2025-12-20 19:44:55 +08:00
Compare commits
1 Commits
provisioni
...
register-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72eec4e995 |
@@ -7,6 +7,7 @@ import (
|
||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||
|
||||
"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) {
|
||||
@@ -70,5 +71,15 @@ func (b *DataSourceAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.Op
|
||||
},
|
||||
}
|
||||
|
||||
// Mark all alias APIServers as deprecated
|
||||
if b.isAlias {
|
||||
oas.Info.Description = "Deprecated. Please use: " + b.pluginJSON.ID
|
||||
for _, p := range oas.Paths.Paths {
|
||||
for _, op := range builder.GetPathOperations(p) {
|
||||
op.Deprecated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return oas, nil
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ var (
|
||||
// DataSourceAPIBuilder is used just so wire has something unique to return
|
||||
type DataSourceAPIBuilder struct {
|
||||
datasourceResourceInfo utils.ResourceInfo
|
||||
isAlias bool // The datasourceResourceInfo group is an alias and the API should be deprecated
|
||||
|
||||
pluginJSON plugins.JSONData
|
||||
client PluginClient // will only ever be called with the same plugin id!
|
||||
@@ -58,10 +59,17 @@ func RegisterAPIService(
|
||||
pluginSources sources.Registry,
|
||||
) (*DataSourceAPIBuilder, error) {
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
if !features.IsEnabledGlobally(featuremgmt.FlagQueryServiceWithConnections) && !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) {
|
||||
useQueryService := !features.IsEnabledGlobally(featuremgmt.FlagQueryServiceWithConnections)
|
||||
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
experimental := features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs)
|
||||
if !experimental && !useQueryService {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Include CRUD when running local dev mode
|
||||
configCrudUseNewApis := experimental
|
||||
|
||||
var err error
|
||||
var builder *DataSourceAPIBuilder
|
||||
|
||||
@@ -84,13 +92,25 @@ func RegisterAPIService(
|
||||
accessControl,
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
features.IsEnabledGlobally(featuremgmt.FlagDatasourceQueryTypes),
|
||||
false,
|
||||
configCrudUseNewApis, // register the CRUD endpoints
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The group is a calculated FQDN (eg testdata.datasource.grafana.app)
|
||||
// and should be replaced with with the raw plugin ID
|
||||
aliasIDs := append(pluginJSON.AliasIDs, builder.datasourceResourceInfo.GroupResource().Group)
|
||||
builder.datasourceResourceInfo = builder.datasourceResourceInfo.WithGroupAndShortName(pluginJSON.ID, "")
|
||||
apiRegistrar.RegisterAPI(builder)
|
||||
|
||||
// Register a deprecated copy with the previous routes
|
||||
for _, aliasId := range aliasIDs {
|
||||
copy := *builder
|
||||
copy.isAlias = true
|
||||
copy.datasourceResourceInfo = builder.datasourceResourceInfo.WithGroupAndShortName(aliasId, "")
|
||||
apiRegistrar.RegisterAPI(©)
|
||||
}
|
||||
}
|
||||
return builder, nil // only used for wire
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"maps"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -217,11 +218,9 @@ func getOpenAPIPostProcessor(version string, builders []APIGroupBuilder, gvs []s
|
||||
parent := copy.Paths.Paths[path[:idx+6]]
|
||||
if parent != nil && parent.Get != nil {
|
||||
for _, op := range GetPathOperations(spec) {
|
||||
if op != nil && op.Extensions != nil {
|
||||
action, ok := op.Extensions.GetString("x-kubernetes-action")
|
||||
if ok && action == "connect" {
|
||||
op.Tags = parent.Get.Tags
|
||||
}
|
||||
action, ok := op.Extensions.GetString("x-kubernetes-action")
|
||||
if ok && action == "connect" {
|
||||
op.Tags = parent.Get.Tags
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,15 +233,32 @@ func getOpenAPIPostProcessor(version string, builders []APIGroupBuilder, gvs []s
|
||||
}
|
||||
}
|
||||
|
||||
func GetPathOperations(path *spec3.Path) []*spec3.Operation {
|
||||
return []*spec3.Operation{
|
||||
path.Get,
|
||||
path.Head,
|
||||
path.Delete,
|
||||
path.Patch,
|
||||
path.Post,
|
||||
path.Put,
|
||||
path.Trace,
|
||||
path.Options,
|
||||
// GetPathOperations returns the set of non-nil operations defined on a path
|
||||
func GetPathOperations(path *spec3.Path) map[string]*spec3.Operation {
|
||||
ops := make(map[string]*spec3.Operation)
|
||||
if path.Get != nil {
|
||||
ops[http.MethodGet] = path.Get
|
||||
}
|
||||
if path.Head != nil {
|
||||
ops[http.MethodHead] = path.Head
|
||||
}
|
||||
if path.Delete != nil {
|
||||
ops[http.MethodDelete] = path.Delete
|
||||
}
|
||||
if path.Post != nil {
|
||||
ops[http.MethodPost] = path.Post
|
||||
}
|
||||
if path.Put != nil {
|
||||
ops[http.MethodPut] = path.Put
|
||||
}
|
||||
if path.Patch != nil {
|
||||
ops[http.MethodPatch] = path.Patch
|
||||
}
|
||||
if path.Trace != nil {
|
||||
ops[http.MethodTrace] = path.Trace
|
||||
}
|
||||
if path.Options != nil {
|
||||
ops[http.MethodOptions] = path.Options
|
||||
}
|
||||
return ops
|
||||
}
|
||||
|
||||
76
pkg/services/apiserver/builder/openapi_test.go
Normal file
76
pkg/services/apiserver/builder/openapi_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/kube-openapi/pkg/spec3"
|
||||
)
|
||||
|
||||
func TestOpenAPI_GetPathOperations(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input *spec3.Path
|
||||
expect []string // the methods we should see
|
||||
exclude []string // the methods we should never see
|
||||
}{
|
||||
{
|
||||
name: "some operations",
|
||||
input: &spec3.Path{
|
||||
PathProps: spec3.PathProps{
|
||||
Get: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "get"}},
|
||||
Post: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "post"}},
|
||||
Delete: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "delete"}},
|
||||
},
|
||||
},
|
||||
expect: []string{"GET", "POST", "DELETE"},
|
||||
exclude: []string{"PUT", "PATCH", "OPTIONS", "HEAD", "TRACE"},
|
||||
},
|
||||
{
|
||||
name: "all operations",
|
||||
input: &spec3.Path{
|
||||
PathProps: spec3.PathProps{
|
||||
Get: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "get"}},
|
||||
Post: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "post"}},
|
||||
Delete: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "delete"}},
|
||||
Put: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "put"}},
|
||||
Patch: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "patch"}},
|
||||
Options: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "options"}},
|
||||
Head: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "head"}},
|
||||
Trace: &spec3.Operation{OperationProps: spec3.OperationProps{Summary: "trace"}},
|
||||
},
|
||||
},
|
||||
expect: []string{"GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD", "TRACE"},
|
||||
exclude: []string{},
|
||||
},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
expect := make(map[string]bool)
|
||||
for _, k := range tt.expect {
|
||||
expect[k] = true
|
||||
}
|
||||
|
||||
for k, op := range GetPathOperations(tt.input) {
|
||||
require.NotNil(t, op)
|
||||
require.Equal(t, strings.ToLower(k), op.Summary)
|
||||
|
||||
if !expect[k] {
|
||||
if slices.Contains(tt.expect, k) {
|
||||
require.Fail(t, "method returned multiple times", k)
|
||||
} else {
|
||||
require.Fail(t, "unexpected method", k)
|
||||
}
|
||||
}
|
||||
delete(expect, k)
|
||||
require.NotContains(t, tt.exclude, k, "exclude")
|
||||
}
|
||||
|
||||
if len(expect) > 0 {
|
||||
require.Fail(t, "missing expected method", expect)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user