Skip to content

Commit 3ccb7af

Browse files
authored
HLRC: Add activate watch action (#33988)
* HLRC: Add activate watcher action Adds activate watch action to the high level rest client. Relates #29827
1 parent f817bc5 commit 3ccb7af

File tree

10 files changed

+442
-0
lines changed

10 files changed

+442
-0
lines changed

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
package org.elasticsearch.client;
2020

2121
import org.elasticsearch.action.ActionListener;
22+
import org.elasticsearch.client.watcher.ActivateWatchRequest;
23+
import org.elasticsearch.client.watcher.ActivateWatchResponse;
2224
import org.elasticsearch.client.watcher.AckWatchRequest;
2325
import org.elasticsearch.client.watcher.AckWatchResponse;
2426
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
@@ -121,4 +123,31 @@ public void ackWatchAsync(AckWatchRequest request, RequestOptions options, Actio
121123
AckWatchResponse::fromXContent, listener, emptySet());
122124
}
123125

126+
/**
127+
* Activate a watch from the cluster
128+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-activate-watch.html">
129+
* the docs</a> for more.
130+
* @param request the request
131+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
132+
* @return the response
133+
* @throws IOException in case there is a problem sending the request or parsing back the response
134+
*/
135+
public ActivateWatchResponse activateWatch(ActivateWatchRequest request, RequestOptions options) throws IOException {
136+
return restHighLevelClient.performRequestAndParseEntity(request, WatcherRequestConverters::activateWatch, options,
137+
ActivateWatchResponse::fromXContent, singleton(404));
138+
}
139+
140+
/**
141+
* Asynchronously activates a watch from the cluster
142+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-activate-watch.html">
143+
* the docs</a> for more.
144+
* @param request the request
145+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
146+
* @param listener the listener to be notified upon request completion
147+
*/
148+
public void activateWatchAsync(ActivateWatchRequest request, RequestOptions options, ActionListener<ActivateWatchResponse> listener) {
149+
restHighLevelClient.performRequestAsyncAndParseEntity(request, WatcherRequestConverters::activateWatch, options,
150+
ActivateWatchResponse::fromXContent, listener, singleton(404));
151+
}
152+
124153
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.apache.http.client.methods.HttpPut;
2424
import org.apache.http.entity.ByteArrayEntity;
2525
import org.apache.http.entity.ContentType;
26+
import org.elasticsearch.client.watcher.ActivateWatchRequest;
2627
import org.elasticsearch.client.watcher.AckWatchRequest;
2728
import org.elasticsearch.common.bytes.BytesReference;
2829
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
@@ -73,4 +74,16 @@ public static Request ackWatch(AckWatchRequest ackWatchRequest) {
7374
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
7475
return request;
7576
}
77+
78+
static Request activateWatch(ActivateWatchRequest activateWatchRequest) {
79+
String endpoint = new RequestConverters.EndpointBuilder()
80+
.addPathPartAsIs("_xpack")
81+
.addPathPartAsIs("watcher")
82+
.addPathPartAsIs("watch")
83+
.addPathPart(activateWatchRequest.getWatchId())
84+
.addPathPartAsIs("_activate")
85+
.build();
86+
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
87+
return request;
88+
}
7689
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
20+
package org.elasticsearch.client.watcher;
21+
22+
import org.elasticsearch.client.Validatable;
23+
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
24+
25+
import java.util.Objects;
26+
27+
/**
28+
* A request to explicitly activate a watch.
29+
*/
30+
public final class ActivateWatchRequest implements Validatable {
31+
32+
private final String watchId;
33+
34+
public ActivateWatchRequest(String watchId) {
35+
this.watchId = Objects.requireNonNull(watchId, "Watch identifier is required");
36+
if (PutWatchRequest.isValidId(this.watchId) == false) {
37+
throw new IllegalArgumentException("Watch identifier contains whitespace");
38+
}
39+
}
40+
41+
/**
42+
* @return The ID of the watch to be activated.
43+
*/
44+
public String getWatchId() {
45+
return watchId;
46+
}
47+
48+
@Override
49+
public boolean equals(Object o) {
50+
if (this == o) return true;
51+
if (o == null || getClass() != o.getClass()) return false;
52+
ActivateWatchRequest that = (ActivateWatchRequest) o;
53+
return Objects.equals(watchId, that.watchId);
54+
}
55+
56+
@Override
57+
public int hashCode() {
58+
int result = Objects.hash(watchId);
59+
return result;
60+
}
61+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
20+
package org.elasticsearch.client.watcher;
21+
22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
24+
import org.elasticsearch.common.xcontent.XContentParser;
25+
26+
import java.io.IOException;
27+
import java.util.Objects;
28+
29+
/**
30+
* Response from an 'activate watch' request.
31+
*/
32+
public final class ActivateWatchResponse {
33+
34+
private static final ParseField STATUS_FIELD = new ParseField("status");
35+
private static ConstructingObjectParser<ActivateWatchResponse, Void> PARSER =
36+
new ConstructingObjectParser<>("activate_watch_response", true,
37+
a -> new ActivateWatchResponse((WatchStatus) a[0]));
38+
39+
static {
40+
PARSER.declareObject(ConstructingObjectParser.constructorArg(),
41+
(parser, context) -> WatchStatus.parse(parser),
42+
STATUS_FIELD);
43+
}
44+
45+
private final WatchStatus status;
46+
47+
public ActivateWatchResponse(WatchStatus status) {
48+
this.status = status;
49+
}
50+
51+
public WatchStatus getStatus() {
52+
return status;
53+
}
54+
55+
@Override
56+
public boolean equals(Object o) {
57+
if (this == o) return true;
58+
if (o == null || getClass() != o.getClass()) return false;
59+
ActivateWatchResponse that = (ActivateWatchResponse) o;
60+
return Objects.equals(status, that.status);
61+
}
62+
63+
@Override
64+
public int hashCode() {
65+
return Objects.hash(status);
66+
}
67+
68+
public static ActivateWatchResponse fromXContent(XContentParser parser) throws IOException {
69+
return PARSER.parse(parser, null);
70+
}
71+
}

client/rest-high-level/src/test/java/org/elasticsearch/client/WatcherIT.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
package org.elasticsearch.client;
2020

2121
import org.elasticsearch.ElasticsearchStatusException;
22+
import org.elasticsearch.client.watcher.ActivateWatchRequest;
23+
import org.elasticsearch.client.watcher.ActivateWatchResponse;
2224
import org.elasticsearch.client.watcher.AckWatchRequest;
2325
import org.elasticsearch.client.watcher.AckWatchResponse;
2426
import org.elasticsearch.client.watcher.ActionStatus;
@@ -33,6 +35,7 @@
3335
import org.elasticsearch.rest.RestStatus;
3436

3537
import static org.hamcrest.Matchers.is;
38+
import static org.hamcrest.Matchers.lessThan;
3639

3740
public class WatcherIT extends ESRestHighLevelClientTestCase {
3841

@@ -108,4 +111,26 @@ public void testAckWatch() throws Exception {
108111
new AckWatchRequest("nonexistent"), RequestOptions.DEFAULT));
109112
assertEquals(RestStatus.NOT_FOUND, exception.status());
110113
}
114+
115+
public void testActivateWatchThatExists() throws Exception {
116+
String watchId = randomAlphaOfLength(10);
117+
createWatch(watchId);
118+
ActivateWatchResponse activateWatchResponse1 = highLevelClient().watcher().activateWatch(new ActivateWatchRequest(watchId),
119+
RequestOptions.DEFAULT);
120+
assertThat(activateWatchResponse1.getStatus().state().isActive(), is(true));
121+
122+
ActivateWatchResponse activateWatchResponse2 = highLevelClient().watcher().activateWatch(new ActivateWatchRequest(watchId),
123+
RequestOptions.DEFAULT);
124+
assertThat(activateWatchResponse2.getStatus().state().isActive(), is(true));
125+
assertThat(activateWatchResponse1.getStatus().state().getTimestamp(),
126+
lessThan(activateWatchResponse2.getStatus().state().getTimestamp()));
127+
}
128+
129+
public void testActivateWatchThatDoesNotExist() throws Exception {
130+
String watchId = randomAlphaOfLength(10);
131+
// exception when activating a not existing watcher
132+
ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, () ->
133+
highLevelClient().watcher().activateWatch(new ActivateWatchRequest(watchId), RequestOptions.DEFAULT));
134+
assertEquals(RestStatus.NOT_FOUND, exception.status());
135+
}
111136
}

