Skip to content

Commit 5c7b2c5

Browse files
authored
HLRC: Add get watch API (#35531)
This changes adds the support for the get watch API in the high level rest client.
1 parent fa3d365 commit 5c7b2c5

File tree

15 files changed

+676
-15
lines changed

15 files changed

+676
-15
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherClient.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import org.elasticsearch.client.watcher.ActivateWatchResponse;
2727
import org.elasticsearch.client.watcher.AckWatchRequest;
2828
import org.elasticsearch.client.watcher.AckWatchResponse;
29+
import org.elasticsearch.client.watcher.GetWatchRequest;
30+
import org.elasticsearch.client.watcher.GetWatchResponse;
2931
import org.elasticsearch.client.watcher.StartWatchServiceRequest;
3032
import org.elasticsearch.client.watcher.StopWatchServiceRequest;
3133
import org.elasticsearch.client.watcher.DeleteWatchRequest;
@@ -129,6 +131,34 @@ public void putWatchAsync(PutWatchRequest request, RequestOptions options,
129131
PutWatchResponse::fromXContent, listener, emptySet());
130132
}
131133

134+
/**
135+
* Gets a watch from the cluster
136+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-get-watch.html">
137+
* the docs</a> for more.
138+
* @param request the request
139+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
140+
* @return the response
141+
* @throws IOException in case there is a problem sending the request or parsing back the response
142+
*/
143+
public GetWatchResponse getWatch(GetWatchRequest request, RequestOptions options) throws IOException {
144+
return restHighLevelClient.performRequestAndParseEntity(request, WatcherRequestConverters::getWatch, options,
145+
GetWatchResponse::fromXContent, emptySet());
146+
}
147+
148+
/**
149+
* Asynchronously gets a watch into the cluster
150+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-get-watch.html">
151+
* the docs</a> for more.
152+
* @param request the request
153+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
154+
* @param listener the listener to be notified upon request completion
155+
*/
156+
public void getWatchAsync(GetWatchRequest request, RequestOptions options,
157+
ActionListener<GetWatchResponse> listener) {
158+
restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::getWatch, options,
159+
GetWatchResponse::fromXContent, listener, emptySet());
160+
}
161+
132162
/**
133163
* Deactivate an existing watch
134164
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-deactivate-watch.html">

client/rest-high-level/src/main/java/org/elasticsearch/client/WatcherRequestConverters.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@
2828
import org.elasticsearch.client.watcher.DeactivateWatchRequest;
2929
import org.elasticsearch.client.watcher.ActivateWatchRequest;
3030
import org.elasticsearch.client.watcher.AckWatchRequest;
31+
import org.elasticsearch.client.watcher.DeleteWatchRequest;
32+
import org.elasticsearch.client.watcher.GetWatchRequest;
33+
import org.elasticsearch.client.watcher.PutWatchRequest;
3134
import org.elasticsearch.client.watcher.StartWatchServiceRequest;
3235
import org.elasticsearch.client.watcher.StopWatchServiceRequest;
3336
import org.elasticsearch.client.watcher.WatcherStatsRequest;
3437
import org.elasticsearch.common.bytes.BytesReference;
35-
import org.elasticsearch.client.watcher.DeleteWatchRequest;
36-
import org.elasticsearch.client.watcher.PutWatchRequest;
3738

3839
final class WatcherRequestConverters {
3940

@@ -76,6 +77,16 @@ static Request putWatch(PutWatchRequest putWatchRequest) {
7677
return request;
7778
}
7879

80+
81+
static Request getWatch(GetWatchRequest getWatchRequest) {
82+
String endpoint = new RequestConverters.EndpointBuilder()
83+
.addPathPartAsIs("_xpack", "watcher", "watch")
84+
.addPathPart(getWatchRequest.getId())
85+
.build();
86+
87+
return new Request(HttpGet.METHOD_NAME, endpoint);
88+
}
89+
7990
static Request deactivateWatch(DeactivateWatchRequest deactivateWatchRequest) {
8091
String endpoint = new RequestConverters.EndpointBuilder()
8192
.addPathPartAsIs("_xpack")
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.watcher;
20+
21+
import org.elasticsearch.client.Validatable;
22+
import org.elasticsearch.client.ValidationException;
23+
24+
/**
25+
* The request to get the watch by name (id)
26+
*/
27+
public final class GetWatchRequest implements Validatable {
28+
29+
private final String id;
30+
31+
public GetWatchRequest(String watchId) {
32+
validateId(watchId);
33+
this.id = watchId;
34+
}
35+
36+
private void validateId(String id) {
37+
ValidationException exception = new ValidationException();
38+
if (id == null) {
39+
exception.addValidationError("watch id is missing");
40+
} else if (PutWatchRequest.isValidId(id) == false) {
41+
exception.addValidationError("watch id contains whitespace");
42+
}
43+
if (exception.validationErrors().isEmpty() == false) {
44+
throw exception;
45+
}
46+
}
47+
48+
/**
49+
* @return The name of the watch to retrieve
50+
*/
51+
public String getId() {
52+
return id;
53+
}
54+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.watcher;
20+
21+
import org.elasticsearch.common.ParseField;
22+
import org.elasticsearch.common.bytes.BytesReference;
23+
import org.elasticsearch.common.lucene.uid.Versions;
24+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
25+
import org.elasticsearch.common.xcontent.XContentBuilder;
26+
import org.elasticsearch.common.xcontent.XContentHelper;
27+
import org.elasticsearch.common.xcontent.XContentParser;
28+
import org.elasticsearch.common.xcontent.XContentType;
29+
30+
import java.io.IOException;
31+
import java.util.Map;
32+
import java.util.Objects;
33+
34+
public class GetWatchResponse {
35+
private final String id;
36+
private final long version;
37+
private final WatchStatus status;
38+
39+
private final BytesReference source;
40+
private final XContentType xContentType;
41+
42+
/**
43+
* Ctor for missing watch
44+
*/
45+
public GetWatchResponse(String id) {
46+
this(id, Versions.NOT_FOUND, null, null, null);
47+
}
48+
49+
public GetWatchResponse(String id, long version, WatchStatus status, BytesReference source, XContentType xContentType) {
50+
this.id = id;
51+
this.version = version;
52+
this.status = status;
53+
this.source = source;
54+
this.xContentType = xContentType;
55+
}
56+
57+
public String getId() {
58+
return id;
59+
}
60+
61+
public long getVersion() {
62+
return version;
63+
}
64+
65+
public boolean isFound() {
66+
return version != Versions.NOT_FOUND;
67+
}
68+
69+
public WatchStatus getStatus() {
70+
return status;
71+
}
72+
73+
/**
74+
* Returns the {@link XContentType} of the source
75+
*/
76+
public XContentType getContentType() {
77+
return xContentType;
78+
}
79+
80+
/**
81+
* Returns the serialized watch
82+
*/
83+
public BytesReference getSource() {
84+
return source;
85+
}
86+
87+
/**
88+
* Returns the source as a map
89+
*/
90+
public Map<String, Object> getSourceAsMap() {
91+
return source == null ? null : XContentHelper.convertToMap(source, false, getContentType()).v2();
92+
}
93+
94+
@Override
95+
public boolean equals(Object o) {
96+
if (this == o) return true;
97+
if (o == null || getClass() != o.getClass()) return false;
98+
GetWatchResponse that = (GetWatchResponse) o;
99+
return version == that.version &&
100+
Objects.equals(id, that.id) &&
101+
Objects.equals(status, that.status) &&
102+
Objects.equals(xContentType, that.xContentType) &&
103+
Objects.equals(source, that.source);
104+
}
105+
106+
@Override
107+
public int hashCode() {
108+
return Objects.hash(id, status, source, version);
109+
}
110+
111+
private static final ParseField ID_FIELD = new ParseField("_id");
112+
private static final ParseField FOUND_FIELD = new ParseField("found");
113+
private static final ParseField VERSION_FIELD = new ParseField("_version");
114+
private static final ParseField STATUS_FIELD = new ParseField("status");
115+
private static final ParseField WATCH_FIELD = new ParseField("watch");
116+
117+
private static ConstructingObjectParser<GetWatchResponse, Void> PARSER =
118+
new ConstructingObjectParser<>("get_watch_response", true,
119+
a -> {
120+
boolean isFound = (boolean) a[1];
121+
if (isFound) {
122+
XContentBuilder builder = (XContentBuilder) a[4];
123+
BytesReference source = BytesReference.bytes(builder);
124+
return new GetWatchResponse((String) a[0], (long) a[2], (WatchStatus) a[3], source, builder.contentType());
125+
} else {
126+
return new GetWatchResponse((String) a[0]);
127+
}
128+
});
129+
130+
static {
131+
PARSER.declareString(ConstructingObjectParser.constructorArg(), ID_FIELD);
132+
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), FOUND_FIELD);
133+
PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), VERSION_FIELD);
134+
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(),
135+
(parser, context) -> WatchStatus.parse(parser), STATUS_FIELD);
136+
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(),
137+
(parser, context) -> {
138+
try (XContentBuilder builder = XContentBuilder.builder(parser.contentType().xContent())) {
139+
builder.copyCurrentStructure(parser);
140+
return builder;
141+
}
142+
}, WATCH_FIELD);
143+
}
144+
145+
public static GetWatchResponse fromXContent(XContentParser parser) throws IOException {
146+
return PARSER.parse(parser, null);
147+
}
148+
}

