Merge branch 'master' into bugfix/data-explorer-error

pull/3457/head
Deniz Kusefoglu 2018-05-15 10:12:06 -07:00 committed by GitHub
commit 921ded2959
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 264 additions and 41 deletions

View File

@ -38,6 +38,7 @@
1. [#3412](https://github.com/influxdata/chronograf/pull/3412): Limit max-width of TICKScript editor.
1. [#3166](https://github.com/influxdata/chronograf/pull/3166): Fixes naming of new TICKScripts
1. [#3449](https://github.com/influxdata/chronograf/pull/3449): Fixes data explorer query error reporting regression
1. [#3453](https://github.com/influxdata/chronograf/pull/3453): Fix Kapacitor Logs fetch regression
## v1.4.4.1 [2018-04-16]

View File

@ -5,6 +5,8 @@ import _ from 'lodash'
import classnames from 'classnames'
import OnClickOutside from 'shared/components/OnClickOutside'
import {ErrorHandling} from 'src/shared/decorators/errors'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import {DROPDOWN_MENU_MAX_HEIGHT} from 'src/shared/constants/index'
@ErrorHandling
class DashboardSwitcher extends Component {
@ -29,9 +31,8 @@ class DashboardSwitcher extends Component {
}
render() {
const {activeDashboard, names} = this.props
const {activeDashboard} = this.props
const {isOpen} = this.state
const sorted = _.sortBy(names, ({name}) => name.toLowerCase())
return (
<div
@ -44,19 +45,29 @@ class DashboardSwitcher extends Component {
<span className="icon dash-f" />
</button>
<ul className="dropdown-menu">
{sorted.map(({name, link}) => (
<NameLink
key={link}
name={name}
link={link}
activeName={activeDashboard}
onClose={this.handleCloseMenu}
/>
))}
<FancyScrollbar
autoHeight={true}
maxHeight={DROPDOWN_MENU_MAX_HEIGHT}
>
{this.sortedList.map(({name, link}) => (
<NameLink
key={link}
name={name}
link={link}
activeName={activeDashboard}
onClose={this.handleCloseMenu}
/>
))}
</FancyScrollbar>
</ul>
</div>
)
}
get sortedList() {
const {names} = this.props
return _.sortBy(names, ({name}) => name.toLowerCase())
}
}
const NameLink = ({name, link, activeName, onClose}) => (

View File

@ -107,22 +107,23 @@ const kapacitorLogHeaders = {
}
export const getLogStream = kapacitor =>
AJAX({
url: `${kapacitor.links.proxy}?path=/kapacitor/v1preview/logs`,
// fetch required for kapacitors log querying
fetch(`${kapacitor.links.proxy}?path=/kapacitor/v1preview/logs`, {
method: 'GET',
headers: kapacitorLogHeaders,
credentials: 'include',
})
export const getLogStreamByRuleID = (kapacitor, ruleID) =>
AJAX({
url: `${
kapacitor.links.proxy
}?path=/kapacitor/v1preview/logs?task=${ruleID}`,
method: 'GET',
headers: kapacitorLogHeaders,
credentials: 'include',
})
// fetch required for kapacitors log querying
fetch(
`${kapacitor.links.proxy}?path=/kapacitor/v1preview/logs?task=${ruleID}`,
{
method: 'GET',
headers: kapacitorLogHeaders,
credentials: 'include',
}
)
export const pingKapacitorVersion = async kapacitor => {
try {

View File

@ -22,6 +22,7 @@ import {
KafkaConfig,
OpsGenieConfig,
PagerDutyConfig,
PagerDuty2Config,
PushoverConfig,
SensuConfig,
SlackConfig,
@ -280,7 +281,7 @@ class AlertTabs extends PureComponent<Props, State> {
type: 'PagerDuty2',
enabled: this.getEnabled(configSections, 'pagerduty2'),
renderComponent: () => (
<PagerDutyConfig
<PagerDuty2Config
onSave={this.handleSaveConfig('pagerduty2')}
config={this.getSection(configSections, 'pagerduty2')}
onTest={this.handleTestConfig('pagerduty2')}

View File

@ -11,6 +11,7 @@ import {
KafkaHandler,
OpsgenieHandler,
PagerdutyHandler,
Pagerduty2Handler,
PushoverHandler,
SensuHandler,
SlackHandler,
@ -131,7 +132,7 @@ class HandlerOptions extends Component {
)
case 'pagerDuty2':
return (
<PagerdutyHandler
<Pagerduty2Handler
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
onGoToConfig={onGoToConfig('pagerduty2')}

View File

@ -56,18 +56,6 @@ const TasksTable: SFC<TasksTableProps> = ({
)
export class TaskRow extends PureComponent<TaskRowProps> {
public handleClickRuleStatusEnabled(task: AlertRule) {
return () => {
this.props.onChangeRuleStatus(task)
}
}
public handleDelete(task: AlertRule) {
return () => {
this.props.onDelete(task)
}
}
public render() {
const {task, source} = this.props
@ -91,9 +79,9 @@ export class TaskRow extends PureComponent<TaskRowProps> {
className="form-control-static"
type="checkbox"
checked={task.status === 'enabled'}
onChange={this.handleClickRuleStatusEnabled(task)}
onChange={this.handleClickRuleStatusEnabled}
/>
<label htmlFor={`kapacitor-task-row-task-enabled ${task.name}`} />
<label htmlFor={`kapacitor-task-row-task-enabled ${task.id}`} />
</div>
</td>
<td style={{width: colActions}} className="text-right">
@ -102,12 +90,24 @@ export class TaskRow extends PureComponent<TaskRowProps> {
type="btn-danger"
size="btn-xs"
customClass="table--show-on-row-hover"
confirmAction={this.handleDelete(task)}
confirmAction={this.handleDelete}
/>
</td>
</tr>
)
}
private handleDelete = () => {
const {onDelete, task} = this.props
onDelete(task)
}
private handleClickRuleStatusEnabled = () => {
const {onChangeRuleStatus, task} = this.props
onChangeRuleStatus(task)
}
}
export default TasksTable

View File

@ -0,0 +1,140 @@
import _ from 'lodash'
import React, {PureComponent, ChangeEvent} from 'react'
import RedactedInput from 'src/kapacitor/components/config/RedactedInput'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Properties {
'routing-key': string
url: string
enabled: boolean
}
interface Config {
options: {
'routing-key': boolean
url: string
enabled: boolean
}
}
interface Props {
config: Config
onSave: (properties: Properties) => void
onTest: (event: React.MouseEvent<HTMLButtonElement>) => void
enabled: boolean
}
interface State {
testEnabled: boolean
enabled: boolean
}
@ErrorHandling
class PagerDuty2Config extends PureComponent<Props, State> {
private routingKey: HTMLInputElement
private url: HTMLInputElement
constructor(props: Props) {
super(props)
this.state = {
testEnabled: this.props.enabled,
enabled: _.get(this.props, 'config.options.enabled', false),
}
}
public render() {
const {options} = this.props.config
const {url} = options
const routingKey = options['routing-key']
const {testEnabled, enabled} = this.state
return (
<form onSubmit={this.handleSubmit}>
<div className="form-group col-xs-12">
<label htmlFor="routing-key">Routing Key</label>
<RedactedInput
defaultValue={routingKey}
id="routing-key"
refFunc={this.handleRoutingKeyRef}
disableTest={this.disableTest}
isFormEditing={!testEnabled}
/>
</div>
<div className="form-group col-xs-12">
<label htmlFor="url">PagerDuty URL</label>
<input
className="form-control"
id="url"
type="text"
ref={r => (this.url = r)}
defaultValue={url || ''}
onChange={this.disableTest}
/>
</div>
<div className="form-group col-xs-12">
<div className="form-control-static">
<input
type="checkbox"
id="disabled"
checked={enabled}
onChange={this.handleEnabledChange}
/>
<label htmlFor="disabled">Configuration Enabled</label>
</div>
</div>
<div className="form-group form-group-submit col-xs-12 text-center">
<button
className="btn btn-primary"
type="submit"
disabled={this.state.testEnabled}
>
<span className="icon checkmark" />
Save Changes
</button>
<button
className="btn btn-primary"
disabled={!this.state.testEnabled || !enabled}
onClick={this.props.onTest}
>
<span className="icon pulse-c" />
Send Test Alert
</button>
</div>
</form>
)
}
private handleRoutingKeyRef = (r: HTMLInputElement): HTMLInputElement =>
(this.routingKey = r)
private handleEnabledChange = (e: ChangeEvent<HTMLInputElement>): void => {
this.setState({enabled: e.target.checked})
this.disableTest()
}
private handleSubmit = async (
e: React.FormEvent<HTMLFormElement>
): Promise<void> => {
e.preventDefault()
const properties: Properties = {
'routing-key': this.routingKey.value,
url: this.url.value,
enabled: this.state.enabled,
}
const success = await this.props.onSave(properties)
if (success) {
this.setState({testEnabled: true})
}
}
private disableTest = (): void => {
this.setState({testEnabled: false})
}
}
export default PagerDuty2Config

View File

@ -3,6 +3,7 @@ import HipChatConfig from './HipChatConfig'
import KafkaConfig from './KafkaConfig'
import OpsGenieConfig from './OpsGenieConfig'
import PagerDutyConfig from './PagerDutyConfig'
import PagerDuty2Config from './PagerDuty2Config'
import PushoverConfig from './PushoverConfig'
import SensuConfig from './SensuConfig'
import SlackConfig from './SlackConfig'
@ -17,6 +18,7 @@ export {
KafkaConfig,
OpsGenieConfig,
PagerDutyConfig,
PagerDuty2Config,
PushoverConfig,
SensuConfig,
SlackConfig,

View File

@ -0,0 +1,59 @@
import React, {SFC} from 'react'
import HandlerInput from 'src/kapacitor/components/HandlerInput'
import HandlerEmpty from 'src/kapacitor/components/HandlerEmpty'
interface Props {
selectedHandler: {
enabled: boolean
}
handleModifyHandler: () => void
onGoToConfig: () => void
validationError: string
}
const Pagerduty2Handler: SFC<Props> = ({
selectedHandler,
handleModifyHandler,
onGoToConfig,
validationError,
}) => {
if (selectedHandler.enabled) {
let goToConfigText
if (validationError) {
goToConfigText = 'Exit this Rule and Edit Configuration'
} else {
goToConfigText = 'Save this Rule and Edit Configuration'
}
return (
<div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters">
<h4 className="u-flex u-jc-space-between">
Parameters from Kapacitor Configuration
<div className="btn btn-default btn-sm" onClick={onGoToConfig}>
<span className="icon cog-thick" />
{goToConfigText}
</div>
</h4>
<HandlerInput
selectedHandler={selectedHandler}
handleModifyHandler={handleModifyHandler}
fieldName="routingKey"
fieldDisplay="Routing Key:"
placeholder="ex: routing_key"
redacted={true}
fieldColumns="col-md-12"
/>
</div>
</div>
)
}
return (
<HandlerEmpty
onGoToConfig={onGoToConfig}
validationError={validationError}
/>
)
}
export default Pagerduty2Handler

View File

@ -7,6 +7,7 @@ import HipchatHandler from './HipchatHandler'
import KafkaHandler from './KafkaHandler'
import OpsgenieHandler from './OpsgenieHandler'
import PagerdutyHandler from './PagerdutyHandler'
import Pagerduty2Handler from './Pagerduty2Handler'
import PushoverHandler from './PushoverHandler'
import SensuHandler from './SensuHandler'
import SlackHandler from './SlackHandler'
@ -26,6 +27,7 @@ export {
KafkaHandler,
OpsgenieHandler,
PagerdutyHandler,
Pagerduty2Handler,
PushoverHandler,
SensuHandler,
SlackHandler,

View File

@ -118,7 +118,7 @@ export const ALERTS_FROM_CONFIG = {
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
pagerDuty2: ['routing-key'], // routing-key = bool
pushover: ['token', 'user-key'], // token = bool, user-key = bool
sensu: ['addr', 'source'],
slack: ['url', 'channel'], // url = bool
@ -143,7 +143,7 @@ export const MAP_FIELD_KEYS_FROM_CONFIG = {
opsGenie: {},
opsGenie2: {},
pagerDuty: {'service-key': 'serviceKey'},
pagerDuty2: {'service-key': 'serviceKey'},
pagerDuty2: {'routing-key': 'routingKey'},
pushover: {'user-key': 'userKey'},
sensu: {},
slack: {},

View File

@ -56,7 +56,7 @@ interface AlertNodes {
log: Log[]
victorOps: VictorOps[]
pagerDuty: PagerDuty[]
pagerDuty2?: PagerDuty[]
pagerDuty2?: PagerDuty2[]
pushover: Pushover[]
sensu: Sensu[]
slack: Slack[]
@ -120,6 +120,11 @@ interface PagerDuty {
serviceKey: string
}
// PagerDuty2 sends alerts to the pagerduty.com service
interface PagerDuty2 {
routingKey: string
}
// HipChat sends alerts to stride.com
interface HipChat {
room: string