client/rest-high-level/src/test/java/org/elasticsearch/client/WatcherRequestConvertersTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.apache.http.client.methods.HttpDelete;
2323
import org.apache.http.client.methods.HttpPut;
24+
import org.elasticsearch.client.watcher.ActivateWatchRequest;
2425
import org.elasticsearch.client.watcher.AckWatchRequest;
2526
import org.elasticsearch.common.bytes.BytesArray;
2627
import org.elasticsearch.common.xcontent.XContentType;
@@ -97,4 +98,14 @@ public void testAckWatch() {
9798
assertEquals(expectedEndpoint.toString(), request.getEndpoint());
9899
assertThat(request.getEntity(), nullValue());
99100
}
101+
102+
public void testActivateWatchRequestConversion() {
103+
String watchId = randomAlphaOfLength(10);
104+
ActivateWatchRequest activateWatchRequest = new ActivateWatchRequest(watchId);
105+
106+
Request request = WatcherRequestConverters.activateWatch(activateWatchRequest);
107+
assertEquals(HttpPut.METHOD_NAME, request.getMethod());
108+
assertEquals("/_xpack/watcher/watch/" + watchId + "/_activate", request.getEndpoint());
109+
assertThat(request.getEntity(), nullValue());
110+
}
100111
}

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/WatcherDocumentationIT.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.elasticsearch.client.RequestOptions;
2626
import org.elasticsearch.client.Response;
2727
import org.elasticsearch.client.RestHighLevelClient;
28+
import org.elasticsearch.client.watcher.ActivateWatchRequest;
29+
import org.elasticsearch.client.watcher.ActivateWatchResponse;
2830
import org.elasticsearch.client.watcher.AckWatchRequest;
2931
import org.elasticsearch.client.watcher.AckWatchResponse;
3032
import org.elasticsearch.client.watcher.ActionStatus;
@@ -203,4 +205,60 @@ public void onFailure(Exception e) {
203205
}
204206
}
205207

