InfluxDB: Use database input for SQL configuration instead of metadata (#79579)

* introduce constants file

* update frontend to use database field

* use dbName field instead of metadata

* use secureGrpc

* betterer
This commit is contained in:
ismail simsek 2023-12-15 18:41:32 +01:00 committed by GitHub
parent d89a8a3a82
commit 2edcf0edbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 58 additions and 146 deletions

View File

@ -7400,10 +7400,6 @@ exports[`no gf-form usage`] = {
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"]
], ],
"public/app/plugins/datasource/influxdb/components/editor/config/InfluxSQLConfig.tsx:5381": [
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"]
],
"public/app/plugins/datasource/influxdb/components/editor/query/QueryEditor.tsx:5381": [ "public/app/plugins/datasource/influxdb/components/editor/query/QueryEditor.tsx:5381": [
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"]
], ],

View File

@ -98,17 +98,9 @@ func runnerFromDataSource(dsInfo *models.DatasourceInfo) (*runner, error) {
} }
md := metadata.MD{} md := metadata.MD{}
for _, m := range dsInfo.Metadata { if dsInfo.DbName != "" {
for k, v := range m { md.Set("database", dsInfo.DbName)
if _, ok := md[k]; ok {
return nil, fmt.Errorf("metadata: duplicate key: %s", k)
}
if k != "" {
md.Set(k, v)
}
}
} }
if dsInfo.Token != "" { if dsInfo.Token != "" {
md.Set("Authorization", fmt.Sprintf("Bearer %s", dsInfo.Token)) md.Set("Authorization", fmt.Sprintf("Bearer %s", dsInfo.Token))
} }

View File

