Remove Hipchat support from Watcher (#39374)
* Remove Hipchat support from Watcher (#39199) Hipchat has been shut down and has previously been deprecated in Watcher (#39160), therefore we should remove support for these actions. * Add migrate note
|
@ -75,3 +75,9 @@ Tribe node functionality has been removed in favor of
|
|||
|
||||
* The method `DiscoveryPlugin#getDiscoveryTypes()` was removed, so that plugins
|
||||
can no longer provide their own discovery implementations.
|
||||
|
||||
[float]
|
||||
==== Watcher 'hipchat' action removed
|
||||
|
||||
Hipchat has been deprecated and shut down as a service. The `hipchat` action for
|
||||
watches has been removed.
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
You configure {watcher} settings to set up {watcher} and send notifications via
|
||||
<<email-notification-settings,email>>,
|
||||
<<hipchat-notification-settings,HipChat>>,
|
||||
<<slack-notification-settings,Slack>>, and
|
||||
<<pagerduty-notification-settings, PagerDuty>>.
|
||||
|
||||
|
@ -67,10 +66,10 @@ Specifies the maximum size an HTTP response is allowed to have, defaults to
|
|||
|
||||
`xpack.http.whitelist`::
|
||||
A list of URLs, that the internal HTTP client is allowed to connect to. This
|
||||
client is used in the HTTP input, the webhook, the slack, pagerduty, hipchat
|
||||
client is used in the HTTP input, the webhook, the slack, pagerduty,
|
||||
and jira actions. This setting can be updated dynamically. It defaults to `*`
|
||||
allowing everything. Note: If you configure this setting and you are using one
|
||||
of the slack/pagerduty/hipchat actions, you have to ensure that the
|
||||
of the slack/pagerduty actions, you have to ensure that the
|
||||
corresponding endpoints are whitelisted as well.
|
||||
|
||||
[[ssl-notification-settings]]
|
||||
|
@ -207,54 +206,6 @@ HTML feature groups>>.
|
|||
Set to `false` to completely disable HTML sanitation. Not recommended.
|
||||
Defaults to `true`.
|
||||
|
||||
[float]
|
||||
[[hipchat-notification-settings]]
|
||||
==== HipChat Notification Settings
|
||||
You can configure the following HipChat notification settings in
|
||||
`elasticsearch.yml`. For more information about sending notifications
|
||||
via HipChat, see {xpack-ref}/actions-hipchat.html#configuring-hipchat-actions[Configuring HipChat].
|
||||
|
||||
`xpack.notification.hipchat` ::
|
||||
Specifies account information for sending notifications
|
||||
via HipChat. You can specify the following HipChat account attributes:
|
||||
|
||||
[[hipchat-account-attributes]]
|
||||
`profile`;;
|
||||
The HipChat account profile to use: `integration`,
|
||||
`user`, or `v1`. Required.
|
||||
|
||||
`secure_auth_token` (<<secure-settings,Secure>>);;
|
||||
The authentication token to use to access the HipChat API. Required.
|
||||
|
||||
`host`;;
|
||||
The HipChat server hostname. Defaults to `api.hipchat.com`.
|
||||
|
||||
`port`;;
|
||||
The HipChat server port number. Defaults to 443.
|
||||
|
||||
`room`;;
|
||||
The room you want to send messages to. Must be specified
|
||||
if the `profile` is set to `integration`. Not valid for
|
||||
the `user` or `vi` profiles.
|
||||
|
||||
`user`;;
|
||||
The HipChat user account to use to send messages.
|
||||
Specified as an email address. Must be specified if the
|
||||
`profile` is set to `user`. Not valid for the `integration`
|
||||
or `v1` profiles.
|
||||
|
||||
`message.format`;;
|
||||
The format of the message: `text` or `html`.
|
||||
Defaults to `html`.
|
||||
|
||||
`message.color`;;
|
||||
The background color of the notification in the room.
|
||||
Defaults to `yellow`.
|
||||
`message.notify`;;
|
||||
Indicates whether people in the room should be
|
||||
actively notified. Defaults to `false`.
|
||||
|
||||
|
||||
[float]
|
||||
[[slack-notification-settings]]
|
||||
==== Slack Notification Settings
|
||||
|
|
|
@ -16,8 +16,8 @@ serve as a model for a templated email body.
|
|||
|
||||
{watcher} supports the following types of actions:
|
||||
<<actions-email, email>>, <<actions-webhook, webhook>>, <<actions-index, index>>,
|
||||
<<actions-logging, logging>>, <<actions-hipchat, hipchat>>, <<actions-slack,
|
||||
Slack>>, and <<actions-pagerduty, pagerduty>>.
|
||||
<<actions-logging, logging>>, <<actions-slack, Slack>>,
|
||||
and <<actions-pagerduty, pagerduty>>.
|
||||
|
||||
[float]
|
||||
[[actions-ack-throttle]]
|
||||
|
@ -271,9 +271,6 @@ include::actions/index.asciidoc[]
|
|||
:edit_url: https://github.com/elastic/elasticsearch/edit/{branch}/x-pack/docs/en/watcher/actions/logging.asciidoc
|
||||
include::actions/logging.asciidoc[]
|
||||
|
||||
:edit_url: https://github.com/elastic/elasticsearch/edit/{branch}/x-pack/docs/en/watcher/actions/hipchat.asciidoc
|
||||
include::actions/hipchat.asciidoc[]
|
||||
|
||||
:edit_url: https://github.com/elastic/elasticsearch/edit/{branch}/x-pack/docs/en/watcher/actions/slack.asciidoc
|
||||
include::actions/slack.asciidoc[]
|
||||
|
||||
|
@ -292,7 +289,7 @@ that even despite the exact same version, an OpenJDK distribution contains
|
|||
different parts under different Linux distributions.
|
||||
|
||||
This can lead to issues with any action or input that uses TLS, like the `jira`,
|
||||
`pagerduty`, `slack`, `hipchat` or `webhook` one, because of missing CA certs.
|
||||
`pagerduty`, `slack`, or `webhook` one, because of missing CA certs.
|
||||
If you encounter TLS errors, when writing watches that connect to TLS endpoints,
|
||||
you should try to upgrade to the latest available OpenJDK distribution for your
|
||||
platform and if that does not help, try to upgrade to Oracle JDK.
|
||||
|
|
|
@ -1,393 +0,0 @@
|
|||
[[actions-hipchat]]
|
||||
=== HipChat Action
|
||||
|
||||
Use the `hipchat` action to send messages to https://www.hipchat.com[HipChat]
|
||||
rooms or users. To send HipChat messages, you must
|
||||
<<configuring-hipchat, configure at least one HipChat account>> in `elasticsearch.yml`.
|
||||
|
||||
[[configuring-hipchat-actions]]
|
||||
==== Configuring HipChat Actions
|
||||
|
||||
You configure HipChat actions in a `actions` array. Action-specific attributes
|
||||
are specified using the `hipchat` keyword. You must specify the `message`
|
||||
attribute for all `hipchat` actions. If you omit the `account` attribute, the
|
||||
message is sent using the default HipChat account configured in
|
||||
`elasticsearch.yml`.
|
||||
|
||||
For example, the following action is configured to send messages using a HipChat
|
||||
account that uses the <<hipchat-api-integration, integration>> profile. Because
|
||||
this type of account can only send messages to a specific room, the only required
|
||||
attribute is the message itself:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
"actions" : {
|
||||
"notify-hipchat" : {
|
||||
"transform" : { ... },
|
||||
"throttle_period" : "5m",
|
||||
"hipchat" : {
|
||||
"account" : "integration-account", <1>
|
||||
"message" : {
|
||||
"body" : "Encountered {{ctx.payload.hits.total.value}} errors in the last 5 minutes (facepalm)", <2>
|
||||
"format" : "text",
|
||||
"color" : "red",
|
||||
"notify" : true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
// NOTCONSOLE
|
||||
<1> The name of a HipChat account configured in `elasticsearch.yml`.
|
||||
<2> The message you want to send to HipChat.
|
||||
|
||||
To send messages with a HipChat account that uses the <<hipchat-api-user, user>>
|
||||
profile, you need to specify what rooms and users you want to send the message to.
|
||||
For example, the following action is configured to send messages to the
|
||||
`mission-control` and `devops` rooms as well as the user `website-admin@example.com`.
|
||||
(To send to multiple users or rooms, specify an array of strings):
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
"actions" : {
|
||||
"notify-hipchat" : {
|
||||
"transform" : { ... },
|
||||
"throttle_period" : "5m",
|
||||
"hipchat" : {
|
||||
"account" : "user-account",
|
||||
"message" : {
|
||||
"room" : [ "mission-control", "devops" ],
|
||||
"user" : "website-admin@example.com",
|
||||
"body" : "Encountered {{ctx.payload.hits.total.value}} errors in the last 5 minutes (facepalm)",
|
||||
"format" : "text",
|
||||
"color" : "red",
|
||||
"notify" : true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
// NOTCONSOLE
|
||||
|
||||
To send messages with a HipChat account that uses the <<hipchat-api-v1, v1>>
|
||||
profile, you need to specify what room or rooms you want to send the message to.
|
||||
For example, the following action is configured to send messages to the
|
||||
`server-status` room. (To send to multiple rooms, specify an array of strings.)
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
"actions" : {
|
||||
"notify-hipchat" : {
|
||||
"transform" : { ... },
|
||||
"throttle_period" : "5m",
|
||||
"hipchat" : {
|
||||
"account" : "v1-account",
|
||||
"message" : {
|
||||
"from" : "Watcher",
|
||||
"room" : [ "server-status", "infra-team" ],
|
||||
"body" : "Encountered {{ctx.payload.hits.total.value}} errors in the last 5 minutes (facepalm)",
|
||||
"format" : "text",
|
||||
"color" : "red",
|
||||
"notify" : true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
// NOTCONSOLE
|
||||
|
||||
[[hipchat-action-attributes]]
|
||||
==== HipChat Action Attributes
|
||||
|
||||
[cols=",^,,", options="header"]
|
||||
|======
|
||||
| Name |Required | Default | Description
|
||||
|
||||
| `account` | no | Default account | The HipChat account to use to send the message.
|
||||
|
||||
| `proxy.host` | no | - | The proxy host to use (only in combination with `proxy.port`)
|
||||
|
||||
| `proxy.port` | no | - | The proxy port to use (only in combination with `proxy.host`)
|
||||
|
||||
| `message.body` | yes | - | The message content. Can contain up to 1000 characters.
|
||||
|
||||
| `message.format` | no | html | The format of the message: `text` or `html`.
|
||||
|
||||
| `message.color` | no | yellow | The background color of the notification in the room:
|
||||
`gray`, `green`, `purple`, `red`, `yellow`.
|
||||
|
||||
| `message.notify` | no | false | Indicates whether people in the room should be actively
|
||||
notified
|
||||
|
||||
| `message.from` | no | the watch ID | The name that appears as the notification sender. Only
|
||||
valid for accounts that use the v1 profile.
|
||||
|
||||
| `message.room` | no | - | The rooms that the notification should go to. Accepts
|
||||
a string value or an array of string values. Must be
|
||||
specified when using the v1 profile. At least one room
|
||||
or user must be specified when using the `user` profile.
|
||||
Not valid for the `integration` profile.
|
||||
|
||||
| `message.user` | no | - | The users that the notification should go to. Accepts
|
||||
a string value or an array of string values. At least
|
||||
one room or user must be specified when using the `user`
|
||||
profile. Not valid for the `integration` or `v1` profiles.
|
||||
|======
|
||||
|
||||
|
||||
[[configuring-hipchat]]
|
||||
==== Configuring HipChat Accounts
|
||||
|
||||
You configure the accounts {watcher} can use to communicate with HipChat in the
|
||||
`xpack.notification.hipchat` namespace in `elasticsearch.yml`. Both
|
||||
https://www.hipchat.com/docs/api[v1] and
|
||||
https://www.hipchat.com/docs/apiv2[v2] HipChat APIs are supported.
|
||||
|
||||
{watcher} provides three HipChat API profiles:
|
||||
|
||||
<<hipchat-api-integration,integration>>::
|
||||
Sends messages to a specific room using HipChat's v2 API
|
||||
https://www.hipchat.com/docs/apiv2/method/send_room_notification[Send room
|
||||
notification].
|
||||
|
||||
<<hipchat-api-user, user>>::
|
||||
Sends messages as a particular user through the HipChat v2 API. Enables you to
|
||||
send messages to arbitrary rooms or users.
|
||||
|
||||
<<hipchat-api-v1, v1>>::
|
||||
Sends messages to rooms using HipChat's v1 API
|
||||
https://www.hipchat.com/docs/api/method/rooms/message[rooms/message].
|
||||
+
|
||||
NOTE: The `v1` profile is provided because it is simple to set up and this API
|
||||
is familiar to many users. That said, HipChat has deprecated the v1 API
|
||||
and is encouraging users to migrate to v2. Both the `integration` and
|
||||
`user` profiles are based on the HipChat v2 API.
|
||||
|
||||
If you configure multiple HipChat accounts, you either need to set a default
|
||||
HipChat account or specify which account the notification should be sent with
|
||||
in the <<actions-hipchat, hipchat>> action.
|
||||
|
||||
deprecated[Storing the `auth_token` in the configuration file or using via updating the settings now is deprecated, as you should use the keystore for this, see {ref}/secure-settings.html[secure settings]]
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.notification.hipchat:
|
||||
default_account: team1
|
||||
account:
|
||||
team1:
|
||||
...
|
||||
team2:
|
||||
...
|
||||
--------------------------------------------------
|
||||
|
||||
|
||||
[[hipchat-api-integration]]
|
||||
===== Using the Hipchat Integration Profile
|
||||
|
||||
You can use the `integration` profile to send messages to specific rooms. When
|
||||
you set an account's profile to `integration`, the messages are sent through
|
||||
HipChat's v2 https://www.hipchat.com/docs/apiv2/method/send_room_notification[
|
||||
Send room notification] API.
|
||||
|
||||
When you use the `integration` profile, you need to configure a separate HipChat
|
||||
account for each room you want to send messages--the account configuration
|
||||
contains a room-specific authentication token. Alternatively, you can use the
|
||||
<<hipchat-api-user, `user`>> or <<hipchat-api-v1, `v1`>> profile to send messages
|
||||
to multiple rooms.
|
||||
|
||||
NOTE: The `integration` profile only supports sending messages to rooms, it does
|
||||
not support sending private messages. Use the <<hipchat-api-user, `user`>>
|
||||
profile to notify a particular HipChat user.
|
||||
|
||||
You need a room-specific authentication token to configure an `integration`
|
||||
account. To generate an authentication token:
|
||||
|
||||
. Log in to http://hipchat.com[hipchat.com] or your HipChat server as a group
|
||||
administrator.
|
||||
. Go to *Group admin > Rooms*.
|
||||
. Click the name of the room you want to send messages to.
|
||||
. Click the *Tokens* link.
|
||||
. Enter a name for the token in the *Label* field.
|
||||
+
|
||||
image::images/hipchat-generate-room-token.jpg[]
|
||||
. Select the *Send Notification* scope.
|
||||
. Click *Create*.
|
||||
. Copy the generated token so you can paste it into your HipChat account
|
||||
configuration in `elasticsearch.yml`.
|
||||
+
|
||||
image::images/hipchat-copy-room-token.jpg[]
|
||||
|
||||
To configure a HipChat account that uses the `integration` profile:
|
||||
|
||||
. Set the `type` to `integration`.
|
||||
. Set `room` to the name of the room you want to send messages to.
|
||||
. Set `auth_token` to the room-specific authentication token.
|
||||
|
||||
For example, the following snippet configures an account called
|
||||
`notify-monitoring` that sends messages to the `monitoring` room:
|
||||
|
||||
[source,shell]
|
||||
--------------------------------------------------
|
||||
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
|
||||
--------------------------------------------------
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.notification.hipchat:
|
||||
account:
|
||||
notify-monitoring:
|
||||
profile: integration
|
||||
room: monitoring
|
||||
--------------------------------------------------
|
||||
|
||||
You can also specify defaults for the {ref}/notification-settings.html#hipchat-account-attributes[
|
||||
message attributes]:
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.notification.hipchat:
|
||||
account:
|
||||
notify-monitoring:
|
||||
profile: integration
|
||||
room: monitoring
|
||||
message:
|
||||
format: text
|
||||
color: blue
|
||||
notify: true
|
||||
--------------------------------------------------
|
||||
|
||||
|
||||
[[hipchat-api-user]]
|
||||
===== Using the HipChat User Profile
|
||||
|
||||
You can use the `user` profile to send messages to rooms as well as individual
|
||||
HipChat users. When you set an account's profile to `user`, {watcher} sends
|
||||
messages as a particular user through the HipChat v2 API.
|
||||
|
||||
Before you can configure a `user` account, you need to:
|
||||
|
||||
. Add a HipChat user for {watcher}. When setting the user name, keep in mind that
|
||||
the messages are sent on behalf of this user.
|
||||
. Create an API token for the {watcher} user:
|
||||
.. Log in to HipChat as the {watcher} user.
|
||||
.. Go to `https://<hipchat-server>/account/api`. For example,
|
||||
`https://www.hipchat.com/account/api`.
|
||||
.. Confirm the user password.
|
||||
.. Enter a name for the token in the *Label* field.
|
||||
+
|
||||
image::images/hipchat-generate-user-token.jpg[]
|
||||
. Select the *Send Notification* and *Send Message* scopes.
|
||||
. Click *Create*.
|
||||
. Copy the generated token so you can paste it into your HipChat account
|
||||
configuration in `elasticsearch.yml`.
|
||||
+
|
||||
image::images/hipchat-copy-room-token.jpg[]
|
||||
|
||||
To configure a HipChat account that uses the `user` profile:
|
||||
|
||||
. Set the `type` to `user`.
|
||||
. Set `user` to the email address associated with the {watcher} user.
|
||||
. Set `auth_token` to the {watcher} user's authentication token.
|
||||
|
||||
For example, the following configuration creates an account called
|
||||
`notify-monitoring` that sends messages to the `monitoring` room:
|
||||
|
||||
[source,shell]
|
||||
--------------------------------------------------
|
||||
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
|
||||
--------------------------------------------------
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.notification.hipchat:
|
||||
account:
|
||||
notify-monitoring:
|
||||
profile: user
|
||||
--------------------------------------------------
|
||||
|
||||
You can also specify defaults for the <{ref}/notification-settings.html#hipchat-account-attributes[
|
||||
message attributes]:
|
||||
|
||||
[source,shell]
|
||||
--------------------------------------------------
|
||||
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
|
||||
--------------------------------------------------
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.notification.hipchat:
|
||||
account:
|
||||
notify-monitoring:
|
||||
profile: user
|
||||
message:
|
||||
format: text
|
||||
color: blue
|
||||
notify: true
|
||||
--------------------------------------------------
|
||||
|
||||
|
||||
[[hipchat-api-v1]]
|
||||
===== Using the HipChat v1 Profile
|
||||
|
||||
You can use the `v1` profile to send messages to particular rooms. When you set
|
||||
an account's profile to `v1`, messages are sent through HipChat's v1
|
||||
https://www.hipchat.com/docs/api/method/rooms/message[rooms/message] API.
|
||||
|
||||
WARNING: The `v1` profile uses a deprecated API that is expected to be removed
|
||||
by HipChat in the future.
|
||||
|
||||
The `v1` profile only supports sending messages to rooms, it does not support
|
||||
sending private messages. Use the <<hipchat-api-user, `user`>> profile to send
|
||||
private messages to HipChat users.
|
||||
|
||||
Before you can configure a `v1` account, you need to generate a `v1` API token:
|
||||
|
||||
. Log in to your HipChat server as a group admin.
|
||||
. Go to `https://<hipchat-server>/admin/api`. For example,
|
||||
`https://hipchat.com/admin/api`.
|
||||
. Confirm your admin password.
|
||||
. Select the *Notification* type.
|
||||
+
|
||||
image::images/hipchat-generate-v1-token.jpg[]
|
||||
. Enter a name for the token in the *Label* field.
|
||||
. Click *Create*.
|
||||
. Copy the generated token so you can paste it into your HipChat account
|
||||
configuration in `elasticsearch.yml`.
|
||||
+
|
||||
image::images/hipchat-copy-v1-token.jpg[]
|
||||
|
||||
To configure a HipChat account that uses the `v1` profile:
|
||||
|
||||
. Set the `type` to `v1`.
|
||||
. Set `auth_token` to the v1 authentication token you generated.
|
||||
|
||||
For example, the following configuration creates an account called
|
||||
`notify-monitoring`:
|
||||
|
||||
[source,shell]
|
||||
--------------------------------------------------
|
||||
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
|
||||
--------------------------------------------------
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.notification.hipchat:
|
||||
account:
|
||||
notify-monitoring:
|
||||
profile: v1
|
||||
--------------------------------------------------
|
||||
|
||||
You can also specify defaults for the {ref}/notification-settings.html#hipchat-account-attributes[
|
||||
message attributes].
|
||||
|
||||
[source,yaml]
|
||||
--------------------------------------------------
|
||||
xpack.notification.hipchat:
|
||||
account:
|
||||
notify-monitoring:
|
||||
profile: v1
|
||||
message:
|
||||
format: text
|
||||
color: blue
|
||||
notify: true
|
||||
--------------------------------------------------
|
|
@ -202,7 +202,7 @@ Actions are associated with a watch and are executed as part of the watch execut
|
|||
only when the watch condition is met.
|
||||
|
||||
{watcher} supports the following action types: <<actions-email, email>>,
|
||||
<<actions-slack, slack>>, <<actions-hipchat, hipchat>>, <<actions-pagerduty, pagerduty>>,
|
||||
<<actions-slack, slack>>, <<actions-pagerduty, pagerduty>>,
|
||||
<<actions-index, index>>, <<actions-logging, logging>>, and <<actions-webhook, webhook>>.
|
||||
|
||||
To use the `email` action, you need to <<configuring-email, configure an email account>>
|
||||
|
|
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 147 KiB |
|
@ -333,63 +333,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"hipchat" : {
|
||||
"type": "object",
|
||||
"dynamic": true,
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"sent_messages": {
|
||||
"type": "nested",
|
||||
"include_in_parent": true,
|
||||
"dynamic": true,
|
||||
"properties": {
|
||||
"status": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"reason": {
|
||||
"type": "text"
|
||||
},
|
||||
"request" : {
|
||||
"type" : "object",
|
||||
"enabled" : false
|
||||
},
|
||||
"response" : {
|
||||
"type" : "object",
|
||||
"enabled" : false
|
||||
},
|
||||
"room" : {
|
||||
"type": "keyword"
|
||||
},
|
||||
"user" : {
|
||||
"type": "keyword"
|
||||
},
|
||||
"message" : {
|
||||
"type" : "object",
|
||||
"dynamic" : true,
|
||||
"properties" : {
|
||||
"message_format" : {
|
||||
"type" : "keyword"
|
||||
},
|
||||
"color" : {
|
||||
"type" : "keyword"
|
||||
},
|
||||
"notify" : {
|
||||
"type" : "boolean"
|
||||
},
|
||||
"message" : {
|
||||
"type" : "text"
|
||||
},
|
||||
"from" : {
|
||||
"type" : "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"jira" : {
|
||||
"type": "object",
|
||||
"dynamic": true,
|
||||
|
|
|
@ -82,8 +82,6 @@ import org.elasticsearch.xpack.core.watcher.trigger.TriggerEvent;
|
|||
import org.elasticsearch.xpack.core.watcher.watch.Watch;
|
||||
import org.elasticsearch.xpack.watcher.actions.email.EmailAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.email.EmailActionFactory;
|
||||
import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatActionFactory;
|
||||
import org.elasticsearch.xpack.watcher.actions.index.IndexAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.index.IndexActionFactory;
|
||||
import org.elasticsearch.xpack.watcher.actions.jira.JiraAction;
|
||||
|
@ -135,7 +133,6 @@ import org.elasticsearch.xpack.watcher.notification.email.attachment.EmailAttach
|
|||
import org.elasticsearch.xpack.watcher.notification.email.attachment.HttpEmailAttachementParser;
|
||||
import org.elasticsearch.xpack.watcher.notification.email.attachment.ReportingAttachmentParser;
|
||||
import org.elasticsearch.xpack.watcher.notification.email.support.BodyPartSource;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatService;
|
||||
import org.elasticsearch.xpack.watcher.notification.jira.JiraService;
|
||||
import org.elasticsearch.xpack.watcher.notification.pagerduty.PagerDutyService;
|
||||
import org.elasticsearch.xpack.watcher.notification.slack.SlackService;
|
||||
|
@ -277,13 +274,11 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
|
|||
|
||||
// notification
|
||||
EmailService emailService = new EmailService(settings, cryptoService, clusterService.getClusterSettings());
|
||||
HipChatService hipChatService = new HipChatService(settings, httpClient, clusterService.getClusterSettings());
|
||||
JiraService jiraService = new JiraService(settings, httpClient, clusterService.getClusterSettings());
|
||||
SlackService slackService = new SlackService(settings, httpClient, clusterService.getClusterSettings());
|
||||
PagerDutyService pagerDutyService = new PagerDutyService(settings, httpClient, clusterService.getClusterSettings());
|
||||
|
||||
reloadableServices.add(emailService);
|
||||
reloadableServices.add(hipChatService);
|
||||
reloadableServices.add(jiraService);
|
||||
reloadableServices.add(slackService);
|
||||
reloadableServices.add(pagerDutyService);
|
||||
|
@ -315,7 +310,6 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
|
|||
actionFactoryMap.put(WebhookAction.TYPE, new WebhookActionFactory(httpClient, templateEngine));
|
||||
actionFactoryMap.put(IndexAction.TYPE, new IndexActionFactory(settings, client));
|
||||
actionFactoryMap.put(LoggingAction.TYPE, new LoggingActionFactory(templateEngine));
|
||||
actionFactoryMap.put(HipChatAction.TYPE, new HipChatActionFactory(templateEngine, hipChatService));
|
||||
actionFactoryMap.put(JiraAction.TYPE, new JiraActionFactory(templateEngine, jiraService));
|
||||
actionFactoryMap.put(SlackAction.TYPE, new SlackActionFactory(templateEngine, slackService));
|
||||
actionFactoryMap.put(PagerDutyAction.TYPE, new PagerDutyActionFactory(templateEngine, pagerDutyService));
|
||||
|
@ -420,7 +414,7 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
|
|||
|
||||
return Arrays.asList(registry, inputRegistry, historyStore, triggerService, triggeredWatchParser,
|
||||
watcherLifeCycleService, executionService, triggerEngineListener, watcherService, watchParser,
|
||||
configuredTriggerEngine, triggeredWatchStore, watcherSearchTemplateService, slackService, pagerDutyService, hipChatService);
|
||||
configuredTriggerEngine, triggeredWatchStore, watcherSearchTemplateService, slackService, pagerDutyService);
|
||||
}
|
||||
|
||||
protected TriggerEngine getTriggerEngine(Clock clock, ScheduleRegistry scheduleRegistry) {
|
||||
|
@ -481,7 +475,6 @@ public class Watcher extends Plugin implements ActionPlugin, ScriptPlugin, Reloa
|
|||
settings.addAll(SlackService.getSettings());
|
||||
settings.addAll(EmailService.getSettings());
|
||||
settings.addAll(HtmlSanitizer.getSettings());
|
||||
settings.addAll(HipChatService.getSettings());
|
||||
settings.addAll(JiraService.getSettings());
|
||||
settings.addAll(PagerDutyService.getSettings());
|
||||
settings.add(ReportingAttachmentParser.RETRIES_SETTING);
|
||||
|
|
|
@ -6,19 +6,18 @@
|
|||
package org.elasticsearch.xpack.watcher.actions;
|
||||
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.notification.email.EmailTemplate;
|
||||
import org.elasticsearch.xpack.watcher.notification.pagerduty.IncidentEvent;
|
||||
import org.elasticsearch.xpack.watcher.notification.slack.message.SlackMessage;
|
||||
import org.elasticsearch.xpack.watcher.actions.email.EmailAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.index.IndexAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.jira.JiraAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.logging.LoggingAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.pagerduty.PagerDutyAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.slack.SlackAction;
|
||||
import org.elasticsearch.xpack.watcher.actions.webhook.WebhookAction;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequestTemplate;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.notification.email.EmailTemplate;
|
||||
import org.elasticsearch.xpack.watcher.notification.pagerduty.IncidentEvent;
|
||||
import org.elasticsearch.xpack.watcher.notification.slack.message.SlackMessage;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -63,22 +62,6 @@ public final class ActionBuilders {
|
|||
return LoggingAction.builder(text);
|
||||
}
|
||||
|
||||
public static HipChatAction.Builder hipchatAction(String message) {
|
||||
return hipchatAction(new TextTemplate(message));
|
||||
}
|
||||
|
||||
public static HipChatAction.Builder hipchatAction(String account, String body) {
|
||||
return hipchatAction(account, new TextTemplate(body));
|
||||
}
|
||||
|
||||
public static HipChatAction.Builder hipchatAction(TextTemplate body) {
|
||||
return hipchatAction(null, body);
|
||||
}
|
||||
|
||||
public static HipChatAction.Builder hipchatAction(String account, TextTemplate body) {
|
||||
return HipChatAction.builder(account, body);
|
||||
}
|
||||
|
||||
public static SlackAction.Builder slackAction(String account, SlackMessage.Template.Builder message) {
|
||||
return slackAction(account, message.build());
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.actions.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.xpack.core.watcher.actions.Action;
|
||||
import org.elasticsearch.xpack.core.watcher.actions.ExecutableAction;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Payload;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatAccount;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatService;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.SentMessages;
|
||||
import org.elasticsearch.xpack.watcher.support.Variables;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ExecutableHipChatAction extends ExecutableAction<HipChatAction> {
|
||||
|
||||
private final TextTemplateEngine templateEngine;
|
||||
private final HipChatService hipchatService;
|
||||
|
||||
public ExecutableHipChatAction(HipChatAction action, Logger logger, HipChatService hipchatService,
|
||||
TextTemplateEngine templateEngine) {
|
||||
super(action, logger);
|
||||
this.hipchatService = hipchatService;
|
||||
this.templateEngine = templateEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action.Result execute(final String actionId, WatchExecutionContext ctx, Payload payload) throws Exception {
|
||||
|
||||
HipChatAccount account = hipchatService.getAccount(action.account);
|
||||
// lets validate the message again, in case the hipchat service were updated since the
|
||||
// watch/action were created.
|
||||
account.validateParsedTemplate(ctx.id().watchId(), actionId, action.message);
|
||||
|
||||
Map<String, Object> model = Variables.createCtxParamsMap(ctx, payload);
|
||||
HipChatMessage message = account.render(ctx.id().watchId(), actionId, templateEngine, action.message, model);
|
||||
|
||||
if (ctx.simulateAction(actionId)) {
|
||||
return new HipChatAction.Result.Simulated(message);
|
||||
}
|
||||
|
||||
SentMessages sentMessages = account.send(message, action.proxy);
|
||||
return new HipChatAction.Result.Executed(sentMessages);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.actions.hipchat;
|
||||
|
||||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.xpack.core.watcher.actions.Action;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.SentMessages;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class HipChatAction implements Action {
|
||||
|
||||
public static final String TYPE = "hipchat";
|
||||
|
||||
@Nullable final String account;
|
||||
@Nullable final HttpProxy proxy;
|
||||
final HipChatMessage.Template message;
|
||||
|
||||
public HipChatAction(@Nullable String account, HipChatMessage.Template message, @Nullable HttpProxy proxy) {
|
||||
this.account = account;
|
||||
this.message = message;
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
HipChatAction that = (HipChatAction) o;
|
||||
|
||||
return Objects.equals(account, that.account) &&
|
||||
Objects.equals(message, that.message) &&
|
||||
Objects.equals(proxy, that.proxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(account, message, proxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
if (account != null) {
|
||||
builder.field(Field.ACCOUNT.getPreferredName(), account);
|
||||
}
|
||||
if (proxy != null) {
|
||||
proxy.toXContent(builder, params);
|
||||
}
|
||||
builder.field(Field.MESSAGE.getPreferredName(), message);
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
public static HipChatAction parse(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
String account = null;
|
||||
HipChatMessage.Template message = null;
|
||||
HttpProxy proxy = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (Field.ACCOUNT.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
if (token == XContentParser.Token.VALUE_STRING) {
|
||||
account = parser.text();
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] action [{}/{}]. expected [{}] to be of type string, but " +
|
||||
"found [{}] instead", TYPE, watchId, actionId, Field.ACCOUNT.getPreferredName(), token);
|
||||
}
|
||||
} else if (Field.PROXY.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
proxy = HttpProxy.parse(parser);
|
||||
} else if (Field.MESSAGE.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
try {
|
||||
message = HipChatMessage.Template.parse(parser);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] action [{}/{}]. failed to parse [{}] field", e, TYPE,
|
||||
watchId, actionId, Field.MESSAGE.getPreferredName());
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] action [{}/{}]. unexpected token [{}]", TYPE, watchId,
|
||||
actionId, token);
|
||||
}
|
||||
}
|
||||
|
||||
if (message == null) {
|
||||
throw new ElasticsearchParseException("failed to parse [{}] action [{}/{}]. missing required [{}] field", TYPE, watchId,
|
||||
actionId, Field.MESSAGE.getPreferredName());
|
||||
}
|
||||
|
||||
return new HipChatAction(account, message, proxy);
|
||||
}
|
||||
|
||||
public static Builder builder(String account, TextTemplate body) {
|
||||
return new Builder(account, body);
|
||||
}
|
||||
|
||||
public interface Result {
|
||||
|
||||
class Executed extends Action.Result implements Result {
|
||||
|
||||
private final SentMessages sentMessages;
|
||||
|
||||
public Executed(SentMessages sentMessages) {
|
||||
super(TYPE, status(sentMessages));
|
||||
this.sentMessages = sentMessages;
|
||||
}
|
||||
|
||||
public SentMessages sentMessages() {
|
||||
return sentMessages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.field(type, sentMessages, params);
|
||||
}
|
||||
|
||||
static Status status(SentMessages sentMessages) {
|
||||
boolean hasSuccesses = false;
|
||||
boolean hasFailures = false;
|
||||
for (SentMessages.SentMessage message : sentMessages) {
|
||||
if (message.isSuccess()) {
|
||||
hasSuccesses = true;
|
||||
} else {
|
||||
hasFailures = true;
|
||||
}
|
||||
if (hasFailures && hasSuccesses) {
|
||||
return Status.PARTIAL_FAILURE;
|
||||
}
|
||||
}
|
||||
return hasFailures ? Status.FAILURE : Status.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
class Simulated extends Action.Result implements Result {
|
||||
|
||||
private final HipChatMessage message;
|
||||
|
||||
protected Simulated(HipChatMessage message) {
|
||||
super(TYPE, Status.SIMULATED);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public HipChatMessage getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.startObject(type)
|
||||
.field(Field.MESSAGE.getPreferredName(), message, params)
|
||||
.endObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder implements Action.Builder<HipChatAction> {
|
||||
|
||||
final String account;
|
||||
final HipChatMessage.Template.Builder messageBuilder;
|
||||
private HttpProxy proxy;
|
||||
|
||||
public Builder(String account, TextTemplate body) {
|
||||
this.account = account;
|
||||
this.messageBuilder = new HipChatMessage.Template.Builder(body);
|
||||
}
|
||||
|
||||
public Builder addRooms(TextTemplate... rooms) {
|
||||
messageBuilder.addRooms(rooms);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addRooms(String... rooms) {
|
||||
TextTemplate[] templates = new TextTemplate[rooms.length];
|
||||
for (int i = 0; i < rooms.length; i++) {
|
||||
templates[i] = new TextTemplate(rooms[i]);
|
||||
}
|
||||
return addRooms(templates);
|
||||
}
|
||||
|
||||
|
||||
public Builder addUsers(TextTemplate... users) {
|
||||
messageBuilder.addUsers(users);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addUsers(String... users) {
|
||||
TextTemplate[] templates = new TextTemplate[users.length];
|
||||
for (int i = 0; i < users.length; i++) {
|
||||
templates[i] = new TextTemplate(users[i]);
|
||||
}
|
||||
return addUsers(templates);
|
||||
}
|
||||
|
||||
public Builder setFrom(String from) {
|
||||
messageBuilder.setFrom(from);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFormat(HipChatMessage.Format format) {
|
||||
messageBuilder.setFormat(format);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setColor(TextTemplate color) {
|
||||
messageBuilder.setColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setColor(HipChatMessage.Color color) {
|
||||
return setColor(color.asTemplate());
|
||||
}
|
||||
|
||||
public Builder setNotify(boolean notify) {
|
||||
messageBuilder.setNotify(notify);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setProxy(HttpProxy proxy) {
|
||||
this.proxy = proxy;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HipChatAction build() {
|
||||
return new HipChatAction(account, messageBuilder.build(), proxy);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Field {
|
||||
ParseField ACCOUNT = new ParseField("account");
|
||||
ParseField MESSAGE = new ParseField("message");
|
||||
ParseField PROXY = new ParseField("proxy");
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.actions.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.xpack.core.watcher.actions.ActionFactory;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatAccount;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class HipChatActionFactory extends ActionFactory {
|
||||
|
||||
private final TextTemplateEngine templateEngine;
|
||||
private final HipChatService hipchatService;
|
||||
|
||||
public HipChatActionFactory(TextTemplateEngine templateEngine, HipChatService hipchatService) {
|
||||
super(LogManager.getLogger(ExecutableHipChatAction.class));
|
||||
this.templateEngine = templateEngine;
|
||||
this.hipchatService = hipchatService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableHipChatAction parseExecutable(String watchId, String actionId, XContentParser parser) throws IOException {
|
||||
HipChatAction action = HipChatAction.parse(watchId, actionId, parser);
|
||||
HipChatAccount account = hipchatService.getAccount(action.account);
|
||||
account.validateParsedTemplate(watchId, actionId, action.message);
|
||||
return new ExecutableHipChatAction(action, actionLogger, hipchatService, templateEngine);
|
||||
}
|
||||
}
|
|
@ -300,7 +300,7 @@ public class HttpClient implements Closeable {
|
|||
Scheme.parse(HttpSettings.PROXY_SCHEME.get(settings)) : Scheme.HTTP;
|
||||
int proxyPort = HttpSettings.PROXY_PORT.get(settings);
|
||||
if (proxyPort != 0 && Strings.hasText(proxyHost)) {
|
||||
logger.info("Using default proxy for http input and slack/hipchat/pagerduty/webhook actions [{}:{}]", proxyHost, proxyPort);
|
||||
logger.info("Using default proxy for http input and slack/pagerduty/webhook actions [{}:{}]", proxyHost, proxyPort);
|
||||
} else if (proxyPort != 0 ^ Strings.hasText(proxyHost)) {
|
||||
throw new IllegalArgumentException("HTTP proxy requires both settings: [" + HttpSettings.PROXY_HOST.getKey() + "] and [" +
|
||||
HttpSettings.PROXY_PORT.getKey() + "]");
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.SecureSetting;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class HipChatAccount {
|
||||
|
||||
public static final String ROOM_SETTING = HipChatMessage.Field.ROOM.getPreferredName();
|
||||
public static final String DEFAULT_ROOM_SETTING = "message_defaults." + HipChatMessage.Field.ROOM.getPreferredName();
|
||||
public static final String DEFAULT_USER_SETTING = "message_defaults." + HipChatMessage.Field.USER.getPreferredName();
|
||||
public static final String DEFAULT_FROM_SETTING = "message_defaults." + HipChatMessage.Field.FROM.getPreferredName();
|
||||
public static final String DEFAULT_FORMAT_SETTING = "message_defaults." + HipChatMessage.Field.FORMAT.getPreferredName();
|
||||
public static final String DEFAULT_COLOR_SETTING = "message_defaults." + HipChatMessage.Field.COLOR.getPreferredName();
|
||||
public static final String DEFAULT_NOTIFY_SETTING = "message_defaults." + HipChatMessage.Field.NOTIFY.getPreferredName();
|
||||
|
||||
static final Setting<SecureString> SECURE_AUTH_TOKEN_SETTING = SecureSetting.secureString("secure_auth_token", null);
|
||||
|
||||
protected final Logger logger;
|
||||
protected final String name;
|
||||
protected final Profile profile;
|
||||
protected final HipChatServer server;
|
||||
protected final HttpClient httpClient;
|
||||
protected final String authToken;
|
||||
|
||||
protected HipChatAccount(String name, Profile profile, Settings settings, HipChatServer defaultServer, HttpClient httpClient,
|
||||
Logger logger) {
|
||||
this.name = name;
|
||||
this.profile = profile;
|
||||
this.server = new HipChatServer(settings, defaultServer);
|
||||
this.httpClient = httpClient;
|
||||
this.authToken = getAuthToken(name, settings);
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private static String getAuthToken(String name, Settings settings) {
|
||||
SecureString secureString = SECURE_AUTH_TOKEN_SETTING.get(settings);
|
||||
if (secureString == null || secureString.length() < 1) {
|
||||
throw new SettingsException(
|
||||
"hipchat account [" + name + "] missing required [" + SECURE_AUTH_TOKEN_SETTING.getKey() + "] secure setting");
|
||||
}
|
||||
return secureString.toString();
|
||||
}
|
||||
|
||||
public abstract String type();
|
||||
|
||||
public abstract void validateParsedTemplate(String watchId, String actionId, HipChatMessage.Template message) throws SettingsException;
|
||||
|
||||
public abstract HipChatMessage render(String watchId, String actionId, TextTemplateEngine engine, HipChatMessage.Template template,
|
||||
Map<String, Object> model);
|
||||
|
||||
public abstract SentMessages send(HipChatMessage message, @Nullable HttpProxy proxy);
|
||||
|
||||
public enum Profile {
|
||||
|
||||
V1() {
|
||||
@Override
|
||||
HipChatAccount createAccount(String name, Settings settings, HipChatServer defaultServer, HttpClient httpClient,
|
||||
Logger logger) {
|
||||
return new V1Account(name, settings, defaultServer, httpClient, logger);
|
||||
}
|
||||
},
|
||||
INTEGRATION() {
|
||||
@Override
|
||||
HipChatAccount createAccount(String name, Settings settings, HipChatServer defaultServer, HttpClient httpClient,
|
||||
Logger logger) {
|
||||
return new IntegrationAccount(name, settings, defaultServer, httpClient, logger);
|
||||
}
|
||||
},
|
||||
USER() {
|
||||
@Override
|
||||
HipChatAccount createAccount(String name, Settings settings, HipChatServer defaultServer, HttpClient httpClient,
|
||||
Logger logger) {
|
||||
return new UserAccount(name, settings, defaultServer, httpClient, logger);
|
||||
}
|
||||
};
|
||||
|
||||
abstract HipChatAccount createAccount(String name, Settings settings, HipChatServer defaultServer, HttpClient httpClient,
|
||||
Logger logger);
|
||||
|
||||
public String value() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public static Profile parse(XContentParser parser) throws IOException {
|
||||
return Profile.valueOf(parser.text().toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public static Profile resolve(String value, Profile defaultValue) {
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Profile.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public static Profile resolve(Settings settings, String setting, Profile defaultValue) {
|
||||
return resolve(settings.get(setting), defaultValue);
|
||||
}
|
||||
|
||||
public static boolean validate(String value) {
|
||||
try {
|
||||
Profile.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
return true;
|
||||
} catch (IllegalArgumentException ilae) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,457 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
public class HipChatMessage implements ToXContentObject {
|
||||
|
||||
final String body;
|
||||
@Nullable final String[] rooms;
|
||||
@Nullable final String[] users;
|
||||
@Nullable final String from;
|
||||
@Nullable final Format format;
|
||||
@Nullable final Color color;
|
||||
@Nullable final Boolean notify;
|
||||
|
||||
public HipChatMessage(String body, String[] rooms, String[] users, String from, Format format, Color color, Boolean notify) {
|
||||
this.body = body;
|
||||
this.rooms = rooms;
|
||||
this.users = users;
|
||||
this.from = from;
|
||||
this.format = format;
|
||||
this.color = color;
|
||||
this.notify = notify;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public String[] getRooms() {
|
||||
return rooms;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String[] getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Format getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Boolean getNotify() {
|
||||
return notify;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
HipChatMessage that = (HipChatMessage) o;
|
||||
return Objects.equals(body, that.body) &&
|
||||
Objects.deepEquals(rooms, that.rooms) &&
|
||||
Objects.deepEquals(users, that.users) &&
|
||||
Objects.equals(from, that.from) &&
|
||||
Objects.equals(format, that.format) &&
|
||||
Objects.equals(color, that.color) &&
|
||||
Objects.equals(notify, that.notify);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = body.hashCode();
|
||||
result = 31 * result + (rooms != null ? Arrays.hashCode(rooms) : 0);
|
||||
result = 31 * result + (users != null ? Arrays.hashCode(users) : 0);
|
||||
result = 31 * result + (from != null ? from.hashCode() : 0);
|
||||
result = 31 * result + (format != null ? format.hashCode() : 0);
|
||||
result = 31 * result + (color != null ? color.hashCode() : 0);
|
||||
result = 31 * result + (notify != null ? notify.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return toXContent(builder, params, true);
|
||||
}
|
||||
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params, boolean includeTargets) throws IOException {
|
||||
builder.startObject();
|
||||
if (from != null) {
|
||||
builder.field(Field.FROM.getPreferredName(), from);
|
||||
}
|
||||
if (includeTargets) {
|
||||
if (rooms != null && rooms.length > 0) {
|
||||
builder.array(Field.ROOM.getPreferredName(), rooms);
|
||||
}
|
||||
if (users != null && users.length > 0) {
|
||||
builder.array(Field.USER.getPreferredName(), users);
|
||||
}
|
||||
}
|
||||
builder.field(Field.BODY.getPreferredName(), body);
|
||||
if (format != null) {
|
||||
builder.field(Field.FORMAT.getPreferredName(), format.value());
|
||||
}
|
||||
if (color != null) {
|
||||
builder.field(Field.COLOR.getPreferredName(), color.value());
|
||||
}
|
||||
if (notify != null) {
|
||||
builder.field(Field.NOTIFY.getPreferredName(), notify);
|
||||
}
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
public static class Template implements ToXContentObject {
|
||||
|
||||
final TextTemplate body;
|
||||
@Nullable final TextTemplate[] rooms;
|
||||
@Nullable final TextTemplate[] users;
|
||||
@Nullable final String from;
|
||||
@Nullable final Format format;
|
||||
@Nullable final TextTemplate color;
|
||||
@Nullable final Boolean notify;
|
||||
|
||||
public Template(TextTemplate body,
|
||||
TextTemplate[] rooms,
|
||||
TextTemplate[] users,
|
||||
String from,
|
||||
Format format,
|
||||
TextTemplate color,
|
||||
Boolean notify) {
|
||||
this.rooms = rooms;
|
||||
this.users = users;
|
||||
this.body = body;
|
||||
this.from = from;
|
||||
this.format = format;
|
||||
this.color = color;
|
||||
this.notify = notify;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Template template = (Template) o;
|
||||
|
||||
return Objects.equals(body, template.body) &&
|
||||
Objects.deepEquals(rooms, template.rooms) &&
|
||||
Objects.deepEquals(users, template.users) &&
|
||||
Objects.equals(from, template.from) &&
|
||||
Objects.equals(format, template.format) &&
|
||||
Objects.equals(color, template.color) &&
|
||||
Objects.equals(notify, template.notify);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(body, rooms, users, from, format, color, notify);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
if (from != null) {
|
||||
builder.field(Field.FROM.getPreferredName(), from);
|
||||
}
|
||||
if (rooms != null && rooms.length > 0) {
|
||||
builder.startArray(Field.ROOM.getPreferredName());
|
||||
for (TextTemplate room : rooms) {
|
||||
room.toXContent(builder, params);
|
||||
}
|
||||
builder.endArray();
|
||||
}
|
||||
if (users != null && users.length > 0) {
|
||||
builder.startArray(Field.USER.getPreferredName());
|
||||
for (TextTemplate user : users) {
|
||||
user.toXContent(builder, params);
|
||||
}
|
||||
builder.endArray();
|
||||
}
|
||||
builder.field(Field.BODY.getPreferredName(), body, params);
|
||||
if (format != null) {
|
||||
builder.field(Field.FORMAT.getPreferredName(), format.value());
|
||||
}
|
||||
if (color != null) {
|
||||
builder.field(Field.COLOR.getPreferredName(), color, params);
|
||||
}
|
||||
if (notify != null) {
|
||||
builder.field(Field.NOTIFY.getPreferredName(), notify);
|
||||
}
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
public static Template parse(XContentParser parser) throws IOException {
|
||||
TextTemplate body = null;
|
||||
TextTemplate[] rooms = null;
|
||||
TextTemplate[] users = null;
|
||||
String from = null;
|
||||
TextTemplate color = null;
|
||||
Boolean notify = null;
|
||||
HipChatMessage.Format messageFormat = null;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (Field.FROM.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
from = parser.text();
|
||||
} else if (Field.ROOM.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
List<TextTemplate> templates = new ArrayList<>();
|
||||
if (token == XContentParser.Token.START_ARRAY) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
try {
|
||||
templates.add(TextTemplate.parse(parser));
|
||||
} catch (ElasticsearchParseException epe) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field", epe,
|
||||
Field.ROOM.getPreferredName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
templates.add(TextTemplate.parse(parser));
|
||||
} catch (ElasticsearchParseException epe) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field", epe,
|
||||
Field.ROOM.getPreferredName());
|
||||
}
|
||||
}
|
||||
rooms = templates.toArray(new TextTemplate[templates.size()]);
|
||||
} else if (Field.USER.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
List<TextTemplate> templates = new ArrayList<>();
|
||||
if (token == XContentParser.Token.START_ARRAY) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
try {
|
||||
templates.add(TextTemplate.parse(parser));
|
||||
} catch (ElasticsearchParseException epe) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field", epe,
|
||||
Field.USER.getPreferredName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
templates.add(TextTemplate.parse(parser));
|
||||
} catch (ElasticsearchParseException epe) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field", epe,
|
||||
Field.USER.getPreferredName());
|
||||
}
|
||||
}
|
||||
users = templates.toArray(new TextTemplate[templates.size()]);
|
||||
} else if (Field.COLOR.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
try {
|
||||
color = TextTemplate.parse(parser);
|
||||
} catch (ElasticsearchParseException | IllegalArgumentException e) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field", e,
|
||||
Field.COLOR.getPreferredName());
|
||||
}
|
||||
} else if (Field.NOTIFY.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
if (token == XContentParser.Token.VALUE_BOOLEAN) {
|
||||
notify = parser.booleanValue();
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field, expected a " +
|
||||
"boolean value but found [{}]", Field.NOTIFY.getPreferredName(), token);
|
||||
}
|
||||
} else if (Field.BODY.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
try {
|
||||
body = TextTemplate.parse(parser);
|
||||
} catch (ElasticsearchParseException pe) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field", pe,
|
||||
Field.BODY.getPreferredName());
|
||||
}
|
||||
} else if (Field.FORMAT.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
try {
|
||||
messageFormat = HipChatMessage.Format.parse(parser);
|
||||
} catch (IllegalArgumentException ilae) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. failed to parse [{}] field", ilae,
|
||||
Field.FORMAT.getPreferredName());
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. unexpected field [{}]", currentFieldName);
|
||||
}
|
||||
}
|
||||
|
||||
if (body == null) {
|
||||
throw new ElasticsearchParseException("failed to parse hipchat message. missing required [{}] field",
|
||||
Field.BODY.getPreferredName());
|
||||
}
|
||||
|
||||
return new HipChatMessage.Template(body, rooms, users, from, messageFormat, color, notify);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
final TextTemplate body;
|
||||
final List<TextTemplate> rooms = new ArrayList<>();
|
||||
final List<TextTemplate> users = new ArrayList<>();
|
||||
@Nullable String from;
|
||||
@Nullable Format format;
|
||||
@Nullable TextTemplate color;
|
||||
@Nullable Boolean notify;
|
||||
|
||||
public Builder(TextTemplate body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public Builder addRooms(TextTemplate... rooms) {
|
||||
this.rooms.addAll(Arrays.asList(rooms));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addUsers(TextTemplate... users) {
|
||||
this.users.addAll(Arrays.asList(users));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFrom(String from) {
|
||||
this.from = from;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFormat(Format format) {
|
||||
this.format = format;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setColor(TextTemplate color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNotify(boolean notify) {
|
||||
this.notify = notify;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Template build() {
|
||||
return new Template(
|
||||
body,
|
||||
rooms.isEmpty() ? null : rooms.toArray(new TextTemplate[rooms.size()]),
|
||||
users.isEmpty() ? null : users.toArray(new TextTemplate[users.size()]),
|
||||
from,
|
||||
format,
|
||||
color,
|
||||
notify);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum Color {
|
||||
YELLOW, GREEN, RED, PURPLE, GRAY, RANDOM;
|
||||
|
||||
private final TextTemplate template = new TextTemplate(name());
|
||||
|
||||
public TextTemplate asTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public static Color parse(XContentParser parser) throws IOException {
|
||||
return Color.valueOf(parser.text().toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public static Color resolve(String value, Color defaultValue) {
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Color.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public static Color resolve(Settings settings, String setting, Color defaultValue) {
|
||||
return resolve(settings.get(setting), defaultValue);
|
||||
}
|
||||
|
||||
public static boolean validate(String value) {
|
||||
try {
|
||||
Color.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
return true;
|
||||
} catch (IllegalArgumentException ilae) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Format {
|
||||
|
||||
TEXT,
|
||||
HTML;
|
||||
|
||||
private final TextTemplate template = new TextTemplate(name());
|
||||
|
||||
public TextTemplate asTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public static Format parse(XContentParser parser) throws IOException {
|
||||
return Format.valueOf(parser.text().toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public static Format resolve(String value, Format defaultValue) {
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Format.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public static Format resolve(Settings settings, String setting, Format defaultValue) {
|
||||
return resolve(settings.get(setting), defaultValue);
|
||||
}
|
||||
|
||||
public static boolean validate(String value) {
|
||||
try {
|
||||
Format.valueOf(value.toUpperCase(Locale.ROOT));
|
||||
return true;
|
||||
} catch (IllegalArgumentException ilae) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Field {
|
||||
ParseField ROOM = new ParseField("room");
|
||||
ParseField USER = new ParseField("user");
|
||||
ParseField BODY = new ParseField("body");
|
||||
ParseField FROM = new ParseField("from");
|
||||
ParseField COLOR = new ParseField("color");
|
||||
ParseField NOTIFY = new ParseField("notify");
|
||||
ParseField FORMAT = new ParseField("format");
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
|
||||
public class HipChatServer {
|
||||
|
||||
public static final String HOST_SETTING = "host";
|
||||
public static final String PORT_SETTING = "port";
|
||||
|
||||
public static final HipChatServer DEFAULT = new HipChatServer("api.hipchat.com", 443, null);
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final HipChatServer fallback;
|
||||
|
||||
public HipChatServer(Settings settings) {
|
||||
this(settings, DEFAULT);
|
||||
}
|
||||
|
||||
public HipChatServer(Settings settings, HipChatServer fallback) {
|
||||
this(settings.get(HOST_SETTING, null), settings.getAsInt(PORT_SETTING, -1), fallback);
|
||||
}
|
||||
|
||||
public HipChatServer(String host, int port, HipChatServer fallback) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.fallback = fallback;
|
||||
}
|
||||
|
||||
public String host() {
|
||||
return host != null ? host : fallback.host();
|
||||
}
|
||||
|
||||
public int port() {
|
||||
return port > 0 ? port : fallback.port();
|
||||
}
|
||||
|
||||
public HipChatServer fallback() {
|
||||
return fallback != null ? fallback : DEFAULT;
|
||||
}
|
||||
|
||||
public HipChatServer rebuild(Settings settings, HipChatServer fallback) {
|
||||
return new HipChatServer(settings.get(HOST_SETTING, host), settings.getAsInt(PORT_SETTING, port), fallback);
|
||||
}
|
||||
|
||||
public synchronized HttpRequest.Builder httpRequest() {
|
||||
return HttpRequest.builder(host(), port());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.SecureSetting;
|
||||
import org.elasticsearch.common.settings.SecureString;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.notification.NotificationService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A component to store hipchat credentials.
|
||||
*/
|
||||
public class HipChatService extends NotificationService<HipChatAccount> {
|
||||
|
||||
private static final Setting<String> SETTING_DEFAULT_ACCOUNT =
|
||||
Setting.simpleString("xpack.notification.hipchat.default_account", Setting.Property.Dynamic, Setting.Property.NodeScope);
|
||||
|
||||
static final Setting<String> SETTING_DEFAULT_HOST =
|
||||
Setting.simpleString("xpack.notification.hipchat.host", Setting.Property.Dynamic, Setting.Property.NodeScope);
|
||||
|
||||
static final Setting<Integer> SETTING_DEFAULT_PORT =
|
||||
Setting.intSetting("xpack.notification.hipchat.port", 443, Setting.Property.Dynamic, Setting.Property.NodeScope);
|
||||
|
||||
private static final Setting.AffixSetting<SecureString> SETTING_AUTH_TOKEN_SECURE =
|
||||
Setting.affixKeySetting("xpack.notification.hipchat.account.", "secure_auth_token",
|
||||
(key) -> SecureSetting.secureString(key, null));
|
||||
|
||||
private static final Setting.AffixSetting<String> SETTING_PROFILE =
|
||||
Setting.affixKeySetting("xpack.notification.hipchat.account.", "profile",
|
||||
(key) -> Setting.simpleString(key, Setting.Property.Dynamic, Setting.Property.NodeScope));
|
||||
|
||||
private static final Setting.AffixSetting<String> SETTING_ROOM =
|
||||
Setting.affixKeySetting("xpack.notification.hipchat.account.", "room",
|
||||
(key) -> Setting.simpleString(key, Setting.Property.Dynamic, Setting.Property.NodeScope));
|
||||
|
||||
private static final Setting.AffixSetting<String> SETTING_HOST =
|
||||
Setting.affixKeySetting("xpack.notification.hipchat.account.", "host",
|
||||
(key) -> Setting.simpleString(key, Setting.Property.Dynamic, Setting.Property.NodeScope));
|
||||
|
||||
private static final Setting.AffixSetting<Integer> SETTING_PORT =
|
||||
Setting.affixKeySetting("xpack.notification.hipchat.account.", "port",
|
||||
(key) -> Setting.intSetting(key, 443, Setting.Property.Dynamic, Setting.Property.NodeScope));
|
||||
|
||||
private static final Setting.AffixSetting<Settings> SETTING_MESSAGE_DEFAULTS =
|
||||
Setting.affixKeySetting("xpack.notification.hipchat.account.", "message",
|
||||
(key) -> Setting.groupSetting(key + ".", Setting.Property.Dynamic, Setting.Property.NodeScope));
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(HipChatService.class);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private HipChatServer defaultServer;
|
||||
|
||||
public HipChatService(Settings settings, HttpClient httpClient, ClusterSettings clusterSettings) {
|
||||
super("hipchat", settings, clusterSettings, HipChatService.getDynamicSettings(), HipChatService.getSecureSettings());
|
||||
this.httpClient = httpClient;
|
||||
// ensure logging of setting changes
|
||||
clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_ACCOUNT, (s) -> {});
|
||||
clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_HOST, (s) -> {});
|
||||
clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_PORT, (s) -> {});
|
||||
clusterSettings.addAffixUpdateConsumer(SETTING_PROFILE, (s, o) -> {}, (s, o) -> {});
|
||||
clusterSettings.addAffixUpdateConsumer(SETTING_ROOM, (s, o) -> {}, (s, o) -> {});
|
||||
clusterSettings.addAffixUpdateConsumer(SETTING_HOST, (s, o) -> {}, (s, o) -> {});
|
||||
clusterSettings.addAffixUpdateConsumer(SETTING_PORT, (s, o) -> {}, (s, o) -> {});
|
||||
clusterSettings.addAffixUpdateConsumer(SETTING_MESSAGE_DEFAULTS, (s, o) -> {}, (s, o) -> {});
|
||||
// do an initial load
|
||||
reload(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reload(Settings settings) {
|
||||
defaultServer = new HipChatServer(settings.getByPrefix("xpack.notification.hipchat."));
|
||||
super.reload(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HipChatAccount createAccount(String name, Settings accountSettings) {
|
||||
HipChatAccount.Profile profile = HipChatAccount.Profile.resolve(accountSettings, "profile", null);
|
||||
if (profile == null) {
|
||||
throw new SettingsException("missing [profile] setting for hipchat account [" + name + "]");
|
||||
}
|
||||
return profile.createAccount(name, accountSettings, defaultServer, httpClient, logger);
|
||||
}
|
||||
|
||||
private static List<Setting<?>> getDynamicSettings() {
|
||||
return Arrays.asList(SETTING_DEFAULT_ACCOUNT, SETTING_PROFILE, SETTING_ROOM, SETTING_MESSAGE_DEFAULTS,
|
||||
SETTING_DEFAULT_HOST, SETTING_DEFAULT_PORT, SETTING_HOST, SETTING_PORT);
|
||||
}
|
||||
|
||||
private static List<Setting<?>> getSecureSettings() {
|
||||
return Arrays.asList(SETTING_AUTH_TOKEN_SECURE);
|
||||
}
|
||||
|
||||
public static List<Setting<?>> getSettings() {
|
||||
List<Setting<?>> allSettings = new ArrayList<Setting<?>>(getDynamicSettings());
|
||||
allSettings.addAll(getSecureSettings());
|
||||
return allSettings;
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatAction;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.http.Scheme;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage.Color;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage.Format;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class IntegrationAccount extends HipChatAccount {
|
||||
|
||||
public static final String TYPE = "integration";
|
||||
|
||||
final String room;
|
||||
final Defaults defaults;
|
||||
|
||||
public IntegrationAccount(String name, Settings settings, HipChatServer defaultServer, HttpClient httpClient, Logger logger) {
|
||||
super(name, Profile.INTEGRATION, settings, defaultServer, httpClient, logger);
|
||||
List<String> rooms = settings.getAsList(ROOM_SETTING, null);
|
||||
if (rooms == null || rooms.isEmpty()) {
|
||||
throw new SettingsException("invalid hipchat account [" + name + "]. missing required [" + ROOM_SETTING + "] setting for [" +
|
||||
TYPE + "] account profile");
|
||||
}
|
||||
if (rooms.size() > 1) {
|
||||
throw new SettingsException("invalid hipchat account [" + name + "]. [" + ROOM_SETTING + "] setting for [" + TYPE + "] " +
|
||||
"account must only be set with a single value");
|
||||
}
|
||||
this.room = rooms.get(0);
|
||||
defaults = new Defaults(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateParsedTemplate(String watchId, String actionId, HipChatMessage.Template template) throws SettingsException {
|
||||
if (template.rooms != null) {
|
||||
throw new ElasticsearchParseException("invalid [" + HipChatAction.TYPE + "] action for [" + watchId + "/" + actionId + "] " +
|
||||
"action. [" + name + "] hipchat account doesn't support custom rooms");
|
||||
}
|
||||
if (template.users != null) {
|
||||
throw new ElasticsearchParseException("invalid [" + HipChatAction.TYPE + "] action for [" + watchId + "/" + actionId + "] " +
|
||||
"action. [" + name + "] hipchat account doesn't support user private messages");
|
||||
}
|
||||
if (template.from != null) {
|
||||
throw new ElasticsearchParseException("invalid [" + HipChatAction.TYPE + "] action for [" + watchId + "/" + actionId + "] " +
|
||||
"action. [" + name + "] hipchat account doesn't support custom `from` fields");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HipChatMessage render(String watchId, String actionId, TextTemplateEngine engine, HipChatMessage.Template template,
|
||||
Map<String, Object> model) {
|
||||
String message = engine.render(template.body, model);
|
||||
Color color = template.color != null ? Color.resolve(engine.render(template.color, model), defaults.color) : defaults.color;
|
||||
Boolean notify = template.notify != null ? template.notify : defaults.notify;
|
||||
Format messageFormat = template.format != null ? template.format : defaults.format;
|
||||
return new HipChatMessage(message, null, null, null, messageFormat, color, notify);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SentMessages send(HipChatMessage message, @Nullable HttpProxy proxy) {
|
||||
List<SentMessages.SentMessage> sentMessages = new ArrayList<>();
|
||||
HttpRequest request = buildRoomRequest(room, message, proxy);
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
sentMessages.add(SentMessages.SentMessage.responded(room, SentMessages.SentMessage.TargetType.ROOM, message, request,
|
||||
response));
|
||||
} catch (Exception e) {
|
||||
sentMessages.add(SentMessages.SentMessage.error(room, SentMessages.SentMessage.TargetType.ROOM, message, e));
|
||||
}
|
||||
return new SentMessages(name, sentMessages);
|
||||
}
|
||||
|
||||
private HttpRequest buildRoomRequest(String room, final HipChatMessage message, HttpProxy proxy) {
|
||||
String urlEncodedRoom = HttpRequest.encodeUrl(room);
|
||||
HttpRequest.Builder builder = server.httpRequest()
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v2/room/" + urlEncodedRoom + "/notification")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer " + authToken)
|
||||
.body(Strings.toString((xbuilder, params) -> {
|
||||
xbuilder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
xbuilder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
xbuilder.field("notify", message.notify);
|
||||
}
|
||||
if (message.color != null) {
|
||||
xbuilder.field("color", String.valueOf(message.color.value()));
|
||||
}
|
||||
return xbuilder;
|
||||
}));
|
||||
if (proxy != null) {
|
||||
builder.proxy(proxy);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static class Defaults {
|
||||
|
||||
@Nullable final Format format;
|
||||
@Nullable final Color color;
|
||||
@Nullable final Boolean notify;
|
||||
|
||||
Defaults(Settings settings) {
|
||||
this.format = Format.resolve(settings, DEFAULT_FORMAT_SETTING, null);
|
||||
this.color = Color.resolve(settings, DEFAULT_COLOR_SETTING, null);
|
||||
this.notify = settings.getAsBoolean(DEFAULT_NOTIFY_SETTING, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherParams;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class SentMessages implements ToXContentObject, Iterable<SentMessages.SentMessage> {
|
||||
|
||||
private static final ParseField ACCOUNT = new ParseField("account");
|
||||
private static final ParseField SENT_MESSAGES = new ParseField("sent_messages");
|
||||
|
||||
private String accountName;
|
||||
private List<SentMessage> messages;
|
||||
|
||||
public SentMessages(String accountName, List<SentMessage> messages) {
|
||||
this.accountName = accountName;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return accountName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<SentMessage> iterator() {
|
||||
return messages.iterator();
|
||||
}
|
||||
|
||||
public int count() {
|
||||
return messages.size();
|
||||
}
|
||||
|
||||
public List<SentMessage> asList() {
|
||||
return Collections.unmodifiableList(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(ACCOUNT.getPreferredName(), accountName);
|
||||
builder.startArray(SENT_MESSAGES.getPreferredName());
|
||||
for (SentMessage message : messages) {
|
||||
message.toXContent(builder, params);
|
||||
}
|
||||
builder.endArray();
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
public static class SentMessage implements ToXContentObject {
|
||||
|
||||
private static final ParseField STATUS = new ParseField("status");
|
||||
private static final ParseField REQUEST = new ParseField("request");
|
||||
private static final ParseField RESPONSE = new ParseField("response");
|
||||
private static final ParseField MESSAGE = new ParseField("message");
|
||||
|
||||
public enum TargetType {
|
||||
ROOM, USER;
|
||||
|
||||
final String fieldName = new String(name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
final String targetName;
|
||||
final TargetType targetType;
|
||||
final HipChatMessage message;
|
||||
@Nullable final HttpRequest request;
|
||||
@Nullable final HttpResponse response;
|
||||
@Nullable final Exception exception;
|
||||
|
||||
public static SentMessage responded(String targetName, TargetType targetType, HipChatMessage message, HttpRequest request,
|
||||
HttpResponse response) {
|
||||
return new SentMessage(targetName, targetType, message, request, response, null);
|
||||
}
|
||||
|
||||
public static SentMessage error(String targetName, TargetType targetType, HipChatMessage message, Exception e) {
|
||||
return new SentMessage(targetName, targetType, message, null, null, e);
|
||||
}
|
||||
|
||||
private SentMessage(String targetName, TargetType targetType, HipChatMessage message, HttpRequest request, HttpResponse response,
|
||||
Exception exception) {
|
||||
this.targetName = targetName;
|
||||
this.targetType = targetType;
|
||||
this.message = message;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public HttpRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
public HttpResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return response != null && response.status() >= 200 && response.status() < 300;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
boolean success = isSuccess();
|
||||
builder.field(STATUS.getPreferredName(), success ? "success" : "failure");
|
||||
if (success == false) {
|
||||
if (request != null) {
|
||||
if (WatcherParams.hideSecrets(params)) {
|
||||
// this writes out the request to the byte array output stream with the correct excludes for hipchat
|
||||
try (InputStream is = HttpRequest.filterToXContent(request, builder.contentType().xContent(),
|
||||
params, "params.auth_token")) {
|
||||
builder.rawField(REQUEST.getPreferredName(), is, builder.contentType());
|
||||
}
|
||||
} else {
|
||||
builder.field(REQUEST.getPreferredName());
|
||||
request.toXContent(builder, params);
|
||||
}
|
||||
}
|
||||
if (response != null) {
|
||||
builder.field(RESPONSE.getPreferredName());
|
||||
response.toXContent(builder, params);
|
||||
}
|
||||
if (exception != null) {
|
||||
ElasticsearchException.generateFailureXContent(builder, params, exception, true);
|
||||
}
|
||||
}
|
||||
builder.field(targetType.fieldName, targetName);
|
||||
builder.field(MESSAGE.getPreferredName());
|
||||
message.toXContent(builder, params, false);
|
||||
return builder.endObject();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.http.Scheme;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage.Color;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage.Format;
|
||||
import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatAction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class UserAccount extends HipChatAccount {
|
||||
|
||||
public static final String TYPE = "user";
|
||||
|
||||
final Defaults defaults;
|
||||
|
||||
public UserAccount(String name, Settings settings, HipChatServer defaultServer, HttpClient httpClient, Logger logger) {
|
||||
super(name, Profile.USER, settings, defaultServer, httpClient, logger);
|
||||
defaults = new Defaults(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateParsedTemplate(String watchId, String actionId, HipChatMessage.Template template) throws SettingsException {
|
||||
if (template.from != null) {
|
||||
throw new ElasticsearchParseException("invalid [" + HipChatAction.TYPE + "] action for [" + watchId + "/" + actionId + "]. ["
|
||||
+ name + "] hipchat account doesn't support custom `from` fields");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HipChatMessage render(String watchId, String actionId, TextTemplateEngine engine, HipChatMessage.Template template,
|
||||
Map<String, Object> model) {
|
||||
String[] rooms = defaults.rooms;
|
||||
if (template.rooms != null) {
|
||||
rooms = new String[template.rooms.length];
|
||||
for (int i = 0; i < template.rooms.length; i++) {
|
||||
rooms[i] = engine.render(template.rooms[i], model);
|
||||
}
|
||||
}
|
||||
String[] users = defaults.users;
|
||||
if (template.users != null) {
|
||||
users = new String[template.users.length];
|
||||
for (int i = 0; i < template.users.length; i++) {
|
||||
users[i] = engine.render(template.users[i], model);
|
||||
}
|
||||
}
|
||||
String message = engine.render(template.body, model);
|
||||
Color color = Color.resolve(engine.render(template.color, model), defaults.color);
|
||||
Boolean notify = template.notify != null ? template.notify : defaults.notify;
|
||||
Format messageFormat = template.format != null ? template.format : defaults.format;
|
||||
return new HipChatMessage(message, rooms, users, null, messageFormat, color, notify);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SentMessages send(HipChatMessage message, HttpProxy proxy) {
|
||||
List<SentMessages.SentMessage> sentMessages = new ArrayList<>();
|
||||
if (message.rooms != null) {
|
||||
for (String room : message.rooms) {
|
||||
HttpRequest request = buildRoomRequest(room, message, proxy);
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
sentMessages.add(SentMessages.SentMessage.responded(room, SentMessages.SentMessage.TargetType.ROOM, message, request,
|
||||
response));
|
||||
} catch (IOException e) {
|
||||
logger.error("failed to execute hipchat api http request", e);
|
||||
sentMessages.add(SentMessages.SentMessage.error(room, SentMessages.SentMessage.TargetType.ROOM, message, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (message.users != null) {
|
||||
for (String user : message.users) {
|
||||
HttpRequest request = buildUserRequest(user, message, proxy);
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
sentMessages.add(SentMessages.SentMessage.responded(user, SentMessages.SentMessage.TargetType.USER, message, request,
|
||||
response));
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to execute hipchat api http request", e);
|
||||
sentMessages.add(SentMessages.SentMessage.error(user, SentMessages.SentMessage.TargetType.USER, message, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SentMessages(name, sentMessages);
|
||||
}
|
||||
|
||||
public HttpRequest buildRoomRequest(String room, final HipChatMessage message, HttpProxy proxy) {
|
||||
String urlEncodedRoom = encodeRoom(room);
|
||||
HttpRequest.Builder builder = server.httpRequest()
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v2/room/" + urlEncodedRoom + "/notification")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer " + authToken)
|
||||
.body(Strings.toString((xbuilder, params) -> {
|
||||
xbuilder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
xbuilder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
xbuilder.field("notify", message.notify);
|
||||
}
|
||||
if (message.color != null) {
|
||||
xbuilder.field("color", String.valueOf(message.color.value()));
|
||||
}
|
||||
return xbuilder;
|
||||
}));
|
||||
if (proxy != null) {
|
||||
builder.proxy(proxy);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
// this specific hipchat API does not accept application-form encoding, but requires real URL encoding
|
||||
// spaces must not be replaced with a plus, but rather with %20
|
||||
// this workaround ensures, that this happens
|
||||
private String encodeRoom(String text) {
|
||||
try {
|
||||
return new URI("//", "", "", text, null).getRawQuery();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException("failed to URL encode text [" + text + "]", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public HttpRequest buildUserRequest(String user, final HipChatMessage message, HttpProxy proxy) {
|
||||
HttpRequest.Builder builder = server.httpRequest()
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v2/user/" + user + "/message")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer " + authToken)
|
||||
.body(Strings.toString((xbuilder, params) -> {
|
||||
xbuilder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
xbuilder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
xbuilder.field("notify", message.notify);
|
||||
}
|
||||
return xbuilder;
|
||||
}));
|
||||
if (proxy != null) {
|
||||
builder.proxy(proxy);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static class Defaults {
|
||||
|
||||
@Nullable final String[] rooms;
|
||||
@Nullable final String[] users;
|
||||
@Nullable final Format format;
|
||||
@Nullable final Color color;
|
||||
@Nullable final Boolean notify;
|
||||
|
||||
Defaults(Settings settings) {
|
||||
List<String> rooms = settings.getAsList(DEFAULT_ROOM_SETTING, null);
|
||||
this.rooms = rooms == null ? null : rooms.toArray(Strings.EMPTY_ARRAY);
|
||||
List<String> users = settings.getAsList(DEFAULT_USER_SETTING, null);
|
||||
this.users = users == null ? null : users.toArray(Strings.EMPTY_ARRAY);
|
||||
this.format = Format.resolve(settings, DEFAULT_FORMAT_SETTING, null);
|
||||
this.color = Color.resolve(settings, DEFAULT_COLOR_SETTING, null);
|
||||
this.notify = settings.getAsBoolean(DEFAULT_NOTIFY_SETTING, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.http.Scheme;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage.Color;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage.Format;
|
||||
import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatAction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class V1Account extends HipChatAccount {
|
||||
|
||||
public static final String TYPE = "v1";
|
||||
|
||||
final Defaults defaults;
|
||||
|
||||
public V1Account(String name, Settings settings, HipChatServer defaultServer, HttpClient httpClient, Logger logger) {
|
||||
super(name, Profile.V1, settings, defaultServer, httpClient, logger);
|
||||
defaults = new Defaults(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateParsedTemplate(String watchId, String actionId,
|
||||
HipChatMessage.Template template) throws ElasticsearchParseException {
|
||||
if (template.users != null) {
|
||||
throw new ElasticsearchParseException("invalid [" + HipChatAction.TYPE + "] action for [" + watchId + "/" + actionId + "]. ["
|
||||
+ name + "] hipchat account doesn't support user private messaging");
|
||||
}
|
||||
if ((template.rooms == null || template.rooms.length == 0) && (defaults.rooms == null || defaults.rooms.length == 0)) {
|
||||
throw new ElasticsearchParseException("invalid [" + HipChatAction.TYPE + "] action for [" + watchId + "/" + actionId + "]. " +
|
||||
"missing required [" + HipChatMessage.Field.ROOM + "] field for [" + name + "] hipchat account");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HipChatMessage render(String watchId, String actionId, TextTemplateEngine engine, HipChatMessage.Template template,
|
||||
Map<String, Object> model) {
|
||||
String message = engine.render(template.body, model);
|
||||
String[] rooms = defaults.rooms;
|
||||
if (template.rooms != null) {
|
||||
rooms = new String[template.rooms.length];
|
||||
for (int i = 0; i < template.rooms.length; i++) {
|
||||
rooms[i] = engine.render(template.rooms[i], model);
|
||||
}
|
||||
}
|
||||
String from = template.from != null ? template.from : defaults.from != null ? defaults.from : watchId;
|
||||
Color color = Color.resolve(engine.render(template.color, model), defaults.color);
|
||||
Boolean notify = template.notify != null ? template.notify : defaults.notify;
|
||||
Format messageFormat = template.format != null ? template.format : defaults.format;
|
||||
return new HipChatMessage(message, rooms, null, from, messageFormat, color, notify);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SentMessages send(HipChatMessage message, @Nullable HttpProxy proxy) {
|
||||
List<SentMessages.SentMessage> sentMessages = new ArrayList<>();
|
||||
if (message.rooms != null) {
|
||||
for (String room : message.rooms) {
|
||||
HttpRequest request = buildRoomRequest(room, message, proxy);
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
sentMessages.add(SentMessages.SentMessage.responded(room, SentMessages.SentMessage.TargetType.ROOM, message, request,
|
||||
response));
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to execute hipchat api http request", e);
|
||||
sentMessages.add(SentMessages.SentMessage.error(room, SentMessages.SentMessage.TargetType.ROOM, message, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SentMessages(name, sentMessages);
|
||||
}
|
||||
|
||||
public HttpRequest buildRoomRequest(String room, HipChatMessage message, HttpProxy proxy) {
|
||||
HttpRequest.Builder builder = server.httpRequest();
|
||||
builder.method(HttpMethod.POST);
|
||||
builder.scheme(Scheme.HTTPS);
|
||||
builder.path("/v1/rooms/message");
|
||||
builder.setHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
builder.setParam("format", "json");
|
||||
builder.setParam("auth_token", authToken);
|
||||
if (proxy != null) {
|
||||
builder.proxy(proxy);
|
||||
}
|
||||
StringBuilder body = new StringBuilder();
|
||||
body.append("room_id=").append(HttpRequest.encodeUrl(room));
|
||||
body.append("&from=").append(HttpRequest.encodeUrl(message.from));
|
||||
body.append("&message=").append(HttpRequest.encodeUrl(message.body));
|
||||
if (message.format != null) {
|
||||
body.append("&message_format=").append(message.format.value());
|
||||
}
|
||||
if (message.color != null) {
|
||||
body.append("&color=").append(message.color.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
body.append("¬ify=").append(message.notify ? "1" : "0");
|
||||
}
|
||||
builder.body(body.toString());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static class Defaults {
|
||||
|
||||
@Nullable final String[] rooms;
|
||||
@Nullable final String from;
|
||||
@Nullable final Format format;
|
||||
@Nullable final Color color;
|
||||
@Nullable final Boolean notify;
|
||||
|
||||
Defaults(Settings settings) {
|
||||
List<String> rooms = settings.getAsList(DEFAULT_ROOM_SETTING, null);
|
||||
this.rooms = rooms == null ? null : rooms.toArray(Strings.EMPTY_ARRAY);
|
||||
this.from = settings.get(DEFAULT_FROM_SETTING);
|
||||
this.format = Format.resolve(settings, DEFAULT_FORMAT_SETTING, null);
|
||||
this.color = Color.resolve(settings, DEFAULT_COLOR_SETTING, null);
|
||||
this.notify = settings.getAsBoolean(DEFAULT_NOTIFY_SETTING, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.actions.hipchat;
|
||||
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatAccount;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatService;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.hipchatAction;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class HipChatActionFactoryTests extends ESTestCase {
|
||||
private HipChatActionFactory factory;
|
||||
private HipChatService hipchatService;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
hipchatService = mock(HipChatService.class);
|
||||
factory = new HipChatActionFactory(mock(TextTemplateEngine.class), hipchatService);
|
||||
}
|
||||
|
||||
public void testParseAction() throws Exception {
|
||||
HipChatAccount account = mock(HipChatAccount.class);
|
||||
when(hipchatService.getAccount("_account1")).thenReturn(account);
|
||||
|
||||
HipChatAction action = hipchatAction("_account1", "_body").build();
|
||||
XContentBuilder jsonBuilder = jsonBuilder().value(action);
|
||||
XContentParser parser = createParser(jsonBuilder);
|
||||
parser.nextToken();
|
||||
|
||||
ExecutableHipChatAction parsedAction = factory.parseExecutable("_w1", "_a1", parser);
|
||||
assertThat(parsedAction.action(), is(action));
|
||||
|
||||
verify(account, times(1)).validateParsedTemplate("_w1", "_a1", action.message);
|
||||
}
|
||||
|
||||
public void testParseActionUnknownAccount() throws Exception {
|
||||
hipchatService = new HipChatService(Settings.EMPTY, null, new ClusterSettings(Settings.EMPTY,
|
||||
new HashSet<>(HipChatService.getSettings())));
|
||||
factory = new HipChatActionFactory(mock(TextTemplateEngine.class), hipchatService);
|
||||
HipChatAction action = hipchatAction("_unknown", "_body").build();
|
||||
XContentBuilder jsonBuilder = jsonBuilder().value(action);
|
||||
XContentParser parser = createParser(jsonBuilder);
|
||||
parser.nextToken();
|
||||
expectThrows(IllegalArgumentException.class, () -> factory.parseExecutable("_w1", "_a1", parser));
|
||||
}
|
||||
}
|
|
@ -1,296 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.actions.hipchat;
|
||||
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.script.JodaCompatibleZonedDateTime;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.watcher.actions.Action;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.core.watcher.execution.Wid;
|
||||
import org.elasticsearch.xpack.core.watcher.watch.Payload;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatAccount;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatService;
|
||||
import org.elasticsearch.xpack.watcher.notification.hipchat.SentMessages;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContextBuilder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class HipChatActionTests extends ESTestCase {
|
||||
private HipChatService service;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
service = mock(HipChatService.class);
|
||||
}
|
||||
|
||||
public void testExecute() throws Exception {
|
||||
final String accountName = "account1";
|
||||
|
||||
TextTemplateEngine templateEngine = mock(TextTemplateEngine.class);
|
||||
|
||||
TextTemplate body = new TextTemplate("_body");
|
||||
HipChatMessage.Template.Builder messageBuilder = new HipChatMessage.Template.Builder(body);
|
||||
|
||||
HipChatMessage.Template messageTemplate = messageBuilder.build();
|
||||
|
||||
HipChatAction action = new HipChatAction(accountName, messageTemplate, null);
|
||||
ExecutableHipChatAction executable = new ExecutableHipChatAction(action, logger, service, templateEngine);
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
Payload payload = new Payload.Simple(data);
|
||||
|
||||
Map<String, Object> metadata = MapBuilder.<String, Object>newMapBuilder().put("_key", "_val").map();
|
||||
|
||||
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
|
||||
JodaCompatibleZonedDateTime jodaJavaNow = new JodaCompatibleZonedDateTime(now.toInstant(), ZoneOffset.UTC);
|
||||
|
||||
Wid wid = new Wid(randomAlphaOfLength(5), now);
|
||||
WatchExecutionContext ctx = mockExecutionContextBuilder(wid.watchId())
|
||||
.wid(wid)
|
||||
.payload(payload)
|
||||
.time(wid.watchId(), now)
|
||||
.metadata(metadata)
|
||||
.buildMock();
|
||||
|
||||
Map<String, Object> triggerModel = new HashMap<>();
|
||||
triggerModel.put("triggered_time", jodaJavaNow);
|
||||
triggerModel.put("scheduled_time", jodaJavaNow);
|
||||
Map<String, Object> ctxModel = new HashMap<>();
|
||||
ctxModel.put("id", ctx.id().value());
|
||||
ctxModel.put("watch_id", wid.watchId());
|
||||
ctxModel.put("payload", data);
|
||||
ctxModel.put("metadata", metadata);
|
||||
ctxModel.put("execution_time", jodaJavaNow);
|
||||
ctxModel.put("trigger", triggerModel);
|
||||
ctxModel.put("vars", Collections.emptyMap());
|
||||
Map<String, Object> expectedModel = singletonMap("ctx", ctxModel);
|
||||
|
||||
if (body != null) {
|
||||
when(templateEngine.render(body, expectedModel)).thenReturn(body.getTemplate());
|
||||
}
|
||||
|
||||
String[] rooms = new String[] { "_r1" };
|
||||
HipChatMessage message = new HipChatMessage(body.getTemplate(), rooms, null, null, null, null, null);
|
||||
HipChatAccount account = mock(HipChatAccount.class);
|
||||
when(account.render(wid.watchId(), "_id", templateEngine, messageTemplate, expectedModel)).thenReturn(message);
|
||||
boolean responseFailure = randomBoolean();
|
||||
HttpResponse response = new HttpResponse(responseFailure ? 404 : 200);
|
||||
HttpRequest request = HttpRequest.builder("localhost", 12345).path("/").build();
|
||||
SentMessages sentMessages = new SentMessages(accountName, Arrays.asList(
|
||||
SentMessages.SentMessage.responded("_r1", SentMessages.SentMessage.TargetType.ROOM, message, request, response)
|
||||
));
|
||||
when(account.send(message, null)).thenReturn(sentMessages);
|
||||
when(service.getAccount(accountName)).thenReturn(account);
|
||||
|
||||
Action.Result result = executable.execute("_id", ctx, payload);
|
||||
|
||||
assertThat(result, notNullValue());
|
||||
assertThat(result, instanceOf(HipChatAction.Result.Executed.class));
|
||||
if (responseFailure) {
|
||||
assertThat(result.status(), equalTo(Action.Result.Status.FAILURE));
|
||||
} else {
|
||||
assertThat(result.status(), equalTo(Action.Result.Status.SUCCESS));
|
||||
}
|
||||
assertThat(((HipChatAction.Result.Executed) result).sentMessages(), sameInstance(sentMessages));
|
||||
assertValidToXContent(result);
|
||||
}
|
||||
|
||||
public void testParser() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject();
|
||||
|
||||
String accountName = randomAlphaOfLength(10);
|
||||
builder.field("account", accountName);
|
||||
builder.startObject("message");
|
||||
|
||||
TextTemplate body = new TextTemplate("_body");
|
||||
builder.field("body", body);
|
||||
|
||||
TextTemplate[] rooms = null;
|
||||
if (randomBoolean()) {
|
||||
TextTemplate r1 = new TextTemplate("_r1");
|
||||
TextTemplate r2 = new TextTemplate("_r2");
|
||||
rooms = new TextTemplate[] { r1, r2 };
|
||||
builder.array("room", r1, r2);
|
||||
}
|
||||
TextTemplate[] users = null;
|
||||
if (randomBoolean()) {
|
||||
TextTemplate u1 = new TextTemplate("_u1");
|
||||
TextTemplate u2 = new TextTemplate("_u2");
|
||||
users = new TextTemplate[] { u1, u2 };
|
||||
builder.array("user", u1, u2);
|
||||
}
|
||||
String from = null;
|
||||
if (randomBoolean()) {
|
||||
from = randomAlphaOfLength(10);
|
||||
builder.field("from", from);
|
||||
}
|
||||
HipChatMessage.Format format = null;
|
||||
if (randomBoolean()) {
|
||||
format = randomFrom(HipChatMessage.Format.values());
|
||||
builder.field("format", format.value());
|
||||
}
|
||||
TextTemplate color = null;
|
||||
if (randomBoolean()) {
|
||||
color = new TextTemplate(randomFrom(HipChatMessage.Color.values()).value());
|
||||
builder.field("color", color);
|
||||
}
|
||||
Boolean notify = null;
|
||||
if (randomBoolean()) {
|
||||
notify = randomBoolean();
|
||||
builder.field("notify", notify);
|
||||
}
|
||||
builder.endObject();
|
||||
HttpProxy proxy = null;
|
||||
if (randomBoolean()) {
|
||||
proxy = new HttpProxy("localhost", 8080);
|
||||
builder.startObject("proxy").field("host", "localhost").field("port", 8080).endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
BytesReference bytes = BytesReference.bytes(builder);
|
||||
logger.info("hipchat action json [{}]", bytes.utf8ToString());
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, bytes);
|
||||
parser.nextToken();
|
||||
|
||||
HipChatAction action = HipChatAction.parse("_watch", "_action", parser);
|
||||
|
||||
assertThat(action, notNullValue());
|
||||
assertThat(action.account, is(accountName));
|
||||
assertThat(action.proxy, is(proxy));
|
||||
assertThat(action.message, notNullValue());
|
||||
assertThat(action.message, is(new HipChatMessage.Template(body, rooms, users, from, format, color, notify)));
|
||||
}
|
||||
|
||||
public void testParserSelfGenerated() throws Exception {
|
||||
String accountName = randomAlphaOfLength(10);
|
||||
TextTemplate body = new TextTemplate("_body");
|
||||
HipChatMessage.Template.Builder templateBuilder = new HipChatMessage.Template.Builder(body);
|
||||
|
||||
XContentBuilder builder = jsonBuilder().startObject();
|
||||
builder.field("account", accountName);
|
||||
|
||||
HttpProxy proxy = null;
|
||||
if (randomBoolean()) {
|
||||
proxy = new HttpProxy("localhost", 8080);
|
||||
builder.startObject("proxy").field("host", "localhost").field("port", 8080).endObject();
|
||||
}
|
||||
|
||||
builder.startObject("message");
|
||||
builder.field("body", body);
|
||||
|
||||
if (randomBoolean()) {
|
||||
TextTemplate r1 = new TextTemplate("_r1");
|
||||
TextTemplate r2 = new TextTemplate("_r2");
|
||||
templateBuilder.addRooms(r1, r2);
|
||||
builder.array("room", r1, r2);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
TextTemplate u1 = new TextTemplate("_u1");
|
||||
TextTemplate u2 = new TextTemplate("_u2");
|
||||
templateBuilder.addUsers(u1, u2);
|
||||
builder.array("user", u1, u2);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
String from = randomAlphaOfLength(10);
|
||||
templateBuilder.setFrom(from);
|
||||
builder.field("from", from);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
HipChatMessage.Format format = randomFrom(HipChatMessage.Format.values());
|
||||
templateBuilder.setFormat(format);
|
||||
builder.field("format", format.value());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
TextTemplate color = new TextTemplate(randomFrom(HipChatMessage.Color.values()).value());
|
||||
templateBuilder.setColor(color);
|
||||
builder.field("color", color);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
boolean notify = randomBoolean();
|
||||
templateBuilder.setNotify(notify);
|
||||
builder.field("notify", notify);
|
||||
}
|
||||
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
|
||||
HipChatMessage.Template template = templateBuilder.build();
|
||||
|
||||
HipChatAction action = new HipChatAction(accountName, template, proxy);
|
||||
|
||||
XContentBuilder jsonBuilder = jsonBuilder();
|
||||
action.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
|
||||
BytesReference bytes = BytesReference.bytes(builder);
|
||||
logger.info("{}", bytes.utf8ToString());
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, bytes);
|
||||
parser.nextToken();
|
||||
|
||||
HipChatAction parsedAction = HipChatAction.parse("_watch", "_action", parser);
|
||||
|
||||
assertThat(parsedAction, notNullValue());
|
||||
assertThat(parsedAction, is(action));
|
||||
}
|
||||
|
||||
public void testParserInvalid() throws Exception {
|
||||
XContentBuilder builder = jsonBuilder().startObject().field("unknown_field", "value").endObject();
|
||||
XContentParser parser = createParser(builder);
|
||||
parser.nextToken();
|
||||
try {
|
||||
HipChatAction.parse("_watch", "_action", parser);
|
||||
fail("Expected ElasticsearchParseException");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
assertThat(e.getMessage(), is("failed to parse [hipchat] action [_watch/_action]. unexpected token [VALUE_STRING]"));
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that toXContent can be serialized and read again
|
||||
private void assertValidToXContent(Action.Result result) throws IOException {
|
||||
try (XContentBuilder builder = jsonBuilder()) {
|
||||
builder.startObject();
|
||||
result.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
builder.endObject();
|
||||
Strings.toString(builder);
|
||||
try (XContentParser parser = XContentType.JSON.xContent()
|
||||
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, Strings.toString(builder))) {
|
||||
parser.map();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class HipChatAccountsTests extends ESTestCase {
|
||||
private HttpClient httpClient;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
httpClient = mock(HttpClient.class);
|
||||
}
|
||||
|
||||
public void testProxy() throws Exception {
|
||||
Settings.Builder builder = Settings.builder()
|
||||
.put("xpack.notification.hipchat.default_account", "account1");
|
||||
addAccountSettings("account1", builder);
|
||||
HipChatService service = new HipChatService(builder.build(), httpClient, new ClusterSettings(Settings.EMPTY,
|
||||
new HashSet<>(HipChatService.getSettings())));
|
||||
HipChatAccount account = service.getAccount("account1");
|
||||
|
||||
HipChatMessage hipChatMessage = new HipChatMessage("body", new String[]{"rooms"}, null, "from", null, null, null);
|
||||
|
||||
ArgumentCaptor<HttpRequest> argumentCaptor = ArgumentCaptor.forClass(HttpRequest.class);
|
||||
when(httpClient.execute(argumentCaptor.capture())).thenReturn(new HttpResponse(200));
|
||||
|
||||
HttpProxy proxy = new HttpProxy("localhost", 8080);
|
||||
account.send(hipChatMessage, proxy);
|
||||
|
||||
HttpRequest request = argumentCaptor.getValue();
|
||||
assertThat(request.proxy(), is(proxy));
|
||||
}
|
||||
|
||||
private void addAccountSettings(String name, Settings.Builder builder) {
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString("xpack.notification.hipchat.account." + name + ".secure_auth_token", randomAlphaOfLength(50));
|
||||
HipChatAccount.Profile profile = randomFrom(HipChatAccount.Profile.values());
|
||||
builder.put("xpack.notification.hipchat.account." + name + ".profile", profile.value());
|
||||
builder.setSecureSettings(secureSettings);
|
||||
if (profile == HipChatAccount.Profile.INTEGRATION) {
|
||||
builder.put("xpack.notification.hipchat.account." + name + ".room", randomAlphaOfLength(10));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,325 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.xcontent.DeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.watcher.support.xcontent.WatcherParams;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
public class HipChatMessageTests extends ESTestCase {
|
||||
|
||||
public void testToXContent() throws Exception {
|
||||
String message = randomAlphaOfLength(10);
|
||||
String[] rooms = generateRandomStringArray(3, 10, true);
|
||||
String[] users = generateRandomStringArray(3, 10, true);
|
||||
String from = randomBoolean() ? null : randomAlphaOfLength(10);
|
||||
HipChatMessage.Format format = rarely() ? null : randomFrom(HipChatMessage.Format.values());
|
||||
HipChatMessage.Color color = rarely() ? null : randomFrom(HipChatMessage.Color.values());
|
||||
Boolean notify = rarely() ? null : randomBoolean();
|
||||
HipChatMessage msg = new HipChatMessage(message, rooms, users, from, format, color, notify);
|
||||
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
boolean includeTarget = randomBoolean();
|
||||
if (includeTarget && randomBoolean()) {
|
||||
msg.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
} else {
|
||||
msg.toXContent(builder, ToXContent.EMPTY_PARAMS, includeTarget);
|
||||
}
|
||||
BytesReference bytes = BytesReference.bytes(builder);
|
||||
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, bytes);
|
||||
parser.nextToken();
|
||||
|
||||
assertThat(parser.currentToken(), is(XContentParser.Token.START_OBJECT));
|
||||
|
||||
message = null;
|
||||
rooms = null;
|
||||
users = null;
|
||||
from = null;
|
||||
format = null;
|
||||
color = null;
|
||||
notify = null;
|
||||
XContentParser.Token token = null;
|
||||
String currentFieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if ("body".equals(currentFieldName)) {
|
||||
message = parser.text();
|
||||
} else if ("room".equals(currentFieldName)) {
|
||||
rooms = parser.list().stream().map(Object::toString).toArray(String[]::new);
|
||||
} else if ("user".equals(currentFieldName)) {
|
||||
users = parser.list().stream().map(Object::toString).toArray(String[]::new);
|
||||
} else if ("from".equals(currentFieldName)) {
|
||||
from = parser.text();
|
||||
} else if ("format".equals(currentFieldName)) {
|
||||
format = HipChatMessage.Format.parse(parser);
|
||||
} else if ("color".equals(currentFieldName)) {
|
||||
color = HipChatMessage.Color.parse(parser);
|
||||
} else if ("notify".equals(currentFieldName)) {
|
||||
notify = parser.booleanValue();
|
||||
} else {
|
||||
fail("unexpected xcontent field [" + currentFieldName + "] in hipchat message");
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(message, notNullValue());
|
||||
assertThat(message, is(msg.body));
|
||||
if (includeTarget) {
|
||||
if (msg.rooms == null || msg.rooms.length == 0) {
|
||||
assertThat(rooms, nullValue());
|
||||
} else {
|
||||
assertThat(rooms, arrayContaining(msg.rooms));
|
||||
}
|
||||
if (msg.users == null || msg.users.length == 0) {
|
||||
assertThat(users, nullValue());
|
||||
} else {
|
||||
assertThat(users, arrayContaining(msg.users));
|
||||
}
|
||||
}
|
||||
assertThat(from, is(msg.from));
|
||||
assertThat(format, is(msg.format));
|
||||
assertThat(color, is(msg.color));
|
||||
assertThat(notify, is(msg.notify));
|
||||
}
|
||||
|
||||
public void testEquals() throws Exception {
|
||||
String message = randomAlphaOfLength(10);
|
||||
String[] rooms = generateRandomStringArray(3, 10, true);
|
||||
String[] users = generateRandomStringArray(3, 10, true);
|
||||
String from = randomBoolean() ? null : randomAlphaOfLength(10);
|
||||
HipChatMessage.Format format = rarely() ? null : randomFrom(HipChatMessage.Format.values());
|
||||
HipChatMessage.Color color = rarely() ? null : randomFrom(HipChatMessage.Color.values());
|
||||
Boolean notify = rarely() ? null : randomBoolean();
|
||||
HipChatMessage msg1 = new HipChatMessage(message, rooms, users, from, format, color, notify);
|
||||
|
||||
boolean equals = randomBoolean();
|
||||
if (!equals) {
|
||||
equals = true;
|
||||
if (rarely()) {
|
||||
equals = false;
|
||||
message = "another message";
|
||||
}
|
||||
if (rarely()) {
|
||||
equals = false;
|
||||
rooms = rooms == null ? new String[] { "roomX" } : randomBoolean() ? null : new String[] { "roomX" , "roomY"};
|
||||
}
|
||||
if (rarely()) {
|
||||
equals = false;
|
||||
users = users == null ? new String[] { "userX" } : randomBoolean() ? null : new String[] { "userX", "userY" };
|
||||
}
|
||||
if (rarely()) {
|
||||
equals = false;
|
||||
from = from == null ? "fromX" : randomBoolean() ? null : "fromY";
|
||||
}
|
||||
if (rarely()) {
|
||||
equals = false;
|
||||
format = format == null ?
|
||||
randomFrom(HipChatMessage.Format.values()) :
|
||||
randomBoolean() ?
|
||||
null :
|
||||
randomFromWithExcludes(HipChatMessage.Format.values(), format);
|
||||
}
|
||||
if (rarely()) {
|
||||
equals = false;
|
||||
color = color == null ?
|
||||
randomFrom(HipChatMessage.Color.values()) :
|
||||
randomBoolean() ?
|
||||
null :
|
||||
randomFromWithExcludes(HipChatMessage.Color.values(), color);
|
||||
}
|
||||
if (rarely()) {
|
||||
equals = false;
|
||||
notify = notify == null ? (Boolean) randomBoolean() : randomBoolean() ? null : !notify;
|
||||
}
|
||||
}
|
||||
|
||||
HipChatMessage msg2 = new HipChatMessage(message, rooms, users, from, format, color, notify);
|
||||
assertThat(msg1.equals(msg2), is(equals));
|
||||
}
|
||||
|
||||
public void testTemplateParse() throws Exception {
|
||||
XContentBuilder jsonBuilder = jsonBuilder();
|
||||
jsonBuilder.startObject();
|
||||
|
||||
TextTemplate body = new TextTemplate(randomAlphaOfLength(200));
|
||||
jsonBuilder.field("body", body, ToXContent.EMPTY_PARAMS);
|
||||
TextTemplate[] rooms = null;
|
||||
if (randomBoolean()) {
|
||||
jsonBuilder.startArray("room");
|
||||
rooms = new TextTemplate[randomIntBetween(1, 3)];
|
||||
for (int i = 0; i < rooms.length; i++) {
|
||||
rooms[i] = new TextTemplate(randomAlphaOfLength(10));
|
||||
rooms[i].toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
|
||||
}
|
||||
jsonBuilder.endArray();
|
||||
}
|
||||
TextTemplate[] users = null;
|
||||
if (randomBoolean()) {
|
||||
jsonBuilder.startArray("user");
|
||||
users = new TextTemplate[randomIntBetween(1, 3)];
|
||||
for (int i = 0; i < users.length; i++) {
|
||||
users[i] = new TextTemplate(randomAlphaOfLength(10));
|
||||
users[i].toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
|
||||
}
|
||||
jsonBuilder.endArray();
|
||||
}
|
||||
String from = null;
|
||||
if (randomBoolean()) {
|
||||
from = randomAlphaOfLength(10);
|
||||
jsonBuilder.field("from", from);
|
||||
}
|
||||
TextTemplate color = null;
|
||||
if (randomBoolean()) {
|
||||
color = new TextTemplate(randomAlphaOfLength(10));
|
||||
jsonBuilder.field("color", color, ToXContent.EMPTY_PARAMS);
|
||||
}
|
||||
HipChatMessage.Format format = null;
|
||||
if (randomBoolean()) {
|
||||
format = randomFrom(HipChatMessage.Format.values());
|
||||
jsonBuilder.field("format", format.value());
|
||||
}
|
||||
Boolean notify = null;
|
||||
if (randomBoolean()) {
|
||||
notify = randomBoolean();
|
||||
jsonBuilder.field("notify", notify);
|
||||
}
|
||||
|
||||
BytesReference bytes = BytesReference.bytes(jsonBuilder.endObject());
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, bytes);
|
||||
parser.nextToken();
|
||||
|
||||
HipChatMessage.Template template = HipChatMessage.Template.parse(parser);
|
||||
|
||||
assertThat(template, notNullValue());
|
||||
assertThat(template.body, is(body));
|
||||
if (rooms == null) {
|
||||
assertThat(template.rooms, nullValue());
|
||||
} else {
|
||||
assertThat(template.rooms, arrayContaining(rooms));
|
||||
}
|
||||
if (users == null) {
|
||||
assertThat(template.users, nullValue());
|
||||
} else {
|
||||
assertThat(template.users, arrayContaining(users));
|
||||
}
|
||||
assertThat(template.from, is(from));
|
||||
assertThat(template.color, is(color));
|
||||
assertThat(template.format, is(format));
|
||||
assertThat(template.notify, is(notify));
|
||||
}
|
||||
|
||||
public void testTemplateParseSelfGenerated() throws Exception {
|
||||
TextTemplate body = new TextTemplate(randomAlphaOfLength(10));
|
||||
HipChatMessage.Template.Builder templateBuilder = new HipChatMessage.Template.Builder(body);
|
||||
|
||||
if (randomBoolean()) {
|
||||
int count = randomIntBetween(1, 3);
|
||||
for (int i = 0; i < count; i++) {
|
||||
templateBuilder.addRooms(new TextTemplate(randomAlphaOfLength(10)));
|
||||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
int count = randomIntBetween(1, 3);
|
||||
for (int i = 0; i < count; i++) {
|
||||
templateBuilder.addUsers(new TextTemplate(randomAlphaOfLength(10)));
|
||||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
templateBuilder.setFrom(randomAlphaOfLength(10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
templateBuilder.setColor(new TextTemplate(randomAlphaOfLength(5)));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
templateBuilder.setFormat(randomFrom(HipChatMessage.Format.values()));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
templateBuilder.setNotify(randomBoolean());
|
||||
}
|
||||
HipChatMessage.Template template = templateBuilder.build();
|
||||
|
||||
XContentBuilder jsonBuilder = jsonBuilder();
|
||||
template.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
|
||||
BytesReference bytes = BytesReference.bytes(jsonBuilder);
|
||||
|
||||
XContentParser parser = createParser(JsonXContent.jsonXContent, bytes);
|
||||
parser.nextToken();
|
||||
|
||||
HipChatMessage.Template parsed = HipChatMessage.Template.parse(parser);
|
||||
|
||||
assertThat(parsed, equalTo(template));
|
||||
}
|
||||
|
||||
public void testAuthTokenParamIsFiltered() throws Exception {
|
||||
HttpResponse response = new HttpResponse(500);
|
||||
String token = randomAlphaOfLength(20);
|
||||
HttpRequest request = HttpRequest.builder("localhost", 1234).setParam("auth_token", token).build();
|
||||
|
||||
// String body, String[] rooms, String[] users, String from, Format format, Color color, Boolean notify
|
||||
HipChatMessage hipChatMessage = new HipChatMessage("body", new String[]{"room"}, null, "from",
|
||||
HipChatMessage.Format.TEXT, HipChatMessage.Color.RED, false);
|
||||
SentMessages.SentMessage sentMessage = SentMessages.SentMessage.responded("targetName", SentMessages.SentMessage.TargetType.ROOM,
|
||||
hipChatMessage, request, response);
|
||||
|
||||
|
||||
try (XContentBuilder builder = jsonBuilder()) {
|
||||
WatcherParams params = WatcherParams.builder().hideSecrets(false).build();
|
||||
sentMessage.toXContent(builder, params);
|
||||
assertThat(Strings.toString(builder), containsString(token));
|
||||
|
||||
try (XContentParser parser = builder.contentType().xContent()
|
||||
.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
|
||||
Strings.toString(builder))) {
|
||||
parser.map();
|
||||
}
|
||||
}
|
||||
try (XContentBuilder builder = jsonBuilder()) {
|
||||
sentMessage.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
assertThat(Strings.toString(builder), not(containsString(token)));
|
||||
|
||||
try (XContentParser parser = builder.contentType().xContent()
|
||||
.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
|
||||
Strings.toString(builder))) {
|
||||
parser.map();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static <E extends Enum> E randomFromWithExcludes(E[] values, E... exclude) {
|
||||
List<E> excludes = Arrays.asList(exclude);
|
||||
List<E> includes = new ArrayList<>();
|
||||
for (E value : values) {
|
||||
if (!excludes.contains(value)) {
|
||||
includes.add(value);
|
||||
}
|
||||
}
|
||||
return randomFrom(includes);
|
||||
}
|
||||
}
|
|
@ -1,279 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class HipChatServiceTests extends ESTestCase {
|
||||
private HttpClient httpClient;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
httpClient = mock(HttpClient.class);
|
||||
}
|
||||
|
||||
public void testSingleAccountV1() throws Exception {
|
||||
String accountName = randomAlphaOfLength(10);
|
||||
String host = randomBoolean() ? null : "_host";
|
||||
int port = randomBoolean() ? -1 : randomIntBetween(300, 400);
|
||||
String defaultRoom = randomBoolean() ? null : "_r1, _r2";
|
||||
String defaultFrom = randomBoolean() ? null : "_from";
|
||||
HipChatMessage.Color defaultColor = randomBoolean() ? null : randomFrom(HipChatMessage.Color.values());
|
||||
HipChatMessage.Format defaultFormat = randomBoolean() ? null : randomFrom(HipChatMessage.Format.values());
|
||||
Boolean defaultNotify = randomBoolean() ? null : (Boolean) randomBoolean();
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString("xpack.notification.hipchat.account." + accountName + ".secure_auth_token", "_token");
|
||||
Settings.Builder settingsBuilder = Settings.builder()
|
||||
.put("xpack.notification.hipchat.account." + accountName + ".profile", HipChatAccount.Profile.V1.value())
|
||||
.setSecureSettings(secureSettings);
|
||||
if (host != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + accountName + ".host", host);
|
||||
}
|
||||
if (port > 0) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + accountName + ".port", port);
|
||||
}
|
||||
buildMessageDefaults(accountName, settingsBuilder, defaultRoom, null, defaultFrom, defaultColor, defaultFormat, defaultNotify);
|
||||
HipChatService service = new HipChatService(settingsBuilder.build(), httpClient,
|
||||
new ClusterSettings(settingsBuilder.build(), new HashSet<>(HipChatService.getSettings())));
|
||||
|
||||
HipChatAccount account = service.getAccount(accountName);
|
||||
assertThat(account, notNullValue());
|
||||
assertThat(account.name, is(accountName));
|
||||
assertThat(account.authToken, is("_token"));
|
||||
assertThat(account.profile, is(HipChatAccount.Profile.V1));
|
||||
assertThat(account.httpClient, is(httpClient));
|
||||
assertThat(account.server, notNullValue());
|
||||
assertThat(account.server.host(), is(host != null ? host : HipChatServer.DEFAULT.host()));
|
||||
assertThat(account.server.port(), is(port > 0 ? port : HipChatServer.DEFAULT.port()));
|
||||
assertThat(account, instanceOf(V1Account.class));
|
||||
if (defaultRoom == null) {
|
||||
assertThat(((V1Account) account).defaults.rooms, nullValue());
|
||||
} else {
|
||||
assertThat(((V1Account) account).defaults.rooms, arrayContaining("_r1", "_r2"));
|
||||
}
|
||||
assertThat(((V1Account) account).defaults.from, is(defaultFrom));
|
||||
assertThat(((V1Account) account).defaults.color, is(defaultColor));
|
||||
assertThat(((V1Account) account).defaults.format, is(defaultFormat));
|
||||
assertThat(((V1Account) account).defaults.notify, is(defaultNotify));
|
||||
|
||||
// with a single account defined, making sure that that account is set to the default one.
|
||||
assertThat(service.getAccount(null), sameInstance(account));
|
||||
}
|
||||
|
||||
public void testSingleAccountIntegration() throws Exception {
|
||||
String accountName = randomAlphaOfLength(10);
|
||||
String host = randomBoolean() ? null : "_host";
|
||||
int port = randomBoolean() ? -1 : randomIntBetween(300, 400);
|
||||
String room = randomAlphaOfLength(10);
|
||||
String defaultFrom = randomBoolean() ? null : "_from";
|
||||
HipChatMessage.Color defaultColor = randomBoolean() ? null : randomFrom(HipChatMessage.Color.values());
|
||||
HipChatMessage.Format defaultFormat = randomBoolean() ? null : randomFrom(HipChatMessage.Format.values());
|
||||
Boolean defaultNotify = randomBoolean() ? null : (Boolean) randomBoolean();
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString("xpack.notification.hipchat.account." + accountName + ".secure_auth_token", "_token");
|
||||
Settings.Builder settingsBuilder = Settings.builder()
|
||||
.put("xpack.notification.hipchat.account." + accountName + ".profile",
|
||||
HipChatAccount.Profile.INTEGRATION.value())
|
||||
.setSecureSettings(secureSettings)
|
||||
.put("xpack.notification.hipchat.account." + accountName + ".room", room);
|
||||
if (host != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + accountName + ".host", host);
|
||||
}
|
||||
if (port > 0) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + accountName + ".port", port);
|
||||
}
|
||||
buildMessageDefaults(accountName, settingsBuilder, null, null, defaultFrom, defaultColor, defaultFormat, defaultNotify);
|
||||
HipChatService service = new HipChatService(settingsBuilder.build(), httpClient,
|
||||
new ClusterSettings(settingsBuilder.build(), new HashSet<>(HipChatService.getSettings())));
|
||||
|
||||
HipChatAccount account = service.getAccount(accountName);
|
||||
assertThat(account, notNullValue());
|
||||
assertThat(account.name, is(accountName));
|
||||
assertThat(account.authToken, is("_token"));
|
||||
assertThat(account.profile, is(HipChatAccount.Profile.INTEGRATION));
|
||||
assertThat(account.httpClient, is(httpClient));
|
||||
assertThat(account.server, notNullValue());
|
||||
assertThat(account.server.host(), is(host != null ? host : HipChatServer.DEFAULT.host()));
|
||||
assertThat(account.server.port(), is(port > 0 ? port : HipChatServer.DEFAULT.port()));
|
||||
assertThat(account, instanceOf(IntegrationAccount.class));
|
||||
assertThat(((IntegrationAccount) account).room, is(room));
|
||||
assertThat(((IntegrationAccount) account).defaults.color, is(defaultColor));
|
||||
assertThat(((IntegrationAccount) account).defaults.format, is(defaultFormat));
|
||||
assertThat(((IntegrationAccount) account).defaults.notify, is(defaultNotify));
|
||||
|
||||
// with a single account defined, making sure that that account is set to the default one.
|
||||
assertThat(service.getAccount(null), sameInstance(account));
|
||||
}
|
||||
|
||||
public void testSingleAccountIntegrationNoRoomSetting() throws Exception {
|
||||
String accountName = randomAlphaOfLength(10);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString("xpack.notification.hipchat.account." + accountName + ".secure_auth_token", "_token");
|
||||
Settings.Builder settingsBuilder = Settings.builder()
|
||||
.put("xpack.notification.hipchat.account." + accountName + ".profile",
|
||||
HipChatAccount.Profile.INTEGRATION.value())
|
||||
.setSecureSettings(secureSettings);
|
||||
SettingsException e = expectThrows(SettingsException.class, () ->
|
||||
new HipChatService(settingsBuilder.build(), httpClient,
|
||||
new ClusterSettings(settingsBuilder.build(), new HashSet<>(HipChatService.getSettings()))).getAccount(null));
|
||||
assertThat(e.getMessage(), containsString("missing required [room] setting for [integration] account profile"));
|
||||
}
|
||||
|
||||
public void testSingleAccountUser() throws Exception {
|
||||
String accountName = randomAlphaOfLength(10);
|
||||
String host = randomBoolean() ? null : "_host";
|
||||
int port = randomBoolean() ? -1 : randomIntBetween(300, 400);
|
||||
String defaultRoom = randomBoolean() ? null : "_r1, _r2";
|
||||
String defaultUser = randomBoolean() ? null : "_u1, _u2";
|
||||
HipChatMessage.Color defaultColor = randomBoolean() ? null : randomFrom(HipChatMessage.Color.values());
|
||||
HipChatMessage.Format defaultFormat = randomBoolean() ? null : randomFrom(HipChatMessage.Format.values());
|
||||
Boolean defaultNotify = randomBoolean() ? null : (Boolean) randomBoolean();
|
||||
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString("xpack.notification.hipchat.account." + accountName + ".secure_auth_token", "_token");
|
||||
Settings.Builder settingsBuilder = Settings.builder()
|
||||
.put("xpack.notification.hipchat.account." + accountName + ".profile", HipChatAccount.Profile.USER.value())
|
||||
.setSecureSettings(secureSettings);
|
||||
if (host != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + accountName + ".host", host);
|
||||
}
|
||||
if (port > 0) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + accountName + ".port", port);
|
||||
}
|
||||
buildMessageDefaults(accountName, settingsBuilder, defaultRoom, defaultUser, null, defaultColor, defaultFormat, defaultNotify);
|
||||
HipChatService service = new HipChatService(settingsBuilder.build(), httpClient,
|
||||
new ClusterSettings(settingsBuilder.build(), new HashSet<>(HipChatService.getSettings())));
|
||||
|
||||
HipChatAccount account = service.getAccount(accountName);
|
||||
assertThat(account, notNullValue());
|
||||
assertThat(account.name, is(accountName));
|
||||
assertThat(account.authToken, is("_token"));
|
||||
assertThat(account.profile, is(HipChatAccount.Profile.USER));
|
||||
assertThat(account.httpClient, is(httpClient));
|
||||
assertThat(account.server, notNullValue());
|
||||
assertThat(account.server.host(), is(host != null ? host : HipChatServer.DEFAULT.host()));
|
||||
assertThat(account.server.port(), is(port > 0 ? port : HipChatServer.DEFAULT.port()));
|
||||
assertThat(account, instanceOf(UserAccount.class));
|
||||
if (defaultRoom == null) {
|
||||
assertThat(((UserAccount) account).defaults.rooms, nullValue());
|
||||
} else {
|
||||
assertThat(((UserAccount) account).defaults.rooms, arrayContaining("_r1", "_r2"));
|
||||
}
|
||||
if (defaultUser == null) {
|
||||
assertThat(((UserAccount) account).defaults.users, nullValue());
|
||||
} else {
|
||||
assertThat(((UserAccount) account).defaults.users, arrayContaining("_u1", "_u2"));
|
||||
}
|
||||
assertThat(((UserAccount) account).defaults.color, is(defaultColor));
|
||||
assertThat(((UserAccount) account).defaults.format, is(defaultFormat));
|
||||
assertThat(((UserAccount) account).defaults.notify, is(defaultNotify));
|
||||
|
||||
// with a single account defined, making sure that that account is set to the default one.
|
||||
assertThat(service.getAccount(null), sameInstance(account));
|
||||
}
|
||||
|
||||
public void testMultipleAccounts() throws Exception {
|
||||
HipChatMessage.Color defaultColor = randomBoolean() ? null : randomFrom(HipChatMessage.Color.values());
|
||||
HipChatMessage.Format defaultFormat = randomBoolean() ? null : randomFrom(HipChatMessage.Format.values());
|
||||
Boolean defaultNotify = randomBoolean() ? null : (Boolean) randomBoolean();
|
||||
Settings.Builder settingsBuilder = Settings.builder();
|
||||
String defaultAccount = "_a" + randomIntBetween(0, 4);
|
||||
settingsBuilder.put("xpack.notification.hipchat.default_account", defaultAccount);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
settingsBuilder.setSecureSettings(secureSettings);
|
||||
|
||||
final boolean customGlobalServer = randomBoolean();
|
||||
if (customGlobalServer) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.host", "_host_global");
|
||||
settingsBuilder.put("xpack.notification.hipchat.port", 299);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
String name = "_a" + i;
|
||||
String prefix = "xpack.notification.hipchat.account." + name;
|
||||
HipChatAccount.Profile profile = randomFrom(HipChatAccount.Profile.values());
|
||||
settingsBuilder.put(prefix + ".profile", profile);
|
||||
secureSettings.setString(prefix + ".secure_auth_token", "_token" + i);
|
||||
if (profile == HipChatAccount.Profile.INTEGRATION) {
|
||||
settingsBuilder.put(prefix + ".room", "_room" + i);
|
||||
}
|
||||
if (i % 2 == 0) {
|
||||
settingsBuilder.put(prefix + ".host", "_host" + i);
|
||||
settingsBuilder.put(prefix + ".port", 300 + i);
|
||||
}
|
||||
buildMessageDefaults(name, settingsBuilder, null, null, null, defaultColor, defaultFormat, defaultNotify);
|
||||
}
|
||||
|
||||
HipChatService service = new HipChatService(settingsBuilder.build(), httpClient,
|
||||
new ClusterSettings(settingsBuilder.build(), new HashSet<>(HipChatService.getSettings())));
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
String name = "_a" + i;
|
||||
HipChatAccount account = service.getAccount(name);
|
||||
assertThat(account, notNullValue());
|
||||
assertThat(account.name, is(name));
|
||||
assertThat(account.authToken, is("_token" + i));
|
||||
assertThat(account.profile, notNullValue());
|
||||
if (account.profile == HipChatAccount.Profile.INTEGRATION) {
|
||||
assertThat(account, instanceOf(IntegrationAccount.class));
|
||||
assertThat(((IntegrationAccount) account).room, is("_room" + i));
|
||||
}
|
||||
assertThat(account.httpClient, is(httpClient));
|
||||
assertThat(account.server, notNullValue());
|
||||
if (i % 2 == 0) {
|
||||
assertThat(account.server.host(), is("_host" + i));
|
||||
assertThat(account.server.port(), is(300 + i));
|
||||
} else if (customGlobalServer) {
|
||||
assertThat(account.server.host(), is("_host_global"));
|
||||
assertThat(account.server.port(), is(299));
|
||||
} else {
|
||||
assertThat(account.server.host(), is(HipChatServer.DEFAULT.host()));
|
||||
assertThat(account.server.port(), is(HipChatServer.DEFAULT.port()));
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(service.getAccount(null), sameInstance(service.getAccount(defaultAccount)));
|
||||
}
|
||||
|
||||
private void buildMessageDefaults(String account, Settings.Builder settingsBuilder, String room, String user, String from,
|
||||
HipChatMessage.Color color, HipChatMessage.Format format, Boolean notify) {
|
||||
if (room != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + account + ".message_defaults.room", room);
|
||||
}
|
||||
if (user != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + account + ".message_defaults.user", user);
|
||||
}
|
||||
if (from != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + account + ".message_defaults.from", from);
|
||||
}
|
||||
if (color != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + account + ".message_defaults.color", color.value());
|
||||
}
|
||||
if (format != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + account + ".message_defaults.format", format);
|
||||
}
|
||||
if (notify != null) {
|
||||
settingsBuilder.put("xpack.notification.hipchat.account." + account + ".message_defaults.notify", notify);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.http.Scheme;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class IntegrationAccountTests extends ESTestCase {
|
||||
|
||||
public void testSettings() throws Exception {
|
||||
String accountName = "_name";
|
||||
|
||||
Settings.Builder sb = Settings.builder();
|
||||
|
||||
String authToken = randomAlphaOfLength(50);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), authToken);
|
||||
sb.setSecureSettings(secureSettings);
|
||||
|
||||
String host = HipChatServer.DEFAULT.host();
|
||||
if (randomBoolean()) {
|
||||
host = randomAlphaOfLength(10);
|
||||
sb.put("host", host);
|
||||
}
|
||||
int port = HipChatServer.DEFAULT.port();
|
||||
if (randomBoolean()) {
|
||||
port = randomIntBetween(300, 400);
|
||||
sb.put("port", port);
|
||||
}
|
||||
|
||||
String room = randomAlphaOfLength(10);
|
||||
sb.put(IntegrationAccount.ROOM_SETTING, room);
|
||||
|
||||
HipChatMessage.Format defaultFormat = null;
|
||||
if (randomBoolean()) {
|
||||
defaultFormat = randomFrom(HipChatMessage.Format.values());
|
||||
sb.put(HipChatAccount.DEFAULT_FORMAT_SETTING, defaultFormat);
|
||||
}
|
||||
HipChatMessage.Color defaultColor = null;
|
||||
if (randomBoolean()) {
|
||||
defaultColor = randomFrom(HipChatMessage.Color.values());
|
||||
sb.put(HipChatAccount.DEFAULT_COLOR_SETTING, defaultColor);
|
||||
}
|
||||
Boolean defaultNotify = null;
|
||||
if (randomBoolean()) {
|
||||
defaultNotify = randomBoolean();
|
||||
sb.put(HipChatAccount.DEFAULT_NOTIFY_SETTING, defaultNotify);
|
||||
}
|
||||
Settings settings = sb.build();
|
||||
|
||||
IntegrationAccount account = new IntegrationAccount(accountName, settings, HipChatServer.DEFAULT, mock(HttpClient.class),
|
||||
mock(Logger.class));
|
||||
|
||||
assertThat(account.profile, is(HipChatAccount.Profile.INTEGRATION));
|
||||
assertThat(account.name, equalTo(accountName));
|
||||
assertThat(account.server.host(), is(host));
|
||||
assertThat(account.server.port(), is(port));
|
||||
assertThat(account.authToken, is(authToken));
|
||||
assertThat(account.room, is(room));
|
||||
assertThat(account.defaults.format, is(defaultFormat));
|
||||
assertThat(account.defaults.color, is(defaultColor));
|
||||
assertThat(account.defaults.notify, is(defaultNotify));
|
||||
}
|
||||
|
||||
public void testSettingsNoAuthToken() throws Exception {
|
||||
Settings.Builder sb = Settings.builder();
|
||||
sb.put(IntegrationAccount.ROOM_SETTING, randomAlphaOfLength(10));
|
||||
try {
|
||||
new IntegrationAccount("_name", sb.build(), HipChatServer.DEFAULT, mock(HttpClient.class), mock(Logger.class));
|
||||
fail("Expected SettingsException");
|
||||
} catch (SettingsException e) {
|
||||
assertThat(e.getMessage(), is("hipchat account [_name] missing required [secure_auth_token] secure setting"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSettingsWithoutRoom() throws Exception {
|
||||
Settings.Builder sb = Settings.builder();
|
||||
String authToken = randomAlphaOfLength(50);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), authToken);
|
||||
sb.setSecureSettings(secureSettings);
|
||||
try {
|
||||
new IntegrationAccount("_name", sb.build(), HipChatServer.DEFAULT, mock(HttpClient.class), mock(Logger.class));
|
||||
fail("Expected SettingsException");
|
||||
} catch (SettingsException e) {
|
||||
assertThat(e.getMessage(), containsString("missing required [room] setting for [integration] account profile"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSettingsWithoutMultipleRooms() throws Exception {
|
||||
Settings.Builder sb = Settings.builder();
|
||||
String authToken = randomAlphaOfLength(50);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), authToken);
|
||||
sb.setSecureSettings(secureSettings);
|
||||
sb.put(IntegrationAccount.ROOM_SETTING, "_r1,_r2");
|
||||
try {
|
||||
new IntegrationAccount("_name", sb.build(), HipChatServer.DEFAULT, mock(HttpClient.class), mock(Logger.class));
|
||||
fail("Expected SettingsException");
|
||||
} catch (SettingsException e) {
|
||||
assertThat(e.getMessage(), containsString("[room] setting for [integration] account must only be set with a single value"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSend() throws Exception {
|
||||
String token = randomAlphaOfLength(10);
|
||||
HttpClient httpClient = mock(HttpClient.class);
|
||||
String room = "Room with Spaces";
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), token);
|
||||
IntegrationAccount account = new IntegrationAccount("_name", Settings.builder()
|
||||
.put("host", "_host")
|
||||
.put("port", "443")
|
||||
.setSecureSettings(secureSettings)
|
||||
.put("room", room)
|
||||
.build(), HipChatServer.DEFAULT, httpClient, mock(Logger.class));
|
||||
|
||||
HipChatMessage.Format format = randomFrom(HipChatMessage.Format.values());
|
||||
HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values());
|
||||
Boolean notify = randomBoolean();
|
||||
final HipChatMessage message = new HipChatMessage("_body", null, null, null, format, color, notify);
|
||||
|
||||
HttpRequest req = HttpRequest.builder("_host", 443)
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
// url encoded already
|
||||
.path("/v2/room/Room+with+Spaces/notification")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer " + token)
|
||||
.body(Strings.toString((builder, params) -> {
|
||||
builder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
builder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
builder.field("notify", message.notify);
|
||||
}
|
||||
if (message.color != null) {
|
||||
builder.field("color", String.valueOf(message.color.value()));
|
||||
}
|
||||
return builder;
|
||||
}))
|
||||
.build();
|
||||
|
||||
HttpResponse res = mock(HttpResponse.class);
|
||||
when(res.status()).thenReturn(200);
|
||||
when(httpClient.execute(req)).thenReturn(res);
|
||||
|
||||
SentMessages sentMessages = account.send(message, null);
|
||||
verify(httpClient).execute(req);
|
||||
assertThat(sentMessages.asList(), hasSize(1));
|
||||
try (XContentBuilder builder = jsonBuilder()) {
|
||||
sentMessages.asList().get(0).toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
assertThat(Strings.toString(builder), not(containsString(token)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,313 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpProxy;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.http.Scheme;
|
||||
import org.elasticsearch.xpack.watcher.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class UserAccountTests extends ESTestCase {
|
||||
|
||||
public void testSettings() throws Exception {
|
||||
String accountName = "_name";
|
||||
|
||||
Settings.Builder sb = Settings.builder();
|
||||
|
||||
String authToken = randomAlphaOfLength(50);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(UserAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), authToken);
|
||||
sb.setSecureSettings(secureSettings);
|
||||
|
||||
String host = HipChatServer.DEFAULT.host();
|
||||
if (randomBoolean()) {
|
||||
host = randomAlphaOfLength(10);
|
||||
sb.put("host", host);
|
||||
}
|
||||
int port = HipChatServer.DEFAULT.port();
|
||||
if (randomBoolean()) {
|
||||
port = randomIntBetween(300, 400);
|
||||
sb.put("port", port);
|
||||
}
|
||||
|
||||
String[] defaultRooms = null;
|
||||
if (randomBoolean()) {
|
||||
defaultRooms = new String[] { "_r1", "_r2" };
|
||||
sb.put(HipChatAccount.DEFAULT_ROOM_SETTING, "_r1,_r2");
|
||||
}
|
||||
String[] defaultUsers = null;
|
||||
if (randomBoolean()) {
|
||||
defaultUsers = new String[] { "_u1", "_u2" };
|
||||
sb.put(HipChatAccount.DEFAULT_USER_SETTING, "_u1,_u2");
|
||||
}
|
||||
HipChatMessage.Format defaultFormat = null;
|
||||
if (randomBoolean()) {
|
||||
defaultFormat = randomFrom(HipChatMessage.Format.values());
|
||||
sb.put(HipChatAccount.DEFAULT_FORMAT_SETTING, defaultFormat);
|
||||
}
|
||||
HipChatMessage.Color defaultColor = null;
|
||||
if (randomBoolean()) {
|
||||
defaultColor = randomFrom(HipChatMessage.Color.values());
|
||||
sb.put(HipChatAccount.DEFAULT_COLOR_SETTING, defaultColor);
|
||||
}
|
||||
Boolean defaultNotify = null;
|
||||
if (randomBoolean()) {
|
||||
defaultNotify = randomBoolean();
|
||||
sb.put(HipChatAccount.DEFAULT_NOTIFY_SETTING, defaultNotify);
|
||||
}
|
||||
Settings settings = sb.build();
|
||||
|
||||
UserAccount account = new UserAccount(accountName, settings, HipChatServer.DEFAULT, mock(HttpClient.class), mock(Logger.class));
|
||||
|
||||
assertThat(account.profile, is(HipChatAccount.Profile.USER));
|
||||
assertThat(account.name, equalTo(accountName));
|
||||
assertThat(account.server.host(), is(host));
|
||||
assertThat(account.server.port(), is(port));
|
||||
assertThat(account.authToken, is(authToken));
|
||||
if (defaultRooms != null) {
|
||||
assertThat(account.defaults.rooms, arrayContaining(defaultRooms));
|
||||
} else {
|
||||
assertThat(account.defaults.rooms, nullValue());
|
||||
}
|
||||
if (defaultUsers != null) {
|
||||
assertThat(account.defaults.users, arrayContaining(defaultUsers));
|
||||
} else {
|
||||
assertThat(account.defaults.users, nullValue());
|
||||
}
|
||||
assertThat(account.defaults.format, is(defaultFormat));
|
||||
assertThat(account.defaults.color, is(defaultColor));
|
||||
assertThat(account.defaults.notify, is(defaultNotify));
|
||||
}
|
||||
|
||||
public void testSettingsNoAuthToken() throws Exception {
|
||||
Settings.Builder sb = Settings.builder();
|
||||
try {
|
||||
new UserAccount("_name", sb.build(), HipChatServer.DEFAULT, mock(HttpClient.class), mock(Logger.class));
|
||||
fail("Expected SettingsException");
|
||||
} catch (SettingsException e) {
|
||||
assertThat(e.getMessage(), is("hipchat account [_name] missing required [secure_auth_token] secure setting"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSend() throws Exception {
|
||||
HttpClient httpClient = mock(HttpClient.class);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), "_token");
|
||||
UserAccount account = new UserAccount("_name", Settings.builder()
|
||||
.put("host", "_host")
|
||||
.put("port", "443")
|
||||
.setSecureSettings(secureSettings)
|
||||
.build(), HipChatServer.DEFAULT, httpClient, mock(Logger.class));
|
||||
|
||||
HipChatMessage.Format format = randomFrom(HipChatMessage.Format.values());
|
||||
HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values());
|
||||
Boolean notify = randomBoolean();
|
||||
final HipChatMessage message = new HipChatMessage("_body", new String[] { "_r1", "_r2" }, new String[] { "_u1", "_u2" }, null,
|
||||
format, color, notify);
|
||||
|
||||
HttpRequest reqR1 = HttpRequest.builder("_host", 443)
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v2/room/_r1/notification")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer _token")
|
||||
.body(Strings.toString((builder, params) -> {
|
||||
builder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
builder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
builder.field("notify", message.notify);
|
||||
}
|
||||
if (message.color != null) {
|
||||
builder.field("color", String.valueOf(message.color.value()));
|
||||
}
|
||||
return builder;
|
||||
}))
|
||||
.build();
|
||||
|
||||
logger.info("expected (r1): {}", BytesReference.bytes(jsonBuilder().value(reqR1)).utf8ToString());
|
||||
|
||||
HttpResponse resR1 = mock(HttpResponse.class);
|
||||
when(resR1.status()).thenReturn(200);
|
||||
when(httpClient.execute(reqR1)).thenReturn(resR1);
|
||||
|
||||
HttpRequest reqR2 = HttpRequest.builder("_host", 443)
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v2/room/_r2/notification")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer _token")
|
||||
.body(Strings.toString((builder, params) -> {
|
||||
builder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
builder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
builder.field("notify", message.notify);
|
||||
}
|
||||
if (message.color != null) {
|
||||
builder.field("color", String.valueOf(message.color.value()));
|
||||
}
|
||||
return builder;
|
||||
}))
|
||||
.build();
|
||||
|
||||
logger.info("expected (r2): {}", BytesReference.bytes(jsonBuilder().value(reqR1)).utf8ToString());
|
||||
|
||||
HttpResponse resR2 = mock(HttpResponse.class);
|
||||
when(resR2.status()).thenReturn(200);
|
||||
when(httpClient.execute(reqR2)).thenReturn(resR2);
|
||||
|
||||
HttpRequest reqU1 = HttpRequest.builder("_host", 443)
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v2/user/_u1/message")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer _token")
|
||||
.body(Strings.toString((builder, params) -> {
|
||||
builder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
builder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
builder.field("notify", message.notify);
|
||||
}
|
||||
return builder;
|
||||
}))
|
||||
.build();
|
||||
|
||||
logger.info("expected (u1): {}", BytesReference.bytes(jsonBuilder().value(reqU1)).utf8ToString());
|
||||
|
||||
HttpResponse resU1 = mock(HttpResponse.class);
|
||||
when(resU1.status()).thenReturn(200);
|
||||
when(httpClient.execute(reqU1)).thenReturn(resU1);
|
||||
|
||||
HttpRequest reqU2 = HttpRequest.builder("_host", 443)
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v2/user/_u2/message")
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setHeader("Authorization", "Bearer _token")
|
||||
.body(Strings.toString((builder, params) -> {
|
||||
builder.field("message", message.body);
|
||||
if (message.format != null) {
|
||||
builder.field("message_format", message.format.value());
|
||||
}
|
||||
if (message.notify != null) {
|
||||
builder.field("notify", message.notify);
|
||||
}
|
||||
return builder;
|
||||
}))
|
||||
.build();
|
||||
|
||||
logger.info("expected (u2): {}", BytesReference.bytes(jsonBuilder().value(reqU2)).utf8ToString());
|
||||
|
||||
HttpResponse resU2 = mock(HttpResponse.class);
|
||||
when(resU2.status()).thenReturn(200);
|
||||
when(httpClient.execute(reqU2)).thenReturn(resU2);
|
||||
|
||||
account.send(message, null);
|
||||
|
||||
verify(httpClient).execute(reqR1);
|
||||
verify(httpClient).execute(reqR2);
|
||||
verify(httpClient).execute(reqU2);
|
||||
verify(httpClient).execute(reqU2);
|
||||
}
|
||||
|
||||
public void testColorIsOptional() throws Exception {
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), "awesome-auth-token");
|
||||
Settings settings = Settings.builder()
|
||||
.put("user", "testuser")
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
UserAccount userAccount = createUserAccount(settings);
|
||||
|
||||
TextTemplate body = new TextTemplate("body");
|
||||
TextTemplate[] rooms = new TextTemplate[] { new TextTemplate("room")};
|
||||
HipChatMessage.Template template =
|
||||
new HipChatMessage.Template(body, rooms, null, "sender", HipChatMessage.Format.TEXT, null, true);
|
||||
|
||||
HipChatMessage message = userAccount.render("watchId", "actionId", new MockTextTemplateEngine(), template, new HashMap<>());
|
||||
assertThat(message.color, is(nullValue()));
|
||||
}
|
||||
|
||||
public void testFormatIsOptional() throws Exception {
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), "awesome-auth-token");
|
||||
Settings settings = Settings.builder()
|
||||
.put("user", "testuser")
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
UserAccount userAccount = createUserAccount(settings);
|
||||
|
||||
TextTemplate body = new TextTemplate("body");
|
||||
TextTemplate[] rooms = new TextTemplate[] { new TextTemplate("room") };
|
||||
HipChatMessage.Template template = new HipChatMessage.Template(body, rooms, null, "sender", null,
|
||||
new TextTemplate("yellow"), true);
|
||||
|
||||
HipChatMessage message = userAccount.render("watchId", "actionId", new MockTextTemplateEngine(), template, new HashMap<>());
|
||||
assertThat(message.format, is(nullValue()));
|
||||
}
|
||||
|
||||
public void testRoomNameIsUrlEncoded() throws Exception {
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), "awesome-auth-token");
|
||||
Settings settings = Settings.builder()
|
||||
.put("user", "testuser")
|
||||
.setSecureSettings(secureSettings)
|
||||
.build();
|
||||
HipChatServer hipChatServer = mock(HipChatServer.class);
|
||||
HttpClient httpClient = mock(HttpClient.class);
|
||||
UserAccount account = new UserAccount("notify-monitoring", settings, hipChatServer, httpClient, logger);
|
||||
|
||||
TextTemplate[] rooms = new TextTemplate[] { new TextTemplate("Room with Spaces")};
|
||||
HipChatMessage.Template template =
|
||||
new HipChatMessage.Template(new TextTemplate("body"), rooms, null, "sender", HipChatMessage.Format.TEXT, null, true);
|
||||
|
||||
HipChatMessage message = account.render("watchId", "actionId", new MockTextTemplateEngine(), template, new HashMap<>());
|
||||
account.send(message, HttpProxy.NO_PROXY);
|
||||
|
||||
ArgumentCaptor<HttpRequest> captor = ArgumentCaptor.forClass(HttpRequest.class);
|
||||
verify(httpClient).execute(captor.capture());
|
||||
assertThat(captor.getAllValues(), hasSize(1));
|
||||
assertThat(captor.getValue().path(), not(containsString("Room with Spaces")));
|
||||
assertThat(captor.getValue().path(), containsString("Room%20with%20Spaces"));
|
||||
}
|
||||
|
||||
private UserAccount createUserAccount(Settings settings) {
|
||||
HipChatServer hipChatServer = mock(HipChatServer.class);
|
||||
HttpClient httpClient = mock(HttpClient.class);
|
||||
return new UserAccount("notify-monitoring", settings, hipChatServer, httpClient, logger);
|
||||
}
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.xpack.watcher.notification.hipchat;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.settings.MockSecureSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.SettingsException;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpClient;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpMethod;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.watcher.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.common.http.Scheme;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class V1AccountTests extends ESTestCase {
|
||||
public void testSettings() throws Exception {
|
||||
String accountName = "_name";
|
||||
|
||||
Settings.Builder sb = Settings.builder();
|
||||
|
||||
String authToken = randomAlphaOfLength(50);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(V1Account.SECURE_AUTH_TOKEN_SETTING.getKey(), authToken);
|
||||
sb.setSecureSettings(secureSettings);
|
||||
|
||||
String host = HipChatServer.DEFAULT.host();
|
||||
if (randomBoolean()) {
|
||||
host = randomAlphaOfLength(10);
|
||||
sb.put("host", host);
|
||||
}
|
||||
int port = HipChatServer.DEFAULT.port();
|
||||
if (randomBoolean()) {
|
||||
port = randomIntBetween(300, 400);
|
||||
sb.put("port", port);
|
||||
}
|
||||
|
||||
String[] defaultRooms = null;
|
||||
if (randomBoolean()) {
|
||||
defaultRooms = new String[] { "_r1", "_r2" };
|
||||
sb.put(HipChatAccount.DEFAULT_ROOM_SETTING, "_r1,_r2");
|
||||
}
|
||||
String defaultFrom = null;
|
||||
if (randomBoolean()) {
|
||||
defaultFrom = randomAlphaOfLength(10);
|
||||
sb.put(HipChatAccount.DEFAULT_FROM_SETTING, defaultFrom);
|
||||
}
|
||||
HipChatMessage.Format defaultFormat = null;
|
||||
if (randomBoolean()) {
|
||||
defaultFormat = randomFrom(HipChatMessage.Format.values());
|
||||
sb.put(HipChatAccount.DEFAULT_FORMAT_SETTING, defaultFormat);
|
||||
}
|
||||
HipChatMessage.Color defaultColor = null;
|
||||
if (randomBoolean()) {
|
||||
defaultColor = randomFrom(HipChatMessage.Color.values());
|
||||
sb.put(HipChatAccount.DEFAULT_COLOR_SETTING, defaultColor);
|
||||
}
|
||||
Boolean defaultNotify = null;
|
||||
if (randomBoolean()) {
|
||||
defaultNotify = randomBoolean();
|
||||
sb.put(HipChatAccount.DEFAULT_NOTIFY_SETTING, defaultNotify);
|
||||
}
|
||||
Settings settings = sb.build();
|
||||
|
||||
V1Account account = new V1Account(accountName, settings, HipChatServer.DEFAULT, mock(HttpClient.class), mock(Logger.class));
|
||||
|
||||
assertThat(account.profile, is(HipChatAccount.Profile.V1));
|
||||
assertThat(account.name, equalTo(accountName));
|
||||
assertThat(account.server.host(), is(host));
|
||||
assertThat(account.server.port(), is(port));
|
||||
assertThat(account.authToken, is(authToken));
|
||||
if (defaultRooms != null) {
|
||||
assertThat(account.defaults.rooms, arrayContaining(defaultRooms));
|
||||
} else {
|
||||
assertThat(account.defaults.rooms, nullValue());
|
||||
}
|
||||
assertThat(account.defaults.from, is(defaultFrom));
|
||||
assertThat(account.defaults.format, is(defaultFormat));
|
||||
assertThat(account.defaults.color, is(defaultColor));
|
||||
assertThat(account.defaults.notify, is(defaultNotify));
|
||||
}
|
||||
|
||||
public void testSettingsNoAuthToken() throws Exception {
|
||||
Settings.Builder sb = Settings.builder();
|
||||
try {
|
||||
new V1Account("_name", sb.build(), HipChatServer.DEFAULT, mock(HttpClient.class), mock(Logger.class));
|
||||
fail("Expected SettingsException");
|
||||
} catch (SettingsException e) {
|
||||
assertThat(e.getMessage(), is("hipchat account [_name] missing required [secure_auth_token] secure setting"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSend() throws Exception {
|
||||
HttpClient httpClient = mock(HttpClient.class);
|
||||
String authToken = randomAlphaOfLength(50);
|
||||
final MockSecureSettings secureSettings = new MockSecureSettings();
|
||||
secureSettings.setString(IntegrationAccount.SECURE_AUTH_TOKEN_SETTING.getKey(), "_token");
|
||||
V1Account account = new V1Account("_name", Settings.builder()
|
||||
.put("host", "_host")
|
||||
.put("port", "443")
|
||||
.setSecureSettings(secureSettings)
|
||||
.build(), HipChatServer.DEFAULT, httpClient, mock(Logger.class));
|
||||
|
||||
HipChatMessage.Format format = randomFrom(HipChatMessage.Format.values());
|
||||
HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values());
|
||||
Boolean notify = randomBoolean();
|
||||
HipChatMessage message = new HipChatMessage("_body", new String[] { "Room with Spaces", "_r2" }, null, "_from", format,
|
||||
color, notify);
|
||||
|
||||
HttpRequest req1 = HttpRequest.builder("_host", 443)
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v1/rooms/message")
|
||||
.setHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
.setParam("format", "json")
|
||||
.setParam("auth_token", "_token")
|
||||
.body(new StringBuilder()
|
||||
.append("room_id=").append("Room+with+Spaces&")
|
||||
.append("from=").append("_from&")
|
||||
.append("message=").append("_body&")
|
||||
.append("message_format=").append(format.value()).append("&")
|
||||
.append("color=").append(color.value()).append("&")
|
||||
.append("notify=").append(notify ? "1" : "0")
|
||||
.toString())
|
||||
.build();
|
||||
|
||||
logger.info("expected (r1): {}", BytesReference.bytes(jsonBuilder().value(req1)).utf8ToString());
|
||||
|
||||
HttpResponse res1 = mock(HttpResponse.class);
|
||||
when(res1.status()).thenReturn(200);
|
||||
when(httpClient.execute(req1)).thenReturn(res1);
|
||||
|
||||
HttpRequest req2 = HttpRequest.builder("_host", 443)
|
||||
.method(HttpMethod.POST)
|
||||
.scheme(Scheme.HTTPS)
|
||||
.path("/v1/rooms/message")
|
||||
.setHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
.setParam("format", "json")
|
||||
.setParam("auth_token", "_token")
|
||||
.body(new StringBuilder()
|
||||
.append("room_id=").append("_r2&")
|
||||
.append("from=").append("_from&")
|
||||
.append("message=").append("_body&")
|
||||
.append("message_format=").append(format.value()).append("&")
|
||||
.append("color=").append(color.value()).append("&")
|
||||
.append("notify=").append(notify ? "1" : "0")
|
||||
.toString())
|
||||
.build();
|
||||
|
||||
logger.info("expected (r2): {}", BytesReference.bytes(jsonBuilder().value(req2)).utf8ToString());
|
||||
|
||||
HttpResponse res2 = mock(HttpResponse.class);
|
||||
when(res2.status()).thenReturn(200);
|
||||
when(httpClient.execute(req2)).thenReturn(res2);
|
||||
|
||||
account.send(message, null);
|
||||
|
||||
verify(httpClient).execute(req1);
|
||||
verify(httpClient).execute(req2);
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
apply plugin: 'elasticsearch.standalone-rest-test'
|
||||
apply plugin: 'elasticsearch.rest-test'
|
||||
|
||||
dependencies {
|
||||
testCompile "org.elasticsearch.plugin:x-pack-core:${version}"
|
||||
testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
|
||||
}
|
||||
|
||||
String integrationAccount = System.getenv('hipchat_auth_token_integration')
|
||||
String userAccount = System.getenv('hipchat_auth_token_user')
|
||||
String v1Account = System.getenv('hipchat_auth_token_v1')
|
||||
|
||||
integTestCluster {
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'xpack.ml.enabled', 'false'
|
||||
setting 'xpack.license.self_generated.type', 'trial'
|
||||
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
|
||||
setting 'xpack.notification.hipchat.account.integration_account.profile', 'integration'
|
||||
setting 'xpack.notification.hipchat.account.integration_account.room', 'test-watcher'
|
||||
setting 'xpack.notification.hipchat.account.user_account.profile', 'user'
|
||||
setting 'xpack.notification.hipchat.account.v1_account.profile', 'v1'
|
||||
keystoreSetting 'xpack.notification.hipchat.account.integration_account.secure_auth_token', integrationAccount
|
||||
keystoreSetting 'xpack.notification.hipchat.account.user_account.secure_auth_token', userAccount
|
||||
keystoreSetting 'xpack.notification.hipchat.account.v1_account.secure_auth_token', v1Account
|
||||
}
|
||||
|
||||
if (!integrationAccount && !userAccount && !v1Account) {
|
||||
integTest.enabled = false
|
||||
testingConventions.enabled = false
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.smoketest;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/** Runs rest tests against external cluster */
|
||||
public class WatcherHipchatYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
public WatcherHipchatYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws Exception {
|
||||
return ESClientYamlSuiteTestCase.createParameters();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startWatcher() throws Exception {
|
||||
final List<String> watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES);
|
||||
assertBusy(() -> {
|
||||
try {
|
||||
getAdminExecutionContext().callApi("watcher.start", emptyMap(), emptyList(), emptyMap());
|
||||
|
||||
for (String template : watcherTemplates) {
|
||||
ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template",
|
||||
singletonMap("name", template), emptyList(), emptyMap());
|
||||
assertThat(templateExistsResponse.getStatusCode(), is(200));
|
||||
}
|
||||
|
||||
ClientYamlTestResponse response =
|
||||
getAdminExecutionContext().callApi("watcher.stats", emptyMap(), emptyList(), emptyMap());
|
||||
String state = (String) response.evaluate("stats.0.watcher_state");
|
||||
assertThat(state, is("started"));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopWatcher() throws Exception {
|
||||
assertBusy(() -> {
|
||||
try {
|
||||
getAdminExecutionContext().callApi("watcher.stop", emptyMap(), emptyList(), emptyMap());
|
||||
ClientYamlTestResponse response =
|
||||
getAdminExecutionContext().callApi("watcher.stats", emptyMap(), emptyList(), emptyMap());
|
||||
String state = (String) response.evaluate("stats.0.watcher_state");
|
||||
assertThat(state, is("stopped"));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,279 +0,0 @@
|
|||
---
|
||||
"Test Hipchat v1 account Action":
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
watcher.put_watch:
|
||||
id: "hipchat_v1_watch"
|
||||
body: >
|
||||
{
|
||||
"trigger": {
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"simple": {
|
||||
"foo": "something from input"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"my_hipchat_action": {
|
||||
"hipchat": {
|
||||
"account": "v1_account",
|
||||
"message": {
|
||||
"from" : "watcher-tests",
|
||||
"room" : ["test-watcher", "test-watcher-2", "test watcher with spaces"],
|
||||
"body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the v1 account",
|
||||
"format": "text",
|
||||
"color": "red",
|
||||
"notify": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- do:
|
||||
watcher.execute_watch:
|
||||
id: "hipchat_v1_watch"
|
||||
body: >
|
||||
{
|
||||
"record_execution": true
|
||||
}
|
||||
|
||||
- match: { watch_record.trigger_event.type: "manual" }
|
||||
- match: { watch_record.state: "executed" }
|
||||
- match: { watch_record.result.actions.0.id: "my_hipchat_action" }
|
||||
- match: { watch_record.result.actions.0.type: "hipchat" }
|
||||
- match: { watch_record.result.actions.0.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.account: "v1_account" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.status: "success" }
|
||||
|
||||
# Waits for the watcher history index to be available
|
||||
- do:
|
||||
cluster.health:
|
||||
index: ".watcher-history-*"
|
||||
wait_for_no_relocating_shards: true
|
||||
timeout: 60s
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
rest_total_hits_as_int: true
|
||||
index: ".watcher-history-*"
|
||||
body: >
|
||||
{
|
||||
"query" : {
|
||||
"term" : {
|
||||
"watch_id" : "hipchat_v1_watch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._source.state: "executed" }
|
||||
- match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" }
|
||||
- match: { hits.hits.0._source.result.actions.0.type: "hipchat" }
|
||||
- match: { hits.hits.0._source.result.actions.0.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.account: "v1_account" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.status: "success" }
|
||||
|
||||
---
|
||||
"Test Hipchat integration account Action":
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
# custom rooms, custom users and custom from are not allowed for this account type to be configured
|
||||
- do:
|
||||
watcher.put_watch:
|
||||
id: "hipchat_integration_account_watch"
|
||||
body: >
|
||||
{
|
||||
"trigger": {
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"simple": {
|
||||
"foo": "something from input"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"my_hipchat_action": {
|
||||
"hipchat": {
|
||||
"account": "integration_account",
|
||||
"message": {
|
||||
"body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the integration account",
|
||||
"format": "text",
|
||||
"color": "red",
|
||||
"notify": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- do:
|
||||
watcher.execute_watch:
|
||||
id: "hipchat_integration_account_watch"
|
||||
body: >
|
||||
{
|
||||
"record_execution": true
|
||||
}
|
||||
|
||||
- match: { watch_record.trigger_event.type: "manual" }
|
||||
- match: { watch_record.state: "executed" }
|
||||
- match: { watch_record.result.actions.0.id: "my_hipchat_action" }
|
||||
- match: { watch_record.result.actions.0.type: "hipchat" }
|
||||
- match: { watch_record.result.actions.0.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.account: "integration_account" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
|
||||
|
||||
# Waits for the watcher history index to be available
|
||||
- do:
|
||||
cluster.health:
|
||||
index: ".watcher-history-*"
|
||||
wait_for_no_relocating_shards: true
|
||||
timeout: 60s
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
rest_total_hits_as_int: true
|
||||
index: ".watcher-history-*"
|
||||
body: >
|
||||
{
|
||||
"query" : {
|
||||
"term" : {
|
||||
"watch_id" : "hipchat_integration_account_watch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._source.state: "executed" }
|
||||
- match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" }
|
||||
- match: { hits.hits.0._source.result.actions.0.type: "hipchat" }
|
||||
- match: { hits.hits.0._source.result.actions.0.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.account: "integration_account" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" }
|
||||
|
||||
---
|
||||
"Test Hipchat user account Action":
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
watcher.put_watch:
|
||||
id: "hipchat_user_account_watch"
|
||||
body: >
|
||||
{
|
||||
"trigger": {
|
||||
"schedule": {
|
||||
"interval": "1d"
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"simple": {
|
||||
"foo": "something from input"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"my_hipchat_action": {
|
||||
"hipchat": {
|
||||
"account": "user_account",
|
||||
"message": {
|
||||
"user" : [ "watcher@elastic.co" ],
|
||||
"room" : ["test-watcher", "test-watcher-2", "test watcher with spaces"],
|
||||
"body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the user_account test. <b>bold</b>",
|
||||
"format": "html"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- do:
|
||||
watcher.execute_watch:
|
||||
id: "hipchat_user_account_watch"
|
||||
body: >
|
||||
{
|
||||
"record_execution": true
|
||||
}
|
||||
|
||||
- match: { watch_record.trigger_event.type: "manual" }
|
||||
- match: { watch_record.state: "executed" }
|
||||
- match: { watch_record.result.actions.0.id: "my_hipchat_action" }
|
||||
- match: { watch_record.result.actions.0.type: "hipchat" }
|
||||
- match: { watch_record.result.actions.0.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.account: "user_account" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.3.user: "watcher@elastic.co" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.status: "success" }
|
||||
- match: { watch_record.result.actions.0.hipchat.sent_messages.3.status: "success" }
|
||||
|
||||
# Waits for the watcher history index to be available
|
||||
- do:
|
||||
cluster.health:
|
||||
index: ".watcher-history-*"
|
||||
wait_for_no_relocating_shards: true
|
||||
timeout: 60s
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
rest_total_hits_as_int: true
|
||||
index: ".watcher-history-*"
|
||||
body: >
|
||||
{
|
||||
"query" : {
|
||||
"term" : {
|
||||
"watch_id" : "hipchat_user_account_watch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._source.state: "executed" }
|
||||
- match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" }
|
||||
- match: { hits.hits.0._source.result.actions.0.type: "hipchat" }
|
||||
- match: { hits.hits.0._source.result.actions.0.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.account: "user_account" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.3.user: "watcher@elastic.co" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" }
|
||||
|
||||
|