208+
public void testActivateWatch() throws Exception {
209+
RestHighLevelClient client = highLevelClient();
210+
211+
{
212+
BytesReference watch = new BytesArray("{ \n" +
213+
" \"trigger\": { \"schedule\": { \"interval\": \"10h\" } },\n" +
214+
" \"input\": { \"simple\": { \"foo\" : \"bar\" } },\n" +
215+
" \"actions\": { \"logme\": { \"logging\": { \"text\": \"{{ctx.payload}}\" } } }\n" +
216+
"}");
217+
PutWatchRequest request = new PutWatchRequest("my_watch_id", watch, XContentType.JSON);
218+
request.setActive(false); // <1>
219+
PutWatchResponse response = client.watcher().putWatch(request, RequestOptions.DEFAULT);
220+
}
221+
222+
{
223+
//tag::activate-watch-request
224+
ActivateWatchRequest request = new ActivateWatchRequest("my_watch_id");
225+
ActivateWatchResponse response = client.watcher().activateWatch(request, RequestOptions.DEFAULT);
226+
//end::activate-watch-request
227+
228+
//tag::activate-watch-request
229+
WatchStatus watchStatus = response.getStatus(); // <1>
230+
//end::activate-watch-request
231+
232+
assertTrue(watchStatus.state().isActive());
233+
}
234+
235+
{
236+
ActivateWatchRequest request = new ActivateWatchRequest("my_watch_id");
237+
//tag::activate-watch-request-listener
238+
ActionListener<ActivateWatchResponse> listener = new ActionListener<ActivateWatchResponse>() {
239+
@Override
240+
public void onResponse(ActivateWatchResponse response) {
241+
// <1>
242+
}
243+
244+
@Override
245+
public void onFailure(Exception e) {
246+
// <2>
247+
}
248+
};
249+
//end::activate-watch-request-listener
250+
251+
//Replace the empty listener by a blocking listener in test
252+
final CountDownLatch latch = new CountDownLatch(1);
253+
listener = new LatchedActionListener<>(listener, latch);
254+
255+
//tag::activate-watch-request-async
256+
client.watcher().activateWatchAsync(request, RequestOptions.DEFAULT, listener); // <1>
257+
//end::activate-watch-request-async
258+
259+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
260+
261+
}
262+
}
263+
206264
}

0 commit comments

Comments
 (0)