Add mappings for Jira action (elastic/elasticsearch#4155)
This commit updates the watch_history.json file so that it includes mappings for the new Jira action. It also update the JiraIssue format so that it now includes the name of the account used to create the Jira issue. It also update the REST tests to check that Jira action result are searchable and hide the user's password. Original commit: elastic/x-pack-elasticsearch@75888f7748
This commit is contained in:
parent
5d042fc1b8
commit
a32f2096a6
|
@ -90,7 +90,7 @@ public class JiraAccount {
|
|||
.build();
|
||||
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
return JiraIssue.responded(fields, request, response);
|
||||
return JiraIssue.responded(name, fields, request, response);
|
||||
}
|
||||
|
||||
private static SettingsException requiredSettingException(String account, String setting) {
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|||
import org.elasticsearch.xpack.common.http.HttpRequest;
|
||||
import org.elasticsearch.xpack.common.http.HttpResponse;
|
||||
import org.elasticsearch.xpack.watcher.actions.jira.JiraAction;
|
||||
import org.elasticsearch.xpack.watcher.support.xcontent.WatcherParams;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -26,16 +27,18 @@ import java.util.Objects;
|
|||
|
||||
public class JiraIssue implements ToXContent {
|
||||
|
||||
@Nullable final String account;
|
||||
private final Map<String, Object> fields;
|
||||
@Nullable private final HttpRequest request;
|
||||
@Nullable private final HttpResponse response;
|
||||
@Nullable private final String failureReason;
|
||||
|
||||
public static JiraIssue responded(Map<String, Object> fields, HttpRequest request, HttpResponse response) {
|
||||
return new JiraIssue(fields, request, response, resolveFailureReason(response));
|
||||
public static JiraIssue responded(String account, Map<String, Object> fields, HttpRequest request, HttpResponse response) {
|
||||
return new JiraIssue(account, fields, request, response, resolveFailureReason(response));
|
||||
}
|
||||
|
||||
JiraIssue(Map<String, Object> fields, HttpRequest request, HttpResponse response, String failureReason) {
|
||||
JiraIssue(String account, Map<String, Object> fields, HttpRequest request, HttpResponse response, String failureReason) {
|
||||
this.account = account;
|
||||
this.fields = fields;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
|
@ -46,6 +49,10 @@ public class JiraIssue implements ToXContent {
|
|||
return failureReason == null;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public HttpRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
@ -67,28 +74,30 @@ public class JiraIssue implements ToXContent {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JiraIssue sentEvent = (JiraIssue) o;
|
||||
return Objects.equals(fields, sentEvent.fields) &&
|
||||
Objects.equals(request, sentEvent.request) &&
|
||||
Objects.equals(response, sentEvent.response) &&
|
||||
Objects.equals(failureReason, sentEvent.failureReason);
|
||||
JiraIssue issue = (JiraIssue) o;
|
||||
return Objects.equals(account, issue.account) &&
|
||||
Objects.equals(fields, issue.fields) &&
|
||||
Objects.equals(request, issue.request) &&
|
||||
Objects.equals(response, issue.response) &&
|
||||
Objects.equals(failureReason, issue.failureReason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(fields, request, response, failureReason);
|
||||
return Objects.hash(account, fields, request, response, failureReason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(Field.ACCOUNT.getPreferredName(), account);
|
||||
if (fields != null) {
|
||||
builder.field(Field.FIELDS.getPreferredName(), fields);
|
||||
}
|
||||
if (successful() == false) {
|
||||
builder.field(Field.REASON.getPreferredName(), failureReason);
|
||||
if (request != null) {
|
||||
builder.field(Field.REQUEST.getPreferredName(), request, params);
|
||||
builder.field(Field.REQUEST.getPreferredName(), request, WatcherParams.builder().hideSecrets(true).build());
|
||||
}
|
||||
if (response != null) {
|
||||
builder.field(Field.RESPONSE.getPreferredName(), response, params);
|
||||
|
@ -181,6 +190,7 @@ public class JiraIssue implements ToXContent {
|
|||
|
||||
private interface Field {
|
||||
ParseField FIELDS = JiraAction.Field.FIELDS;
|
||||
ParseField ACCOUNT = new ParseField("account");
|
||||
ParseField REASON = new ParseField("reason");
|
||||
ParseField REQUEST = new ParseField("request");
|
||||
ParseField RESPONSE = new ParseField("response");
|
||||
|
|
|
@ -28,6 +28,15 @@
|
|||
"enabled": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"disabled_jira_custom_fields": {
|
||||
"path_match": "result.actions.jira.fields.customfield_*",
|
||||
"mapping": {
|
||||
"type": "object",
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dynamic": false,
|
||||
|
@ -358,6 +367,80 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"jira" : {
|
||||
"type": "object",
|
||||
"dynamic": true,
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"reason": {
|
||||
"type": "text"
|
||||
},
|
||||
"request" : {
|
||||
"type" : "object",
|
||||
"enabled" : false
|
||||
},
|
||||
"response" : {
|
||||
"type" : "object",
|
||||
"enabled" : false
|
||||
},
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"dynamic": true,
|
||||
"properties": {
|
||||
"summary": {
|
||||
"type": "text"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"labels" : {
|
||||
"type": "text"
|
||||
},
|
||||
"project" : {
|
||||
"type" : "object",
|
||||
"dynamic" : true,
|
||||
"properties" : {
|
||||
"key" : {
|
||||
"type" : "keyword"
|
||||
},
|
||||
"id" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"issuetype" : {
|
||||
"type" : "object",
|
||||
"dynamic" : true,
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type": "keyword"
|
||||
},
|
||||
"id" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"type": "object",
|
||||
"dynamic": true,
|
||||
"properties" : {
|
||||
"id" : {
|
||||
"type" : "keyword"
|
||||
},
|
||||
"key" : {
|
||||
"type" : "keyword"
|
||||
},
|
||||
"self" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"slack" : {
|
||||
"type": "object",
|
||||
"dynamic": true,
|
||||
|
|
|
@ -52,6 +52,7 @@ public class JiraIssueTests extends ESTestCase {
|
|||
|
||||
HttpRequest parsedRequest = null;
|
||||
HttpResponse parsedResponse = null;
|
||||
String parsedAccount = null;
|
||||
String parsedReason = null;
|
||||
|
||||
try (XContentParser parser = XContentHelper.createParser(bytes)) {
|
||||
|
@ -65,6 +66,8 @@ public class JiraIssueTests extends ESTestCase {
|
|||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if ("account".equals(currentFieldName)) {
|
||||
parsedAccount = parser.text();
|
||||
} else if ("result".equals(currentFieldName)) {
|
||||
parsedResult = parser.map();
|
||||
} else if ("request".equals(currentFieldName)) {
|
||||
|
@ -83,6 +86,7 @@ public class JiraIssueTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
assertThat(parsedAccount, equalTo(issue.getAccount()));
|
||||
assertThat(parsedFields, equalTo(issue.getFields()));
|
||||
if (issue.successful()) {
|
||||
assertThat(parsedResult, hasEntry("key", "TEST"));
|
||||
|
@ -108,11 +112,12 @@ public class JiraIssueTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
JiraIssue issue2 = new JiraIssue(fields, issue1.getRequest(), issue1.getResponse(), issue1.getFailureReason());
|
||||
JiraIssue issue2 = new JiraIssue(issue1.getAccount(), fields, issue1.getRequest(), issue1.getResponse(), issue1.getFailureReason());
|
||||
assertThat(issue1.equals(issue2), is(equals));
|
||||
}
|
||||
|
||||
private static JiraIssue randomJiraIssue() throws IOException {
|
||||
String account = "account_" + randomIntBetween(0, 100);
|
||||
Map<String, Object> fields = randomIssueDefaults();
|
||||
HttpRequest request = HttpRequest.builder(randomFrom("localhost", "internal-jira.elastic.co"), randomFrom(80, 443))
|
||||
.method(HttpMethod.POST)
|
||||
|
@ -121,8 +126,8 @@ public class JiraIssueTests extends ESTestCase {
|
|||
.build();
|
||||
if (rarely()) {
|
||||
Tuple<Integer, String> error = randomHttpError();
|
||||
return JiraIssue.responded(fields, request, new HttpResponse(error.v1(), "{\"error\": \"" + error.v2() + "\"}"));
|
||||
return JiraIssue.responded(account, fields, request, new HttpResponse(error.v1(), "{\"error\": \"" + error.v2() + "\"}"));
|
||||
}
|
||||
return JiraIssue.responded(fields, request, new HttpResponse(HttpStatus.SC_CREATED, "{\"key\": \"TEST\"}"));
|
||||
return JiraIssue.responded(account, fields, request, new HttpResponse(HttpStatus.SC_CREATED, "{\"key\": \"TEST\"}"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,12 +82,40 @@
|
|||
- match: { hits.hits.0._source.result.actions.0.id: "create_jira_issue" }
|
||||
- match: { hits.hits.0._source.result.actions.0.type: "jira" }
|
||||
- match: { hits.hits.0._source.result.actions.0.status: "success" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.account: "test" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.fields.summary: "Hello from jira_watch" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.fields.issuetype.name: "Bug" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.fields.project.key: "BAS" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.fields.labels.0: "integration-tests" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.result.id: /\d+/ }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.result.key: /BAS-\d+/ }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.result.self: /http(.)*/ }
|
||||
|
||||
- set: { hits.hits.0._id: id }
|
||||
- set: { hits.hits.0._source.result.actions.0.jira.result.self: self }
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: ".watcher-history-*"
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
result.actions.jira.fields.project.key: "BAS"
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._id: $id }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.result.self: $self }
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: ".watcher-history-*"
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
result.actions.jira.fields.summary: "hello jira_watch"
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._id: $id }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.result.self: $self }
|
||||
|
||||
---
|
||||
"Test Jira Action with Error":
|
||||
- do:
|
||||
|
@ -137,7 +165,8 @@
|
|||
"trigger_data" : {
|
||||
"triggered_time" : "2012-12-12T12:12:12.120Z",
|
||||
"scheduled_time" : "2000-12-12T12:12:12.120Z"
|
||||
}
|
||||
},
|
||||
"record_execution": true
|
||||
}
|
||||
|
||||
- match: { watch_record.watch_id: "wrong_jira_watch" }
|
||||
|
@ -146,14 +175,169 @@
|
|||
- match: { watch_record.trigger_event.manual.schedule.scheduled_time: "2000-12-12T12:12:12.120Z" }
|
||||
- match: { watch_record.state: "executed" }
|
||||
|
||||
- match: { watch_record.result.actions.0.id: "fail_to_create_jira_issue" }
|
||||
- match: { watch_record.result.actions.0.type: "jira" }
|
||||
- match: { watch_record.result.actions.0.status: "failure" }
|
||||
- match: { watch_record.result.actions.0.jira.fields.summary: "Hello from wrong_jira_watch" }
|
||||
- is_false: watch_record.result.actions.0.jira.fields.issuetype.name
|
||||
- match: { watch_record.result.actions.0.jira.fields.project.key: "BAS" }
|
||||
- match: { watch_record.result.actions.0.jira.fields.labels.0: "integration-tests" }
|
||||
- match: { watch_record.result.actions.0.jira.reason: "Bad Request - Field [issuetype] has error [issue type is required]\n" }
|
||||
- match: { watch_record.result.actions.0.jira.request.method: "post" }
|
||||
- match: { watch_record.result.actions.0.jira.request.path: "/rest/api/2/issue" }
|
||||
- match: { watch_record.result.actions.0.jira.response.body: "{\"errorMessages\":[],\"errors\":{\"issuetype\":\"issue type is required\"}}" }
|
||||
# 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:
|
||||
index: ".watcher-history-*"
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
result.actions.status: "failure"
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
- match: { hits.hits.0._type: "watch_record" }
|
||||
- match: { hits.hits.0._source.watch_id: "wrong_jira_watch" }
|
||||
- match: { hits.hits.0._source.state: "executed" }
|
||||
|
||||
- match: { hits.hits.0._source.result.actions.0.id: "fail_to_create_jira_issue" }
|
||||
- match: { hits.hits.0._source.result.actions.0.type: "jira" }
|
||||
- match: { hits.hits.0._source.result.actions.0.status: "failure" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.account: "test" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.fields.summary: "Hello from wrong_jira_watch" }
|
||||
- is_false: hits.hits.0._source.result.actions.0.jira.fields.issuetype.name
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.fields.project.key: "BAS" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.fields.labels.0: "integration-tests" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.reason: "Bad Request - Field [issuetype] has error [issue type is required]\n" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.request.method: "post" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.request.path: "/rest/api/2/issue" }
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.request.auth.basic.username: "jira_user" }
|
||||
- is_false: hits.hits.0._source.result.actions.0.jira.request.auth.basic.password
|
||||
- match: { hits.hits.0._source.result.actions.0.jira.response.body: "{\"errorMessages\":[],\"errors\":{\"issuetype\":\"issue type is required\"}}" }
|
||||
|
||||
---
|
||||
"Test Jira action with custom fields of different types":
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
xpack.watcher.put_watch:
|
||||
id: "jira_watch_with_custom_field_one"
|
||||
body: >
|
||||
{
|
||||
"trigger": {
|
||||
"schedule": {
|
||||
"interval": "1s"
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"simple": {
|
||||
}
|
||||
},
|
||||
"condition": {
|
||||
"always": {}
|
||||
},
|
||||
"actions": {
|
||||
"create_jira_issue": {
|
||||
"jira": {
|
||||
"account": "test",
|
||||
"fields": {
|
||||
"summary": "Jira watch with custom field of string type",
|
||||
"description": "Issue created by the REST integration test [/watcher/actions/10_jira.yaml]",
|
||||
"issuetype" : {
|
||||
"name": "Bug"
|
||||
},
|
||||
"customfield_70000": "jira-software-users"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
- match: { _id: "jira_watch_with_custom_field_one" }
|
||||
- match: { created: true }
|
||||
|
||||
- do:
|
||||
xpack.watcher.execute_watch:
|
||||
id: "jira_watch_with_custom_field_one"
|
||||
body: >
|
||||
{
|
||||
"trigger_data" : {
|
||||
"triggered_time" : "2012-12-12T12:12:12.120Z",
|
||||
"scheduled_time" : "2000-12-12T12:12:12.120Z"
|
||||
},
|
||||
"record_execution": true
|
||||
}
|
||||
|
||||
- match: { watch_record.watch_id: "jira_watch_with_custom_field_one" }
|
||||
- match: { watch_record.state: "executed" }
|
||||
|
||||
- do:
|
||||
xpack.watcher.put_watch:
|
||||
id: "jira_watch_with_custom_field_two"
|
||||
body: >
|
||||
{
|
||||
"trigger": {
|
||||
"schedule": {
|
||||
"interval": "1s"
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"simple": {
|
||||
}
|
||||
},
|
||||
"condition": {
|
||||
"always": {}
|
||||
},
|
||||
"actions": {
|
||||
"create_jira_issue": {
|
||||
"jira": {
|
||||
"account": "test",
|
||||
"fields": {
|
||||
"summary": "Jira watch with custom field of object (Jira's CascadingSelectField) type",
|
||||
"description": "Issue created by the REST integration test [/watcher/actions/10_jira.yaml]",
|
||||
"issuetype" : {
|
||||
"name": "Bug"
|
||||
},
|
||||
"customfield_70000": {
|
||||
"value": "green",
|
||||
"child": {
|
||||
"value":"blue"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
- match: { _id: "jira_watch_with_custom_field_two" }
|
||||
- match: { created: true }
|
||||
|
||||
- do:
|
||||
xpack.watcher.execute_watch:
|
||||
id: "jira_watch_with_custom_field_two"
|
||||
body: >
|
||||
{
|
||||
"trigger_data" : {
|
||||
"triggered_time" : "2012-12-12T12:12:12.120Z",
|
||||
"scheduled_time" : "2000-12-12T12:12:12.120Z"
|
||||
},
|
||||
"record_execution": true
|
||||
}
|
||||
|
||||
- match: { watch_record.watch_id: "jira_watch_with_custom_field_two" }
|
||||
- match: { watch_record.state: "executed" }
|
||||
|
||||
- do:
|
||||
indices.refresh:
|
||||
index: ".watcher-history-*"
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: ".watcher-history-*"
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
result.actions.status: "failure"
|
||||
|
||||
- match: { hits.total: 2 }
|
||||
|
|
Loading…
Reference in New Issue