Skip to content

Commit

Permalink
Client side migration for v3 config name changes
Browse files Browse the repository at this point in the history
  • Loading branch information
SpencerTorres committed Dec 5, 2023
1 parent eac3968 commit ec71bff
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/views/CHConfigEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { RadioButtonGroup, Switch, Input, SecretInput, Button, Field, Horizontal
import { CertificationKey } from '../components/ui/CertificationKey';
import { Components } from 'selectors';
import { CHConfig, CHCustomSetting, CHSecureConfig, CHLogsConfig, Protocol, CHTracesConfig } from 'types/config';
import { gte } from 'semver';
import { gte as versionGte } from 'semver';
import { ConfigSection, ConfigSubSection, DataSourceDescription } from '@grafana/experimental';
import { config } from '@grafana/runtime';
import { Divider } from 'components/Divider';
Expand All @@ -17,6 +17,7 @@ import { DefaultDatabaseTableConfig } from 'components/configEditor/DefaultDatab
import { QuerySettingsConfig } from 'components/configEditor/QuerySettingsConfig';
import { LogsConfig } from 'components/configEditor/LogsConfig';
import { TracesConfig } from 'components/configEditor/TracesConfig';
import { useMigrateV3Config } from './CHConfigEditorHooks';

export interface ConfigEditorProps extends DataSourcePluginOptionsEditorProps<CHConfig> {}

Expand All @@ -32,6 +33,9 @@ export const ConfigEditor: React.FC<ConfigEditorProps> = (props) => {
{ label: 'Native', value: Protocol.Native },
{ label: 'HTTP', value: Protocol.Http },
];

useMigrateV3Config(options, onOptionsChange);

const onPortChange = (port: string) => {
onOptionsChange({
...options,
Expand Down Expand Up @@ -382,7 +386,7 @@ export const ConfigEditor: React.FC<ConfigEditorProps> = (props) => {
/>

<Divider />
{config.featureToggles['secureSocksDSProxyEnabled'] && gte(config.buildInfo.version, '10.0.0') && (
{config.featureToggles['secureSocksDSProxyEnabled'] && versionGte(config.buildInfo.version, '10.0.0') && (
<Field
label={labels.SecureSocksProxy.label}
description={labels.SecureSocksProxy.tooltip}
Expand Down
64 changes: 64 additions & 0 deletions src/views/CHConfigEditorHooks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { DataSourceSettings } from "@grafana/data";
import { renderHook } from "@testing-library/react";
import { CHConfig } from "types/config";
import { useMigrateV3Config } from "./CHConfigEditorHooks";

describe('useMigrateV3Config', () => {
it('should not call onOptionsChange if no v3 fields are present', async () => {
const onOptionsChange = jest.fn();
const options = {
jsonData: {
host: 'new',
dialTimeout: '8'
}
} as any as DataSourceSettings<CHConfig>;

renderHook(opts => useMigrateV3Config(opts, onOptionsChange), { initialProps: options });

expect(onOptionsChange).toHaveBeenCalledTimes(0);
});

it('should rename v3 fields to latest config names', async () => {
const onOptionsChange = jest.fn();
const options = {
jsonData: {
server: 'address',
timeout: '8'
}
} as any as DataSourceSettings<CHConfig>;

renderHook(opts => useMigrateV3Config(opts, onOptionsChange), { initialProps: options });

const expectedOptions = {
jsonData: {
host: 'address',
dialTimeout: '8'
}
};
expect(onOptionsChange).toHaveBeenCalledTimes(1);
expect(onOptionsChange).toHaveBeenCalledWith(expect.objectContaining(expectedOptions));
});

it('should remove v3 fields without overwriting latest config names', async () => {
const onOptionsChange = jest.fn();
const options = {
jsonData: {
server: 'old',
host: 'new',
timeout: '6',
dialTimeout: '8'
}
} as any as DataSourceSettings<CHConfig>;

renderHook(opts => useMigrateV3Config(opts, onOptionsChange), { initialProps: options });

const expectedOptions = {
jsonData: {
host: 'new',
dialTimeout: '8'
}
};
expect(onOptionsChange).toHaveBeenCalledTimes(1);
expect(onOptionsChange).toHaveBeenCalledWith(expect.objectContaining(expectedOptions));
});
});
37 changes: 37 additions & 0 deletions src/views/CHConfigEditorHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { DataSourceSettings } from "@grafana/data";
import { useEffect, useRef } from "react";
import { CHConfig } from "types/config";

/**
* Migrates v3 config to latest config schema.
* Copies and removes old "server" to "host" field
* Copies and removes old "timeout" to "dialTimeout" field
*/
export const useMigrateV3Config = (options: DataSourceSettings<CHConfig>, onOptionsChange: (opts: DataSourceSettings<CHConfig>) => void) => {
const { jsonData } = options;
const v3ServerField = (jsonData as any)['server'];
const v3TimeoutField = (jsonData as any)['timeout'];

const migrated = useRef<boolean>(!v3ServerField && !v3TimeoutField);
useEffect(() => {
if (!migrated.current) {
const nextJsonOptions = { ...options.jsonData };

if (v3ServerField && !nextJsonOptions.host) {
nextJsonOptions.host = v3ServerField;
}
delete (nextJsonOptions as any)['server'];

if (v3TimeoutField && !nextJsonOptions.dialTimeout) {
nextJsonOptions.dialTimeout = v3TimeoutField;
}
delete (nextJsonOptions as any)['timeout'];

onOptionsChange({
...options,
jsonData: nextJsonOptions,
});
migrated.current = true;
}
}, [v3ServerField, v3TimeoutField, options, onOptionsChange]);
};

0 comments on commit ec71bff

Please sign in to comment.