Create/update telegraf plugin at verify step of onboarding

pull/10616/head
Alirie Gray 2018-12-17 11:18:16 -08:00
parent f432ec1cc2
commit 758af5eaaf
18 changed files with 202 additions and 114 deletions

View File

@ -5,6 +5,8 @@ import _ from 'lodash'
import {
writeLineProtocol,
createTelegrafConfig,
getTelegrafConfigs,
updateTelegrafConfig,
} from 'src/onboarding/apis/index'
// Utils
@ -226,7 +228,7 @@ export const removePluginBundleWithPlugins = (
dispatch(removeBundlePlugins(bundle))
}
export const createTelegrafConfigAsync = (authToken: string) => async (
export const createOrUpdateTelegrafConfigAsync = (authToken: string) => async (
dispatch,
getState: GetState
) => {
@ -239,7 +241,28 @@ export const createTelegrafConfigAsync = (authToken: string) => async (
},
} = getState()
let plugins = telegrafPlugins.map(tp => tp.plugin || createNewPlugin(tp.name))
const telegrafConfigsFromServer = await getTelegrafConfigs(org)
let plugins = []
telegrafPlugins.forEach(tp => {
if (tp.configured === ConfigurationState.Configured) {
plugins = [...plugins, tp.plugin || createNewPlugin(tp.name)]
}
})
let body = {
name: 'new config',
agent: {collectionInterval: DEFAULT_COLLECTION_INTERVAL},
plugins,
}
if (telegrafConfigsFromServer.length) {
const id = _.get(telegrafConfigsFromServer, '0.id', '')
await updateTelegrafConfig(id, body)
dispatch(setTelegrafConfigID(id))
return
}
const influxDB2Out = {
name: TelegrafPluginOutputInfluxDBV2.NameEnum.InfluxdbV2,
@ -254,9 +277,8 @@ export const createTelegrafConfigAsync = (authToken: string) => async (
plugins = [...plugins, influxDB2Out]
const body = {
name: 'new config',
agent: {collectionInterval: DEFAULT_COLLECTION_INTERVAL},
body = {
...body,
plugins,
}

View File

@ -130,3 +130,19 @@ export const createTelegrafConfig = async (
console.error(error)
}
}
export const updateTelegrafConfig = async (
telegrafID: string,
telegrafConfig: TelegrafRequest
) => {
try {
const {data} = await telegrafsAPI.telegrafsTelegrafIDPut(
telegrafID,
telegrafConfig
)
return data
} catch (error) {
console.error(error)
}
}

View File

@ -19,7 +19,7 @@ import {
setActiveTelegrafPlugin,
addConfigValue,
removeConfigValue,
createTelegrafConfigAsync,
createOrUpdateTelegrafConfigAsync,
addPluginBundleWithPlugins,
removePluginBundleWithPlugins,
setPluginConfiguration,
@ -42,7 +42,7 @@ interface Props {
setupParams: SetupParams
dataLoaders: DataLoadersState
currentStepIndex: number
onSaveTelegrafConfig: typeof createTelegrafConfigAsync
onSaveTelegrafConfig: typeof createOrUpdateTelegrafConfigAsync
onAddPluginBundle: typeof addPluginBundleWithPlugins
onRemovePluginBundle: typeof removePluginBundleWithPlugins
onSetConfigArrayValue: typeof setConfigArrayValue
@ -100,7 +100,6 @@ class OnboardingStepSwitcher extends PureComponent<Props> {
onSetPluginConfiguration={onSetPluginConfiguration}
onAddConfigValue={onAddConfigValue}
onRemoveConfigValue={onRemoveConfigValue}
onSaveTelegrafConfig={onSaveTelegrafConfig}
onSetActiveTelegrafPlugin={onSetActiveTelegrafPlugin}
onSetConfigArrayValue={onSetConfigArrayValue}
/>
@ -109,12 +108,21 @@ class OnboardingStepSwitcher extends PureComponent<Props> {
)
case 4:
return (
<VerifyDataStep
{...onboardingStepProps}
{...dataLoaders}
onSetActiveTelegrafPlugin={onSetActiveTelegrafPlugin}
stepIndex={currentStepIndex}
/>
<FetchAuthToken
bucket={_.get(setupParams, 'bucket', '')}
username={_.get(setupParams, 'username', '')}
>
{authToken => (
<VerifyDataStep
{...onboardingStepProps}
{...dataLoaders}
authToken={authToken}
onSaveTelegrafConfig={onSaveTelegrafConfig}
onSetActiveTelegrafPlugin={onSetActiveTelegrafPlugin}
stepIndex={currentStepIndex}
/>
)}
</FetchAuthToken>
)
case 5:
return <CompletionStep {...onboardingStepProps} />

View File

@ -20,16 +20,11 @@ import {
setPluginConfiguration,
addConfigValue,
removeConfigValue,
createTelegrafConfigAsync,
setConfigArrayValue,
} from 'src/onboarding/actions/dataLoaders'
// Constants
import {StepStatus} from 'src/clockface/constants/wizard'
import {
TelegrafConfigCreationSuccess,
TelegrafConfigCreationError,
} from 'src/shared/copy/notifications'
// Types
import {OnboardingStepProps} from 'src/onboarding/containers/OnboardingWizard'
@ -47,7 +42,6 @@ export interface OwnProps extends OnboardingStepProps {
type: DataLoaderType
onAddConfigValue: typeof addConfigValue
onRemoveConfigValue: typeof removeConfigValue
onSaveTelegrafConfig: typeof createTelegrafConfigAsync
authToken: string
onSetConfigArrayValue: typeof setConfigArrayValue
}
@ -82,7 +76,6 @@ export class ConfigureDataSourceStep extends PureComponent<Props> {
const {
telegrafPlugins,
type,
authToken,
params: {substepID},
setupParams,
onUpdateTelegrafPluginConfig,
@ -105,7 +98,6 @@ export class ConfigureDataSourceStep extends PureComponent<Props> {
onRemoveConfigValue={onRemoveConfigValue}
dataLoaderType={type}
currentIndex={+substepID}
authToken={authToken}
onSetConfigArrayValue={onSetConfigArrayValue}
/>
<div className="wizard-button-container">
@ -201,11 +193,7 @@ export class ConfigureDataSourceStep extends PureComponent<Props> {
onSetActiveTelegrafPlugin,
onSetPluginConfiguration,
telegrafPlugins,
authToken,
notify,
params: {substepID, stepID},
type,
onSaveTelegrafConfig,
onSetSubstepIndex,
} = this.props
@ -216,15 +204,6 @@ export class ConfigureDataSourceStep extends PureComponent<Props> {
this.handleSetStepStatus()
if (index >= telegrafPlugins.length - 1) {
if (type === DataLoaderType.Streaming) {
try {
await onSaveTelegrafConfig(authToken)
notify(TelegrafConfigCreationSuccess)
} catch (error) {
notify(TelegrafConfigCreationError)
}
}
onIncrementCurrentStepIndex()
onSetActiveTelegrafPlugin('')
} else {

View File

@ -28,7 +28,6 @@ export interface Props {
onAddConfigValue: typeof addConfigValue
onRemoveConfigValue: typeof removeConfigValue
dataLoaderType: DataLoaderType
authToken: string
bucket: string
org: string
username: string
@ -41,7 +40,6 @@ class ConfigureDataSourceSwitcher extends PureComponent<Props> {
const {
bucket,
org,
authToken,
telegrafPlugins,
currentIndex,
dataLoaderType,
@ -62,7 +60,6 @@ class ConfigureDataSourceSwitcher extends PureComponent<Props> {
telegrafPlugins={telegrafPlugins}
currentIndex={currentIndex}
onAddConfigValue={onAddConfigValue}
authToken={authToken}
onSetConfigArrayValue={onSetConfigArrayValue}
/>
)

View File

@ -29,7 +29,6 @@ interface Props {
onSetPluginConfiguration: typeof setPluginConfiguration
onAddConfigValue: typeof addConfigValue
onRemoveConfigValue: typeof removeConfigValue
authToken: string
onSetConfigArrayValue: typeof setConfigArrayValue
}

View File

@ -28,14 +28,12 @@ interface Props {
onAddConfigValue: typeof addConfigValue
onRemoveConfigValue: typeof removeConfigValue
currentIndex: number
authToken: string
onSetConfigArrayValue: typeof setConfigArrayValue
}
class PluginConfigSwitcher extends PureComponent<Props> {
public render() {
const {
authToken,
onUpdateTelegrafPluginConfig,
onSetPluginConfiguration,
onAddConfigValue,
@ -46,7 +44,6 @@ class PluginConfigSwitcher extends PureComponent<Props> {
if (this.currentTelegrafPlugin) {
return (
<PluginConfigForm
authToken={authToken}
telegrafPlugin={this.currentTelegrafPlugin}
onUpdateTelegrafPluginConfig={onUpdateTelegrafPluginConfig}
onSetPluginConfiguration={onSetPluginConfiguration}

View File

@ -3,7 +3,7 @@ import React from 'react'
import {shallow} from 'enzyme'
// Components
import FetchConfigID from 'src/onboarding/components/verifyStep/FetchConfigID'
import CreateOrUpdateConfig from 'src/onboarding/components/verifyStep/CreateOrUpdateConfig'
jest.mock('src/utils/api', () => require('src/onboarding/apis/mocks'))
@ -11,15 +11,17 @@ const setup = async (override = {}) => {
const props = {
org: 'default',
children: jest.fn(),
onSaveTelegrafConfig: jest.fn(),
authToken: '',
...override,
}
const wrapper = await shallow(<FetchConfigID {...props} />)
const wrapper = await shallow(<CreateOrUpdateConfig {...props} />)
return {wrapper}
}
describe('FetchConfigID', () => {
describe('CreateOrUpdateConfig', () => {
it('renders', async () => {
const {wrapper} = await setup()
expect(wrapper.exists()).toBe(true)

View File

@ -0,0 +1,63 @@
// Libraries
import React, {PureComponent} from 'react'
import _ from 'lodash'
// Components
import {Spinner} from 'src/clockface'
import {ErrorHandling} from 'src/shared/decorators/errors'
// Actions
import {notify} from 'src/shared/actions/notifications'
import {createOrUpdateTelegrafConfigAsync} from 'src/onboarding/actions/dataLoaders'
// Constants
import {
TelegrafConfigCreationSuccess,
TelegrafConfigCreationError,
} from 'src/shared/copy/notifications'
// Types
import {RemoteDataState} from 'src/types'
export interface Props {
org: string
authToken: string
children: () => JSX.Element
onSaveTelegrafConfig: typeof createOrUpdateTelegrafConfigAsync
}
interface State {
loading: RemoteDataState
}
@ErrorHandling
class CreateOrUpdateConfig extends PureComponent<Props, State> {
constructor(props: Props) {
super(props)
this.state = {loading: RemoteDataState.NotStarted}
}
public async componentDidMount() {
const {onSaveTelegrafConfig, authToken} = this.props
this.setState({loading: RemoteDataState.Loading})
try {
await onSaveTelegrafConfig(authToken)
notify(TelegrafConfigCreationSuccess)
this.setState({loading: RemoteDataState.Done})
} catch (error) {
notify(TelegrafConfigCreationError)
}
}
public render() {
return (
<Spinner loading={this.state.loading}>{this.props.children()}</Spinner>
)
}
}
export default CreateOrUpdateConfig

View File

@ -4,10 +4,13 @@ import _ from 'lodash'
// Components
import TelegrafInstructions from 'src/onboarding/components/verifyStep/TelegrafInstructions'
import FetchConfigID from 'src/onboarding/components/verifyStep/FetchConfigID'
import CreateOrUpdateConfig from 'src/onboarding/components/verifyStep/CreateOrUpdateConfig'
import FetchAuthToken from 'src/onboarding/components/verifyStep/FetchAuthToken'
import DataListening from 'src/onboarding/components/verifyStep/DataListening'
// Actions
import {createOrUpdateTelegrafConfigAsync} from 'src/onboarding/actions/dataLoaders'
// Constants
import {StepStatus} from 'src/clockface/constants/wizard'
@ -17,22 +20,37 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
bucket: string
org: string
configID: string
username: string
stepIndex: number
authToken: string
onSetStepStatus: (index: number, status: StepStatus) => void
onSaveTelegrafConfig: typeof createOrUpdateTelegrafConfigAsync
}
@ErrorHandling
class DataStreaming extends PureComponent<Props> {
public render() {
const {
authToken,
org,
username,
configID,
onSaveTelegrafConfig,
onSetStepStatus,
bucket,
stepIndex,
} = this.props
return (
<>
<FetchConfigID org={this.props.org}>
{configID => (
<FetchAuthToken
bucket={this.props.bucket}
username={this.props.username}
>
<CreateOrUpdateConfig
org={org}
authToken={authToken}
onSaveTelegrafConfig={onSaveTelegrafConfig}
>
{() => (
<FetchAuthToken bucket={bucket} username={username}>
{authToken => (
<TelegrafInstructions
authToken={authToken}
@ -41,12 +59,12 @@ class DataStreaming extends PureComponent<Props> {
)}
</FetchAuthToken>
)}
</FetchConfigID>
</CreateOrUpdateConfig>
<DataListening
bucket={this.props.bucket}
stepIndex={this.props.stepIndex}
onSetStepStatus={this.props.onSetStepStatus}
bucket={bucket}
stepIndex={stepIndex}
onSetStepStatus={onSetStepStatus}
/>
</>
)

View File

@ -36,6 +36,7 @@ class FetchAuthToken extends PureComponent<Props, State> {
this.setState({loading: RemoteDataState.Loading})
const authToken = await getAuthorizationToken(username)
this.setState({authToken, loading: RemoteDataState.Done})
}

View File

@ -1,51 +0,0 @@
// Libraries
import React, {PureComponent} from 'react'
import _ from 'lodash'
// Components
import {Spinner} from 'src/clockface'
import {ErrorHandling} from 'src/shared/decorators/errors'
// Apis
import {getTelegrafConfigs} from 'src/onboarding/apis/index'
// types
import {RemoteDataState} from 'src/types'
export interface Props {
org: string
children: (configID: string) => JSX.Element
}
interface State {
loading: RemoteDataState
configID?: string
}
@ErrorHandling
class FetchConfigID extends PureComponent<Props, State> {
constructor(props: Props) {
super(props)
this.state = {loading: RemoteDataState.NotStarted}
}
public async componentDidMount() {
const {org} = this.props
this.setState({loading: RemoteDataState.Loading})
const telegrafConfigs = await getTelegrafConfigs(org)
const configID = _.get(telegrafConfigs, '0.id', '')
this.setState({configID, loading: RemoteDataState.Done})
}
public render() {
return (
<Spinner loading={this.state.loading}>
{this.props.children(this.state.configID)}
</Spinner>
)
}
}
export default FetchConfigID

View File

@ -19,6 +19,9 @@ const setup = (override = {}) => {
type: DataLoaderType.Empty,
telegrafPlugins: [],
stepIndex: 4,
authToken: '',
telegrafConfigID: '',
onSaveTelegrafConfig: jest.fn(),
onSetActiveTelegrafPlugin: jest.fn(),
...override,
}

View File

@ -13,7 +13,10 @@ import {
import VerifyDataSwitcher from 'src/onboarding/components/verifyStep/VerifyDataSwitcher'
// Actions
import {setActiveTelegrafPlugin} from 'src/onboarding/actions/dataLoaders'
import {
setActiveTelegrafPlugin,
createOrUpdateTelegrafConfigAsync,
} from 'src/onboarding/actions/dataLoaders'
// Types
import {OnboardingStepProps} from 'src/onboarding/containers/OnboardingWizard'
@ -21,8 +24,11 @@ import {DataLoaderType, TelegrafPlugin} from 'src/types/v2/dataLoaders'
export interface Props extends OnboardingStepProps {
type: DataLoaderType
authToken: string
telegrafConfigID: string
telegrafPlugins: TelegrafPlugin[]
onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin
onSaveTelegrafConfig: typeof createOrUpdateTelegrafConfigAsync
stepIndex: number
}
@ -31,7 +37,10 @@ class VerifyDataStep extends PureComponent<Props> {
public render() {
const {
setupParams,
telegrafConfigID,
authToken,
type,
onSaveTelegrafConfig,
onIncrementCurrentStepIndex,
onSetStepStatus,
stepIndex,
@ -41,6 +50,9 @@ class VerifyDataStep extends PureComponent<Props> {
<div className="onboarding-step">
<VerifyDataSwitcher
type={type}
telegrafConfigID={telegrafConfigID}
authToken={authToken}
onSaveTelegrafConfig={onSaveTelegrafConfig}
org={_.get(setupParams, 'org', '')}
username={_.get(setupParams, 'username', '')}
bucket={_.get(setupParams, 'bucket', '')}

View File

@ -15,6 +15,9 @@ const setup = (override = {}) => {
org: '',
username: '',
bucket: '',
authToken: '',
telegrafConfigID: '',
onSaveTelegrafConfig: jest.fn(),
stepIndex: 4,
onSetStepStatus: jest.fn(),
...override,

View File

@ -5,6 +5,9 @@ import React, {PureComponent} from 'react'
import {ErrorHandling} from 'src/shared/decorators/errors'
import DataStreaming from 'src/onboarding/components/verifyStep/DataStreaming'
// Actions
import {createOrUpdateTelegrafConfigAsync} from 'src/onboarding/actions/dataLoaders'
// Constants
import {StepStatus} from 'src/clockface/constants/wizard'
@ -17,22 +20,38 @@ export interface Props {
username: string
bucket: string
stepIndex: number
authToken: string
telegrafConfigID: string
onSaveTelegrafConfig: typeof createOrUpdateTelegrafConfigAsync
onSetStepStatus: (index: number, status: StepStatus) => void
}
@ErrorHandling
class VerifyDataSwitcher extends PureComponent<Props> {
public render() {
const {org, username, bucket, type, stepIndex, onSetStepStatus} = this.props
const {
org,
username,
bucket,
type,
stepIndex,
onSetStepStatus,
authToken,
telegrafConfigID,
onSaveTelegrafConfig,
} = this.props
switch (type) {
case DataLoaderType.Streaming:
return (
<DataStreaming
org={org}
configID={telegrafConfigID}
authToken={authToken}
username={username}
bucket={bucket}
onSetStepStatus={onSetStepStatus}
onSaveTelegrafConfig={onSaveTelegrafConfig}
stepIndex={stepIndex}
/>
)

View File

@ -24,7 +24,7 @@ import {
removeConfigValue,
setActiveTelegrafPlugin,
setPluginConfiguration,
createTelegrafConfigAsync,
createOrUpdateTelegrafConfigAsync,
addPluginBundleWithPlugins,
removePluginBundleWithPlugins,
setConfigArrayValue,
@ -81,8 +81,8 @@ interface DispatchProps {
onRemoveConfigValue: typeof removeConfigValue
onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin
onSetPluginConfiguration: typeof setPluginConfiguration
onSaveTelegrafConfig: typeof createTelegrafConfigAsync
onSetConfigArrayValue: typeof setConfigArrayValue
onSaveTelegrafConfig: typeof createOrUpdateTelegrafConfigAsync
}
interface StateProps {
@ -297,7 +297,7 @@ const mdtp: DispatchProps = {
onAddConfigValue: addConfigValue,
onRemoveConfigValue: removeConfigValue,
onSetActiveTelegrafPlugin: setActiveTelegrafPlugin,
onSaveTelegrafConfig: createTelegrafConfigAsync,
onSaveTelegrafConfig: createOrUpdateTelegrafConfigAsync,
onAddPluginBundle: addPluginBundleWithPlugins,
onRemovePluginBundle: removePluginBundleWithPlugins,
onSetPluginConfiguration: setPluginConfiguration,

View File

@ -18,7 +18,7 @@ import {
removeBundlePlugins,
addPluginBundleWithPlugins,
removePluginBundleWithPlugins,
createTelegrafConfigAsync,
createOrUpdateTelegrafConfigAsync,
setPluginConfiguration,
} from 'src/onboarding/actions/dataLoaders'
@ -415,7 +415,7 @@ describe('dataLoader reducer', () => {
},
},
})
await createTelegrafConfigAsync(token)(dispatch, getState)
await createOrUpdateTelegrafConfigAsync(token)(dispatch, getState)
expect(dispatch).toBeCalledWith(setTelegrafConfigID(telegrafConfig.id))
})