mirror of
https://github.com/grafana/grafana.git
synced 2026-08-09 04:38:16 -05:00
Prometheus: Remove from core plugins (#129332)
* remove prometheus frontend * remove prometheus backend * remove prometheus from more places * remove prometheus datasource from backend * remove from more places * mroe removal * move logos * fix proxy_test * fix unit tests maybe * prettier * remove * update with alertlist * update tests
This commit is contained in:
@@ -357,9 +357,6 @@
|
||||
/pkg/tsdb/cloudwatch/ @grafana/data-sources-plugins
|
||||
/pkg/tsdb/azuremonitor/ @grafana/data-sources-plugins
|
||||
|
||||
# Observability backend code
|
||||
/pkg/tsdb/prometheus/ @grafana/data-sources-plugins
|
||||
|
||||
# OSS Big Tent backend code
|
||||
/pkg/tsdb/mysql/ @grafana/data-sources-plugins
|
||||
/pkg/tsdb/sqlmacro/ @grafana/data-sources-plugins
|
||||
@@ -1156,7 +1153,6 @@ eslint-suppressions.json @grafanabot
|
||||
/public/app/plugins/datasource/influxdb/ @grafana/data-sources-plugins
|
||||
/public/app/plugins/datasource/mixed/ @grafana/dashboards-squad
|
||||
/public/app/plugins/datasource/mysql/ @grafana/data-sources-plugins
|
||||
/public/app/plugins/datasource/prometheus/ @grafana/data-sources-plugins
|
||||
/public/app/plugins/datasource/alertmanager/ @grafana/alerting-squad
|
||||
|
||||
# Grafana Sharing Squad
|
||||
|
||||
@@ -91,14 +91,6 @@
|
||||
"url": "https://github.com/orgs/grafana/projects/190"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "datasource/Prometheus",
|
||||
"action": "addToProject",
|
||||
"addToProject": {
|
||||
"url": "https://github.com/orgs/grafana/projects/457"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "datasource/InfluxDB",
|
||||
|
||||
@@ -116,15 +116,6 @@
|
||||
"action": "updateLabel",
|
||||
"addLabel": "datasource/MySQL"
|
||||
},
|
||||
{
|
||||
"type": "changedfiles",
|
||||
"matches": [
|
||||
"public/app/plugins/datasource/prometheus/**/*",
|
||||
"pkg/tsdb/prometheus/**/*"
|
||||
],
|
||||
"action": "updateLabel",
|
||||
"addLabel": "datasource/Prometheus"
|
||||
},
|
||||
{
|
||||
"type": "changedfiles",
|
||||
"matches": [
|
||||
|
||||
@@ -108,8 +108,6 @@ datasource/MSSQL
|
||||
datasource/MySQL
|
||||
datasource/OpenSearch
|
||||
datasource/Phlare
|
||||
datasource/Postgres
|
||||
datasource/Prometheus
|
||||
datasource/SiteWIse
|
||||
datasource/Splunk
|
||||
datasource/TestDataDB
|
||||
|
||||
@@ -4,15 +4,12 @@ on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
paths:
|
||||
- "packages/grafana-prometheus/**"
|
||||
- "public/app/plugins/datasource/cloudwatch/**"
|
||||
- "public/app/plugins/datasource/graphite/**"
|
||||
- "public/app/plugins/datasource/influxdb/**"
|
||||
- "public/app/plugins/datasource/prometheus/**"
|
||||
- "pkg/tsdb/cloudwatch/**"
|
||||
- "pkg/tsdb/graphite/**"
|
||||
- "pkg/tsdb/influxdb/**"
|
||||
- "pkg/tsdb/prometheus/**"
|
||||
|
||||
jobs:
|
||||
add-comment:
|
||||
|
||||
@@ -137,7 +137,7 @@ func TestCoreProvider_loadPlugins(t *testing.T) {
|
||||
provider := NewCoreProviderWithTTL(&logging.NoOpLogger{}, staticRootPath, false, defaultCoreTTL)
|
||||
err = provider.loadPlugins(ctx)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, provider.loadedPlugins, 41)
|
||||
assert.Len(t, provider.loadedPlugins, 40)
|
||||
})
|
||||
|
||||
t.Run("loads plugins from staticRootPath", func(t *testing.T) {
|
||||
|
||||
@@ -237,10 +237,6 @@ require (
|
||||
|
||||
// Internal module references (every entry should also have a replace in the section below)
|
||||
require (
|
||||
// This needs to be here for other projects that import grafana/grafana
|
||||
// For local development grafana/grafana will always use the local files
|
||||
// Check go.work file for details
|
||||
github.com/grafana/grafana-prometheus-datasource/pkg/promlib v0.0.11 // @grafana/data-sources-plugins
|
||||
github.com/grafana/grafana/apps/advisor v0.0.0 // @grafana/grafana-catalog
|
||||
github.com/grafana/grafana/apps/alerting/alertenrichment v0.0.0 // @grafana/alerting-backend
|
||||
github.com/grafana/grafana/apps/alerting/notifications v0.0.0 // @grafana/alerting-backend
|
||||
|
||||
@@ -1620,8 +1620,6 @@ github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79
|
||||
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.292.2 h1:6xrNZpe905vzX1pY33Fyet7Oxw5xULcAHm2b8dvNZNY=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.292.2/go.mod h1:MPviZeixuZDc5T3f62FBCCPSOJ51/JocZH5+ZiQ1DmM=
|
||||
github.com/grafana/grafana-prometheus-datasource/pkg/promlib v0.0.11 h1:dN402Jd/FsSi6lvfCJR5lXiv7j2ucbPV/ZJCjOX4+zc=
|
||||
github.com/grafana/grafana-prometheus-datasource/pkg/promlib v0.0.11/go.mod h1:rmYghozhFPZ5p+o8erXoCQ3BuSVDOuT5Y8dXWBUIXjs=
|
||||
github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000 h1:/5LKSYgLmAhwA4m6iGUD4w1YkydEWWjazn9qxCFT8W0=
|
||||
github.com/grafana/loki/pkg/push v0.0.0-20250823105456-332df2b20000/go.mod h1:/ZklAgE1i4f3Z8uriXwESmCr1VLF8lBGaJspuaGuf78=
|
||||
github.com/grafana/memberlist v0.3.1-0.20251126142931-6f9f62ab6f86 h1:aTwfQuroOmOr//QEn9J1MtC4R4CPR9/IbUd8hZrbWKo=
|
||||
|
||||
@@ -2,11 +2,11 @@ import { clockPanelMetaCDN, v0alpha1Response } from '../test-fixtures/v0alpha1Re
|
||||
|
||||
import { isCorePlugin, isDecoupledCorePlugin } from './shared';
|
||||
|
||||
const prometheusResponse = v0alpha1Response.items.find((i) => i.spec.pluginJson.id === 'prometheus')!;
|
||||
const alertListResponse = v0alpha1Response.items.find((i) => i.spec.pluginJson.id === 'alertlist')!;
|
||||
|
||||
describe('isCorePlugin', () => {
|
||||
it('should return true for core plugins', () => {
|
||||
expect(isCorePlugin(prometheusResponse.spec)).toBe(true);
|
||||
expect(isCorePlugin(alertListResponse.spec)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non core plugins', () => {
|
||||
@@ -16,7 +16,7 @@ describe('isCorePlugin', () => {
|
||||
|
||||
describe('isDecoupledCorePlugin', () => {
|
||||
it('should return false for core plugins that are not decoupled', () => {
|
||||
expect(isDecoupledCorePlugin(prometheusResponse.spec)).toBe(false);
|
||||
expect(isDecoupledCorePlugin(alertListResponse.spec)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for non core plugins', () => {
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('v0alpha1AppMapper', () => {
|
||||
it('should only map specs with type app', () => {
|
||||
const result = v0alpha1AppMapper(v0alpha1Response);
|
||||
|
||||
expect(v0alpha1Response.items).toHaveLength(44);
|
||||
expect(v0alpha1Response.items).toHaveLength(43);
|
||||
expect(Object.keys(result)).toHaveLength(4);
|
||||
expect(Object.keys(result)).toEqual(Object.keys(apps));
|
||||
});
|
||||
|
||||
+10
-10
@@ -134,7 +134,7 @@ describe('v0alpha1PanelMapper', () => {
|
||||
it('should only map specs with type panel', () => {
|
||||
const result = v0alpha1PanelMapper(v0alpha1Response);
|
||||
|
||||
expect(v0alpha1Response.items).toHaveLength(44);
|
||||
expect(v0alpha1Response.items).toHaveLength(43);
|
||||
expect(Object.keys(result)).toHaveLength(28);
|
||||
expect(Object.keys(result)).toEqual(Object.keys(panels));
|
||||
});
|
||||
@@ -159,7 +159,7 @@ describe('v0alpha1PanelMapper', () => {
|
||||
});
|
||||
|
||||
const azureMeta = v0alpha1Response.items.find((i) => i.spec.pluginJson.id === 'grafana-azure-monitor-datasource')!;
|
||||
const promMeta = v0alpha1Response.items.find((i) => i.spec.pluginJson.id === 'prometheus')!;
|
||||
const promMeta = v0alpha1Response.items.find((i) => i.spec.pluginJson.id === 'dashboard')!;
|
||||
|
||||
describe('coreSpecMapper when called with a core plugin on cloud', () => {
|
||||
beforeEach(() => {
|
||||
@@ -206,14 +206,14 @@ describe('coreSpecMapper when called with a core plugin on cloud', () => {
|
||||
const result = coreSpecMapper(promMeta.spec);
|
||||
|
||||
expect(result.baseUrl).toBe(
|
||||
'https://grafana-assets.grafana-dev.net/grafana/13.0.0-24045599351/public/app/plugins/datasource/prometheus'
|
||||
'https://grafana-assets.grafana-dev.net/grafana/13.0.0-24045599351/public/app/plugins/datasource/dashboard'
|
||||
);
|
||||
expect(result.module).toBe('core:plugin/prometheus');
|
||||
expect(result.module).toBe('core:plugin/dashboard');
|
||||
expect(result.info.logos.large).toBe(
|
||||
'https://grafana-assets.grafana-dev.net/grafana/13.0.0-24045599351/public/app/plugins/datasource/prometheus/img/prometheus_logo.svg'
|
||||
'https://grafana-assets.grafana-dev.net/grafana/13.0.0-24045599351/public/app/plugins/datasource/dashboard/dist/img/icn-reusequeries.svg'
|
||||
);
|
||||
expect(result.info.logos.small).toBe(
|
||||
'https://grafana-assets.grafana-dev.net/grafana/13.0.0-24045599351/public/app/plugins/datasource/prometheus/img/prometheus_logo.svg'
|
||||
'https://grafana-assets.grafana-dev.net/grafana/13.0.0-24045599351/public/app/plugins/datasource/dashboard/dist/img/icn-reusequeries.svg'
|
||||
);
|
||||
expect(result.info.screenshots).toEqual([]);
|
||||
});
|
||||
@@ -258,10 +258,10 @@ describe('coreSpecMapper when called with a core plugin on prem', () => {
|
||||
it('should resolve correct urls for a non decoupled plugin', () => {
|
||||
const result = coreSpecMapper(promMeta.spec);
|
||||
|
||||
expect(result.baseUrl).toBe('public/app/plugins/datasource/prometheus');
|
||||
expect(result.module).toBe('core:plugin/prometheus');
|
||||
expect(result.info.logos.large).toBe('public/app/plugins/datasource/prometheus/img/prometheus_logo.svg');
|
||||
expect(result.info.logos.small).toBe('public/app/plugins/datasource/prometheus/img/prometheus_logo.svg');
|
||||
expect(result.baseUrl).toBe('public/app/plugins/datasource/dashboard');
|
||||
expect(result.module).toBe('core:plugin/dashboard');
|
||||
expect(result.info.logos.large).toBe('public/app/plugins/datasource/dashboard/dist/img/icn-reusequeries.svg');
|
||||
expect(result.info.logos.small).toBe('public/app/plugins/datasource/dashboard/dist/img/icn-reusequeries.svg');
|
||||
expect(result.info.screenshots).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3044,157 +3044,6 @@ export const v0alpha1Response: PluginMetasResponse = structuredClone({
|
||||
},
|
||||
status: {},
|
||||
},
|
||||
{
|
||||
kind: 'Meta',
|
||||
apiVersion: 'plugins.grafana.app/v0alpha1',
|
||||
metadata: {
|
||||
name: 'prometheus',
|
||||
namespace: 'default',
|
||||
},
|
||||
spec: {
|
||||
pluginJson: {
|
||||
id: 'prometheus',
|
||||
type: 'datasource',
|
||||
name: 'Prometheus',
|
||||
info: {
|
||||
keywords: [],
|
||||
logos: {
|
||||
small: 'app/plugins/datasource/prometheus/img/prometheus_logo.svg',
|
||||
large: 'app/plugins/datasource/prometheus/img/prometheus_logo.svg',
|
||||
},
|
||||
updated: '',
|
||||
version: '',
|
||||
author: {
|
||||
name: 'Grafana Labs',
|
||||
url: 'https://grafana.com',
|
||||
},
|
||||
description: 'Open source time series database & alerting',
|
||||
links: [
|
||||
{
|
||||
name: 'Learn more',
|
||||
url: 'https://prometheus.io/',
|
||||
},
|
||||
{
|
||||
name: 'Raise issue',
|
||||
url: 'https://github.com/grafana/grafana/issues/new',
|
||||
},
|
||||
{
|
||||
name: 'Documentation',
|
||||
url: 'https://grafana.com/docs/grafana/latest/datasources/prometheus/',
|
||||
},
|
||||
],
|
||||
},
|
||||
dependencies: {
|
||||
grafanaDependency: '',
|
||||
grafanaVersion: '*',
|
||||
},
|
||||
alerting: true,
|
||||
annotations: true,
|
||||
backend: true,
|
||||
category: 'tsdb',
|
||||
includes: [
|
||||
{
|
||||
type: 'dashboard',
|
||||
name: 'Prometheus Stats',
|
||||
role: 'Viewer',
|
||||
path: 'dashboards/prometheus_stats.json',
|
||||
},
|
||||
{
|
||||
type: 'dashboard',
|
||||
name: 'Prometheus 2.0 Stats',
|
||||
role: 'Viewer',
|
||||
path: 'dashboards/prometheus_2_stats.json',
|
||||
},
|
||||
{
|
||||
type: 'dashboard',
|
||||
name: 'Grafana Stats',
|
||||
role: 'Viewer',
|
||||
path: 'dashboards/grafana_stats.json',
|
||||
},
|
||||
],
|
||||
metrics: true,
|
||||
multiValueFilterOperators: true,
|
||||
queryOptions: {
|
||||
minInterval: true,
|
||||
},
|
||||
routes: [
|
||||
{
|
||||
path: 'api/v1/query',
|
||||
method: 'POST',
|
||||
reqRole: 'Viewer',
|
||||
reqAction: 'datasources:query',
|
||||
},
|
||||
{
|
||||
path: 'api/v1/query_range',
|
||||
method: 'POST',
|
||||
reqRole: 'Viewer',
|
||||
reqAction: 'datasources:query',
|
||||
},
|
||||
{
|
||||
path: 'api/v1/series',
|
||||
method: 'POST',
|
||||
reqRole: 'Viewer',
|
||||
reqAction: 'datasources:query',
|
||||
},
|
||||
{
|
||||
path: 'api/v1/labels',
|
||||
method: 'POST',
|
||||
reqRole: 'Viewer',
|
||||
reqAction: 'datasources:query',
|
||||
},
|
||||
{
|
||||
path: 'api/v1/query_exemplars',
|
||||
method: 'POST',
|
||||
reqRole: 'Viewer',
|
||||
reqAction: 'datasources:query',
|
||||
},
|
||||
{
|
||||
path: '/rules',
|
||||
method: 'GET',
|
||||
reqRole: 'Viewer',
|
||||
reqAction: 'alert.rules.external:read',
|
||||
},
|
||||
{
|
||||
path: '/rules',
|
||||
method: 'POST',
|
||||
reqRole: 'Editor',
|
||||
reqAction: 'alert.rules.external:write',
|
||||
},
|
||||
{
|
||||
path: '/rules',
|
||||
method: 'DELETE',
|
||||
reqRole: 'Editor',
|
||||
reqAction: 'alert.rules.external:write',
|
||||
},
|
||||
{
|
||||
path: '/config/v1/rules',
|
||||
method: 'DELETE',
|
||||
reqRole: 'Editor',
|
||||
reqAction: 'alert.rules.external:write',
|
||||
},
|
||||
{
|
||||
path: '/config/v1/rules',
|
||||
method: 'POST',
|
||||
reqRole: 'Editor',
|
||||
reqAction: 'alert.rules.external:write',
|
||||
},
|
||||
],
|
||||
},
|
||||
class: 'core',
|
||||
module: {
|
||||
path: 'core:plugin/prometheus',
|
||||
loadingStrategy: 'script',
|
||||
},
|
||||
baseURL: 'app/plugins/datasource/prometheus',
|
||||
signature: {
|
||||
status: 'internal',
|
||||
},
|
||||
angular: {
|
||||
detected: false,
|
||||
},
|
||||
},
|
||||
status: {},
|
||||
},
|
||||
{
|
||||
kind: 'Meta',
|
||||
apiVersion: 'plugins.grafana.app/v0alpha1',
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestIntegrationCallResource(t *testing.T) {
|
||||
cfg.StaticRootPath = staticRootPath
|
||||
cfg.Azure = &azsettings.AzureSettings{}
|
||||
|
||||
coreRegistry := coreplugin.ProvideCoreRegistry(tracing.InitializeTracerForTest(), nil, &cloudwatch.Service{}, nil, nil, nil,
|
||||
coreRegistry := coreplugin.ProvideCoreRegistry(tracing.InitializeTracerForTest(), nil, &cloudwatch.Service{}, nil, nil,
|
||||
testdatasource.ProvideService(), nil, nil)
|
||||
|
||||
testCtx := pluginsintegration.CreateIntegrationTestCtx(t, cfg, coreRegistry)
|
||||
|
||||
@@ -549,7 +549,6 @@ import (
|
||||
_ "github.com/grafana/grafana/pkg/tsdb/graphite"
|
||||
_ "github.com/grafana/grafana/pkg/tsdb/influxdb"
|
||||
_ "github.com/grafana/grafana/pkg/tsdb/mysql"
|
||||
_ "github.com/grafana/grafana/pkg/tsdb/prometheus"
|
||||
_ "github.com/grafana/grafana/pkg/util"
|
||||
_ "github.com/grafana/grafana/pkg/util/errhttp"
|
||||
_ "github.com/grafana/grafana/pkg/util/retryer"
|
||||
|
||||
@@ -192,7 +192,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/tsdb/graphite"
|
||||
"github.com/grafana/grafana/pkg/tsdb/influxdb"
|
||||
"github.com/grafana/grafana/pkg/tsdb/mysql"
|
||||
"github.com/grafana/grafana/pkg/tsdb/prometheus"
|
||||
)
|
||||
|
||||
var withOTelSet = wire.NewSet(
|
||||
@@ -305,7 +304,6 @@ var Basic = wire.NewSet(
|
||||
influxdb.ProvideService,
|
||||
wire.Bind(new(social.Service), new(*socialimpl.SocialService)),
|
||||
graphite.ProvideService,
|
||||
prometheus.ProvideService,
|
||||
datasourceservice.ProvideCacheService,
|
||||
wire.Bind(new(datasources.CacheService), new(*datasourceservice.CacheServiceImpl)),
|
||||
encryptionservice.ProvideEncryptionService,
|
||||
|
||||
Generated
+2
-5
@@ -261,7 +261,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/tsdb/graphite"
|
||||
"github.com/grafana/grafana/pkg/tsdb/influxdb"
|
||||
"github.com/grafana/grafana/pkg/tsdb/mysql"
|
||||
"github.com/grafana/grafana/pkg/tsdb/prometheus"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
@@ -356,7 +355,6 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts server.Options, apiO
|
||||
cloudwatchService := cloudwatch.ProvideService()
|
||||
graphiteService := graphite.ProvideService(httpclientProvider, tracer)
|
||||
influxdbService := influxdb.ProvideService(httpclientProvider)
|
||||
prometheusService := prometheus.ProvideService(httpclientProvider)
|
||||
testdatasourceService := testdatasource.ProvideService()
|
||||
mysqlService := mysql.ProvideService()
|
||||
systemUsers := store.ProvideSystemUsersService()
|
||||
@@ -365,7 +363,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts server.Options, apiO
|
||||
return nil, err
|
||||
}
|
||||
grafanadsService := grafanads.ProvideService(storageService, featureToggles)
|
||||
corepluginRegistry := coreplugin.ProvideCoreRegistry(tracer, azuremonitorService, cloudwatchService, graphiteService, influxdbService, prometheusService, testdatasourceService, mysqlService, grafanadsService)
|
||||
corepluginRegistry := coreplugin.ProvideCoreRegistry(tracer, azuremonitorService, cloudwatchService, graphiteService, influxdbService, testdatasourceService, mysqlService, grafanadsService)
|
||||
backendFactoryProvider := coreplugin.ProvideCoreProvider(corepluginRegistry)
|
||||
processService := process.ProvideService()
|
||||
legacyDatabaseProvider := legacysql.NewDatabaseProvider(sqlStore)
|
||||
@@ -1118,7 +1116,6 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
cloudwatchService := cloudwatch.ProvideService()
|
||||
graphiteService := graphite.ProvideService(httpclientProvider, tracer)
|
||||
influxdbService := influxdb.ProvideService(httpclientProvider)
|
||||
prometheusService := prometheus.ProvideService(httpclientProvider)
|
||||
testdatasourceService := testdatasource.ProvideService()
|
||||
mysqlService := mysql.ProvideService()
|
||||
systemUsers := store.ProvideSystemUsersService()
|
||||
@@ -1127,7 +1124,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac
|
||||
return nil, err
|
||||
}
|
||||
grafanadsService := grafanads.ProvideService(storageService, featureToggles)
|
||||
corepluginRegistry := coreplugin.ProvideCoreRegistry(tracer, azuremonitorService, cloudwatchService, graphiteService, influxdbService, prometheusService, testdatasourceService, mysqlService, grafanadsService)
|
||||
corepluginRegistry := coreplugin.ProvideCoreRegistry(tracer, azuremonitorService, cloudwatchService, graphiteService, influxdbService, testdatasourceService, mysqlService, grafanadsService)
|
||||
backendFactoryProvider := coreplugin.ProvideCoreProvider(corepluginRegistry)
|
||||
processService := process.ProvideService()
|
||||
legacyDatabaseProvider := legacysql.NewDatabaseProvider(sqlStore)
|
||||
|
||||
@@ -191,7 +191,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/tsdb/graphite"
|
||||
"github.com/grafana/grafana/pkg/tsdb/influxdb"
|
||||
"github.com/grafana/grafana/pkg/tsdb/mysql"
|
||||
"github.com/grafana/grafana/pkg/tsdb/prometheus"
|
||||
)
|
||||
|
||||
var withOTelSet = wire.NewSet(
|
||||
@@ -304,7 +303,6 @@ var wireBasicSet = wire.NewSet(
|
||||
influxdb.ProvideService,
|
||||
wire.Bind(new(social.Service), new(*socialimpl.SocialService)),
|
||||
graphite.ProvideService,
|
||||
prometheus.ProvideService,
|
||||
datasourceservice.ProvideCacheService,
|
||||
wire.Bind(new(datasources.CacheService), new(*datasourceservice.CacheServiceImpl)),
|
||||
encryptionservice.ProvideEncryptionService,
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/tsdb/graphite"
|
||||
"github.com/grafana/grafana/pkg/tsdb/influxdb"
|
||||
"github.com/grafana/grafana/pkg/tsdb/mysql"
|
||||
"github.com/grafana/grafana/pkg/tsdb/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -32,7 +31,6 @@ const (
|
||||
AzureMonitor = "grafana-azure-monitor-datasource"
|
||||
Graphite = "graphite"
|
||||
InfluxDB = "influxdb"
|
||||
Prometheus = "prometheus"
|
||||
TestData = "grafana-testdata-datasource"
|
||||
TestDataAlias = "testdata"
|
||||
MySQL = "mysql"
|
||||
@@ -77,8 +75,7 @@ func ProvideCoreProvider(coreRegistry *Registry) plugins.BackendFactoryProvider
|
||||
}
|
||||
|
||||
func ProvideCoreRegistry(tracer trace.Tracer, am *azuremonitor.Service, cw *cloudwatch.Service,
|
||||
grap *graphite.Service, idb *influxdb.Service,
|
||||
pr *prometheus.Service, td *testdatasource.Service, my *mysql.Service,
|
||||
grap *graphite.Service, idb *influxdb.Service, td *testdatasource.Service, my *mysql.Service,
|
||||
graf *grafanads.Service) *Registry {
|
||||
// Non-optimal global solution to replace plugin SDK default tracer for core plugins.
|
||||
sdktracing.InitDefaultTracer(tracer)
|
||||
@@ -88,7 +85,6 @@ func ProvideCoreRegistry(tracer trace.Tracer, am *azuremonitor.Service, cw *clou
|
||||
AzureMonitor: asBackendPlugin(am),
|
||||
Graphite: asBackendPlugin(grap),
|
||||
InfluxDB: asBackendPlugin(idb),
|
||||
Prometheus: asBackendPlugin(pr),
|
||||
TestData: asBackendPlugin(td),
|
||||
MySQL: asBackendPlugin(my),
|
||||
Grafana: asBackendPlugin(graf),
|
||||
@@ -199,8 +195,6 @@ func NewPlugin(pluginID string, httpClientProvider *httpclient.Provider, tracer
|
||||
svc = graphite.ProvideService(httpClientProvider, tracer)
|
||||
case InfluxDB:
|
||||
svc = influxdb.ProvideService(httpClientProvider)
|
||||
case Prometheus:
|
||||
svc = prometheus.ProvideService(httpClientProvider)
|
||||
case MySQL:
|
||||
svc = mysql.ProvideService()
|
||||
default:
|
||||
|
||||
@@ -23,7 +23,6 @@ func TestNewPlugin(t *testing.T) {
|
||||
{ID: Graphite},
|
||||
{ID: InfluxDB},
|
||||
{ID: MySQL},
|
||||
{ID: Prometheus},
|
||||
{ID: TestData, ExpectedAlias: TestDataAlias},
|
||||
{ID: TestDataAlias, ExpectedID: TestData, ExpectedAlias: TestDataAlias},
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/tsdb/graphite"
|
||||
"github.com/grafana/grafana/pkg/tsdb/influxdb"
|
||||
"github.com/grafana/grafana/pkg/tsdb/mysql"
|
||||
"github.com/grafana/grafana/pkg/tsdb/prometheus"
|
||||
"github.com/grafana/grafana/pkg/util/testutil"
|
||||
)
|
||||
|
||||
@@ -140,11 +139,10 @@ func TestIntegrationPluginManager(t *testing.T) {
|
||||
cw := cloudwatch.ProvideService()
|
||||
grap := graphite.ProvideService(hcp, tracer)
|
||||
idb := influxdb.ProvideService(hcp)
|
||||
pr := prometheus.ProvideService(hcp)
|
||||
td := testdatasource.ProvideService()
|
||||
my := mysql.ProvideService()
|
||||
graf := grafanads.ProvideService(nil, features)
|
||||
coreRegistry := coreplugin.ProvideCoreRegistry(tracing.InitializeTracerForTest(), am, cw, grap, idb, pr, td, my, graf)
|
||||
coreRegistry := coreplugin.ProvideCoreRegistry(tracing.InitializeTracerForTest(), am, cw, grap, idb, td, my, graf)
|
||||
|
||||
testCtx := pluginsintegration.CreateIntegrationTestCtx(t, cfg, coreRegistry)
|
||||
|
||||
@@ -221,7 +219,6 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *pluginstor
|
||||
"grafana-azure-monitor-datasource": {},
|
||||
"graphite": {},
|
||||
"influxdb": {},
|
||||
"prometheus": {},
|
||||
"grafana-testdata-datasource": {},
|
||||
"mysql": {},
|
||||
"grafana": {},
|
||||
|
||||
@@ -78,7 +78,7 @@ func TestIntegrationDataSourceGetByUID(t *testing.T) {
|
||||
func runGetTests(t *testing.T, ctx context.Context, grafanaListeningAddr string, testEnv *server.TestEnv, store db.DB, cfg *setting.Cfg, modePrefix string) {
|
||||
t.Run("GET - succeeds", func(t *testing.T) {
|
||||
// make a unique-enough UID - all the tests in this file share the same grafana instance.
|
||||
uid := fmt.Sprintf("%s-prometheus-get", modePrefix)
|
||||
uid := fmt.Sprintf("%s-testdata-get", modePrefix)
|
||||
jsonData := simplejson.NewFromAny(map[string]any{
|
||||
"httpMethod": "POST",
|
||||
})
|
||||
@@ -88,8 +88,8 @@ func runGetTests(t *testing.T, ctx context.Context, grafanaListeningAddr string,
|
||||
&datasources.AddDataSourceCommand{
|
||||
OrgID: 1,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Name: "Test Prometheus",
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
Name: "Test Data",
|
||||
Type: datasources.DS_TESTDATA,
|
||||
UID: uid,
|
||||
URL: "http://localhost:9090",
|
||||
User: "testuser",
|
||||
@@ -115,8 +115,8 @@ func runGetTests(t *testing.T, ctx context.Context, grafanaListeningAddr string,
|
||||
require.NoError(t, resp.Body.Close())
|
||||
|
||||
assert.Equal(t, uid, dto.UID)
|
||||
assert.Equal(t, "Test Prometheus", dto.Name)
|
||||
assert.Equal(t, "prometheus", dto.Type)
|
||||
assert.Equal(t, "Test Data", dto.Name)
|
||||
assert.Equal(t, datasources.DS_TESTDATA, dto.Type)
|
||||
assert.Equal(t, datasources.DsAccess(datasources.DS_ACCESS_PROXY), dto.Access)
|
||||
assert.Equal(t, "http://localhost:9090", dto.Url)
|
||||
assert.Equal(t, "testuser", dto.User)
|
||||
@@ -165,7 +165,7 @@ func runGetTests(t *testing.T, ctx context.Context, grafanaListeningAddr string,
|
||||
OrgID: 1,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Name: "Test DS for GET Permissions 1",
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
Type: datasources.DS_TESTDATA,
|
||||
UID: dsUID,
|
||||
URL: "http://localhost:9090",
|
||||
})
|
||||
@@ -197,7 +197,7 @@ func runGetTests(t *testing.T, ctx context.Context, grafanaListeningAddr string,
|
||||
OrgID: 1,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Name: "Test DS for GET Permissions 2",
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
Type: datasources.DS_TESTDATA,
|
||||
UID: dsUID,
|
||||
URL: "http://localhost:9090",
|
||||
})
|
||||
@@ -229,7 +229,7 @@ func runGetTests(t *testing.T, ctx context.Context, grafanaListeningAddr string,
|
||||
OrgID: 1,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Name: "Test DS for GET Permissions 3",
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
Type: datasources.DS_TESTDATA,
|
||||
UID: dsUID,
|
||||
URL: "http://localhost:9090",
|
||||
})
|
||||
@@ -1003,7 +1003,7 @@ func createTestDataSource(t *testing.T, ctx context.Context, dsService datasourc
|
||||
OrgID: 1,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Name: name,
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
Type: datasources.DS_TESTDATA,
|
||||
UID: uid,
|
||||
URL: "http://localhost:9090",
|
||||
})
|
||||
|
||||
@@ -1253,60 +1253,6 @@
|
||||
"signatureOrg": "",
|
||||
"angularDetected": false
|
||||
},
|
||||
{
|
||||
"name": "Prometheus",
|
||||
"type": "datasource",
|
||||
"id": "prometheus",
|
||||
"enabled": true,
|
||||
"pinned": false,
|
||||
"info": {
|
||||
"author": {
|
||||
"name": "Grafana Labs",
|
||||
"url": "https://grafana.com"
|
||||
},
|
||||
"description": "Open source time series database \u0026 alerting",
|
||||
"links": [
|
||||
{
|
||||
"name": "Learn more",
|
||||
"url": "https://prometheus.io/"
|
||||
},
|
||||
{
|
||||
"name": "Raise issue",
|
||||
"url": "https://github.com/grafana/grafana/issues/new"
|
||||
},
|
||||
{
|
||||
"name": "Documentation",
|
||||
"url": "https://grafana.com/docs/grafana/latest/datasources/prometheus/"
|
||||
}
|
||||
],
|
||||
"logos": {
|
||||
"small": "public/plugins/prometheus/img/prometheus_logo.svg",
|
||||
"large": "public/plugins/prometheus/img/prometheus_logo.svg"
|
||||
},
|
||||
"build": {},
|
||||
"screenshots": null,
|
||||
"version": "",
|
||||
"updated": "",
|
||||
"keywords": null
|
||||
},
|
||||
"dependencies": {
|
||||
"grafanaDependency": "",
|
||||
"grafanaVersion": "*",
|
||||
"plugins": [],
|
||||
"extensions": {
|
||||
"exposedComponents": []
|
||||
}
|
||||
},
|
||||
"latestVersion": "",
|
||||
"hasUpdate": false,
|
||||
"defaultNavUrl": "/plugins/prometheus/",
|
||||
"category": "tsdb",
|
||||
"state": "",
|
||||
"signature": "internal",
|
||||
"signatureType": "",
|
||||
"signatureOrg": "",
|
||||
"angularDetected": false
|
||||
},
|
||||
{
|
||||
"name": "Stat",
|
||||
"type": "panel",
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/tests/testinfra"
|
||||
"github.com/grafana/grafana/pkg/tests/testsuite"
|
||||
"github.com/grafana/grafana/pkg/util/testutil"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testsuite.Run(m)
|
||||
}
|
||||
|
||||
func TestIntegrationPrometheus(t *testing.T) {
|
||||
testutil.SkipIntegrationTestInShortMode(t)
|
||||
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableAnonymous: true,
|
||||
})
|
||||
|
||||
grafanaListeningAddr, testEnv := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
ctx := context.Background()
|
||||
|
||||
var outgoingRequest *http.Request
|
||||
outgoingServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
outgoingRequest = r
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
}))
|
||||
t.Cleanup(outgoingServer.Close)
|
||||
|
||||
jsonData := simplejson.NewFromAny(map[string]any{
|
||||
"httpMethod": "post",
|
||||
"httpHeaderName1": "X-CUSTOM-HEADER",
|
||||
"customQueryParameters": "q1=1&q2=2",
|
||||
})
|
||||
secureJSONData := map[string]string{
|
||||
"basicAuthPassword": "basicAuthPassword",
|
||||
"httpHeaderValue1": "custom-header-value",
|
||||
}
|
||||
|
||||
uid := "prometheus"
|
||||
_, err := testEnv.Server.HTTPServer.DataSourcesService.AddDataSource(ctx, &datasources.AddDataSourceCommand{
|
||||
OrgID: 1,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Name: "Prometheus",
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
UID: uid,
|
||||
URL: outgoingServer.URL,
|
||||
BasicAuth: true,
|
||||
BasicAuthUser: "basicAuthUser",
|
||||
JsonData: jsonData,
|
||||
SecureJsonData: secureJSONData,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("When calling /api/ds/query should set expected headers on outgoing HTTP request", func(t *testing.T) {
|
||||
query := simplejson.NewFromAny(map[string]any{
|
||||
"datasource": map[string]any{
|
||||
"uid": uid,
|
||||
},
|
||||
"expr": "1",
|
||||
"instantQuery": true,
|
||||
})
|
||||
buf1 := &bytes.Buffer{}
|
||||
err = json.NewEncoder(buf1).Encode(dtos.MetricRequest{
|
||||
From: "1668078080000",
|
||||
To: "1668081680000",
|
||||
Queries: []*simplejson.Json{query},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
u := fmt.Sprintf("http://admin:admin@%s/api/ds/query", grafanaListeningAddr)
|
||||
// nolint:gosec
|
||||
resp, err := http.Post(u, "application/json", buf1)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = resp.Body.Close()
|
||||
})
|
||||
|
||||
require.NotNil(t, outgoingRequest)
|
||||
require.Equal(t, "/api/v1/query_range?q1=1&q2=2", outgoingRequest.URL.String())
|
||||
require.Equal(t, "custom-header-value", outgoingRequest.Header.Get("X-CUSTOM-HEADER"))
|
||||
username, pwd, ok := outgoingRequest.BasicAuth()
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "basicAuthUser", username)
|
||||
require.Equal(t, "basicAuthPassword", pwd)
|
||||
})
|
||||
|
||||
t.Run("When calling /api/ds/query should set expected headers on outgoing HTTP request", func(t *testing.T) {
|
||||
query := simplejson.NewFromAny(map[string]any{
|
||||
"datasource": map[string]any{
|
||||
"uid": uid,
|
||||
},
|
||||
"expr": "up",
|
||||
"instantQuery": true,
|
||||
})
|
||||
buf1 := &bytes.Buffer{}
|
||||
err = json.NewEncoder(buf1).Encode(dtos.MetricRequest{
|
||||
From: "now-1h",
|
||||
To: "now",
|
||||
Queries: []*simplejson.Json{query},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
u := fmt.Sprintf("http://admin:admin@%s/api/ds/query", grafanaListeningAddr)
|
||||
// nolint:gosec
|
||||
resp, err := http.Post(u, "application/json", buf1)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = resp.Body.Close()
|
||||
})
|
||||
|
||||
require.NotNil(t, outgoingRequest)
|
||||
require.Equal(t, "/api/v1/query_range", outgoingRequest.URL.Path)
|
||||
require.Contains(t, outgoingRequest.URL.String(), "?q1=1&q2=2")
|
||||
require.Equal(t, "custom-header-value", outgoingRequest.Header.Get("X-CUSTOM-HEADER"))
|
||||
username, pwd, ok := outgoingRequest.BasicAuth()
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "basicAuthUser", username)
|
||||
require.Equal(t, "basicAuthPassword", pwd)
|
||||
})
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@@ -37,9 +38,8 @@ func TestPublicDashboardQueryAPI(t *testing.T) {
|
||||
|
||||
datasourcePayload := map[string]interface{}{
|
||||
"name": "Test Data Source",
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus",
|
||||
"url": "http://localhost:9090",
|
||||
"type": datasources.DS_TESTDATA,
|
||||
"uid": "testdata",
|
||||
"access": "proxy",
|
||||
}
|
||||
datasourceBytes, err := json.Marshal(datasourcePayload)
|
||||
@@ -64,11 +64,11 @@ func TestPublicDashboardQueryAPI(t *testing.T) {
|
||||
"title": "Test Panel",
|
||||
"targets": []map[string]interface{}{
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "up",
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"datasource": map[string]interface{}{
|
||||
"type": "prometheus",
|
||||
"uid": "prometheus",
|
||||
"type": datasources.DS_TESTDATA,
|
||||
"uid": "testdata",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -87,12 +89,43 @@ func TestIntegrationDatasourceProxy(t *testing.T) {
|
||||
return last
|
||||
}
|
||||
|
||||
helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
|
||||
grafanaOpts := testinfra.GrafanaOpts{
|
||||
DisableAnonymous: true,
|
||||
EnableFeatureToggles: []string{
|
||||
featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, // start the datasource api servers
|
||||
featuremgmt.FlagDatasourceUseNewCRUDAPIs, // register the datasource api groups
|
||||
},
|
||||
}
|
||||
grafanaDir, cfgPath := testinfra.CreateGrafDir(t, grafanaOpts)
|
||||
|
||||
pluginDir := filepath.Join(grafanaDir, "plugins", datasources.DS_PROMETHEUS)
|
||||
require.NoError(t, os.MkdirAll(pluginDir, 0o750))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(pluginDir, "plugin.json"), []byte(`{
|
||||
"type": "datasource",
|
||||
"name": "Prometheus",
|
||||
"id": "prometheus",
|
||||
"routes": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/rules",
|
||||
"reqRole": "Viewer",
|
||||
"reqAction": "alert.rules.external:read"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/rules",
|
||||
"reqRole": "Editor",
|
||||
"reqAction": "alert.rules.external:write"
|
||||
}
|
||||
],
|
||||
"info": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}`), 0o600))
|
||||
|
||||
helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
|
||||
Dir: grafanaDir,
|
||||
DirPath: cfgPath,
|
||||
})
|
||||
|
||||
ds := helper.CreateDS(&datasources.AddDataSourceCommand{
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
|
||||
"github.com/grafana/grafana-prometheus-datasource/pkg/promlib"
|
||||
)
|
||||
|
||||
type prometheusLib interface {
|
||||
QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error)
|
||||
CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error
|
||||
GetBuildInfo(ctx context.Context, req promlib.BuildInfoRequest) (*promlib.BuildInfoResponse, error)
|
||||
GetHeuristics(ctx context.Context, req promlib.HeuristicsRequest) (*promlib.Heuristics, error)
|
||||
CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error)
|
||||
ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error)
|
||||
MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error)
|
||||
ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error)
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
lib prometheusLib
|
||||
}
|
||||
|
||||
func ProvideService(httpClientProvider *sdkhttpclient.Provider) *Service {
|
||||
plog := backend.NewLoggerWith("logger", "tsdb.prometheus")
|
||||
plog.Debug("Initializing")
|
||||
return &Service{
|
||||
lib: promlib.NewService(httpClientProvider, plog, nil),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
return s.lib.QueryData(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
return s.lib.CallResource(ctx, req, sender)
|
||||
}
|
||||
|
||||
func (s *Service) GetBuildInfo(ctx context.Context, req promlib.BuildInfoRequest) (*promlib.BuildInfoResponse, error) {
|
||||
return s.lib.GetBuildInfo(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) GetHeuristics(ctx context.Context, req promlib.HeuristicsRequest) (*promlib.Heuristics, error) {
|
||||
return s.lib.GetHeuristics(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult,
|
||||
error) {
|
||||
return s.lib.CheckHealth(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
||||
return s.lib.ValidateAdmission(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
||||
return s.lib.MutateAdmission(ctx, req)
|
||||
}
|
||||
func (s *Service) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
||||
return s.lib.ConvertObjects(ctx, req)
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
"github.com/grafana/grafana-prometheus-datasource/pkg/promlib"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type mockLib struct {
|
||||
queryDataFn func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error)
|
||||
callResourceFn func(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error
|
||||
getBuildInfoFn func(ctx context.Context, req promlib.BuildInfoRequest) (*promlib.BuildInfoResponse, error)
|
||||
getHeuristicsFn func(ctx context.Context, req promlib.HeuristicsRequest) (*promlib.Heuristics, error)
|
||||
checkHealthFn func(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error)
|
||||
validateAdmissionFn func(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error)
|
||||
mutateAdmissionFn func(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error)
|
||||
convertObjectsFn func(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error)
|
||||
}
|
||||
|
||||
func (m *mockLib) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
return m.queryDataFn(ctx, req)
|
||||
}
|
||||
func (m *mockLib) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
return m.callResourceFn(ctx, req, sender)
|
||||
}
|
||||
func (m *mockLib) GetBuildInfo(ctx context.Context, req promlib.BuildInfoRequest) (*promlib.BuildInfoResponse, error) {
|
||||
return m.getBuildInfoFn(ctx, req)
|
||||
}
|
||||
func (m *mockLib) GetHeuristics(ctx context.Context, req promlib.HeuristicsRequest) (*promlib.Heuristics, error) {
|
||||
return m.getHeuristicsFn(ctx, req)
|
||||
}
|
||||
func (m *mockLib) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||
return m.checkHealthFn(ctx, req)
|
||||
}
|
||||
func (m *mockLib) ValidateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
||||
return m.validateAdmissionFn(ctx, req)
|
||||
}
|
||||
func (m *mockLib) MutateAdmission(ctx context.Context, req *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
||||
return m.mutateAdmissionFn(ctx, req)
|
||||
}
|
||||
func (m *mockLib) ConvertObjects(ctx context.Context, req *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
||||
return m.convertObjectsFn(ctx, req)
|
||||
}
|
||||
|
||||
func TestProvideService(t *testing.T) {
|
||||
svc := ProvideService(sdkhttpclient.NewProvider())
|
||||
require.NotNil(t, svc)
|
||||
require.NotNil(t, svc.lib)
|
||||
}
|
||||
|
||||
func TestQueryData(t *testing.T) {
|
||||
want := &backend.QueryDataResponse{}
|
||||
svc := &Service{lib: &mockLib{
|
||||
queryDataFn: func(_ context.Context, _ *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
return want, nil
|
||||
},
|
||||
}}
|
||||
got, err := svc.QueryData(context.Background(), &backend.QueryDataRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, want, got)
|
||||
}
|
||||
|
||||
func TestQueryData_Error(t *testing.T) {
|
||||
wantErr := errors.New("query failed")
|
||||
svc := &Service{lib: &mockLib{
|
||||
queryDataFn: func(_ context.Context, _ *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
return nil, wantErr
|
||||
},
|
||||
}}
|
||||
_, err := svc.QueryData(context.Background(), &backend.QueryDataRequest{})
|
||||
assert.ErrorIs(t, err, wantErr)
|
||||
}
|
||||
|
||||
func TestCallResource(t *testing.T) {
|
||||
called := false
|
||||
svc := &Service{lib: &mockLib{
|
||||
callResourceFn: func(_ context.Context, _ *backend.CallResourceRequest, _ backend.CallResourceResponseSender) error {
|
||||
called = true
|
||||
return nil
|
||||
},
|
||||
}}
|
||||
err := svc.CallResource(context.Background(), &backend.CallResourceRequest{}, nil)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, called)
|
||||
}
|
||||
|
||||
func TestCallResource_Error(t *testing.T) {
|
||||
wantErr := errors.New("resource failed")
|
||||
svc := &Service{lib: &mockLib{
|
||||
callResourceFn: func(_ context.Context, _ *backend.CallResourceRequest, _ backend.CallResourceResponseSender) error {
|
||||
return wantErr
|
||||
},
|
||||
}}
|
||||
err := svc.CallResource(context.Background(), &backend.CallResourceRequest{}, nil)
|
||||
assert.ErrorIs(t, err, wantErr)
|
||||
}
|
||||
|
||||
func TestGetBuildInfo(t *testing.T) {
|
||||
want := &promlib.BuildInfoResponse{}
|
||||
svc := &Service{lib: &mockLib{
|
||||
getBuildInfoFn: func(_ context.Context, _ promlib.BuildInfoRequest) (*promlib.BuildInfoResponse, error) {
|
||||
return want, nil
|
||||
},
|
||||
}}
|
||||
got, err := svc.GetBuildInfo(context.Background(), promlib.BuildInfoRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, want, got)
|
||||
}
|
||||
|
||||
func TestGetHeuristics(t *testing.T) {
|
||||
want := &promlib.Heuristics{}
|
||||
svc := &Service{lib: &mockLib{
|
||||
getHeuristicsFn: func(_ context.Context, _ promlib.HeuristicsRequest) (*promlib.Heuristics, error) {
|
||||
return want, nil
|
||||
},
|
||||
}}
|
||||
got, err := svc.GetHeuristics(context.Background(), promlib.HeuristicsRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, want, got)
|
||||
}
|
||||
|
||||
func TestCheckHealth(t *testing.T) {
|
||||
want := &backend.CheckHealthResult{Status: backend.HealthStatusOk}
|
||||
svc := &Service{lib: &mockLib{
|
||||
checkHealthFn: func(_ context.Context, _ *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||
return want, nil
|
||||
},
|
||||
}}
|
||||
got, err := svc.CheckHealth(context.Background(), &backend.CheckHealthRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, want, got)
|
||||
}
|
||||
|
||||
func TestCheckHealth_Error(t *testing.T) {
|
||||
wantErr := errors.New("health check failed")
|
||||
svc := &Service{lib: &mockLib{
|
||||
checkHealthFn: func(_ context.Context, _ *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
|
||||
return nil, wantErr
|
||||
},
|
||||
}}
|
||||
_, err := svc.CheckHealth(context.Background(), &backend.CheckHealthRequest{})
|
||||
assert.ErrorIs(t, err, wantErr)
|
||||
}
|
||||
|
||||
func TestValidateAdmission(t *testing.T) {
|
||||
want := &backend.ValidationResponse{Allowed: true}
|
||||
svc := &Service{lib: &mockLib{
|
||||
validateAdmissionFn: func(_ context.Context, _ *backend.AdmissionRequest) (*backend.ValidationResponse, error) {
|
||||
return want, nil
|
||||
},
|
||||
}}
|
||||
got, err := svc.ValidateAdmission(context.Background(), &backend.AdmissionRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, want, got)
|
||||
}
|
||||
|
||||
func TestMutateAdmission(t *testing.T) {
|
||||
want := &backend.MutationResponse{Allowed: true}
|
||||
svc := &Service{lib: &mockLib{
|
||||
mutateAdmissionFn: func(_ context.Context, _ *backend.AdmissionRequest) (*backend.MutationResponse, error) {
|
||||
return want, nil
|
||||
},
|
||||
}}
|
||||
got, err := svc.MutateAdmission(context.Background(), &backend.AdmissionRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, want, got)
|
||||
}
|
||||
|
||||
func TestConvertObjects(t *testing.T) {
|
||||
want := &backend.ConversionResponse{}
|
||||
svc := &Service{lib: &mockLib{
|
||||
convertObjectsFn: func(_ context.Context, _ *backend.ConversionRequest) (*backend.ConversionResponse, error) {
|
||||
return want, nil
|
||||
},
|
||||
}}
|
||||
got, err := svc.ConvertObjects(context.Background(), &backend.ConversionRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Same(t, want, got)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { render } from 'test/test-utils';
|
||||
import { byTestId, byText } from 'testing-library-selector';
|
||||
|
||||
import { type DataSourceApi } from '@grafana/data';
|
||||
import { type PromOptions } from '@grafana/prometheus';
|
||||
import { setPluginLinksHook } from '@grafana/runtime';
|
||||
import config from 'app/core/config';
|
||||
@@ -197,7 +198,24 @@ describe('PanelAlertTabContent', () => {
|
||||
AccessControlAction.AlertingRuleExternalRead,
|
||||
AccessControlAction.AlertingRuleExternalWrite,
|
||||
]);
|
||||
setupDataSources(...Object.values(dataSources));
|
||||
const dataSourceSrv = setupDataSources(...Object.values(dataSources));
|
||||
jest.spyOn(dataSourceSrv, 'get').mockImplementation(async (ref) => {
|
||||
const settings = dataSourceSrv.getInstanceSettings(ref);
|
||||
const options = settings?.jsonData as PromOptions | undefined;
|
||||
const dataSource: Partial<DataSourceApi> = {
|
||||
uid: settings?.uid,
|
||||
type: settings?.type,
|
||||
interval: options?.timeInterval ?? '15s',
|
||||
interpolateVariablesInQueries: (queries, scopedVars) =>
|
||||
queries.map((query) => ({
|
||||
...query,
|
||||
datasource: { uid: settings?.uid, type: settings?.type },
|
||||
expr: (query as { expr?: string }).expr?.replace('$__interval', String(scopedVars.__interval?.value)),
|
||||
interval: '',
|
||||
})),
|
||||
};
|
||||
return dataSource as DataSourceApi;
|
||||
});
|
||||
|
||||
setPluginLinksHook(() => ({
|
||||
links: [],
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Icon } from '@grafana/ui';
|
||||
import mimirLogoSvg from 'app/plugins/datasource/prometheus/img/mimir_logo.svg';
|
||||
import prometheusLogoSvg from 'app/plugins/datasource/prometheus/img/prometheus_logo.svg';
|
||||
import { PromApplication, type RulesSourceApplication } from 'app/types/unified-alerting-dto';
|
||||
|
||||
import lokiIconSvg from '../../../../loki-helpers/loki_icon.svg';
|
||||
|
||||
import mimirLogoSvg from './img/mimir_logo.svg';
|
||||
import prometheusLogoSvg from './img/prometheus_logo.svg';
|
||||
|
||||
interface DataSourceIconProps {
|
||||
application?: RulesSourceApplication;
|
||||
size?: number;
|
||||
|
||||
+19
-1
@@ -2,6 +2,7 @@ import userEvent from '@testing-library/user-event';
|
||||
import { render } from 'test/test-utils';
|
||||
import { byTestId } from 'testing-library-selector';
|
||||
|
||||
import { type DataSourceApi } from '@grafana/data';
|
||||
import { type PromOptions } from '@grafana/prometheus';
|
||||
import { config, locationService, setPluginLinksHook } from '@grafana/runtime';
|
||||
import * as ruler from 'app/features/alerting/unified/api/ruler';
|
||||
@@ -189,7 +190,24 @@ describe('PanelAlertTabContent', () => {
|
||||
AccessControlAction.AlertingRuleExternalWrite,
|
||||
]);
|
||||
|
||||
setupDataSources(...Object.values(dataSources));
|
||||
const dataSourceSrv = setupDataSources(...Object.values(dataSources));
|
||||
jest.spyOn(dataSourceSrv, 'get').mockImplementation(async (ref) => {
|
||||
const settings = dataSourceSrv.getInstanceSettings(ref);
|
||||
const options = settings?.jsonData as PromOptions | undefined;
|
||||
const dataSource: Partial<DataSourceApi> = {
|
||||
uid: settings?.uid,
|
||||
type: settings?.type,
|
||||
interval: options?.timeInterval ?? '15s',
|
||||
interpolateVariablesInQueries: (queries, scopedVars) =>
|
||||
queries.map((query) => ({
|
||||
...query,
|
||||
datasource: { uid: settings?.uid, type: settings?.type },
|
||||
expr: (query as { expr?: string }).expr?.replace('$__interval', String(scopedVars.__interval?.value)),
|
||||
interval: '',
|
||||
})),
|
||||
};
|
||||
return dataSource as DataSourceApi;
|
||||
});
|
||||
|
||||
mocks.rulerBuilderMock.mockReturnValue({
|
||||
rules: () => ({ path: `api/ruler/${GRAFANA_RULES_SOURCE_NAME}/api/v1/rules` }),
|
||||
|
||||
@@ -10,8 +10,6 @@ const influxdbPlugin = async () =>
|
||||
await import(/* webpackChunkName: "influxdbPlugin" */ 'app/plugins/datasource/influxdb/module');
|
||||
const mixedPlugin = async () =>
|
||||
await import(/* webpackChunkName: "mixedPlugin" */ 'app/plugins/datasource/mixed/module');
|
||||
const prometheusPlugin = async () =>
|
||||
await import(/* webpackChunkName: "prometheusPlugin" */ 'app/plugins/datasource/prometheus/module');
|
||||
const alertmanagerPlugin = async () =>
|
||||
await import(/* webpackChunkName: "alertmanagerPlugin" */ 'app/plugins/datasource/alertmanager/module');
|
||||
|
||||
@@ -74,7 +72,6 @@ const builtInPlugins: Record<string, System.Module | (() => Promise<System.Modul
|
||||
'core:plugin/grafana': grafanaPlugin,
|
||||
'core:plugin/influxdb': influxdbPlugin,
|
||||
'core:plugin/mixed': mixedPlugin,
|
||||
'core:plugin/prometheus': prometheusPlugin,
|
||||
'core:plugin/alertmanager': alertmanagerPlugin,
|
||||
// panels
|
||||
'core:plugin/text': () =>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Prometheus Data Source - Native Plugin
|
||||
|
||||
Grafana ships with **built in** support for Prometheus, the open-source service monitoring system and time series database.
|
||||
|
||||
Read more about it here:
|
||||
|
||||
[http://docs.grafana.org/datasources/prometheus/](http://docs.grafana.org/datasources/prometheus/)
|
||||
@@ -1,52 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import { type DataSourceSettings } from '@grafana/data';
|
||||
import { type PromOptions } from '@grafana/prometheus';
|
||||
|
||||
import { ConfigEditor } from './ConfigEditor';
|
||||
|
||||
function createDefaultConfigOptions(): DataSourceSettings<PromOptions> {
|
||||
return {
|
||||
jsonData: {},
|
||||
secureJsonFields: {},
|
||||
access: 'proxy',
|
||||
} as DataSourceSettings<PromOptions>;
|
||||
}
|
||||
|
||||
describe('ConfigEditor', () => {
|
||||
it('renders without error', () => {
|
||||
expect(() =>
|
||||
render(<ConfigEditor onOptionsChange={() => {}} options={createDefaultConfigOptions()} />)
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it('shows browser access mode alert when access is direct', () => {
|
||||
const options = { ...createDefaultConfigOptions(), access: 'direct' as const };
|
||||
render(<ConfigEditor onOptionsChange={() => {}} options={options} />);
|
||||
expect(
|
||||
screen.getByText(/Browser access mode in the Prometheus data source is no longer available/)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show browser access mode alert for proxy access', () => {
|
||||
render(<ConfigEditor onOptionsChange={() => {}} options={createDefaultConfigOptions()} />);
|
||||
expect(
|
||||
screen.queryByText(/Browser access mode in the Prometheus data source is no longer available/)
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the Prometheus server URL input', () => {
|
||||
render(<ConfigEditor onOptionsChange={() => {}} options={createDefaultConfigOptions()} />);
|
||||
expect(screen.getByPlaceholderText('http://localhost:9090')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the Authentication section', () => {
|
||||
render(<ConfigEditor onOptionsChange={() => {}} options={createDefaultConfigOptions()} />);
|
||||
expect(screen.getByRole('heading', { name: 'Authentication' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the Advanced settings section', () => {
|
||||
render(<ConfigEditor onOptionsChange={() => {}} options={createDefaultConfigOptions()} />);
|
||||
expect(screen.getByText('Advanced settings')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,105 +0,0 @@
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import { type DataSourcePluginOptionsEditorProps, type GrafanaTheme2 } from '@grafana/data';
|
||||
import { AdvancedHttpSettings, ConfigSection, DataSourceDescription } from '@grafana/plugin-ui';
|
||||
import { AlertingSettingsOverhaul, type PromOptions, PromSettings } from '@grafana/prometheus';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Alert, useTheme2 } from '@grafana/ui';
|
||||
|
||||
import { HttpSettings } from './HttpSettings';
|
||||
|
||||
export type Props = DataSourcePluginOptionsEditorProps<PromOptions>;
|
||||
|
||||
export const ConfigEditor = (props: Props) => {
|
||||
const { options, onOptionsChange } = props;
|
||||
const theme = useTheme2();
|
||||
const styles = overhaulStyles(theme);
|
||||
|
||||
return (
|
||||
<>
|
||||
{options.access === 'direct' && (
|
||||
<Alert title="Error" severity="error">
|
||||
Browser access mode in the Prometheus data source is no longer available. Switch to server access mode.
|
||||
</Alert>
|
||||
)}
|
||||
<DataSourceDescription
|
||||
dataSourceName="Prometheus"
|
||||
docsLink="https://grafana.com/docs/grafana/latest/datasources/prometheus/configure/"
|
||||
/>
|
||||
<hr className={`${styles.hrTopSpace} ${styles.hrBottomSpace}`} />
|
||||
<HttpSettings
|
||||
options={options}
|
||||
onOptionsChange={onOptionsChange}
|
||||
secureSocksDSProxyEnabled={config.secureSocksDSProxyEnabled}
|
||||
/>
|
||||
<hr />
|
||||
<ConfigSection
|
||||
className={styles.advancedSettings}
|
||||
title="Advanced settings"
|
||||
description="Additional settings are optional settings that can be configured for more control over your data source."
|
||||
>
|
||||
<AdvancedHttpSettings
|
||||
className={styles.advancedHTTPSettingsMargin}
|
||||
config={options}
|
||||
onChange={onOptionsChange}
|
||||
/>
|
||||
<AlertingSettingsOverhaul<PromOptions> options={options} onOptionsChange={onOptionsChange} />
|
||||
<PromSettings options={options} onOptionsChange={onOptionsChange} />
|
||||
</ConfigSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
function overhaulStyles(theme: GrafanaTheme2) {
|
||||
return {
|
||||
additionalSettings: css({
|
||||
marginBottom: '25px',
|
||||
}),
|
||||
secondaryGrey: css({
|
||||
color: `${theme.colors.secondary.text}`,
|
||||
opacity: '65%',
|
||||
}),
|
||||
inlineError: css({
|
||||
margin: '0px 0px 4px 245px',
|
||||
}),
|
||||
switchField: css({
|
||||
alignItems: 'center',
|
||||
}),
|
||||
sectionHeaderPadding: css({
|
||||
paddingTop: '32px',
|
||||
}),
|
||||
sectionBottomPadding: css({
|
||||
paddingBottom: '28px',
|
||||
}),
|
||||
subsectionText: css({
|
||||
fontSize: '12px',
|
||||
}),
|
||||
hrBottomSpace: css({
|
||||
marginBottom: '56px',
|
||||
}),
|
||||
hrTopSpace: css({
|
||||
marginTop: '50px',
|
||||
}),
|
||||
textUnderline: css({
|
||||
textDecoration: 'underline',
|
||||
}),
|
||||
versionMargin: css({
|
||||
marginBottom: '12px',
|
||||
}),
|
||||
advancedHTTPSettingsMargin: css({
|
||||
margin: '24px 0 8px 0',
|
||||
}),
|
||||
advancedSettings: css({
|
||||
paddingTop: '32px',
|
||||
}),
|
||||
alertingTop: css({
|
||||
marginTop: '40px !important',
|
||||
}),
|
||||
overhaulPageHeading: css({
|
||||
fontWeight: '400',
|
||||
}),
|
||||
container: css({
|
||||
maxwidth: '578',
|
||||
}),
|
||||
};
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { type DataSourceSettings } from '@grafana/data';
|
||||
import { type PromOptions } from '@grafana/prometheus';
|
||||
|
||||
import { HttpSettings } from './HttpSettings';
|
||||
|
||||
// Replace Auth with a test double that exposes onAuthMethodSelect as buttons,
|
||||
// so we can test the callback logic without depending on the Auth component's internal UI.
|
||||
jest.mock('@grafana/plugin-ui', () => ({
|
||||
...jest.requireActual('@grafana/plugin-ui'),
|
||||
Auth: ({ onAuthMethodSelect }: { onAuthMethodSelect: (method: string) => void }) => (
|
||||
<div>
|
||||
<button onClick={() => onAuthMethodSelect('BasicAuth')}>Basic auth</button>
|
||||
<button onClick={() => onAuthMethodSelect('OAuthForward')}>Forward OAuth Identity</button>
|
||||
<button onClick={() => onAuthMethodSelect('CrossSiteCredentials')}>Cross-site credentials</button>
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
function createDefaultConfigOptions(): DataSourceSettings<PromOptions> {
|
||||
return {
|
||||
jsonData: {},
|
||||
secureJsonFields: {},
|
||||
access: 'proxy',
|
||||
basicAuth: false,
|
||||
withCredentials: false,
|
||||
} as DataSourceSettings<PromOptions>;
|
||||
}
|
||||
|
||||
describe('HttpSettings', () => {
|
||||
it('renders without error', () => {
|
||||
expect(() =>
|
||||
render(
|
||||
<HttpSettings
|
||||
options={createDefaultConfigOptions()}
|
||||
onOptionsChange={() => {}}
|
||||
secureSocksDSProxyEnabled={false}
|
||||
/>
|
||||
)
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it('renders the Prometheus server URL input', () => {
|
||||
render(
|
||||
<HttpSettings
|
||||
options={createDefaultConfigOptions()}
|
||||
onOptionsChange={() => {}}
|
||||
secureSocksDSProxyEnabled={false}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByPlaceholderText('http://localhost:9090')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows SecureSocksProxy settings when enabled', () => {
|
||||
render(
|
||||
<HttpSettings
|
||||
options={createDefaultConfigOptions()}
|
||||
onOptionsChange={() => {}}
|
||||
secureSocksDSProxyEnabled={true}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Secure Socks Proxy')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('hides SecureSocksProxy settings when disabled', () => {
|
||||
render(
|
||||
<HttpSettings
|
||||
options={createDefaultConfigOptions()}
|
||||
onOptionsChange={() => {}}
|
||||
secureSocksDSProxyEnabled={false}
|
||||
/>
|
||||
);
|
||||
expect(screen.queryByText('Secure Socks Proxy')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onOptionsChange with basicAuth:true when BasicAuth is selected', async () => {
|
||||
const onOptionsChange = jest.fn();
|
||||
render(
|
||||
<HttpSettings
|
||||
options={createDefaultConfigOptions()}
|
||||
onOptionsChange={onOptionsChange}
|
||||
secureSocksDSProxyEnabled={false}
|
||||
/>
|
||||
);
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Basic auth' }));
|
||||
expect(onOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ basicAuth: true, withCredentials: false }));
|
||||
});
|
||||
|
||||
it('calls onOptionsChange with oauthPassThru:true when OAuthForward is selected', async () => {
|
||||
const onOptionsChange = jest.fn();
|
||||
render(
|
||||
<HttpSettings
|
||||
options={createDefaultConfigOptions()}
|
||||
onOptionsChange={onOptionsChange}
|
||||
secureSocksDSProxyEnabled={false}
|
||||
/>
|
||||
);
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Forward OAuth Identity' }));
|
||||
expect(onOptionsChange).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
basicAuth: false,
|
||||
withCredentials: false,
|
||||
jsonData: expect.objectContaining({ oauthPassThru: true }),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('calls onOptionsChange with withCredentials:true when CrossSiteCredentials is selected', async () => {
|
||||
const onOptionsChange = jest.fn();
|
||||
render(
|
||||
<HttpSettings
|
||||
options={createDefaultConfigOptions()}
|
||||
onOptionsChange={onOptionsChange}
|
||||
secureSocksDSProxyEnabled={false}
|
||||
/>
|
||||
);
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Cross-site credentials' }));
|
||||
expect(onOptionsChange).toHaveBeenCalledWith(expect.objectContaining({ basicAuth: false, withCredentials: true }));
|
||||
});
|
||||
});
|
||||
@@ -1,83 +0,0 @@
|
||||
import { type DataSourceSettings } from '@grafana/data';
|
||||
import { Auth, AuthMethod, ConnectionSettings, convertLegacyAuthProps } from '@grafana/plugin-ui';
|
||||
import { docsTip, overhaulStyles, type PromOptions } from '@grafana/prometheus';
|
||||
import { SecureSocksProxySettings, useTheme2 } from '@grafana/ui';
|
||||
|
||||
type Props = {
|
||||
options: DataSourceSettings<PromOptions>;
|
||||
onOptionsChange: (options: DataSourceSettings<PromOptions>) => void;
|
||||
secureSocksDSProxyEnabled: boolean;
|
||||
};
|
||||
|
||||
export const HttpSettings = (props: Props) => {
|
||||
const { options, onOptionsChange, secureSocksDSProxyEnabled } = props;
|
||||
|
||||
const newAuthProps = convertLegacyAuthProps({
|
||||
config: options,
|
||||
onChange: onOptionsChange,
|
||||
});
|
||||
|
||||
const theme = useTheme2();
|
||||
const styles = overhaulStyles(theme);
|
||||
|
||||
// Do we need this switch anymore? Update the language.
|
||||
let urlTooltip;
|
||||
switch (options.access) {
|
||||
case 'direct':
|
||||
urlTooltip = (
|
||||
<>
|
||||
Your access method is <em>Browser</em>, this means the URL needs to be accessible from the browser.
|
||||
{docsTip()}
|
||||
</>
|
||||
);
|
||||
break;
|
||||
case 'proxy':
|
||||
urlTooltip = (
|
||||
<>
|
||||
Your access method is <em>Server</em>, this means the URL needs to be accessible from the grafana
|
||||
backend/server.
|
||||
{docsTip()}
|
||||
</>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
urlTooltip = <>Specify a complete HTTP URL (for example http://your_server:8080) {docsTip()}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConnectionSettings
|
||||
urlPlaceholder="http://localhost:9090"
|
||||
config={options}
|
||||
onChange={onOptionsChange}
|
||||
urlLabel="Prometheus server URL"
|
||||
urlTooltip={urlTooltip}
|
||||
/>
|
||||
<hr className={`${styles.hrTopSpace} ${styles.hrBottomSpace}`} />
|
||||
<Auth
|
||||
{...newAuthProps}
|
||||
onAuthMethodSelect={(method) => {
|
||||
onOptionsChange({
|
||||
...options,
|
||||
basicAuth: method === AuthMethod.BasicAuth,
|
||||
withCredentials: method === AuthMethod.CrossSiteCredentials,
|
||||
jsonData: {
|
||||
...options.jsonData,
|
||||
oauthPassThru: method === AuthMethod.OAuthForward,
|
||||
},
|
||||
});
|
||||
}}
|
||||
// If your method is selected pass its id to `selectedMethod`,
|
||||
// otherwise pass the id from converted legacy data
|
||||
selectedMethod={newAuthProps.selectedMethod}
|
||||
/>
|
||||
<div className={styles.sectionBottomPadding} />
|
||||
{secureSocksDSProxyEnabled && (
|
||||
<>
|
||||
<SecureSocksProxySettings options={options} onOptionsChange={onOptionsChange} />
|
||||
<div className={styles.sectionBottomPadding} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><g fill="#3b697e"><path d="m64.001 32c0-17.646-14.356-32.001-32.001-32.001-17.646 0-32.001 14.355-32.001 32.001s14.355 32.001 32.001 32.001 32.001-14.355 32.001-32.001zm-62.592 0c0-16.868 13.723-30.591 30.591-30.591s30.591 13.723 30.591 30.591-13.723 30.591-30.591 30.591-30.591-13.723-30.591-30.591z" fill-rule="nonzero"/><circle cx="49.3" cy="32.725" r="5.296"/><circle cx="31.875" cy="52.94" r="5.296"/><path d="m31.148 33.103 3.295-8.185 2.988 8.538h2.684c.226 2.71 1.641 5.186 3.861 6.757l-8.659 8.659.665.665 8.808-8.808c1.378.774 2.932 1.18 4.512 1.18 5.056 0 9.216-4.16 9.216-9.215 0-5.056-4.16-9.216-9.216-9.216-1.464 0-2.907.349-4.209 1.017l-9.039-8.587c.797-.953 1.234-2.156 1.234-3.399 0-2.906-2.391-5.297-5.297-5.297s-5.297 2.391-5.297 5.297 2.391 5.297 5.297 5.297c1.242 0 2.445-.436 3.397-1.233l8.86 8.417c-2.542 1.666-4.102 4.486-4.162 7.525h-1.987l-3.594-10.267-3.992 9.915h-4.457l-3.788 8.766-3.341-8.353-.01.004v-.09h-3.378c-.124-2.816-2.474-5.064-5.292-5.064-2.907 0-5.298 2.391-5.298 5.298 0 2.906 2.391 5.298 5.298 5.298 2.64 0 4.898-1.975 5.25-4.592h2.759l3.978 9.947 4.44-10.274zm18.152-8.685c4.54 0 8.276 3.736 8.276 8.276s-3.736 8.276-8.276 8.276-8.276-3.736-8.276-8.276c.005-4.538 3.737-8.271 8.276-8.276z" fill-rule="nonzero"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="2.41 2.16 355.42 355.17"><path fill="#fff" d="M9.49808 9.14822v341.59786h241.93485a99.66306 99.66306 0 0 0 99.657-99.663V9.14822zm266.263 215.32837h12.75033v12.75018h-12.75035zm-4.00963-54.89h20.71531v20.72131h-20.71533zm-3.186-54.10261h27.09335v27.11729h-27.09343zm-43.739 159.90321h12.7381v12.75018h-12.75017zm-3.98558-55.53932h20.72129V240.587h-20.72129zm-3.186-53.44731h27.12344v27.09337h-27.09339zm3.186-27.00322v-20.71528h20.72129v20.71527zm-97.82954 135.98981h12.75021v12.75018h-12.75021zm-3.98558-54.8901h20.72131v20.69121h-20.72124zm3.98558-34.1748v-12.75019h12.75021v12.75018zm-3.98558-67.64019h20.72131v20.71527h-20.72124zM72.10081 275.38715H84.875v12.75018H72.10081zm0-50.91056H84.875v12.75018H72.10081zm-3.97955-54.89h20.7153v20.72131h-20.7153zm-3.19206-54.10265h27.09939v27.11729H64.9292zM53.01459 52.67679h254.53469v50.91052H205.74622v203.6302h-50.90449v-203.6302H53.01459z"/></svg>
|
||||
|
Before Width: | Height: | Size: 958 B |
@@ -1,7 +0,0 @@
|
||||
import { plugin as PrometheusDatasourcePlugin } from './module';
|
||||
|
||||
describe('module', () => {
|
||||
it('should have metrics query field in panels and Explore', () => {
|
||||
expect(PrometheusDatasourcePlugin.components.QueryEditor).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
import { DataSourcePlugin } from '@grafana/data';
|
||||
import { PromCheatSheet, PrometheusDatasource, PromQueryEditorByApp } from '@grafana/prometheus';
|
||||
|
||||
import { ConfigEditor } from './configuration/ConfigEditor';
|
||||
|
||||
export const plugin = new DataSourcePlugin(PrometheusDatasource)
|
||||
.setQueryEditor(PromQueryEditorByApp)
|
||||
.setConfigEditor(ConfigEditor)
|
||||
.setQueryEditorHelp(PromCheatSheet);
|
||||
@@ -1,102 +0,0 @@
|
||||
{
|
||||
"type": "datasource",
|
||||
"name": "Prometheus",
|
||||
"id": "prometheus",
|
||||
"category": "tsdb",
|
||||
"routes": [
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/query",
|
||||
"reqRole": "Viewer",
|
||||
"reqAction": "datasources:query"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/query_range",
|
||||
"reqRole": "Viewer",
|
||||
"reqAction": "datasources:query"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/series",
|
||||
"reqRole": "Viewer",
|
||||
"reqAction": "datasources:query"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/labels",
|
||||
"reqRole": "Viewer",
|
||||
"reqAction": "datasources:query"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/query_exemplars",
|
||||
"reqRole": "Viewer",
|
||||
"reqAction": "datasources:query"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/rules",
|
||||
"reqRole": "Viewer",
|
||||
"reqAction": "alert.rules.external:read"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/rules",
|
||||
"reqRole": "Editor",
|
||||
"reqAction": "alert.rules.external:write"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/rules",
|
||||
"reqRole": "Editor",
|
||||
"reqAction": "alert.rules.external:write"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "/config/v1/rules",
|
||||
"reqRole": "Editor",
|
||||
"reqAction": "alert.rules.external:write"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/config/v1/rules",
|
||||
"reqRole": "Editor",
|
||||
"reqAction": "alert.rules.external:write"
|
||||
}
|
||||
],
|
||||
"includes": [],
|
||||
"metrics": true,
|
||||
"alerting": true,
|
||||
"annotations": true,
|
||||
"backend": true,
|
||||
"queryOptions": {
|
||||
"minInterval": true
|
||||
},
|
||||
"multiValueFilterOperators": true,
|
||||
"info": {
|
||||
"description": "Open source time series database & alerting",
|
||||
"author": {
|
||||
"name": "Grafana Labs",
|
||||
"url": "https://grafana.com"
|
||||
},
|
||||
"logos": {
|
||||
"small": "img/prometheus_logo.svg",
|
||||
"large": "img/prometheus_logo.svg"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"name": "Learn more",
|
||||
"url": "https://prometheus.io/"
|
||||
},
|
||||
{
|
||||
"name": "Raise issue",
|
||||
"url": "https://github.com/grafana/grafana/issues/new"
|
||||
},
|
||||
{
|
||||
"name": "Documentation",
|
||||
"url": "https://grafana.com/docs/grafana/latest/datasources/prometheus/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user