Add http endpoint (#14845)
* Add http endpoint * Add http notification rule as option * Update testpull/14855/head
parent
2fa1ca3f49
commit
456dfcf4d8
|
@ -50,7 +50,7 @@ describe('Notification Endpoints', () => {
|
|||
.click()
|
||||
.within(() => {
|
||||
cy.getByTestID('endpoint--dropdown--button').within(() => {
|
||||
cy.contains('Slack')
|
||||
cy.contains('HTTP')
|
||||
})
|
||||
|
||||
cy.getByTestID('endpoint--dropdown-item pagerduty').click()
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// Libraries
|
||||
import React, {FC} from 'react'
|
||||
|
||||
// Components
|
||||
import {Dropdown} from '@influxdata/clockface'
|
||||
|
||||
// Types
|
||||
import {HTTPAuthMethodType} from 'src/types'
|
||||
|
||||
interface AuthMethodType {
|
||||
name: string
|
||||
type: HTTPAuthMethodType
|
||||
id: HTTPAuthMethodType
|
||||
}
|
||||
|
||||
interface Props {
|
||||
selectedType: string
|
||||
onSelectType: (type: HTTPAuthMethodType) => void
|
||||
}
|
||||
|
||||
const types: AuthMethodType[] = [
|
||||
{name: 'none', type: 'none', id: 'none'},
|
||||
{name: 'basic', type: 'basic', id: 'basic'},
|
||||
{name: 'bearer', type: 'bearer', id: 'bearer'},
|
||||
]
|
||||
|
||||
const AuthMethodTypeDropdown: FC<Props> = ({selectedType, onSelectType}) => {
|
||||
const items = types.map(({id, type, name}) => (
|
||||
<Dropdown.Item
|
||||
key={id}
|
||||
id={id}
|
||||
value={id}
|
||||
testID={`http-authMethod--dropdown-item ${type}`}
|
||||
onClick={onSelectType}
|
||||
>
|
||||
{name}
|
||||
</Dropdown.Item>
|
||||
))
|
||||
|
||||
const selected = types.find(t => t.type === selectedType)
|
||||
|
||||
if (!selected) {
|
||||
throw new Error(
|
||||
'Incorrect authMethod type provided to <AuthMethodTypeDropdown/>'
|
||||
)
|
||||
}
|
||||
|
||||
const button = (active, onClick) => (
|
||||
<Dropdown.Button
|
||||
testID="http-authMethod--dropdown--button"
|
||||
active={active}
|
||||
onClick={onClick}
|
||||
>
|
||||
{selected.name}
|
||||
</Dropdown.Button>
|
||||
)
|
||||
|
||||
const menu = onCollapse => (
|
||||
<Dropdown.Menu onCollapse={onCollapse}>{items}</Dropdown.Menu>
|
||||
)
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
button={button}
|
||||
menu={menu}
|
||||
widthPixels={160}
|
||||
testID="http-authMethod-change--dropdown"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default AuthMethodTypeDropdown
|
|
@ -16,10 +16,15 @@ import {
|
|||
|
||||
interface Props {
|
||||
endpoint: NotificationEndpoint
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void
|
||||
onChange: (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void
|
||||
onChangeParameter: (key: string) => (value: string) => void
|
||||
}
|
||||
|
||||
const EndpointOptions: FC<Props> = ({endpoint, onChange}) => {
|
||||
const EndpointOptions: FC<Props> = ({
|
||||
endpoint,
|
||||
onChange,
|
||||
onChangeParameter,
|
||||
}) => {
|
||||
switch (endpoint.type) {
|
||||
case 'slack': {
|
||||
const {url, token} = endpoint as SlackNotificationEndpoint
|
||||
|
@ -38,8 +43,6 @@ const EndpointOptions: FC<Props> = ({endpoint, onChange}) => {
|
|||
)
|
||||
}
|
||||
case 'http': {
|
||||
// TODO(watts): add webhook type to the `Destination` dropdown
|
||||
// when webhooks are implemented in the backend.
|
||||
const {
|
||||
url,
|
||||
token,
|
||||
|
@ -51,6 +54,8 @@ const EndpointOptions: FC<Props> = ({endpoint, onChange}) => {
|
|||
} = endpoint as HTTPNotificationEndpoint
|
||||
return (
|
||||
<EndpointOptionsHTTP
|
||||
onChange={onChange}
|
||||
onChangeParameter={onChangeParameter}
|
||||
url={url}
|
||||
token={token}
|
||||
username={username}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// Libraries
|
||||
import React, {FC} from 'react'
|
||||
import React, {FC, ChangeEvent} from 'react'
|
||||
|
||||
// Components
|
||||
import {Input, FormElement, InputType} from '@influxdata/clockface'
|
||||
import {Input, FormElement, InputType, TextArea} from '@influxdata/clockface'
|
||||
import MethodTypeDropdown from 'src/alerting/components/endpoints/MethodTypeDropdown'
|
||||
import AuthMethodTypeDropdown from 'src/alerting/components/endpoints/AuthMethodTypeDropdown'
|
||||
|
||||
// Types
|
||||
import {HTTPNotificationEndpoint} from 'src/types'
|
||||
|
@ -15,32 +17,80 @@ interface Props {
|
|||
method?: HTTPNotificationEndpoint['method']
|
||||
authMethod?: HTTPNotificationEndpoint['authMethod']
|
||||
contentTemplate: string
|
||||
onChange: (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void
|
||||
onChangeParameter: (key: string) => (value: string) => void
|
||||
}
|
||||
|
||||
const EndpointOptionsHTTP: FC<Props> = ({
|
||||
url,
|
||||
onChange,
|
||||
token,
|
||||
username,
|
||||
password,
|
||||
contentTemplate,
|
||||
method,
|
||||
authMethod,
|
||||
onChangeParameter,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<FormElement label="URL">
|
||||
<Input name="url" value={url} />
|
||||
<Input name="url" value={url} onChange={onChange} required={true} />
|
||||
</FormElement>
|
||||
<FormElement label="Token">
|
||||
<Input name="token" value={token} />
|
||||
<FormElement label="HTTP method">
|
||||
<MethodTypeDropdown
|
||||
onSelectType={onChangeParameter('method')}
|
||||
selectedType={method}
|
||||
/>
|
||||
</FormElement>
|
||||
<FormElement label="username">
|
||||
<Input name="username" value={username} />
|
||||
<FormElement label="auth method">
|
||||
<AuthMethodTypeDropdown
|
||||
onSelectType={onChangeParameter('authMethod')}
|
||||
selectedType={authMethod}
|
||||
/>
|
||||
</FormElement>
|
||||
<FormElement label="password">
|
||||
<Input name="password" value={password} type={InputType.Password} />
|
||||
</FormElement>
|
||||
{/** add dropdowns for method and authmethod */}
|
||||
{authMethod === 'bearer' && (
|
||||
<FormElement label="Token">
|
||||
<Input
|
||||
name="token"
|
||||
value={token}
|
||||
onChange={onChange}
|
||||
type={InputType.Password}
|
||||
/>
|
||||
</FormElement>
|
||||
)}
|
||||
{authMethod === 'basic' && (
|
||||
<>
|
||||
<FormElement label="username">
|
||||
<Input
|
||||
name="username"
|
||||
value={username}
|
||||
onChange={onChange}
|
||||
type={
|
||||
username && username.includes('secret: ')
|
||||
? InputType.Password
|
||||
: InputType.Text
|
||||
}
|
||||
/>
|
||||
</FormElement>
|
||||
<FormElement label="password">
|
||||
<Input
|
||||
name="password"
|
||||
value={password}
|
||||
type={InputType.Password}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</FormElement>
|
||||
</>
|
||||
)}
|
||||
<FormElement label="Content Template">
|
||||
<Input name="contentTemplate" value={contentTemplate} />
|
||||
<TextArea
|
||||
rows={2}
|
||||
className="endpoint-description--textarea"
|
||||
name="contentTemplate"
|
||||
value={contentTemplate}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</FormElement>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -30,6 +30,13 @@ const EndpointOverlayContents: FC<Props> = ({onSave, saveButtonText}) => {
|
|||
})
|
||||
}
|
||||
|
||||
const handleChangeParameter = (key: string) => (value: string) => {
|
||||
dispatch({
|
||||
type: 'UPDATE_ENDPOINT',
|
||||
endpoint: {...endpoint, [key]: value},
|
||||
})
|
||||
}
|
||||
|
||||
const handleSelectType = (type: NotificationEndpointType) => {
|
||||
dispatch({
|
||||
type: 'UPDATE_ENDPOINT',
|
||||
|
@ -55,11 +62,10 @@ const EndpointOverlayContents: FC<Props> = ({onSave, saveButtonText}) => {
|
|||
</Form.Element>
|
||||
<Form.Element label="Description">
|
||||
<TextArea
|
||||
rows={5}
|
||||
rows={1}
|
||||
className="endpoint-description--textarea"
|
||||
testID="endpoint-description--textarea"
|
||||
name="description"
|
||||
placeholder="Optional"
|
||||
value={endpoint.description}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
|
@ -70,7 +76,11 @@ const EndpointOverlayContents: FC<Props> = ({onSave, saveButtonText}) => {
|
|||
selectedType={endpoint.type}
|
||||
/>
|
||||
</Form.Element>
|
||||
<EndpointOptions endpoint={endpoint} onChange={handleChange} />
|
||||
<EndpointOptions
|
||||
endpoint={endpoint}
|
||||
onChange={handleChange}
|
||||
onChangeParameter={handleChangeParameter}
|
||||
/>
|
||||
<EndpointOverlayFooter
|
||||
onSave={onSave}
|
||||
saveButtonText={saveButtonText}
|
||||
|
|
|
@ -19,6 +19,7 @@ interface Props {
|
|||
}
|
||||
|
||||
const types: EndpointType[] = [
|
||||
{name: 'HTTP', type: 'http', id: 'http'},
|
||||
{name: 'Slack', type: 'slack', id: 'slack'},
|
||||
{name: 'Pagerduty', type: 'pagerduty', id: 'pagerduty'},
|
||||
]
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// Libraries
|
||||
import React, {FC} from 'react'
|
||||
|
||||
// Components
|
||||
import {Dropdown} from '@influxdata/clockface'
|
||||
|
||||
// Types
|
||||
import {HTTPMethodType} from 'src/types'
|
||||
|
||||
interface MethodType {
|
||||
name: string
|
||||
type: HTTPMethodType
|
||||
id: HTTPMethodType
|
||||
}
|
||||
|
||||
interface Props {
|
||||
selectedType: string
|
||||
onSelectType: (type: HTTPMethodType) => void
|
||||
}
|
||||
|
||||
const types: MethodType[] = [
|
||||
{name: 'POST', type: 'POST', id: 'POST'},
|
||||
{name: 'GET', type: 'GET', id: 'GET'},
|
||||
{name: 'PUT', type: 'PUT', id: 'PUT'},
|
||||
]
|
||||
|
||||
const MethodTypeDropdown: FC<Props> = ({selectedType, onSelectType}) => {
|
||||
const items = types.map(({id, type, name}) => (
|
||||
<Dropdown.Item
|
||||
key={id}
|
||||
id={id}
|
||||
value={id}
|
||||
testID={`http-method--dropdown-item ${type}`}
|
||||
onClick={onSelectType}
|
||||
>
|
||||
{name}
|
||||
</Dropdown.Item>
|
||||
))
|
||||
|
||||
const selected = types.find(t => t.type === selectedType)
|
||||
|
||||
if (!selected) {
|
||||
throw new Error('Incorrect method type provided to <MethodTypeDropdown/>')
|
||||
}
|
||||
|
||||
const button = (active, onClick) => (
|
||||
<Dropdown.Button
|
||||
testID="http-method--dropdown--button"
|
||||
active={active}
|
||||
onClick={onClick}
|
||||
>
|
||||
{selected.name}
|
||||
</Dropdown.Button>
|
||||
)
|
||||
|
||||
const menu = onCollapse => (
|
||||
<Dropdown.Menu onCollapse={onCollapse}>{items}</Dropdown.Menu>
|
||||
)
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
button={button}
|
||||
menu={menu}
|
||||
widthPixels={160}
|
||||
testID="http-method-change--dropdown"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default MethodTypeDropdown
|
|
@ -15,12 +15,14 @@ import {
|
|||
NotificationRule,
|
||||
NotificationRuleDraft,
|
||||
NewNotificationRule,
|
||||
HTTPNotificationRuleBase,
|
||||
} from 'src/types'
|
||||
|
||||
type RuleVariantFields =
|
||||
| SlackNotificationRuleBase
|
||||
| SMTPNotificationRuleBase
|
||||
| PagerDutyNotificationRuleBase
|
||||
| HTTPNotificationRuleBase
|
||||
|
||||
export const getRuleVariantDefaults = (
|
||||
endpoints: NotificationEndpoint[],
|
||||
|
@ -37,6 +39,10 @@ export const getRuleVariantDefaults = (
|
|||
return {messageTemplate: '', type: 'pagerduty'}
|
||||
}
|
||||
|
||||
case 'http': {
|
||||
return {type: 'http', url: ''}
|
||||
}
|
||||
|
||||
default: {
|
||||
throw new Error(`Could not find NotificationEndpoint with id "${id}"`)
|
||||
}
|
||||
|
|
|
@ -112,10 +112,12 @@ export const NEW_TAG_RULE_DRAFT: TagRuleDraft = {
|
|||
}
|
||||
|
||||
export const NEW_ENDPOINT_DRAFT: NotificationEndpoint = {
|
||||
name: 'HTTP Endpoint',
|
||||
method: 'POST',
|
||||
authMethod: 'none',
|
||||
description: '',
|
||||
name: 'Slack Endpoint',
|
||||
status: 'active',
|
||||
type: 'slack',
|
||||
type: 'http',
|
||||
token: '',
|
||||
url: '',
|
||||
}
|
||||
|
|
|
@ -89,16 +89,18 @@ export {
|
|||
SMTPNotificationRuleBase,
|
||||
SlackNotificationRuleBase,
|
||||
PagerDutyNotificationRuleBase,
|
||||
HTTPNotificationRuleBase,
|
||||
SMTPNotificationRule,
|
||||
SlackNotificationRule,
|
||||
PagerDutyNotificationRule,
|
||||
HTTPNotificationRule,
|
||||
PagerDutyNotificationEndpoint,
|
||||
SlackNotificationEndpoint,
|
||||
HTTPNotificationEndpoint,
|
||||
NotificationEndpointUpdate,
|
||||
} from '../client'
|
||||
|
||||
import {Check, Threshold} from '../client'
|
||||
import {Check, Threshold, HTTPNotificationEndpoint} from '../client'
|
||||
|
||||
export type CheckType = Check['type']
|
||||
export type ThresholdType = Threshold['type']
|
||||
|
@ -106,3 +108,6 @@ export type ThresholdType = Threshold['type']
|
|||
export type CheckTagSet = Check['tags'][0]
|
||||
|
||||
export type AlertHistoryType = 'statuses' | 'notifications'
|
||||
|
||||
export type HTTPMethodType = HTTPNotificationEndpoint['method']
|
||||
export type HTTPAuthMethodType = HTTPNotificationEndpoint['authMethod']
|
||||
|
|
Loading…
Reference in New Issue