Add ability to create multiple Kapacitor configs

Co-authored-by: Brandon Farmer <bthesorceror@gmail.com>
pull/3490/head
Iris Scholten 2018-05-17 16:04:28 -07:00
parent 80420b6cf1
commit f3c691de4d
5 changed files with 113 additions and 36 deletions

View File

@ -22,7 +22,6 @@ import {
import { import {
AlertaConfig, AlertaConfig,
HipChatConfig, HipChatConfig,
KafkaConfig,
OpsGenieConfig, OpsGenieConfig,
PagerDutyConfig, PagerDutyConfig,
PagerDuty2Config, PagerDuty2Config,
@ -32,6 +31,8 @@ import {
TalkConfig, TalkConfig,
TelegramConfig, TelegramConfig,
VictorOpsConfig, VictorOpsConfig,
SlackConfigs,
KafkaConfigs,
} from './config' } from './config'
import { import {
@ -50,7 +51,7 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
import {Source, Kapacitor} from 'src/types' import {Source, Kapacitor} from 'src/types'
import {Notification} from 'src/types/notifications' import {Notification} from 'src/types/notifications'
import {ServiceProperties, SpecificConfigOptions} from 'src/types/kapacitor' import {ServiceProperties, SpecificConfigOptions} from 'src/types/kapacitor'
import SlackConfigs from 'src/kapacitor/components/config/SlackConfigs'
import { import {
AlertDisplayText, AlertDisplayText,
SupportedServices, SupportedServices,
@ -259,16 +260,22 @@ class AlertTabs extends PureComponent<Props, State> {
) )
case AlertTypes.kafka: case AlertTypes.kafka:
return ( return (
<KafkaConfig <KafkaConfigs
onSave={this.handleSaveConfig(AlertTypes.kafka)} onSave={this.handleSaveConfig(AlertTypes.kafka)}
config={this.getSectionElement(configSections, AlertTypes.kafka)} configs={this.getSectionElements(configSections, AlertTypes.kafka)}
onTest={this.handleTestConfig(AlertTypes.kafka, { onTest={this.handleTestConfig(AlertTypes.kafka, {
cluster: this.getProperty(configSections, AlertTypes.kafka, 'id'), cluster: this.getProperty(configSections, AlertTypes.kafka, 'id'),
})} })}
enabled={this.getConfigEnabled(configSections, AlertTypes.kafka)} onEnabled={this.getSpecificConfigEnabled(
configSections,
AlertTypes.kafka
)}
notify={this.props.notify} notify={this.props.notify}
isMultipleConfigsSupported={true}
onDelete={this.handleDeleteConfig(AlertTypes.kafka)}
/> />
) )
case AlertTypes.opsgenie: case AlertTypes.opsgenie:
return ( return (
<OpsGenieConfig <OpsGenieConfig

View File

@ -1,4 +1,4 @@
import React, {PureComponent} from 'react' import React, {PureComponent, MouseEvent} from 'react'
import TagInput from 'src/shared/components/TagInput' import TagInput from 'src/shared/components/TagInput'
import {ErrorHandling} from 'src/shared/decorators/errors' import {ErrorHandling} from 'src/shared/decorators/errors'
@ -8,10 +8,11 @@ import {Notification, NotificationFunc} from 'src/types'
import {KafkaProperties} from 'src/types/kapacitor' import {KafkaProperties} from 'src/types/kapacitor'
import {notifyInvalidBatchSizeValue} from 'src/shared/copy/notifications' import {notifyInvalidBatchSizeValue} from 'src/shared/copy/notifications'
import {get} from 'src/utils/wrappers'
interface Config { interface Config {
options: KafkaProperties & { options: KafkaProperties
id: string isNewConfig?: boolean
}
} }
interface Item { interface Item {
@ -20,10 +21,19 @@ interface Item {
interface Props { interface Props {
config: Config config: Config
onSave: (properties: KafkaProperties) => void onSave: (
onTest: (event: React.MouseEvent<HTMLButtonElement>) => void properties: KafkaProperties,
isNewConfig: boolean,
specificConfig: string
) => void
onTest: (
event: React.MouseEvent<HTMLButtonElement>,
specificConfigOptions: Partial<KafkaProperties>
) => void
enabled: boolean enabled: boolean
notify: (message: Notification | NotificationFunc) => void notify: (message: Notification | NotificationFunc) => void
id: number
onDelete: (specificConfig: string) => void
} }
interface State { interface State {
@ -56,6 +66,7 @@ class KafkaConfig extends PureComponent<Props, State> {
public render() { public render() {
const {options} = this.props.config const {options} = this.props.config
const {id: keyID} = this.props
const id = options.id const id = options.id
const timeout = options.timeout const timeout = options.timeout
const batchSize = options['batch-size'] const batchSize = options['batch-size']
@ -69,29 +80,30 @@ class KafkaConfig extends PureComponent<Props, State> {
return ( return (
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor="id">ID</label> <label htmlFor={`${keyID}-id`}>ID</label>
<input <input
className="form-control" className="form-control"
id="id" id={`${keyID}-id`}
type="text" type="text"
ref={r => (this.id = r)} ref={r => (this.id = r)}
defaultValue={id || ''} defaultValue={id || ''}
onChange={this.disableTest} onChange={this.disableTest}
readOnly={true} readOnly={!this.isNewConfig}
/> />
</div> </div>
<TagInput <TagInput
title="Brokers" title="Brokers"
inputID={`${keyID}-brokers`}
onAddTag={this.handleAddBroker} onAddTag={this.handleAddBroker}
onDeleteTag={this.handleDeleteBroker} onDeleteTag={this.handleDeleteBroker}
tags={this.currentBrokersForTags} tags={this.currentBrokersForTags}
disableTest={this.disableTest} disableTest={this.disableTest}
/> />
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor="timeout">Timeout</label> <label htmlFor={`${keyID}-timeout`}>Timeout</label>
<input <input
className="form-control" className="form-control"
id="timeout" id={`${keyID}-timeout`}
type="text" type="text"
ref={r => (this.timeout = r)} ref={r => (this.timeout = r)}
defaultValue={timeout || ''} defaultValue={timeout || ''}
@ -99,10 +111,10 @@ class KafkaConfig extends PureComponent<Props, State> {
/> />
</div> </div>
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor="batchSize">Batch Size</label> <label htmlFor={`${keyID}-batchsize`}>Batch Size</label>
<input <input
className="form-control" className="form-control"
id="batchSize" id={`${keyID}-batchsize`}
type="number" type="number"
ref={r => (this.batchSize = r)} ref={r => (this.batchSize = r)}
defaultValue={batchSize.toString() || '0'} defaultValue={batchSize.toString() || '0'}
@ -110,10 +122,10 @@ class KafkaConfig extends PureComponent<Props, State> {
/> />
</div> </div>
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor="batchTimeout">Batch Timeout</label> <label htmlFor={`${keyID}-batch-timeout`}>Batch Timeout</label>
<input <input
className="form-control" className="form-control"
id="batchTimeout" id={`${keyID}-batch-timeout`}
type="text" type="text"
ref={r => (this.batchTimeout = r)} ref={r => (this.batchTimeout = r)}
defaultValue={batchTimeout || ''} defaultValue={batchTimeout || ''}
@ -123,20 +135,20 @@ class KafkaConfig extends PureComponent<Props, State> {
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<div className="form-control-static"> <div className="form-control-static">
<input <input
id="useSSL" id={`${keyID}-useSSL`}
type="checkbox" type="checkbox"
defaultChecked={useSSL} defaultChecked={useSSL}
ref={r => (this.useSSL = r)} ref={r => (this.useSSL = r)}
onChange={this.disableTest} onChange={this.disableTest}
/> />
<label htmlFor="useSSL">Use SSL</label> <label htmlFor={`${keyID}-useSSL`}>Use SSL</label>
</div> </div>
</div> </div>
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor="sslCA">SSL CA</label> <label htmlFor={`${keyID}-sslCA`}>SSL CA</label>
<input <input
className="form-control" className="form-control"
id="sslCA" id={`${keyID}-sslCA`}
type="text" type="text"
ref={r => (this.sslCA = r)} ref={r => (this.sslCA = r)}
defaultValue={sslCA || ''} defaultValue={sslCA || ''}
@ -144,10 +156,10 @@ class KafkaConfig extends PureComponent<Props, State> {
/> />
</div> </div>
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor="sslCert">SSL Cert</label> <label htmlFor={`${keyID}-sslCert`}>SSL Cert</label>
<input <input
className="form-control" className="form-control"
id="sslCert" id={`${keyID}-sslCert`}
type="text" type="text"
ref={r => (this.sslCert = r)} ref={r => (this.sslCert = r)}
defaultValue={sslCert || ''} defaultValue={sslCert || ''}
@ -155,10 +167,10 @@ class KafkaConfig extends PureComponent<Props, State> {
/> />
</div> </div>
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor="sslKey">SSL Key</label> <label htmlFor={`${keyID}-sslKey`}>SSL Key</label>
<input <input
className="form-control" className="form-control"
id="sslKey" id={`${keyID}-sslKey`}
type="text" type="text"
ref={r => (this.sslKey = r)} ref={r => (this.sslKey = r)}
defaultValue={sslKey || ''} defaultValue={sslKey || ''}
@ -168,13 +180,15 @@ class KafkaConfig extends PureComponent<Props, State> {
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<div className="form-control-static"> <div className="form-control-static">
<input <input
id="insecureSkipVerify" id={`${keyID}-insecureSkipVerify`}
type="checkbox" type="checkbox"
defaultChecked={insecureSkipVerify} defaultChecked={insecureSkipVerify}
ref={r => (this.insecureSkipVerify = r)} ref={r => (this.insecureSkipVerify = r)}
onChange={this.disableTest} onChange={this.disableTest}
/> />
<label htmlFor="insecureSkipVerify">Insecure Skip Verify</label> <label htmlFor={`${keyID}-insecureSkipVerify`}>
Insecure Skip Verify
</label>
</div> </div>
</div> </div>
<div className="form-group form-group-submit col-xs-12 text-center"> <div className="form-group form-group-submit col-xs-12 text-center">
@ -189,11 +203,13 @@ class KafkaConfig extends PureComponent<Props, State> {
<button <button
className="btn btn-primary" className="btn btn-primary"
disabled={!this.state.testEnabled} disabled={!this.state.testEnabled}
onClick={this.props.onTest} onClick={this.handleTest}
> >
<span className="icon pulse-c" /> <span className="icon pulse-c" />
Send Test Alert Send Test Alert
</button> </button>
{this.deleteButton}
<hr />
</div> </div>
</form> </form>
) )
@ -204,6 +220,36 @@ class KafkaConfig extends PureComponent<Props, State> {
return currentBrokers.map(broker => ({name: broker})) return currentBrokers.map(broker => ({name: broker}))
} }
private get configID(): string {
const {
config: {
options: {id},
},
} = this.props
return id
}
private get isNewConfig(): boolean {
return get(this.props, 'config.isNewConfig', false)
}
private get isDefaultConfig(): boolean {
return this.configID === 'default'
}
private get deleteButton(): JSX.Element {
if (this.isDefaultConfig) {
return null
}
return (
<button className="btn btn-danger" onClick={this.handleDelete}>
<span className="icon trash" />
Delete
</button>
)
}
private handleSubmit = async e => { private handleSubmit = async e => {
e.preventDefault() e.preventDefault()
@ -213,7 +259,7 @@ class KafkaConfig extends PureComponent<Props, State> {
return return
} }
const properties = { const properties: KafkaProperties = {
brokers: this.state.currentBrokers, brokers: this.state.currentBrokers,
timeout: this.timeout.value, timeout: this.timeout.value,
'batch-size': batchSize, 'batch-size': batchSize,
@ -225,12 +271,29 @@ class KafkaConfig extends PureComponent<Props, State> {
'insecure-skip-verify': this.insecureSkipVerify.checked, 'insecure-skip-verify': this.insecureSkipVerify.checked,
} }
const success = await this.props.onSave(properties) if (this.isNewConfig) {
properties.id = this.id.value
}
const success = await this.props.onSave(
properties,
this.isNewConfig,
this.configID
)
if (success) { if (success) {
this.setState({testEnabled: true}) this.setState({testEnabled: true})
} }
} }
private handleTest = (e: MouseEvent<HTMLButtonElement>): void => {
this.props.onTest(e, {id: this.configID})
}
private handleDelete = (e: MouseEvent<HTMLButtonElement>): void => {
e.preventDefault()
this.props.onDelete(this.configID)
}
private disableTest = () => { private disableTest = () => {
this.setState({testEnabled: false}) this.setState({testEnabled: false})
} }

View File

@ -11,6 +11,8 @@ import SMTPConfig from './SMTPConfig'
import TalkConfig from './TalkConfig' import TalkConfig from './TalkConfig'
import TelegramConfig from './TelegramConfig' import TelegramConfig from './TelegramConfig'
import VictorOpsConfig from './VictorOpsConfig' import VictorOpsConfig from './VictorOpsConfig'
import SlackConfigs from './SlackConfigs'
import KafkaConfigs from './KafkaConfigs'
export { export {
AlertaConfig, AlertaConfig,
@ -26,4 +28,6 @@ export {
TalkConfig, TalkConfig,
TelegramConfig, TelegramConfig,
VictorOpsConfig, VictorOpsConfig,
SlackConfigs,
KafkaConfigs,
} }

View File

@ -14,6 +14,7 @@ interface Props {
tags: Item[] tags: Item[]
title: string title: string
disableTest: () => void disableTest: () => void
inputID?: string
} }
@ErrorHandling @ErrorHandling
@ -21,16 +22,17 @@ class TagInput extends PureComponent<Props> {
private input: HTMLInputElement private input: HTMLInputElement
public render() { public render() {
const {title, tags} = this.props const {title, tags, inputID} = this.props
const id = inputID || title
return ( return (
<div className="form-group col-xs-12"> <div className="form-group col-xs-12">
<label htmlFor={title}>{title}</label> <label htmlFor={id}>{title}</label>
<input <input
placeholder={`Type and hit 'Enter' to add to list of ${title}`} placeholder={`Type and hit 'Enter' to add to list of ${title}`}
autoComplete="off" autoComplete="off"
className="form-control tag-input" className="form-control tag-input"
id={title} id={id}
type="text" type="text"
ref={r => (this.input = r)} ref={r => (this.input = r)}
onKeyDown={this.handleAddTag} onKeyDown={this.handleAddTag}

View File

@ -305,6 +305,7 @@ export interface HipChatProperties {
} }
export interface KafkaProperties { export interface KafkaProperties {
id?: string
brokers: string[] brokers: string[]
timeout: string timeout: string
'batch-size': number 'batch-size': number