mirror of
https://github.com/grafana/grafana.git
synced 2025-02-13 00:55:47 -06:00
Elasticsearch: Run version check thorugh backend if enableElasticsearchBackendQuerying enabled (#67679)
* Elasticsearch: Run getDBversion trough resource calls * Update * Update * Fix lint * Close response body * Fix lint * Refactor
This commit is contained in:
parent
681925fb63
commit
4d7c0904ef
@ -1,10 +1,15 @@
|
||||
package elasticsearch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
@ -172,3 +177,66 @@ func (s *Service) getDSInfo(pluginCtx backend.PluginContext) (*es.DatasourceInfo
|
||||
|
||||
return &instance, nil
|
||||
}
|
||||
|
||||
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
|
||||
logger := eslog.FromContext(ctx)
|
||||
// allowed paths for resource calls:
|
||||
// - empty string for fetching db version
|
||||
if req.Path != "" {
|
||||
return fmt.Errorf("invalid resource URL: %s", req.Path)
|
||||
}
|
||||
|
||||
ds, err := s.getDSInfo(req.PluginContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
esUrl, err := url.Parse(ds.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resourcePath, err := url.Parse(req.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We take the path and the query-string only
|
||||
esUrl.RawQuery = resourcePath.RawQuery
|
||||
esUrl.Path = path.Join(esUrl.Path, resourcePath.Path)
|
||||
|
||||
request, err := http.NewRequestWithContext(ctx, req.Method, esUrl.String(), bytes.NewBuffer(req.Body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response, err := ds.HTTPClient.Do(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := response.Body.Close(); err != nil {
|
||||
logger.Warn("Failed to close response body", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
responseHeaders := map[string][]string{
|
||||
"content-type": {"application/json"},
|
||||
}
|
||||
|
||||
if response.Header.Get("Content-Encoding") != "" {
|
||||
responseHeaders["content-encoding"] = []string{response.Header.Get("Content-Encoding")}
|
||||
}
|
||||
|
||||
return sender.Send(&backend.CallResourceResponse{
|
||||
Status: response.StatusCode,
|
||||
Headers: responseHeaders,
|
||||
Body: body,
|
||||
})
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
TimeRange,
|
||||
toUtc,
|
||||
} from '@grafana/data';
|
||||
import { BackendSrvRequest, FetchResponse, reportInteraction } from '@grafana/runtime';
|
||||
import { BackendSrvRequest, FetchResponse, reportInteraction, config } from '@grafana/runtime';
|
||||
import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__
|
||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
@ -31,6 +31,8 @@ import { Filters, ElasticsearchOptions, ElasticsearchQuery } from './types';
|
||||
|
||||
const ELASTICSEARCH_MOCK_URL = 'http://elasticsearch.local';
|
||||
|
||||
const originalConsoleError = console.error;
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getBackendSrv: () => backendSrv,
|
||||
@ -1291,3 +1293,37 @@ const logsResponse = {
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
describe('ElasticDatasource using backend', () => {
|
||||
beforeEach(() => {
|
||||
console.error = jest.fn();
|
||||
config.featureToggles.enableElasticsearchBackendQuerying = true;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
console.error = originalConsoleError;
|
||||
config.featureToggles.enableElasticsearchBackendQuerying = false;
|
||||
});
|
||||
describe('getDatabaseVersion', () => {
|
||||
it('should correctly get db version', async () => {
|
||||
const { ds } = getTestContext();
|
||||
ds.getResource = jest.fn().mockResolvedValue({ version: { number: '8.0.0' } });
|
||||
const version = await ds.getDatabaseVersion();
|
||||
expect(version?.raw).toBe('8.0.0');
|
||||
});
|
||||
|
||||
it('should correctly return null if invalid numeric version', async () => {
|
||||
const { ds } = getTestContext();
|
||||
ds.getResource = jest.fn().mockResolvedValue({ version: { number: 8 } });
|
||||
const version = await ds.getDatabaseVersion();
|
||||
expect(version).toBe(null);
|
||||
});
|
||||
|
||||
it('should correctly return null if rejected request', async () => {
|
||||
const { ds } = getTestContext();
|
||||
ds.getResource = jest.fn().mockRejectedValue({});
|
||||
const version = await ds.getDatabaseVersion();
|
||||
expect(version).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { cloneDeep, find, first as _first, isObject, isString, map as _map } from 'lodash';
|
||||
import { generate, lastValueFrom, Observable, of } from 'rxjs';
|
||||
import { from, generate, lastValueFrom, Observable, of } from 'rxjs';
|
||||
import { catchError, first, map, mergeMap, skipWhile, throwIfEmpty, tap } from 'rxjs/operators';
|
||||
import { SemVer } from 'semver';
|
||||
|
||||
@ -739,7 +739,11 @@ export class ElasticDatasource
|
||||
|
||||
private getDatabaseVersionUncached(): Promise<SemVer | null> {
|
||||
// we want this function to never fail
|
||||
return lastValueFrom(this.legacyQueryRunner.request('GET', '/')).then(
|
||||
const getDbVersionObservable = config.featureToggles.enableElasticsearchBackendQuerying
|
||||
? from(this.getResource(''))
|
||||
: this.legacyQueryRunner.request('GET', '/');
|
||||
|
||||
return lastValueFrom(getDbVersionObservable).then(
|
||||
(data) => {
|
||||
const versionNumber = data?.version?.number;
|
||||
if (typeof versionNumber !== 'string') {
|
||||
|
Loading…
Reference in New Issue
Block a user