diff --git a/pkg/registry/apis/datasource/connections.go b/pkg/registry/apis/datasource/connections.go new file mode 100644 index 00000000000..687578ee009 --- /dev/null +++ b/pkg/registry/apis/datasource/connections.go @@ -0,0 +1,59 @@ +package datasource + +import ( + "context" + + "github.com/grafana/grafana/pkg/apimachinery/utils" + "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 = (*connectionAccess)(nil) + _ rest.SingularNameProvider = (*connectionAccess)(nil) + _ rest.Getter = (*connectionAccess)(nil) + _ rest.Lister = (*connectionAccess)(nil) + _ rest.Storage = (*connectionAccess)(nil) +) + +type connectionAccess struct { + resourceInfo utils.ResourceInfo + tableConverter rest.TableConvertor + datasources PluginDatasourceProvider +} + +func (s *connectionAccess) New() runtime.Object { + return s.resourceInfo.NewFunc() +} + +func (s *connectionAccess) Destroy() {} + +func (s *connectionAccess) NamespaceScoped() bool { + return true +} + +func (s *connectionAccess) GetSingularName() string { + return s.resourceInfo.GetSingularName() +} + +func (s *connectionAccess) ShortNames() []string { + return s.resourceInfo.GetShortNames() +} + +func (s *connectionAccess) NewList() runtime.Object { + return s.resourceInfo.NewListFunc() +} + +func (s *connectionAccess) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) { + return s.tableConverter.ConvertToTable(ctx, object, tableOptions) +} + +func (s *connectionAccess) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { + return s.datasources.GetDataSource(ctx, name) +} + +func (s *connectionAccess) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) { + return s.datasources.ListDataSources(ctx) +} diff --git a/pkg/registry/apis/datasource/register.go b/pkg/registry/apis/datasource/register.go index c4bf8f734c1..454e760a3a3 100644 --- a/pkg/registry/apis/datasource/register.go +++ b/pkg/registry/apis/datasource/register.go @@ -3,8 +3,10 @@ package datasource import ( "context" "encoding/json" + "errors" "fmt" "maps" + "path/filepath" "github.com/prometheus/client_golang/prometheus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -24,11 +26,13 @@ import ( "github.com/grafana/grafana/pkg/configprovider" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/plugins/manager/sources" "github.com/grafana/grafana/pkg/promlib/models" "github.com/grafana/grafana/pkg/registry/apis/query/queryschema" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/apiserver/builder" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tsdb/grafana-testdata-datasource/kinds" ) @@ -40,13 +44,14 @@ var ( type DataSourceAPIBuilder struct { datasourceResourceInfo utils.ResourceInfo - pluginJSON plugins.JSONData - client PluginClient // will only ever be called with the same plugin id! - datasources PluginDatasourceProvider - contextProvider PluginContextWrapper - accessControl accesscontrol.AccessControl - queryTypes *queryV0.QueryTypeDefinitionList - log log.Logger + pluginJSON plugins.JSONData + client PluginClient // will only ever be called with the same plugin id! + datasources PluginDatasourceProvider + contextProvider PluginContextWrapper + accessControl accesscontrol.AccessControl + queryTypes *queryV0.QueryTypeDefinitionList + log log.Logger + configCrudUseNewApis bool } func RegisterAPIService( @@ -109,16 +114,12 @@ func RegisterAPIService( contextProvider, accessControl, features.IsEnabledGlobally(featuremgmt.FlagDatasourceQueryTypes), + false, ) if err != nil { return nil, err } - // TODO: load the schema provider from a static manifest - // if ds.ID == "grafana-testdata-datasource" { - // builder.schemaProvider = hardcoded.TestdataOpenAPIExtension - // } - apiRegistrar.RegisterAPI(builder) } return builder, nil // only used for wire @@ -140,6 +141,7 @@ func NewDataSourceAPIBuilder( contextProvider PluginContextWrapper, accessControl accesscontrol.AccessControl, loadQueryTypes bool, + configCrudUseNewApis bool, ) (*DataSourceAPIBuilder, error) { group, err := plugins.GetDatasourceGroupNameFromPluginID(plugin.ID) if err != nil { @@ -154,6 +156,7 @@ func NewDataSourceAPIBuilder( contextProvider: contextProvider, accessControl: accessControl, log: log.New("grafana-apiserver.datasource"), + configCrudUseNewApis: configCrudUseNewApis, } if loadQueryTypes { // In the future, this will somehow come from the plugin @@ -232,19 +235,6 @@ func (b *DataSourceAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver // Register the raw datasource connection ds := b.datasourceResourceInfo - legacyStore := &legacyStorage{ - datasources: b.datasources, - resourceInfo: &ds, - } - unified, err := grafanaregistry.NewRegistryStore(opts.Scheme, ds, opts.OptsGetter) - if err != nil { - return err - } - storage[ds.StoragePath()], err = opts.DualWriteBuilder(ds.GroupResource(), legacyStore, unified) - if err != nil { - return err - } - storage[ds.StoragePath("query")] = &subQueryREST{builder: b} storage[ds.StoragePath("health")] = &subHealthREST{builder: b} storage[ds.StoragePath("resource")] = &subResourceREST{builder: b} @@ -255,13 +245,34 @@ func (b *DataSourceAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver storage["connections"] = &noopREST{} // hidden from openapi storage["connections/query"] = storage[ds.StoragePath("query")] // deprecated in openapi + if b.configCrudUseNewApis { + legacyStore := &legacyStorage{ + datasources: b.datasources, + resourceInfo: &ds, + } + unified, err := grafanaregistry.NewRegistryStore(opts.Scheme, ds, opts.OptsGetter) + if err != nil { + return err + } + storage[ds.StoragePath()], err = opts.DualWriteBuilder(ds.GroupResource(), legacyStore, unified) + if err != nil { + return err + } + } else { + storage[ds.StoragePath()] = &connectionAccess{ + datasources: b.datasources, + resourceInfo: ds, + tableConverter: ds.TableConverter(), + } + } + // Frontend proxy if len(b.pluginJSON.Routes) > 0 { storage[ds.StoragePath("proxy")] = &subProxyREST{pluginJSON: b.pluginJSON} } // Register hardcoded query schemas - err = queryschema.RegisterQueryTypes(b.queryTypes, storage) + err := queryschema.RegisterQueryTypes(b.queryTypes, storage) if err != nil { return err } @@ -287,3 +298,22 @@ func (b *DataSourceAPIBuilder) GetOpenAPIDefinitions() openapi.GetOpenAPIDefinit return defs } } + +func getCorePlugins(cfg *setting.Cfg) ([]plugins.JSONData, error) { + coreDataSourcesPath := filepath.Join(cfg.StaticRootPath, "app", "plugins", "datasource") + coreDataSourcesSrc := sources.NewLocalSource( + plugins.ClassCore, + []string{coreDataSourcesPath}, + ) + + res, err := coreDataSourcesSrc.Discover(context.Background()) + if err != nil { + return nil, errors.New("failed to load core data source plugins") + } + + pluginJSONs := make([]plugins.JSONData, 0, len(res)) + for _, p := range res { + pluginJSONs = append(pluginJSONs, p.Primary.JSONData) + } + return pluginJSONs, nil +} diff --git a/pkg/registry/apis/datasource/testdata/convert-resource-empty-to-cmd-update-roundtrip.json b/pkg/registry/apis/datasource/testdata/convert-resource-empty-to-cmd-update-roundtrip.json index 4b16a1455a2..a8c49ba7637 100644 --- a/pkg/registry/apis/datasource/testdata/convert-resource-empty-to-cmd-update-roundtrip.json +++ b/pkg/registry/apis/datasource/testdata/convert-resource-empty-to-cmd-update-roundtrip.json @@ -2,8 +2,7 @@ "metadata": { "name": "cejobd88i85j4d", "namespace": "org-0", - "uid": "boDNh7zU3nXj46rOXIJI7r44qaxjs8yy9I9dOj1MyBoX", - "creationTimestamp": null + "uid": "boDNh7zU3nXj46rOXIJI7r44qaxjs8yy9I9dOj1MyBoX" }, "spec": { "jsonData": null, diff --git a/pkg/registry/apis/datasource/testdata/convert-resource-full-to-cmd-update-roundtrip.json b/pkg/registry/apis/datasource/testdata/convert-resource-full-to-cmd-update-roundtrip.json index 85535306cb0..fa3286d3ea3 100644 --- a/pkg/registry/apis/datasource/testdata/convert-resource-full-to-cmd-update-roundtrip.json +++ b/pkg/registry/apis/datasource/testdata/convert-resource-full-to-cmd-update-roundtrip.json @@ -3,8 +3,7 @@ "name": "cejobd88i85j4d", "namespace": "org-0", "uid": "boDNh7zU3nXj46rOXIJI7r44qaxjs8yy9I9dOj1MyBoX", - "generation": 2, - "creationTimestamp": null + "generation": 2 }, "spec": { "access": "proxy",