From c9508d4ac98eededa3046923400a77ef9a4ef39e Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Tue, 11 Dec 2018 17:28:05 -0800 Subject: [PATCH] Feat(ui/dataLoaders): Change individual plugin selection to bundle selection --- ui/mocks/dummyData.ts | 62 +++++- ui/src/onboarding/actions/dataLoaders.ts | 108 +++++++--- ui/src/onboarding/apis/index.ts | 15 +- ui/src/onboarding/apis/mocks.ts | 12 +- ui/src/onboarding/apis/onboarding.test.ts | 10 + .../components/OnboardingStepSwitcher.tsx | 20 +- .../selectionStep/SelectDataSourceStep.tsx | 42 ++-- .../selectionStep/StreamingSelector.tsx | 39 ++-- .../components/selectionStep/TypeSelector.tsx | 6 +- ui/src/onboarding/constants/pluginConfigs.ts | 67 +++++- .../containers/OnboardingWizard.tsx | 22 +- .../onboarding/reducers/dataLoaders.test.ts | 200 +++++++++++++----- ui/src/onboarding/reducers/dataLoaders.ts | 47 ++-- ui/src/onboarding/utils/pluginConfigs.test.ts | 58 +++++ ui/src/onboarding/utils/pluginConfigs.ts | 33 ++- ui/src/types/v2/dataLoaders.ts | 18 ++ 16 files changed, 587 insertions(+), 172 deletions(-) create mode 100644 ui/src/onboarding/utils/pluginConfigs.test.ts diff --git a/ui/mocks/dummyData.ts b/ui/mocks/dummyData.ts index 2c13c546f2..976365408d 100644 --- a/ui/mocks/dummyData.ts +++ b/ui/mocks/dummyData.ts @@ -12,7 +12,17 @@ import {Links} from 'src/types/v2/links' import {Task, TaskStatus} from 'src/types/v2/tasks' import {OnboardingStepProps} from 'src/onboarding/containers/OnboardingWizard' import {ConfigurationState} from 'src/types/v2/dataLoaders' -import {TelegrafPluginInputCpu, TelegrafPluginInputRedis} from 'src/api' +import { + TelegrafPluginInputCpu, + TelegrafPluginInputRedis, + TelegrafPluginInputDisk, + TelegrafPluginInputKernel, + TelegrafPluginInputDiskio, + TelegrafPluginInputMem, + TelegrafPluginInputSwap, + TelegrafPluginInputSystem, + TelegrafPluginInputProcesses, +} from 'src/api' export const links: Links = { authorizations: '/api/v2/authorizations', @@ -289,7 +299,49 @@ export const cpuPlugin = { export const telegrafPlugin = { name: TelegrafPluginInputCpu.NameEnum.Cpu, configured: ConfigurationState.Unconfigured, - active: true, + active: false, +} + +export const cpuTelegrafPlugin = {...telegrafPlugin} + +export const diskTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputDisk.NameEnum.Disk, +} + +export const diskioTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputDiskio.NameEnum.Diskio, +} + +export const kernelTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputKernel.NameEnum.Kernel, +} + +export const memTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputMem.NameEnum.Mem, +} + +export const processesTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputProcesses.NameEnum.Processes, +} + +export const swapTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputSwap.NameEnum.Swap, +} + +export const systemTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputSystem.NameEnum.System, +} + +export const redisTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputRedis.NameEnum.Redis, } export const redisPlugin = { @@ -323,7 +375,7 @@ export const telegrafConfig = { plugins: [cpuPlugin, influxDB2Plugin], } -export const telegrafConfigsResponse = { +export const getTelegrafConfigsResponse = { data: { configurations: [telegrafConfig], }, @@ -348,6 +400,10 @@ export const telegrafConfigsResponse = { request: {}, } +export const createTelegrafConfigResponse = { + data: telegrafConfig, +} + export const authResponse = { data: { links: {self: '/api/v2/authorizations'}, diff --git a/ui/src/onboarding/actions/dataLoaders.ts b/ui/src/onboarding/actions/dataLoaders.ts index 72865778bc..ad093a6001 100644 --- a/ui/src/onboarding/actions/dataLoaders.ts +++ b/ui/src/onboarding/actions/dataLoaders.ts @@ -2,18 +2,25 @@ import _ from 'lodash' // Apis -import {writeLineProtocol} from 'src/onboarding/apis/index' -import {telegrafsAPI} from 'src/utils/api' +import { + writeLineProtocol, + createTelegrafConfig, +} from 'src/onboarding/apis/index' // Utils import {createNewPlugin} from 'src/onboarding/utils/pluginConfigs' +// Constants +import {pluginsByBundle} from 'src/onboarding/constants/pluginConfigs' + // Types import { TelegrafPlugin, DataLoaderType, LineProtocolTab, Plugin, + BundleName, + ConfigurationState, } from 'src/types/v2/dataLoaders' import {AppState} from 'src/types/v2' import {RemoteDataState} from 'src/types' @@ -27,17 +34,19 @@ const DEFAULT_COLLECTION_INTERVAL = 15 export type Action = | SetDataLoadersType | SetTelegrafConfigID - | AddTelegrafPlugin | UpdateTelegrafPluginConfig | AddConfigValue | RemoveConfigValue - | RemoveTelegrafPlugin | SetActiveTelegrafPlugin | SetLineProtocolBody | SetActiveLPTab | SetLPStatus | SetPrecision | UpdateTelegrafPlugin + | AddPluginBundle + | AddTelegrafPlugins + | RemoveBundlePlugins + | RemovePluginBundle interface SetDataLoadersType { type: 'SET_DATA_LOADERS_TYPE' @@ -51,18 +60,6 @@ export const setDataLoadersType = ( payload: {type}, }) -interface AddTelegrafPlugin { - type: 'ADD_TELEGRAF_PLUGIN' - payload: {telegrafPlugin: TelegrafPlugin} -} - -export const addTelegrafPlugin = ( - telegrafPlugin: TelegrafPlugin -): AddTelegrafPlugin => ({ - type: 'ADD_TELEGRAF_PLUGIN', - payload: {telegrafPlugin}, -}) - interface UpdateTelegrafPluginConfig { type: 'UPDATE_TELEGRAF_PLUGIN_CONFIG' payload: {name: string; field: string; value: string} @@ -133,6 +130,70 @@ export const setTelegrafConfigID = (id: string): SetTelegrafConfigID => ({ payload: {id}, }) +interface AddPluginBundle { + type: 'ADD_PLUGIN_BUNDLE' + payload: {bundle: BundleName} +} + +export const addPluginBundle = (bundle: BundleName): AddPluginBundle => ({ + type: 'ADD_PLUGIN_BUNDLE', + payload: {bundle}, +}) + +interface RemovePluginBundle { + type: 'REMOVE_PLUGIN_BUNDLE' + payload: {bundle: BundleName} +} + +export const removePluginBundle = (bundle: BundleName): RemovePluginBundle => ({ + type: 'REMOVE_PLUGIN_BUNDLE', + payload: {bundle}, +}) +interface AddTelegrafPlugins { + type: 'ADD_TELEGRAF_PLUGINS' + payload: {telegrafPlugins: TelegrafPlugin[]} +} + +export const addTelegrafPlugins = ( + telegrafPlugins: TelegrafPlugin[] +): AddTelegrafPlugins => ({ + type: 'ADD_TELEGRAF_PLUGINS', + payload: {telegrafPlugins}, +}) + +interface RemoveBundlePlugins { + type: 'REMOVE_BUNDLE_PLUGINS' + payload: {bundle: BundleName} +} + +export const removeBundlePlugins = ( + bundle: BundleName +): RemoveBundlePlugins => ({ + type: 'REMOVE_BUNDLE_PLUGINS', + payload: {bundle}, +}) + +export const addPluginBundleWithPlugins = (bundle: BundleName) => dispatch => { + dispatch(addPluginBundle(bundle)) + const plugins = pluginsByBundle[bundle] + dispatch( + addTelegrafPlugins( + plugins.map(p => ({ + name: p, + active: false, + configured: ConfigurationState.Unconfigured, + })) + ) + ) +} + +export const removePluginBundleWithPlugins = ( + bundle: BundleName +) => dispatch => { + dispatch(removePluginBundle(bundle)) + dispatch(removeBundlePlugins(bundle)) +} + export const createTelegrafConfigAsync = (authToken: string) => async ( dispatch, getState: GetState @@ -166,22 +227,11 @@ export const createTelegrafConfigAsync = (authToken: string) => async ( agent: {collectionInterval: DEFAULT_COLLECTION_INTERVAL}, plugins, } - const created = await telegrafsAPI.telegrafsPost(org, body) - dispatch(setTelegrafConfigID(created.data.id)) -} -interface RemoveTelegrafPlugin { - type: 'REMOVE_TELEGRAF_PLUGIN' - payload: {telegrafPlugin: string} + const created = await createTelegrafConfig(org, body) + dispatch(setTelegrafConfigID(created.id)) } -export const removeTelegrafPlugin = ( - telegrafPlugin: string -): RemoveTelegrafPlugin => ({ - type: 'REMOVE_TELEGRAF_PLUGIN', - payload: {telegrafPlugin}, -}) - interface SetActiveTelegrafPlugin { type: 'SET_ACTIVE_TELEGRAF_PLUGIN' payload: {telegrafPlugin: string} diff --git a/ui/src/onboarding/apis/index.ts b/ui/src/onboarding/apis/index.ts index 85b8672e42..419488acab 100644 --- a/ui/src/onboarding/apis/index.ts +++ b/ui/src/onboarding/apis/index.ts @@ -6,7 +6,7 @@ import {baseAPI} from 'src/utils/api' // Utils import AJAX from 'src/utils/ajax' import {telegrafsAPI, authorizationsAPI, writeAPI} from 'src/utils/api' -import {Telegraf, WritePrecision} from 'src/api' +import {Telegraf, WritePrecision, TelegrafRequest} from 'src/api' import {getDeep} from 'src/utils/wrappers' @@ -129,3 +129,16 @@ export const writeLineProtocol = async ( ) return data } + +export const createTelegrafConfig = async ( + org: string, + telegrafConfig: TelegrafRequest +): Promise => { + try { + const {data} = await telegrafsAPI.telegrafsPost(org, telegrafConfig) + + return data + } catch (error) { + console.error(error) + } +} diff --git a/ui/src/onboarding/apis/mocks.ts b/ui/src/onboarding/apis/mocks.ts index e747bffaff..42a9610b65 100644 --- a/ui/src/onboarding/apis/mocks.ts +++ b/ui/src/onboarding/apis/mocks.ts @@ -1,10 +1,18 @@ -import {telegrafConfigsResponse, authResponse} from 'mocks/dummyData' +import { + getTelegrafConfigsResponse, + authResponse, + createTelegrafConfigResponse, +} from 'mocks/dummyData' -const telegrafsGet = jest.fn(() => Promise.resolve(telegrafConfigsResponse)) +const telegrafsGet = jest.fn(() => Promise.resolve(getTelegrafConfigsResponse)) +const telegrafsPost = jest.fn(() => + Promise.resolve(createTelegrafConfigResponse) +) const authorizationsGet = jest.fn(() => Promise.resolve(authResponse)) export const telegrafsAPI = { telegrafsGet, + telegrafsPost, } export const authorizationsAPI = { diff --git a/ui/src/onboarding/apis/onboarding.test.ts b/ui/src/onboarding/apis/onboarding.test.ts index 10b2d919da..7ab73c7be4 100644 --- a/ui/src/onboarding/apis/onboarding.test.ts +++ b/ui/src/onboarding/apis/onboarding.test.ts @@ -3,6 +3,7 @@ import { setSetupParams, SetupParams, getTelegrafConfigs, + createTelegrafConfig, getAuthorizationToken, } from 'src/onboarding/apis' @@ -58,6 +59,15 @@ describe('Onboarding.Apis', () => { }) }) + describe('createTelegrafConfig', () => { + it('should return the newly created config', async () => { + const org = 'default' + const result = await createTelegrafConfig(org, telegrafConfig) + + expect(result).toEqual(telegrafConfig) + }) + }) + describe('getAuthorizationToken', () => { it('should return a token', async () => { const username = 'iris' diff --git a/ui/src/onboarding/components/OnboardingStepSwitcher.tsx b/ui/src/onboarding/components/OnboardingStepSwitcher.tsx index 13189c3d12..c8fd123e25 100644 --- a/ui/src/onboarding/components/OnboardingStepSwitcher.tsx +++ b/ui/src/onboarding/components/OnboardingStepSwitcher.tsx @@ -14,34 +14,34 @@ import FetchAuthToken from 'src/onboarding/components/verifyStep/FetchAuthToken' // Actions import { - addTelegrafPlugin, updateTelegrafPluginConfig, - removeTelegrafPlugin, setDataLoadersType, setActiveTelegrafPlugin, addConfigValue, removeConfigValue, createTelegrafConfigAsync, + addPluginBundleWithPlugins, + removePluginBundleWithPlugins, } from 'src/onboarding/actions/dataLoaders' // Types import {SetupParams} from 'src/onboarding/apis' -import {TelegrafPlugin, DataLoaderType} from 'src/types/v2/dataLoaders' +import {DataLoadersState} from 'src/types/v2/dataLoaders' import {OnboardingStepProps} from 'src/onboarding/containers/OnboardingWizard' interface Props { onboardingStepProps: OnboardingStepProps - onAddTelegrafPlugin: typeof addTelegrafPlugin onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig onAddConfigValue: typeof addConfigValue onRemoveConfigValue: typeof removeConfigValue - onRemoveTelegrafPlugin: typeof removeTelegrafPlugin onSetDataLoadersType: typeof setDataLoadersType onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin setupParams: SetupParams - dataLoaders: {telegrafPlugins: TelegrafPlugin[]; type: DataLoaderType} + dataLoaders: DataLoadersState currentStepIndex: number onSaveTelegrafConfig: typeof createTelegrafConfigAsync + onAddPluginBundle: typeof addPluginBundleWithPlugins + onRemovePluginBundle: typeof removePluginBundleWithPlugins } @ErrorHandling @@ -53,13 +53,13 @@ class OnboardingStepSwitcher extends PureComponent { setupParams, dataLoaders, onSetDataLoadersType, - onAddTelegrafPlugin, onSaveTelegrafConfig, onUpdateTelegrafPluginConfig, - onRemoveTelegrafPlugin, onSetActiveTelegrafPlugin, onAddConfigValue, onRemoveConfigValue, + onAddPluginBundle, + onRemovePluginBundle, } = this.props switch (currentStepIndex) { @@ -74,9 +74,9 @@ class OnboardingStepSwitcher extends PureComponent { {...dataLoaders} onSetDataLoadersType={onSetDataLoadersType} bucket={_.get(setupParams, 'bucket', '')} - onAddTelegrafPlugin={onAddTelegrafPlugin} - onRemoveTelegrafPlugin={onRemoveTelegrafPlugin} onSetActiveTelegrafPlugin={onSetActiveTelegrafPlugin} + onAddPluginBundle={onAddPluginBundle} + onRemovePluginBundle={onRemovePluginBundle} /> ) case 3: diff --git a/ui/src/onboarding/components/selectionStep/SelectDataSourceStep.tsx b/ui/src/onboarding/components/selectionStep/SelectDataSourceStep.tsx index 094c67152b..5385729b5b 100644 --- a/ui/src/onboarding/components/selectionStep/SelectDataSourceStep.tsx +++ b/ui/src/onboarding/components/selectionStep/SelectDataSourceStep.tsx @@ -12,26 +12,30 @@ import { ComponentStatus, } from 'src/clockface' import TypeSelector from 'src/onboarding/components/selectionStep/TypeSelector' -import StreamingDataSourceSelector from 'src/onboarding/components/selectionStep/StreamingSelector' +import StreamingSelector from 'src/onboarding/components/selectionStep/StreamingSelector' // Actions -import {setActiveTelegrafPlugin} from 'src/onboarding/actions/dataLoaders' +import { + setActiveTelegrafPlugin, + addPluginBundleWithPlugins, + removePluginBundleWithPlugins, +} from 'src/onboarding/actions/dataLoaders' // Types import {OnboardingStepProps} from 'src/onboarding/containers/OnboardingWizard' import { TelegrafPlugin, DataLoaderType, - ConfigurationState, - TelegrafPluginName, + BundleName, } from 'src/types/v2/dataLoaders' export interface OwnProps extends OnboardingStepProps { bucket: string telegrafPlugins: TelegrafPlugin[] + pluginBundles: BundleName[] type: DataLoaderType - onAddTelegrafPlugin: (telegrafPlugin: TelegrafPlugin) => void - onRemoveTelegrafPlugin: (TelegrafPlugin: string) => void + onAddPluginBundle: typeof addPluginBundleWithPlugins + onRemovePluginBundle: typeof removePluginBundleWithPlugins onSetDataLoadersType: (type: DataLoaderType) => void onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin } @@ -100,15 +104,16 @@ class SelectDataSourceStep extends PureComponent { private get selector(): JSX.Element { if (this.props.type === DataLoaderType.Streaming && this.isStreaming) { return ( - ) } return ( ) @@ -156,31 +161,24 @@ class SelectDataSourceStep extends PureComponent { this.props.onDecrementCurrentStepIndex() } - private handleSelectTelegrafPlugin = async ( - telegrafPlugin: DataLoaderType - ) => { - await this.props.onSetDataLoadersType(telegrafPlugin) + private handleSelectDataLoaderType = async (type: DataLoaderType) => { + await this.props.onSetDataLoadersType(type) this.handleClickNext() return } - private handleToggleTelegrafPlugin = ( - telegrafPlugin: TelegrafPluginName, + private handleTogglePluginBundle = ( + bundle: BundleName, isSelected: boolean ) => { if (isSelected) { - this.props.onRemoveTelegrafPlugin(telegrafPlugin) + this.props.onRemovePluginBundle(bundle) return } - const plugin: TelegrafPlugin = { - name: telegrafPlugin, - configured: ConfigurationState.Unconfigured, - active: false, - } - this.props.onAddTelegrafPlugin(plugin) + this.props.onAddPluginBundle(bundle) } private get isStreaming(): boolean { diff --git a/ui/src/onboarding/components/selectionStep/StreamingSelector.tsx b/ui/src/onboarding/components/selectionStep/StreamingSelector.tsx index 34b2450c16..5921a1e5f0 100644 --- a/ui/src/onboarding/components/selectionStep/StreamingSelector.tsx +++ b/ui/src/onboarding/components/selectionStep/StreamingSelector.tsx @@ -9,18 +9,20 @@ import {GridSizer} from 'src/clockface' // Constants import { - PLUGIN_OPTIONS, - PLUGIN_LOGOS, + PLUGIN_BUNDLE_OPTIONS, + BUNDLE_LOGOS, } from 'src/onboarding/constants/pluginConfigs' // Types -import {TelegrafPlugin} from 'src/types/v2/dataLoaders' +import {TelegrafPlugin, BundleName} from 'src/types/v2/dataLoaders' import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' export interface Props { + pluginBundles: BundleName[] telegrafPlugins: TelegrafPlugin[] - onToggleTelegrafPlugin: (telegrafPlugin: string, isSelected: boolean) => void + onTogglePluginBundle: (telegrafPlugin: string, isSelected: boolean) => void } + interface State { gridSizerUpdateFlag: string } @@ -66,16 +68,16 @@ class StreamingSelector extends PureComponent { wait={ANIMATION_LENGTH} recalculateFlag={gridSizerUpdateFlag} > - {PLUGIN_OPTIONS.map(ds => { + {PLUGIN_BUNDLE_OPTIONS.map(b => { return ( ) })} @@ -85,20 +87,17 @@ class StreamingSelector extends PureComponent { ) } - private isCardChecked(telegrafPlugin: string) { - const {telegrafPlugins} = this.props + private isCardChecked(bundle: BundleName) { + const {pluginBundles} = this.props - if (telegrafPlugins.find(ds => ds.name === telegrafPlugin)) { + if (pluginBundles.find(b => b === bundle)) { return true } return false } - private handleToggle = (telegrafPlugin: string) => () => { - this.props.onToggleTelegrafPlugin( - telegrafPlugin, - this.isCardChecked(telegrafPlugin) - ) + private handleToggle = (bundle: BundleName) => () => { + this.props.onTogglePluginBundle(bundle, this.isCardChecked(bundle)) } } diff --git a/ui/src/onboarding/components/selectionStep/TypeSelector.tsx b/ui/src/onboarding/components/selectionStep/TypeSelector.tsx index deda5b410a..5b3813d682 100644 --- a/ui/src/onboarding/components/selectionStep/TypeSelector.tsx +++ b/ui/src/onboarding/components/selectionStep/TypeSelector.tsx @@ -11,7 +11,7 @@ import {IconCSV, IconLineProtocol, IconStreaming} from 'src/onboarding/graphics' import {DataLoaderType} from 'src/types/v2/dataLoaders' export interface Props { - onSelectTelegrafPlugin: (telegrafPlugin: string) => void + onSelectDataLoaderType: (type: string) => void type: DataLoaderType } @@ -57,8 +57,8 @@ class TypeSelector extends PureComponent { return dataLoaderType === type } - private handleClick = (telegrafPlugin: string) => () => { - this.props.onSelectTelegrafPlugin(telegrafPlugin) + private handleClick = (type: string) => () => { + this.props.onSelectDataLoaderType(type) } } diff --git a/ui/src/onboarding/constants/pluginConfigs.ts b/ui/src/onboarding/constants/pluginConfigs.ts index d167336701..48545be6f2 100644 --- a/ui/src/onboarding/constants/pluginConfigs.ts +++ b/ui/src/onboarding/constants/pluginConfigs.ts @@ -3,6 +3,7 @@ import { TelegrafPluginName, TelegrafPluginInfo, ConfigFieldType, + BundleName, } from 'src/types/v2/dataLoaders' import { TelegrafPluginInputCpu, @@ -27,6 +28,41 @@ import { TelegrafPluginInputTail, } from 'src/api' +interface PluginBundles { + [bundleName: string]: TelegrafPluginName[] +} + +export const pluginsByBundle: PluginBundles = { + [BundleName.System]: [ + TelegrafPluginInputCpu.NameEnum.Cpu, + TelegrafPluginInputDisk.NameEnum.Disk, + TelegrafPluginInputDiskio.NameEnum.Diskio, + TelegrafPluginInputKernel.NameEnum.Kernel, + TelegrafPluginInputMem.NameEnum.Mem, + TelegrafPluginInputProcesses.NameEnum.Processes, + TelegrafPluginInputSwap.NameEnum.Swap, + TelegrafPluginInputSystem.NameEnum.System, + ], + [BundleName.Disk]: [ + TelegrafPluginInputDisk.NameEnum.Disk, + TelegrafPluginInputDiskio.NameEnum.Diskio, + ], + [BundleName.Docker]: [TelegrafPluginInputDocker.NameEnum.Docker], + [BundleName.File]: [TelegrafPluginInputFile.NameEnum.File], + [BundleName.Kubernetes]: [TelegrafPluginInputKubernetes.NameEnum.Kubernetes], + [BundleName.Logparser]: [TelegrafPluginInputLogParser.NameEnum.Logparser], + [BundleName.Net]: [TelegrafPluginInputNet.NameEnum.Net], + [BundleName.NetResponse]: [ + TelegrafPluginInputNetResponse.NameEnum.NetResponse, + ], + [BundleName.Ngnix]: [TelegrafPluginInputNgnix.NameEnum.Ngnix], + [BundleName.Procstat]: [TelegrafPluginInputProcstat.NameEnum.Procstat], + [BundleName.Prometheus]: [TelegrafPluginInputPrometheus.NameEnum.Prometheus], + [BundleName.Redis]: [TelegrafPluginInputRedis.NameEnum.Redis], + [BundleName.Syslog]: [TelegrafPluginInputSyslog.NameEnum.Syslog], + [BundleName.Tail]: [TelegrafPluginInputTail.NameEnum.Tail], +} + export const telegrafPluginsInfo: TelegrafPluginInfo = { [TelegrafPluginInputCpu.NameEnum.Cpu]: { fields: null, @@ -225,11 +261,28 @@ import { LogoRedis, } from 'src/onboarding/graphics' -export const PLUGIN_LOGOS = { - [TelegrafPluginInputCpu.NameEnum.Cpu]: LogoCpu, - [TelegrafPluginInputDocker.NameEnum.Docker]: LogoDocker, - [TelegrafPluginInputKubernetes.NameEnum.Kubernetes]: LogoKubernetes, - [TelegrafPluginInputNgnix.NameEnum.Ngnix]: LogoNginx, - [TelegrafPluginInputPrometheus.NameEnum.Prometheus]: LogoPrometheus, - [TelegrafPluginInputRedis.NameEnum.Redis]: LogoRedis, +export const BUNDLE_LOGOS = { + [BundleName.System]: LogoCpu, + [BundleName.Docker]: LogoDocker, + [BundleName.Kubernetes]: LogoKubernetes, + [BundleName.Ngnix]: LogoNginx, + [BundleName.Prometheus]: LogoPrometheus, + [BundleName.Redis]: LogoRedis, } + +export const PLUGIN_BUNDLE_OPTIONS: BundleName[] = [ + BundleName.System, + BundleName.Disk, + BundleName.Docker, + BundleName.File, + BundleName.Kubernetes, + BundleName.Logparser, + BundleName.Net, + BundleName.NetResponse, + BundleName.Ngnix, + BundleName.Procstat, + BundleName.Prometheus, + BundleName.Redis, + BundleName.Syslog, + BundleName.Tail, +] diff --git a/ui/src/onboarding/containers/OnboardingWizard.tsx b/ui/src/onboarding/containers/OnboardingWizard.tsx index fc0df6d919..e714890e3d 100644 --- a/ui/src/onboarding/containers/OnboardingWizard.tsx +++ b/ui/src/onboarding/containers/OnboardingWizard.tsx @@ -19,13 +19,13 @@ import {setSetupParams, setStepStatus} from 'src/onboarding/actions/steps' import { setDataLoadersType, - addTelegrafPlugin, updateTelegrafPluginConfig, addConfigValue, removeConfigValue, - removeTelegrafPlugin, setActiveTelegrafPlugin, createTelegrafConfigAsync, + addPluginBundleWithPlugins, + removePluginBundleWithPlugins, } from 'src/onboarding/actions/dataLoaders' // Constants @@ -71,11 +71,11 @@ interface DispatchProps { onSetSetupParams: typeof setSetupParams onSetStepStatus: typeof setStepStatus onSetDataLoadersType: typeof setDataLoadersType - onAddTelegrafPlugin: typeof addTelegrafPlugin + onAddPluginBundle: typeof addPluginBundleWithPlugins + onRemovePluginBundle: typeof removePluginBundleWithPlugins onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig onAddConfigValue: typeof addConfigValue onRemoveConfigValue: typeof removeConfigValue - onRemoveTelegrafPlugin: typeof removeTelegrafPlugin onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin onSaveTelegrafConfig: typeof createTelegrafConfigAsync } @@ -112,13 +112,13 @@ class OnboardingWizard extends PureComponent { dataLoaders, dataLoaders: {telegrafPlugins, telegrafConfigID}, onSetDataLoadersType, - onAddTelegrafPlugin, onSetActiveTelegrafPlugin, onUpdateTelegrafPluginConfig, onAddConfigValue, onRemoveConfigValue, - onRemoveTelegrafPlugin, onSaveTelegrafConfig, + onAddPluginBundle, + onRemovePluginBundle, setupParams, notify, onDecrementCurrentStepIndex, @@ -133,7 +133,7 @@ class OnboardingWizard extends PureComponent { telegrafPlugins={telegrafPlugins} telegrafConfigID={telegrafConfigID} onTabClick={this.handleClickSideBarTab} - title="Selected Sources" + title="Plugins to Configure" visible={this.sideBarVisible} currentStepIndex={currentStepIndex} handleNewSourceClick={onDecrementCurrentStepIndex} @@ -145,13 +145,13 @@ class OnboardingWizard extends PureComponent { setupParams={setupParams} dataLoaders={dataLoaders} onSetDataLoadersType={onSetDataLoadersType} - onAddTelegrafPlugin={onAddTelegrafPlugin} onUpdateTelegrafPluginConfig={onUpdateTelegrafPluginConfig} - onRemoveTelegrafPlugin={onRemoveTelegrafPlugin} onSetActiveTelegrafPlugin={onSetActiveTelegrafPlugin} onAddConfigValue={onAddConfigValue} onRemoveConfigValue={onRemoveConfigValue} onSaveTelegrafConfig={onSaveTelegrafConfig} + onAddPluginBundle={onAddPluginBundle} + onRemovePluginBundle={onRemovePluginBundle} /> @@ -276,13 +276,13 @@ const mdtp: DispatchProps = { onSetSetupParams: setSetupParams, onSetStepStatus: setStepStatus, onSetDataLoadersType: setDataLoadersType, - onAddTelegrafPlugin: addTelegrafPlugin, onUpdateTelegrafPluginConfig: updateTelegrafPluginConfig, onAddConfigValue: addConfigValue, onRemoveConfigValue: removeConfigValue, - onRemoveTelegrafPlugin: removeTelegrafPlugin, onSetActiveTelegrafPlugin: setActiveTelegrafPlugin, onSaveTelegrafConfig: createTelegrafConfigAsync, + onAddPluginBundle: addPluginBundleWithPlugins, + onRemovePluginBundle: removePluginBundleWithPlugins, } export default connect( diff --git a/ui/src/onboarding/reducers/dataLoaders.test.ts b/ui/src/onboarding/reducers/dataLoaders.test.ts index 9677990645..f4cb9c1b39 100644 --- a/ui/src/onboarding/reducers/dataLoaders.test.ts +++ b/ui/src/onboarding/reducers/dataLoaders.test.ts @@ -7,15 +7,36 @@ import dataLoadersReducer, { // Actions import { setDataLoadersType, - addTelegrafPlugin, addConfigValue, removeConfigValue, - removeTelegrafPlugin, + removePluginBundle, setActiveTelegrafPlugin, setTelegrafConfigID, updateTelegrafPluginConfig, + addPluginBundle, + addTelegrafPlugins, + removeBundlePlugins, + addPluginBundleWithPlugins, + removePluginBundleWithPlugins, + createTelegrafConfigAsync, } from 'src/onboarding/actions/dataLoaders' +// Mock Data +import { + redisPlugin, + cpuTelegrafPlugin, + diskTelegrafPlugin, + diskioTelegrafPlugin, + kernelTelegrafPlugin, + memTelegrafPlugin, + processesTelegrafPlugin, + swapTelegrafPlugin, + systemTelegrafPlugin, + redisTelegrafPlugin, + token, + telegrafConfig, +} from 'mocks/dummyData' + // Types import { TelegrafPluginInputCpu, @@ -26,8 +47,10 @@ import { DataLoaderType, ConfigurationState, TelegrafPlugin, + BundleName, } from 'src/types/v2/dataLoaders' -import {redisPlugin} from 'mocks/dummyData' + +jest.mock('src/utils/api', () => require('src/onboarding/apis/mocks')) describe('dataLoader reducer', () => { it('can set a type', () => { @@ -44,30 +67,6 @@ describe('dataLoader reducer', () => { expect(actual).toEqual(expected) }) - it('can add a telegraf plugin', () => { - const actual = dataLoadersReducer( - INITIAL_STATE, - addTelegrafPlugin({ - name: TelegrafPluginInputCpu.NameEnum.Cpu, - configured: ConfigurationState.Unconfigured, - active: true, - }) - ) - const expected = { - ...INITIAL_STATE, - telegrafPlugins: [ - { - name: TelegrafPluginInputCpu.NameEnum.Cpu, - configured: ConfigurationState.Unconfigured, - active: true, - }, - ], - type: DataLoaderType.Empty, - } - - expect(actual).toEqual(expected) - }) - it('can set the active telegraf plugin', () => { const actual = dataLoadersReducer( { @@ -109,30 +108,6 @@ describe('dataLoader reducer', () => { expect(actual).toEqual(expected) }) - it('can remove a telegraf plugin', () => { - const actual = dataLoadersReducer( - { - ...INITIAL_STATE, - type: DataLoaderType.Streaming, - telegrafPlugins: [ - { - name: TelegrafPluginInputCpu.NameEnum.Cpu, - configured: ConfigurationState.Unconfigured, - active: true, - }, - ], - }, - removeTelegrafPlugin(TelegrafPluginInputCpu.NameEnum.Cpu) - ) - const expected = { - ...INITIAL_STATE, - telegrafPlugins: [], - type: DataLoaderType.Streaming, - } - - expect(actual).toEqual(expected) - }) - it('can set a telegraf config id', () => { const id = '285973845720345ajfajfkl;' const actual = dataLoadersReducer(INITIAL_STATE, setTelegrafConfigID(id)) @@ -246,7 +221,130 @@ describe('dataLoader reducer', () => { }, ], } + expect(actual).toEqual(expected) + }) + + it('can add a plugin bundle', () => { + const actual = dataLoadersReducer( + {...INITIAL_STATE, pluginBundles: [BundleName.Redis]}, + addPluginBundle(BundleName.System) + ) + + const expected = { + ...INITIAL_STATE, + pluginBundles: [BundleName.Redis, BundleName.System], + } + expect(actual).toEqual(expected) + }) + + it('can remove a plugin bundle', () => { + const actual = dataLoadersReducer( + {...INITIAL_STATE, pluginBundles: [BundleName.Redis, BundleName.System]}, + removePluginBundle(BundleName.Redis) + ) + + const expected = { + ...INITIAL_STATE, + pluginBundles: [BundleName.System], + } + expect(actual).toEqual(expected) + }) + + it('can add telegraf Plugins', () => { + const actual = dataLoadersReducer( + { + ...INITIAL_STATE, + telegrafPlugins: [redisTelegrafPlugin, diskTelegrafPlugin], + }, + addTelegrafPlugins([cpuTelegrafPlugin, diskTelegrafPlugin]) + ) + + const expected = { + ...INITIAL_STATE, + telegrafPlugins: [ + redisTelegrafPlugin, + diskTelegrafPlugin, + cpuTelegrafPlugin, + ], + } expect(actual).toEqual(expected) }) + + it('can remove telegraf Plugins', () => { + const actual = dataLoadersReducer( + { + ...INITIAL_STATE, + pluginBundles: [BundleName.Disk, BundleName.System], + telegrafPlugins: [ + cpuTelegrafPlugin, + diskTelegrafPlugin, + diskioTelegrafPlugin, + kernelTelegrafPlugin, + memTelegrafPlugin, + processesTelegrafPlugin, + swapTelegrafPlugin, + systemTelegrafPlugin, + ], + }, + removeBundlePlugins(BundleName.System) + ) + + const expected = { + ...INITIAL_STATE, + pluginBundles: [BundleName.Disk, BundleName.System], + telegrafPlugins: [diskTelegrafPlugin, diskioTelegrafPlugin], + } + + expect(actual).toEqual(expected) + }) + + // ---------- Thunks ------------ // + + it('can create a telegraf config', async () => { + const dispatch = jest.fn() + const org = 'default' + const bucket = 'defbuck' + const telegrafPlugins = [cpuTelegrafPlugin] + const getState = (): any => ({ + onboarding: { + dataLoaders: { + telegrafPlugins, + }, + steps: { + setupParams: {org, bucket}, + }, + }, + }) + await createTelegrafConfigAsync(token)(dispatch, getState) + + expect(dispatch).toBeCalledWith(setTelegrafConfigID(telegrafConfig.id)) + }) + + it('can add a plugin bundle with plugins', () => { + const dispatch = jest.fn() + addPluginBundleWithPlugins(BundleName.System)(dispatch) + + expect(dispatch).toBeCalledWith(addPluginBundle(BundleName.System)) + expect(dispatch).toBeCalledWith( + addTelegrafPlugins([ + cpuTelegrafPlugin, + diskTelegrafPlugin, + diskioTelegrafPlugin, + kernelTelegrafPlugin, + memTelegrafPlugin, + processesTelegrafPlugin, + swapTelegrafPlugin, + systemTelegrafPlugin, + ]) + ) + }) + + it('can remove a plugin bundle and its plugins', () => { + const dispatch = jest.fn() + removePluginBundleWithPlugins(BundleName.System)(dispatch) + + expect(dispatch).toBeCalledWith(removePluginBundle(BundleName.System)) + expect(dispatch).toBeCalledWith(removeBundlePlugins(BundleName.System)) + }) }) diff --git a/ui/src/onboarding/reducers/dataLoaders.ts b/ui/src/onboarding/reducers/dataLoaders.ts index 2dc1b53161..acb733fa3d 100644 --- a/ui/src/onboarding/reducers/dataLoaders.ts +++ b/ui/src/onboarding/reducers/dataLoaders.ts @@ -5,6 +5,8 @@ import _ from 'lodash' import { createNewPlugin, updateConfigFields, + isPluginInBundle, + isPluginUniqueToBundle, } from 'src/onboarding/utils/pluginConfigs' // Types @@ -25,6 +27,7 @@ export const INITIAL_STATE: DataLoadersState = { lpStatus: RemoteDataState.NotStarted, precision: WritePrecision.Ms, telegrafConfigID: null, + pluginBundles: [], } export default (state = INITIAL_STATE, action: Action): DataLoadersState => { @@ -39,13 +42,40 @@ export default (state = INITIAL_STATE, action: Action): DataLoadersState => { ...state, telegrafConfigID: action.payload.id, } - case 'ADD_TELEGRAF_PLUGIN': + case 'ADD_PLUGIN_BUNDLE': return { ...state, - telegrafPlugins: [ - ...state.telegrafPlugins, - action.payload.telegrafPlugin, - ], + pluginBundles: [...state.pluginBundles, action.payload.bundle], + } + case 'REMOVE_PLUGIN_BUNDLE': + return { + ...state, + pluginBundles: state.pluginBundles.filter( + b => b !== action.payload.bundle + ), + } + case 'REMOVE_BUNDLE_PLUGINS': + return { + ...state, + telegrafPlugins: state.telegrafPlugins.filter(tp => { + if (isPluginInBundle(tp.name, action.payload.bundle)) { + return !isPluginUniqueToBundle( + tp.name, + action.payload.bundle, + state.pluginBundles + ) + } + + return true + }), + } + case 'ADD_TELEGRAF_PLUGINS': + return { + ...state, + telegrafPlugins: _.uniqBy( + [...state.telegrafPlugins, ...action.payload.telegrafPlugins], + 'name' + ), } case 'UPDATE_TELEGRAF_PLUGIN': return { @@ -132,13 +162,6 @@ export default (state = INITIAL_STATE, action: Action): DataLoadersState => { return tp }), } - case 'REMOVE_TELEGRAF_PLUGIN': - return { - ...state, - telegrafPlugins: state.telegrafPlugins.filter( - tp => tp.name !== action.payload.telegrafPlugin - ), - } case 'SET_ACTIVE_TELEGRAF_PLUGIN': return { ...state, diff --git a/ui/src/onboarding/utils/pluginConfigs.test.ts b/ui/src/onboarding/utils/pluginConfigs.test.ts new file mode 100644 index 0000000000..3abc9d69d6 --- /dev/null +++ b/ui/src/onboarding/utils/pluginConfigs.test.ts @@ -0,0 +1,58 @@ +// Utils +import { + isPluginInBundle, + isPluginUniqueToBundle, +} from 'src/onboarding/utils/pluginConfigs' + +// Types +import {BundleName} from 'src/types/v2/dataLoaders' +import { + TelegrafPluginInputCpu, + TelegrafPluginInputDisk, + TelegrafPluginInputSystem, +} from 'src/api' + +describe('Onboarding.Utils.PluginConfig', () => { + describe('if plugin is found in only one bundle', () => { + it('isPluginUniqueToBundle returns true', () => { + const telegrafPlugin = TelegrafPluginInputCpu.NameEnum.Cpu + const bundle = BundleName.System + const bundles = [BundleName.System, BundleName.Disk] + + const actual = isPluginUniqueToBundle(telegrafPlugin, bundle, bundles) + + expect(actual).toBe(true) + }) + }) + describe('if plugin is found in multiple bundles', () => { + it('isPluginUniqueToBundle returns false', () => { + const telegrafPlugin = TelegrafPluginInputDisk.NameEnum.Disk + const bundle = BundleName.System + const bundles = [BundleName.System, BundleName.Disk] + + const actual = isPluginUniqueToBundle(telegrafPlugin, bundle, bundles) + + expect(actual).toBe(false) + }) + }) + describe('if plugin is not in bundle', () => { + it('isPluginInBundle returns false', () => { + const telegrafPlugin = TelegrafPluginInputSystem.NameEnum.System + const bundle = BundleName.Disk + + const actual = isPluginInBundle(telegrafPlugin, bundle) + + expect(actual).toBe(false) + }) + }) + describe('if plugin is in bundle', () => { + it('isPluginInBundle returns true', () => { + const telegrafPlugin = TelegrafPluginInputSystem.NameEnum.System + const bundle = BundleName.System + + const actual = isPluginInBundle(telegrafPlugin, bundle) + + expect(actual).toBe(true) + }) + }) +}) diff --git a/ui/src/onboarding/utils/pluginConfigs.ts b/ui/src/onboarding/utils/pluginConfigs.ts index be19a50dee..83f92dcaed 100644 --- a/ui/src/onboarding/utils/pluginConfigs.ts +++ b/ui/src/onboarding/utils/pluginConfigs.ts @@ -1,11 +1,15 @@ // Constants -import {telegrafPluginsInfo} from 'src/onboarding/constants/pluginConfigs' +import { + telegrafPluginsInfo, + pluginsByBundle, +} from 'src/onboarding/constants/pluginConfigs' // Types import { TelegrafPluginName, ConfigFields, Plugin, + BundleName, } from 'src/types/v2/dataLoaders' export const getConfigFields = ( @@ -27,3 +31,30 @@ export const updateConfigFields = ( export const createNewPlugin = (name: TelegrafPluginName): Plugin => { return telegrafPluginsInfo[name].defaults } + +export const isPluginUniqueToBundle = ( + telegrafPlugin: TelegrafPluginName, + bundle: BundleName, + bundles: BundleName[] +): boolean => { + return bundles.reduce((acc, b) => { + if (b === bundle) { + return acc + } + + pluginsByBundle[b].forEach(p => { + if (p === telegrafPlugin) { + acc = false + } + }) + + return acc + }, true) +} + +export const isPluginInBundle = ( + telegrafPlugin: TelegrafPluginName, + bundle: BundleName +) => { + return !!pluginsByBundle[bundle].find(p => p === telegrafPlugin) +} diff --git a/ui/src/types/v2/dataLoaders.ts b/ui/src/types/v2/dataLoaders.ts index 4abc2801c4..bf8ebe5623 100644 --- a/ui/src/types/v2/dataLoaders.ts +++ b/ui/src/types/v2/dataLoaders.ts @@ -39,6 +39,7 @@ import {WritePrecision} from 'src/api' export interface DataLoadersState { telegrafPlugins: TelegrafPlugin[] + pluginBundles: BundleName[] type: DataLoaderType activeLPTab: LineProtocolTab telegrafConfigID: string @@ -103,6 +104,23 @@ export interface TelegrafPlugin { plugin?: Plugin } +export enum BundleName { + System = 'System', + Disk = 'Disk', + Docker = 'Docker', + File = 'File', + Kubernetes = 'Kubernetes', + Logparser = 'LogParser', + Net = 'Net', + NetResponse = 'NetResponse', + Ngnix = 'NGNIX', + Procstat = 'Procstat', + Prometheus = 'Prometheus', + Redis = 'Redis', + Syslog = 'Syslog', + Tail = 'Tail', +} + export type TelegrafPluginName = | TelegrafPluginInputCpu.NameEnum.Cpu | TelegrafPluginInputDisk.NameEnum.Disk