client/rest-high-level/src/main/java/org/elasticsearch/client/watcher/WatchStatus.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.client.watcher;
2121

2222
import org.elasticsearch.ElasticsearchParseException;
23+
import org.elasticsearch.common.Nullable;
2324
import org.elasticsearch.common.ParseField;
2425
import org.elasticsearch.common.xcontent.XContentParser;
2526
import org.joda.time.DateTime;
@@ -44,19 +45,22 @@ public class WatchStatus {
4445
private final DateTime lastMetCondition;
4546
private final long version;
4647
private final Map<String, ActionStatus> actions;
48+
@Nullable private Map<String, String> headers;
4749

4850
public WatchStatus(long version,
4951
State state,
5052
ExecutionState executionState,
5153
DateTime lastChecked,
5254
DateTime lastMetCondition,
53-
Map<String, ActionStatus> actions) {
55+
Map<String, ActionStatus> actions,
56+
Map<String, String> headers) {
5457
this.version = version;
5558
this.lastChecked = lastChecked;
5659
this.lastMetCondition = lastMetCondition;
5760
this.actions = actions;
5861
this.state = state;
5962
this.executionState = executionState;
63+
this.headers = headers;
6064
}
6165

6266
public State state() {
@@ -79,6 +83,10 @@ public ActionStatus actionStatus(String actionId) {
7983
return actions.get(actionId);
8084
}
8185

86+
public Map<String, ActionStatus> getActions() {
87+
return actions;
88+
}
89+
8290
public long version() {
8391
return version;
8492
}
@@ -87,6 +95,10 @@ public ExecutionState getExecutionState() {
8795
return executionState;
8896
}
8997

98+
public Map<String, String> getHeaders() {
99+
return headers;
100+
}
101+
90102
@Override
91103
public boolean equals(Object o) {
92104
if (this == o) return true;
@@ -98,7 +110,8 @@ public boolean equals(Object o) {
98110
Objects.equals(lastMetCondition, that.lastMetCondition) &&
99111
Objects.equals(version, that.version) &&
100112
Objects.equals(executionState, that.executionState) &&
101-
Objects.equals(actions, that.actions);
113+
Objects.equals(actions, that.actions) &&
114+
Objects.equals(headers, that.headers);
102115
}
103116

104117
@Override
@@ -112,6 +125,7 @@ public static WatchStatus parse(XContentParser parser) throws IOException {
112125
DateTime lastChecked = null;
113126
DateTime lastMetCondition = null;
114127
Map<String, ActionStatus> actions = null;
128+
Map<String, String> headers = null;
115129
long version = -1;
116130

117131
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation);
@@ -172,13 +186,17 @@ public static WatchStatus parse(XContentParser parser) throws IOException {
172186
throw new ElasticsearchParseException("could not parse watch status. expecting field [{}] to be an object, " +
173187
"found [{}] instead", currentFieldName, token);
174188
}
189+
} else if (Field.HEADERS.match(currentFieldName, parser.getDeprecationHandler())) {
190+
if (token == XContentParser.Token.START_OBJECT) {
191+
headers = parser.mapStrings();
192+
}
175193
} else {
176194
parser.skipChildren();
177195
}
178196
}
179197

180198
actions = actions == null ? emptyMap() : unmodifiableMap(actions);
181-
return new WatchStatus(version, state, executionState, lastChecked, lastMetCondition, actions);
199+
return new WatchStatus(version, state, executionState, lastChecked, lastMetCondition, actions, headers);
182200
}
183201

184202
public static class State {
@@ -214,6 +232,8 @@ public static State parse(XContentParser parser) throws IOException {
214232
active = parser.booleanValue();
215233
} else if (Field.TIMESTAMP.match(currentFieldName, parser.getDeprecationHandler())) {
216234
timestamp = parseDate(currentFieldName, parser);
235+
} else {
236+
parser.skipChildren();
217237
}
218238
}
219239
return new State(active, timestamp);
@@ -229,5 +249,6 @@ public interface Field {
229249
ParseField ACTIONS = new ParseField("actions");
230250
ParseField VERSION = new ParseField("version");
231251
ParseField EXECUTION_STATE = new ParseField("execution_state");
252+
ParseField HEADERS = new ParseField("headers");
232253
}
233254
}

0 commit comments

Comments
 (0)