From d36752a14254c2239541bd629ca07bb32bf6a6a7 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Wed, 2 May 2018 18:42:28 -0700 Subject: [PATCH 01/10] Add opsgenie2 section to supportedConfigs --- ui/src/kapacitor/components/AlertTabs.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ui/src/kapacitor/components/AlertTabs.js b/ui/src/kapacitor/components/AlertTabs.js index 0f48d47aac..ebe385b2a0 100644 --- a/ui/src/kapacitor/components/AlertTabs.js +++ b/ui/src/kapacitor/components/AlertTabs.js @@ -220,6 +220,18 @@ class AlertTabs extends Component { /> ), }, + opsgenie2: { + type: 'OpsGenie2', + enabled: this.getEnabled(configSections, 'opsgenie2'), + renderComponent: () => ( + + ), + }, pagerduty: { type: 'PagerDuty', enabled: this.getEnabled(configSections, 'pagerduty'), From 5376bc6ab16fba74fad0de2b242027c2ae831e46 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Wed, 2 May 2018 19:16:15 -0700 Subject: [PATCH 02/10] Add OpsGenie deprecation warning --- ui/src/kapacitor/components/AlertTabs.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ui/src/kapacitor/components/AlertTabs.js b/ui/src/kapacitor/components/AlertTabs.js index ebe385b2a0..1f8329e0b0 100644 --- a/ui/src/kapacitor/components/AlertTabs.js +++ b/ui/src/kapacitor/components/AlertTabs.js @@ -167,7 +167,8 @@ class AlertTabs extends Component { } const pagerDutyV1Enabled = this.getEnabled(configSections, 'pagerduty') - const showDeprecation = pagerDutyV1Enabled + const opsGenieV1Enabled = this.getEnabled(configSections, 'opsgenie') + const pagerDutyDeprecationMessage = (
PagerDuty v1 is being{' '} @@ -183,6 +184,13 @@ class AlertTabs extends Component {
) + const opsGenieDeprecationMessage = ( +
+ OpsGenie v1 is being deprecated. Please update your Kapacitor and + configure OpsGenie v2. +
+ ) + const supportedConfigs = { alerta: { type: 'Alerta', @@ -346,9 +354,12 @@ class AlertTabs extends Component {

Configure Alert Endpoints

- {showDeprecation && ( + {pagerDutyV1Enabled && ( )} + {opsGenieV1Enabled && ( + + )} Date: Thu, 3 May 2018 11:00:26 -0700 Subject: [PATCH 03/10] Update chronograf backend with OpsGenie2 --- kapacitor.go | 1 + server/kapacitors.go | 16 ++++++++++++++++ server/kapacitors_test.go | 1 + 3 files changed, 18 insertions(+) diff --git a/kapacitor.go b/kapacitor.go index 3d03b73cb7..c5c3cc3ce3 100644 --- a/kapacitor.go +++ b/kapacitor.go @@ -21,6 +21,7 @@ type AlertNodes struct { HipChat []*HipChat `json:"hipChat"` // HipChat will send alert to all HipChat Alerta []*Alerta `json:"alerta"` // Alerta will send alert to all Alerta OpsGenie []*OpsGenie `json:"opsGenie"` // OpsGenie will send alert to all OpsGenie + OpsGenie2 []*OpsGenie `json:"opsGenie2"` // OpsGenie2 will send alert to all OpsGenie v2 Talk []*Talk `json:"talk"` // Talk will send alert to all Talk } diff --git a/server/kapacitors.go b/server/kapacitors.go index fd6940d9b0..a528ba8943 100644 --- a/server/kapacitors.go +++ b/server/kapacitors.go @@ -429,6 +429,22 @@ func newAlertResponse(task *kapa.Task, srcID, kapaID int) *alertResponse { } } + if res.AlertNodes.OpsGenie2 == nil { + res.AlertNodes.OpsGenie2 = []*chronograf.OpsGenie{} + } + + for i, a := range res.AlertNodes.OpsGenie2 { + if a.Teams == nil { + a.Teams = []string{} + res.AlertNodes.OpsGenie2[i] = a + } + + if a.Recipients == nil { + a.Recipients = []string{} + res.AlertNodes.OpsGenie2[i] = a + } + } + if res.AlertNodes.PagerDuty == nil { res.AlertNodes.PagerDuty = []*chronograf.PagerDuty{} } diff --git a/server/kapacitors_test.go b/server/kapacitors_test.go index 9eb1146124..f528a540aa 100644 --- a/server/kapacitors_test.go +++ b/server/kapacitors_test.go @@ -130,6 +130,7 @@ func Test_KapacitorRulesGet(t *testing.T) { HipChat: []*chronograf.HipChat{}, Alerta: []*chronograf.Alerta{}, OpsGenie: []*chronograf.OpsGenie{}, + OpsGenie2: []*chronograf.OpsGenie{}, Talk: []*chronograf.Talk{}, }, }, From 3f3f19960895a0ffe73a20e5aa8ae53f99adc4c5 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Thu, 3 May 2018 13:57:40 -0700 Subject: [PATCH 04/10] Add handler for OpsGenie2 --- ui/src/kapacitor/components/HandlerOptions.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ui/src/kapacitor/components/HandlerOptions.js b/ui/src/kapacitor/components/HandlerOptions.js index 5e0c4b7bde..6149a75e70 100644 --- a/ui/src/kapacitor/components/HandlerOptions.js +++ b/ui/src/kapacitor/components/HandlerOptions.js @@ -101,6 +101,15 @@ class HandlerOptions extends Component { validationError={validationError} /> ) + case 'opsGenie2': + return ( + + ) case 'pagerDuty': return ( Date: Thu, 3 May 2018 13:58:11 -0700 Subject: [PATCH 05/10] Add constants and types for OpsGenie v2 --- ui/src/kapacitor/constants/index.js | 4 ++++ ui/src/types/kapacitor.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/ui/src/kapacitor/constants/index.js b/ui/src/kapacitor/constants/index.js index 40f0d91a25..e134f29747 100644 --- a/ui/src/kapacitor/constants/index.js +++ b/ui/src/kapacitor/constants/index.js @@ -103,6 +103,7 @@ export const DEFAULT_HANDLERS = [ export const MAP_KEYS_FROM_CONFIG = { hipchat: 'hipChat', opsgenie: 'opsGenie', + opsgenie2: 'opsGenie2', pagerduty: 'pagerDuty', pagerduty2: 'pagerDuty2', smtp: 'email', @@ -114,6 +115,7 @@ export const ALERTS_FROM_CONFIG = { alerta: ['environment', 'origin', 'token'], // token = bool hipChat: ['url', 'room', 'token'], // token = bool opsGenie: ['api-key', 'teams', 'recipients'], // api-key = bool + opsGenie2: ['api-key', 'teams', 'recipients'], // api-key = bool pagerDuty: ['service-key'], // service-key = bool pagerDuty2: ['service-key'], // service-key = bool pushover: ['token', 'user-key'], // token = bool, user-key = bool @@ -138,6 +140,7 @@ export const MAP_FIELD_KEYS_FROM_CONFIG = { alerta: {}, hipChat: {}, opsGenie: {}, + opsGenie2: {}, pagerDuty: {'service-key': 'serviceKey'}, pagerDuty2: {'service-key': 'serviceKey'}, pushover: {'user-key': 'userKey'}, @@ -170,6 +173,7 @@ export const HANDLERS_TO_RULE = { ], hipChat: ['room'], opsGenie: ['teams', 'recipients'], + opsGenie2: ['teams', 'recipients'], pagerDuty: [], pagerDuty2: [], pushover: ['device', 'title', 'sound', 'url', 'urlTitle'], diff --git a/ui/src/types/kapacitor.ts b/ui/src/types/kapacitor.ts index 37b320b2dc..6c9e02c12b 100644 --- a/ui/src/types/kapacitor.ts +++ b/ui/src/types/kapacitor.ts @@ -64,6 +64,7 @@ interface AlertNodes { hipChat: HipChat[] alerta: Alerta[] opsGenie: OpsGenie[] + opsGenie2?: OpsGenie[] talk: Talk[] } From d4f136c986a8d9a21d38de361789aca98252953f Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Thu, 3 May 2018 16:15:39 -0700 Subject: [PATCH 06/10] Update RedactedInput and AlertConfigs to redact necesary fields afterwhen submitting form --- ui/src/kapacitor/components/config/AlertaConfig.tsx | 2 ++ ui/src/kapacitor/components/config/HipChatConfig.tsx | 2 ++ ui/src/kapacitor/components/config/OpsGenieConfig.tsx | 2 ++ .../kapacitor/components/config/PagerDutyConfig.tsx | 3 +++ ui/src/kapacitor/components/config/PushoverConfig.tsx | 3 +++ ui/src/kapacitor/components/config/RedactedInput.tsx | 11 +++++++++-- ui/src/kapacitor/components/config/SlackConfig.tsx | 2 ++ ui/src/kapacitor/components/config/TalkConfig.tsx | 2 ++ ui/src/kapacitor/components/config/TelegramConfig.tsx | 2 ++ .../kapacitor/components/config/VictorOpsConfig.tsx | 2 ++ 10 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ui/src/kapacitor/components/config/AlertaConfig.tsx b/ui/src/kapacitor/components/config/AlertaConfig.tsx index 1bbcc57b8b..a1faa2e04d 100644 --- a/ui/src/kapacitor/components/config/AlertaConfig.tsx +++ b/ui/src/kapacitor/components/config/AlertaConfig.tsx @@ -46,6 +46,7 @@ class AlertaConfig extends PureComponent { public render() { const {environment, origin, token, url} = this.props.config.options + const {testEnabled} = this.state return (
@@ -80,6 +81,7 @@ class AlertaConfig extends PureComponent { id="token" refFunc={this.handleTokenRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> diff --git a/ui/src/kapacitor/components/config/HipChatConfig.tsx b/ui/src/kapacitor/components/config/HipChatConfig.tsx index 26875496cd..27d1499d34 100644 --- a/ui/src/kapacitor/components/config/HipChatConfig.tsx +++ b/ui/src/kapacitor/components/config/HipChatConfig.tsx @@ -46,6 +46,7 @@ class HipchatConfig extends PureComponent { public render() { const {options} = this.props.config const {url, room, token} = options + const {testEnabled} = this.state const subdomain = url .replace('https://', '') @@ -89,6 +90,7 @@ class HipchatConfig extends PureComponent { id="token" refFunc={this.handleTokenRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> diff --git a/ui/src/kapacitor/components/config/OpsGenieConfig.tsx b/ui/src/kapacitor/components/config/OpsGenieConfig.tsx index 81220edbc6..3f09e42f5b 100644 --- a/ui/src/kapacitor/components/config/OpsGenieConfig.tsx +++ b/ui/src/kapacitor/components/config/OpsGenieConfig.tsx @@ -54,6 +54,7 @@ class OpsGenieConfig extends PureComponent { public render() { const {options} = this.props.config const apiKey = options['api-key'] + const {testEnabled} = this.state return ( @@ -64,6 +65,7 @@ class OpsGenieConfig extends PureComponent { id="api-key" refFunc={this.handleApiKeyRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> diff --git a/ui/src/kapacitor/components/config/PagerDutyConfig.tsx b/ui/src/kapacitor/components/config/PagerDutyConfig.tsx index 576a700a6b..7def068017 100644 --- a/ui/src/kapacitor/components/config/PagerDutyConfig.tsx +++ b/ui/src/kapacitor/components/config/PagerDutyConfig.tsx @@ -41,6 +41,8 @@ class PagerDutyConfig extends PureComponent { const {options} = this.props.config const {url} = options const serviceKey = options['service-key'] + const {testEnabled} = this.state + return (
@@ -50,6 +52,7 @@ class PagerDutyConfig extends PureComponent { id="service-key" refFunc={this.handleServiceKeyRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} />
diff --git a/ui/src/kapacitor/components/config/PushoverConfig.tsx b/ui/src/kapacitor/components/config/PushoverConfig.tsx index 91301df25d..2ad9656a68 100644 --- a/ui/src/kapacitor/components/config/PushoverConfig.tsx +++ b/ui/src/kapacitor/components/config/PushoverConfig.tsx @@ -48,6 +48,7 @@ class PushoverConfig extends PureComponent { const {options} = this.props.config const {token, url} = options const userKey = options['user-key'] + const {testEnabled} = this.state return ( @@ -64,6 +65,7 @@ class PushoverConfig extends PureComponent { id="user-key" refFunc={this.handleUserKeyRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> @@ -80,6 +82,7 @@ class PushoverConfig extends PureComponent { id="token" refFunc={this.handleTokenRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> diff --git a/ui/src/kapacitor/components/config/RedactedInput.tsx b/ui/src/kapacitor/components/config/RedactedInput.tsx index f61bb41790..7b1b3b430e 100644 --- a/ui/src/kapacitor/components/config/RedactedInput.tsx +++ b/ui/src/kapacitor/components/config/RedactedInput.tsx @@ -6,6 +6,7 @@ interface Props { defaultValue?: boolean refFunc: (r: any) => void disableTest?: () => void + isFormEditing: boolean } interface State { @@ -21,6 +22,12 @@ class RedactedInput extends PureComponent { } } + public componentWillReceiveProps(nextProps) { + if (!nextProps.isFormEditing) { + this.setState({editing: false}) + } + } + public render() { const {defaultValue, id, refFunc, disableTest} = this.props const {editing} = this.state @@ -31,9 +38,9 @@ class RedactedInput extends PureComponent { Value set - + { public render() { const {url, channel} = this.props.config.options + const {testEnabled} = this.state return ( @@ -55,6 +56,7 @@ class SlackConfig extends PureComponent { id="url" refFunc={this.handleUrlRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> diff --git a/ui/src/kapacitor/components/config/TalkConfig.tsx b/ui/src/kapacitor/components/config/TalkConfig.tsx index 0d4345a64c..c37838dd20 100644 --- a/ui/src/kapacitor/components/config/TalkConfig.tsx +++ b/ui/src/kapacitor/components/config/TalkConfig.tsx @@ -40,6 +40,7 @@ class TalkConfig extends PureComponent { public render() { const {url, author_name: author} = this.props.config.options + const {testEnabled} = this.state return ( @@ -50,6 +51,7 @@ class TalkConfig extends PureComponent { id="url" refFunc={this.handleUrlRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> diff --git a/ui/src/kapacitor/components/config/TelegramConfig.tsx b/ui/src/kapacitor/components/config/TelegramConfig.tsx index 626a8abffb..cc9bddc0d9 100644 --- a/ui/src/kapacitor/components/config/TelegramConfig.tsx +++ b/ui/src/kapacitor/components/config/TelegramConfig.tsx @@ -57,6 +57,7 @@ class TelegramConfig extends PureComponent { const disableNotification = options['disable-notification'] const disableWebPagePreview = options['disable-web-page-preview'] const parseMode = options['parse-mode'] + const {testEnabled} = this.state return ( @@ -88,6 +89,7 @@ class TelegramConfig extends PureComponent { id="token" refFunc={this.handleTokenRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> diff --git a/ui/src/kapacitor/components/config/VictorOpsConfig.tsx b/ui/src/kapacitor/components/config/VictorOpsConfig.tsx index 477301073e..9939174728 100644 --- a/ui/src/kapacitor/components/config/VictorOpsConfig.tsx +++ b/ui/src/kapacitor/components/config/VictorOpsConfig.tsx @@ -46,6 +46,7 @@ class VictorOpsConfig extends PureComponent { const apiKey = options['api-key'] const routingKey = options['routing-key'] const {url} = options + const {testEnabled} = this.state return ( @@ -56,6 +57,7 @@ class VictorOpsConfig extends PureComponent { id="api-key" refFunc={this.handleApiRef} disableTest={this.disableTest} + isFormEditing={!testEnabled} /> From 848fcfd1d9140e0a0d1537d2ffae75cf91c46b28 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Thu, 3 May 2018 16:21:01 -0700 Subject: [PATCH 07/10] Update Kapacitor dependency to v1.5 rc 2 --- Gopkg.lock | 4 ++-- Gopkg.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index bbcfd85803..b80f9dc90c 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -150,7 +150,7 @@ "tick/stateful", "udf/agent" ] - revision = "97e77198c3f4a16503110979f066bc3a4f9adc49" + revision = "761f380db46c20bb24f9bf3dbdd89c2661dc0c2b" [[projects]] branch = "master" @@ -311,6 +311,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "00da66795f1ffe85f031f7fbd69e5974a72167895057a43ba4187cfa84efe3b5" + inputs-digest = "22ca158a5cab9595de1d2604e9cf063e271759528e70b36e1b7e643ec138078e" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 3d74c55966..dfee6129ae 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -78,4 +78,4 @@ required = ["github.com/kevinburke/go-bindata","github.com/gogo/protobuf/proto", [[constraint]] name = "github.com/influxdata/kapacitor" - revision = "97e77198c3f4a16503110979f066bc3a4f9adc49" + revision = "761f380db46c20bb24f9bf3dbdd89c2661dc0c2b" From ffa0b119d8aea915b13fac93db5e0628a57ab5bf Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Thu, 3 May 2018 17:40:46 -0700 Subject: [PATCH 08/10] Convert AlertTabs to typescript --- .../{AlertTabs.js => AlertTabs.tsx} | 337 +++++++++++------- ui/src/shared/components/Tabs.tsx | 2 +- 2 files changed, 214 insertions(+), 125 deletions(-) rename ui/src/kapacitor/components/{AlertTabs.js => AlertTabs.tsx} (79%) diff --git a/ui/src/kapacitor/components/AlertTabs.js b/ui/src/kapacitor/components/AlertTabs.tsx similarity index 79% rename from ui/src/kapacitor/components/AlertTabs.js rename to ui/src/kapacitor/components/AlertTabs.tsx index 1f8329e0b0..34e79ef20e 100644 --- a/ui/src/kapacitor/components/AlertTabs.js +++ b/ui/src/kapacitor/components/AlertTabs.tsx @@ -1,15 +1,20 @@ -import React, {Component} from 'react' -import PropTypes from 'prop-types' +import React, {PureComponent, MouseEvent} from 'react' import _ from 'lodash' -import {Tab, Tabs, TabPanel, TabPanels, TabList} from 'shared/components/Tabs' +import { + Tab, + Tabs, + TabPanel, + TabPanels, + TabList, +} from 'src/shared/components/Tabs' import { getKapacitorConfig, updateKapacitorConfigSection, testAlertOutput, getAllServices, -} from 'shared/apis' +} from 'src/shared/apis' import { AlertaConfig, @@ -32,12 +37,100 @@ import { notifyTestAlertSent, notifyTestAlertFailed, notifyCouldNotRetrieveKapacitorServices, -} from 'shared/copy/notifications' +} from 'src/shared/copy/notifications' import DeprecationWarning from 'src/admin/components/DeprecationWarning' import {ErrorHandling} from 'src/shared/decorators/errors' +import {Source, Kapacitor} from 'src/types' + +interface Service { + link: Link + name: string + options: { + id: string + } +} + +interface Link { + rel: string + href: string +} + +interface Element { + link: Link + options: any + redacted: string[] +} + +interface Section { + link: string + elements: Element[] +} + +interface Sections { + alerta: Section + hipchat: Section + httppost: Section + influxdb: Section + mqtt: Section + opsgenie: Section + opsgenie2: Section + pagerduty: Section + pagerduty2: Section + pushover: Section + sensu: Section + slack: Section + smtp: Section + snmptrap: Section + talk: Section + telegram: Section + victorops: Section +} + +interface Config { + type: string + enabled: boolean + renderComponent: () => JSX.Element +} + +interface SupportedConfig { + alerta: Config + hipchat: Config + opsgenie: Config + opsgenie2: Config + pagerduty: Config + pagerduty2: Config + pushover: Config + sensu: Config + slack: Config + smtp: Config + talk: Config + telegram: Config + victorops: Config +} + +interface Notification { + id?: string + type: string + icon: string + duration: number + message: string +} + +interface Props { + source: Source + kapacitor: Kapacitor + notify: (message: Notification) => void + hash: string +} + +interface State { + configSections: Sections + services: Service[] +} + @ErrorHandling -class AlertTabs extends Component { +class AlertTabs extends PureComponent { constructor(props) { super(props) @@ -47,11 +140,11 @@ class AlertTabs extends Component { } } - async componentDidMount() { + public async componentDidMount() { const {kapacitor} = this.props try { this.refreshKapacitorConfig(kapacitor) - const services = await getAllServices(kapacitor) + const services: Service[] = await getAllServices(kapacitor) this.setState({services}) } catch (error) { this.setState({services: null}) @@ -59,117 +152,32 @@ class AlertTabs extends Component { } } - componentWillReceiveProps(nextProps) { + public componentWillReceiveProps(nextProps) { if (this.props.kapacitor.url !== nextProps.kapacitor.url) { this.refreshKapacitorConfig(nextProps.kapacitor) } } - refreshKapacitorConfig = async kapacitor => { - try { - const { - data: {sections}, - } = await getKapacitorConfig(kapacitor) - this.setState({configSections: sections}) - } catch (error) { - this.setState({configSections: null}) - this.props.notify(notifyRefreshKapacitorFailed()) - } - } - - getSection = (sections, section) => { - return _.get(sections, [section, 'elements', '0'], null) - } - - getEnabled = (sections, section) => { - return _.get( - sections, - [section, 'elements', '0', 'options', 'enabled'], - null - ) - } - - handleGetSection = (sections, section) => () => { - return this.getSection(sections, section) - } - - handleSaveConfig = section => async properties => { - if (section !== '') { - const propsToSend = this.sanitizeProperties(section, properties) - try { - await updateKapacitorConfigSection( - this.props.kapacitor, - section, - propsToSend - ) - this.refreshKapacitorConfig(this.props.kapacitor) - this.props.notify(notifyAlertEndpointSaved(section)) - return true - } catch ({ - data: {error}, - }) { - const errorMsg = _.join(_.drop(_.split(error, ': '), 2), ': ') - this.props.notify(notifyAlertEndpointSaveFailed(section, errorMsg)) - return false - } - } - } - - handleTestConfig = section => async e => { - e.preventDefault() - - try { - const {data} = await testAlertOutput(this.props.kapacitor, section) - if (data.success) { - this.props.notify(notifyTestAlertSent(section)) - } else { - this.props.notify(notifyTestAlertFailed(section, data.message)) - } - } catch (error) { - this.props.notify(notifyTestAlertFailed(section)) - } - } - - sanitizeProperties = (section, properties) => { - const cleanProps = {...properties, enabled: true} - const {redacted} = this.getSection(this.state.configSections, section) - if (redacted && redacted.length) { - redacted.forEach(badProp => { - if (properties[badProp] === 'true') { - delete cleanProps[badProp] - } - }) - } - - return cleanProps - } - - getInitialIndex = (supportedConfigs, hash) => { - const index = _.indexOf(_.keys(supportedConfigs), _.replace(hash, '#', '')) - return index >= 0 ? index : 0 - } - - isSupportedService = config => { - return ( - config && - this.state.services.find(service => { - return service.name === _.toLower(config.type) - }) - ) - } - - render() { + public render() { const {configSections} = this.state const {hash} = this.props + // console.log(configSections) + if (!configSections) { return null } - const pagerDutyV1Enabled = this.getEnabled(configSections, 'pagerduty') - const opsGenieV1Enabled = this.getEnabled(configSections, 'opsgenie') + const pagerDutyV1Enabled: boolean = this.getEnabled( + configSections, + 'pagerduty' + ) + const opsGenieV1Enabled: boolean = this.getEnabled( + configSections, + 'opsgenie' + ) - const pagerDutyDeprecationMessage = ( + const pagerDutyDeprecationMessage: JSX.Element = (
PagerDuty v1 is being{' '} { @@ -184,14 +192,14 @@ class AlertTabs extends Component {
) - const opsGenieDeprecationMessage = ( + const opsGenieDeprecationMessage: JSX.Element = (
OpsGenie v1 is being deprecated. Please update your Kapacitor and configure OpsGenie v2.
) - const supportedConfigs = { + const supportedConfigs: SupportedConfig = { alerta: { type: 'Alerta', enabled: this.getEnabled(configSections, 'alerta'), @@ -368,7 +376,7 @@ class AlertTabs extends Component { {_.reduce( configSections, - (acc, _cur, k) => { + (acc, __, k) => { return this.isSupportedService(supportedConfigs[k]) ? acc.concat( {_.reduce( configSections, - (acc, _cur, k) => + (acc, __, k) => this.isSupportedService(supportedConfigs[k]) ? acc.concat( @@ -401,22 +409,103 @@ class AlertTabs extends Component { ) } -} -const {func, shape, string} = PropTypes + private refreshKapacitorConfig = async ( + kapacitor: Kapacitor + ): Promise => { + try { + const { + data: {sections}, + } = await getKapacitorConfig(kapacitor) + this.setState({configSections: sections}) + } catch (error) { + this.setState({configSections: null}) + this.props.notify(notifyRefreshKapacitorFailed()) + } + } -AlertTabs.propTypes = { - source: shape({ - id: string.isRequired, - }).isRequired, - kapacitor: shape({ - url: string.isRequired, - links: shape({ - proxy: string.isRequired, - }).isRequired, - }), - notify: func.isRequired, - hash: string.isRequired, + private getSection = (sections: Sections, section: string): Element => { + return _.get(sections, [section, 'elements', '0'], null) + } + + private getEnabled = (sections: Sections, section: string): boolean => { + return _.get( + sections, + [section, 'elements', '0', 'options', 'enabled'], + null + ) + } + + private handleSaveConfig = (section: string) => async ( + properties + ): Promise => { + if (section !== '') { + const propsToSend = this.sanitizeProperties(section, properties) + try { + await updateKapacitorConfigSection( + this.props.kapacitor, + section, + propsToSend + ) + this.refreshKapacitorConfig(this.props.kapacitor) + this.props.notify(notifyAlertEndpointSaved(section)) + return true + } catch ({ + data: {error}, + }) { + const errorMsg = _.join(_.drop(_.split(error, ': '), 2), ': ') + this.props.notify(notifyAlertEndpointSaveFailed(section, errorMsg)) + return false + } + } + } + private handleTestConfig = (section: string) => async ( + e: MouseEvent + ): Promise => { + e.preventDefault() + + try { + const {data} = await testAlertOutput(this.props.kapacitor, section) + if (data.success) { + this.props.notify(notifyTestAlertSent(section)) + } else { + this.props.notify(notifyTestAlertFailed(section, data.message)) + } + } catch (error) { + this.props.notify(notifyTestAlertFailed(section)) + } + } + + private sanitizeProperties = (section: string, properties: Props): Props => { + const cleanProps = {...properties, enabled: true} + const {redacted} = this.getSection(this.state.configSections, section) + if (redacted && redacted.length) { + redacted.forEach(badProp => { + if (properties[badProp] === 'true') { + delete cleanProps[badProp] + } + }) + } + + return cleanProps + } + + private getInitialIndex = ( + supportedConfigs: SupportedConfig, + hash: string + ): number => { + const index = _.indexOf(_.keys(supportedConfigs), _.replace(hash, '#', '')) + return index >= 0 ? index : 0 + } + + private isSupportedService = config => { + return ( + config && + this.state.services.find(service => { + return service.name === _.toLower(config.type) + }) + ) + } } export default AlertTabs diff --git a/ui/src/shared/components/Tabs.tsx b/ui/src/shared/components/Tabs.tsx index c10b7337a3..b5c46c2f19 100644 --- a/ui/src/shared/components/Tabs.tsx +++ b/ui/src/shared/components/Tabs.tsx @@ -96,7 +96,7 @@ TabList.defaultProps = { interface TabPanelsProps { children: JSX.Element[] | JSX.Element - activeIndex: number + activeIndex?: number customClass: string } From 0d5a94a6ca3c8dcb81534f985f28a76adc3d8e29 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Thu, 3 May 2018 17:45:05 -0700 Subject: [PATCH 09/10] Update Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d1c9baf62..74b0b1ce58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ 1. [#3233](https://github.com/influxdata/chronograf/pull/3233): Add default retention policy field as option in source configuration for use in querying hosts from Host List page & Host pages 1. [#3290](https://github.com/influxdata/chronograf/pull/3290): Add support for PagerDuty v2 in UI +1. [#3369](https://github.com/influxdata/chronograf/pull/3369): Add support for OpsGenie v2 in UI ### UI Improvements @@ -16,7 +17,6 @@ 1. [#3354](https://github.com/influxdata/chronograf/pull/3354): Disable template variables for non editing users 1. [#3353](https://github.com/influxdata/chronograf/pull/3353): YAxisLabels in Dashboard Graph Builder not showing until graph is redrawn - ### Bug Fixes 1. [#3252](https://github.com/influxdata/chronograf/pull/3252): Allows users to select tickscript editor with mouse From 97df38faf4424fdc0156c50b48955c0e32f7a27d Mon Sep 17 00:00:00 2001 From: Jared Scheib Date: Fri, 4 May 2018 16:46:07 -0700 Subject: [PATCH 10/10] Remove console.log --- ui/src/kapacitor/components/AlertTabs.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/src/kapacitor/components/AlertTabs.tsx b/ui/src/kapacitor/components/AlertTabs.tsx index 34e79ef20e..16c5f652ca 100644 --- a/ui/src/kapacitor/components/AlertTabs.tsx +++ b/ui/src/kapacitor/components/AlertTabs.tsx @@ -162,8 +162,6 @@ class AlertTabs extends PureComponent { const {configSections} = this.state const {hash} = this.props - // console.log(configSections) - if (!configSections) { return null }