@ -63,11 +63,6 @@ func (suite *FSQLTestSuite) TestIntegration_QueryData() {
DbName: "influxdb", DbName: "influxdb",
Version: "test", Version: "test",
HTTPMode: "proxy", HTTPMode: "proxy",
Metadata: []map[string]string{
{
"bucket": "bucket",
},
},
SecureGrpc: false, SecureGrpc: false,
}, },
backend.QueryDataRequest{ backend.QueryDataRequest{

View File

@ -81,7 +81,6 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
TimeInterval: jsonData.TimeInterval, TimeInterval: jsonData.TimeInterval,
DefaultBucket: jsonData.DefaultBucket, DefaultBucket: jsonData.DefaultBucket,
Organization: jsonData.Organization, Organization: jsonData.Organization,
Metadata: jsonData.Metadata,
MaxSeries: maxSeries, MaxSeries: maxSeries,
SecureGrpc: true, SecureGrpc: true,
Token: settings.DecryptedSecureJSONData["token"], Token: settings.DecryptedSecureJSONData["token"],

View File

@ -18,8 +18,6 @@ type DatasourceInfo struct {
Organization string `json:"organization"` Organization string `json:"organization"`
MaxSeries int `json:"maxSeries"` MaxSeries int `json:"maxSeries"`
// Flight SQL metadata
Metadata []map[string]string `json:"metadata"`
// FlightSQL grpc connection // FlightSQL grpc connection
SecureGrpc bool `json:"secureGrpc"` SecureGrpc bool `json:"secureGrpc"`
} }

View File

@ -11,7 +11,7 @@ import { InlineField, InlineFieldRow, Input, SecretInput } from '@grafana/ui';
import { InfluxOptions, InfluxSecureJsonData } from '../../../types'; import { InfluxOptions, InfluxSecureJsonData } from '../../../types';
const WIDTH_SHORT = 20; import { WIDTH_SHORT } from './constants';
export type Props = DataSourcePluginOptionsEditorProps<InfluxOptions, InfluxSecureJsonData>; export type Props = DataSourcePluginOptionsEditorProps<InfluxOptions, InfluxSecureJsonData>;

View File

@ -4,6 +4,7 @@ import React from 'react';
import { import {
DataSourcePluginOptionsEditorProps, DataSourcePluginOptionsEditorProps,
GrafanaTheme2,
onUpdateDatasourceJsonDataOption, onUpdateDatasourceJsonDataOption,
onUpdateDatasourceJsonDataOptionSelect, onUpdateDatasourceJsonDataOptionSelect,
onUpdateDatasourceOption, onUpdateDatasourceOption,
@ -11,18 +12,17 @@ import {
SelectableValue, SelectableValue,
updateDatasourcePluginResetOption, updateDatasourcePluginResetOption,
} from '@grafana/data'; } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data/src/themes';
import { Alert, Field, InlineLabel, Input, SecretInput, Select, useStyles2 } from '@grafana/ui'; import { Alert, Field, InlineLabel, Input, SecretInput, Select, useStyles2 } from '@grafana/ui';
import { InfluxOptions, InfluxSecureJsonData } from '../../../types'; import { InfluxOptions, InfluxSecureJsonData } from '../../../types';
import { WIDTH_SHORT } from './constants';
const httpModes: SelectableValue[] = [ const httpModes: SelectableValue[] = [
{ label: 'GET', value: 'GET' }, { label: 'GET', value: 'GET' },
{ label: 'POST', value: 'POST' }, { label: 'POST', value: 'POST' },
]; ];
const WIDTH_SHORT = 20;
export type Props = DataSourcePluginOptionsEditorProps<InfluxOptions, InfluxSecureJsonData>; export type Props = DataSourcePluginOptionsEditorProps<InfluxOptions, InfluxSecureJsonData>;
export const InfluxInfluxQLConfig = (props: Props) => { export const InfluxInfluxQLConfig = (props: Props) => {

View File

@ -1,138 +1,69 @@
import React, { useEffect, useState } from 'react'; import { css } from '@emotion/css';
import { uniqueId } from 'lodash';
import React from 'react';
import { import {
DataSourcePluginOptionsEditorProps, DataSourcePluginOptionsEditorProps,
GrafanaTheme2,
onUpdateDatasourceSecureJsonDataOption, onUpdateDatasourceSecureJsonDataOption,
updateDatasourcePluginResetOption, updateDatasourcePluginResetOption,
} from '@grafana/data'; } from '@grafana/data';
import { InlineField, SecretInput, Input, InlineFieldRow, InlineLabel } from '@grafana/ui'; import { Field, InlineLabel, Input, SecretInput, useStyles2 } from '@grafana/ui';
import { InfluxOptions, InfluxSecureJsonData } from '../../../types'; import { InfluxOptions, InfluxSecureJsonData } from '../../../types';
import { WIDTH_SHORT } from './constants';
export type Props = DataSourcePluginOptionsEditorProps<InfluxOptions, InfluxSecureJsonData>; export type Props = DataSourcePluginOptionsEditorProps<InfluxOptions, InfluxSecureJsonData>;
type MetadataState = Array<{ key: string; value: string }>;
export const addMetaData = (setMetaData: (val: MetadataState) => void, metaDataArr: MetadataState) => {
setMetaData([...metaDataArr, { key: '', value: '' }]);
};
export const removeMetaData = (i: number, setMetaData: (val: MetadataState) => void, metaDataArr: MetadataState) => {
const newMetaValues = [...metaDataArr];
newMetaValues.splice(i, 1);
setMetaData(newMetaValues);
};
export const onKeyChange = (
key: string,
metaDataArr: MetadataState,
index: number,
setMetaData: (val: MetadataState) => void
) => {
const newMetaValues = [...metaDataArr];
newMetaValues[index]['key'] = key;
setMetaData(newMetaValues);
};
export const onValueChange = (
value: string,
metaDataArr: MetadataState,
index: number,
setMetaData: (val: MetadataState) => void
) => {
const newMetaValues = [...metaDataArr];
newMetaValues[index]['value'] = value;
setMetaData(newMetaValues);
};
export const InfluxSqlConfig = (props: Props) => { export const InfluxSqlConfig = (props: Props) => {
const { const { options, onOptionsChange } = props;
options: { jsonData, secureJsonData, secureJsonFields }, const { jsonData, secureJsonData, secureJsonFields } = options;
} = props; const styles = useStyles2(getStyles);
const htmlPrefix = uniqueId('influxdb-sql-config');
const existingMetadata: MetadataState = jsonData?.metadata?.length
? jsonData?.metadata?.map((md) => ({ key: Object.keys(md)[0], value: Object.values(md)[0] }))
: [{ key: '', value: '' }];
const [metaDataArr, setMetaData] = useState<MetadataState>(existingMetadata);
useEffect(() => {
const { onOptionsChange, options } = props;
const mapData = metaDataArr?.map((m) => ({ [m.key]: m.value }));
const jsonData = {
...options.jsonData,
metadata: mapData,
};
onOptionsChange({
...options,
jsonData,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [metaDataArr]);
return ( return (
<div> <div>
<div className="gf-form"> <Field
<h6>Token</h6> horizontal
</div> label={<InlineLabel width={WIDTH_SHORT}>Database</InlineLabel>}
<div> className={styles.horizontalField}
<InlineField labelWidth={20} label="Token"> htmlFor={`${htmlPrefix}-dbName`}
<SecretInput >
width={40} <Input
name="token" id={`${htmlPrefix}-dbName`}
type="text" className="width-20"
value={secureJsonData?.token || ''} aria-label="Database or bucket name"
onReset={() => updateDatasourcePluginResetOption(props, 'token')} value={jsonData.dbName}
onChange={onUpdateDatasourceSecureJsonDataOption(props, 'token')} onChange={(event) => {
isConfigured={secureJsonFields?.token} onOptionsChange({
/> ...options,
</InlineField> jsonData: {
</div> ...jsonData,
<div> dbName: event.currentTarget.value,
<div className="gf-form"> },
<h6>MetaData</h6> });
</div> }}
{metaDataArr?.map((_, i) => ( />
<InlineFieldRow key={i} style={{ flexFlow: 'row' }}> </Field>
<InlineField labelWidth={20} label="Key"> <Field horizontal label={<InlineLabel width={WIDTH_SHORT}>Token</InlineLabel>} className={styles.horizontalField}>
<Input <SecretInput
key={i} label="Token"
width={40} aria-label="Token"
name="key" className="width-20"
type="text" value={secureJsonData?.token || ''}
value={metaDataArr[i]?.key || ''} onReset={() => updateDatasourcePluginResetOption(props, 'token')}
placeholder="key" onChange={onUpdateDatasourceSecureJsonDataOption(props, 'token')}
onChange={(e) => onKeyChange(e.currentTarget.value.trim(), metaDataArr, i, setMetaData)} isConfigured={Boolean(secureJsonFields && secureJsonFields.token)}
></Input> />
</InlineField> </Field>
<InlineField labelWidth={20} label="Value">
<Input
key={i}
width={40}
name="value"
type="text"
value={metaDataArr[i]?.value?.toString() ?? ''}
placeholder="value"
onChange={(e) => onValueChange(e.currentTarget.value.trim(), metaDataArr, i, setMetaData)}
></Input>
</InlineField>
{i + 1 >= metaDataArr.length && (
<InlineLabel as="button" className="" onClick={() => addMetaData(setMetaData, metaDataArr)} width="auto">
+
</InlineLabel>
)}
{i > 0 && (
<InlineLabel
as="button"
className=""
width="auto"
onClick={() => removeMetaData(i, setMetaData, metaDataArr)}
>
-
</InlineLabel>
)}
</InlineFieldRow>
))}
</div>
</div> </div>
); );
}; };
const getStyles = (theme: GrafanaTheme2) => ({
horizontalField: css({
justifyContent: 'initial',
margin: `0 ${theme.spacing(0.5)} ${theme.spacing(0.5)} 0`,
}),
});

View File

@ -0,0 +1 @@
export const WIDTH_SHORT = 20;