Skip to content

Commit d94406a

Browse files
authored
HLRC: Deactivate Watch API (#34192)
Relates to #29827
1 parent 3211760 commit d94406a

File tree

11 files changed

+348
-0
lines changed

11 files changed

+348
-0
lines changed

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

Lines changed: 31 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.DeactivateWatchRequest;
23+
import org.elasticsearch.client.watcher.DeactivateWatchResponse;
2224
import org.elasticsearch.action.support.master.AcknowledgedResponse;
2325
import org.elasticsearch.client.watcher.ActivateWatchRequest;
2426
import org.elasticsearch.client.watcher.ActivateWatchResponse;
@@ -125,6 +127,35 @@ public void putWatchAsync(PutWatchRequest request, RequestOptions options,
125127
PutWatchResponse::fromXContent, listener, emptySet());
126128
}
127129

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

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.http.client.methods.HttpPut;
2525
import org.apache.http.entity.ByteArrayEntity;
2626
import org.apache.http.entity.ContentType;
27+
import org.elasticsearch.client.watcher.DeactivateWatchRequest;
2728
import org.elasticsearch.client.watcher.ActivateWatchRequest;
2829
import org.elasticsearch.client.watcher.AckWatchRequest;
2930
import org.elasticsearch.client.watcher.StartWatchServiceRequest;
@@ -75,6 +76,17 @@ static Request putWatch(PutWatchRequest putWatchRequest) {
7576
return request;
7677
}
7778

79+
static Request deactivateWatch(DeactivateWatchRequest deactivateWatchRequest) {
80+
String endpoint = new RequestConverters.EndpointBuilder()
81+
.addPathPartAsIs("_xpack")
82+
.addPathPartAsIs("watcher")
83+
.addPathPartAsIs("watch")
84+
.addPathPart(deactivateWatchRequest.getWatchId())
85+
.addPathPartAsIs("_deactivate")
86+
.build();
87+
return new Request(HttpPut.METHOD_NAME, endpoint);
88+
}
89+
7890
static Request deleteWatch(DeleteWatchRequest deleteWatchRequest) {
7991
String endpoint = new RequestConverters.EndpointBuilder()
8092
.addPathPartAsIs("_xpack")
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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.protocol.xpack.watcher.PutWatchRequest;
23+
24+
import java.util.Objects;
25+
26+
public class DeactivateWatchRequest implements Validatable {
27+
private final String watchId;
28+
29+
public DeactivateWatchRequest(String watchId) {
30+
31+
Objects.requireNonNull(watchId, "watch id is missing");
32+
if (PutWatchRequest.isValidId(watchId) == false) {
33+
throw new IllegalArgumentException("watch id contains whitespace");
34+
}
35+
36+
this.watchId = watchId;
37+
}
38+
39+
public String getWatchId() {
40+
return watchId;
41+
}
42+
}
43+
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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.xcontent.ConstructingObjectParser;
23+
import org.elasticsearch.common.xcontent.XContentParser;
24+
25+
import java.io.IOException;
26+
import java.util.Objects;
27+
28+
public class DeactivateWatchResponse {
29+
private WatchStatus status;
30+
31+
private static final ParseField STATUS_FIELD = new ParseField("status");
32+
private static final ConstructingObjectParser<DeactivateWatchResponse, Void> PARSER
33+
= new ConstructingObjectParser<>("x_pack_deactivate_watch_response", true,
34+
(fields) -> new DeactivateWatchResponse((WatchStatus) fields[0]));
35+
static {
36+
PARSER.declareObject(ConstructingObjectParser.constructorArg(),
37+
(parser, context) -> WatchStatus.parse(parser),
38+
STATUS_FIELD);
39+
}
40+
41+
public static DeactivateWatchResponse fromXContent(XContentParser parser) throws IOException {
42+
return PARSER.parse(parser, null);
43+
}
44+
45+
public DeactivateWatchResponse(WatchStatus status) {
46+
this.status = status;
47+
}
48+
49+
@Override
50+
public boolean equals(Object o) {
51+
if (this == o) return true;
52+
if (o == null || getClass() != o.getClass()) return false;
53+
DeactivateWatchResponse that = (DeactivateWatchResponse) o;
54+
return Objects.equals(status, that.status);
55+
}
56+
57+
@Override
58+
public int hashCode() {
59+
return Objects.hash(status);
60+
}
61+
62+
public WatchStatus getStatus() {
63+
return status;
64+
}
65+
}

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

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

2121
import org.elasticsearch.ElasticsearchStatusException;
22+
import org.elasticsearch.client.watcher.DeactivateWatchRequest;
23+
import org.elasticsearch.client.watcher.DeactivateWatchResponse;
24+
import org.elasticsearch.client.watcher.ActivateWatchRequest;
25+
import org.elasticsearch.client.watcher.ActivateWatchResponse;
2226
import org.elasticsearch.action.support.master.AcknowledgedResponse;
2327
import org.elasticsearch.client.watcher.AckWatchRequest;
2428
import org.elasticsearch.client.watcher.AckWatchResponse;
@@ -73,6 +77,23 @@ private PutWatchResponse createWatch(String watchId) throws Exception {
7377
return highLevelClient().watcher().putWatch(putWatchRequest, RequestOptions.DEFAULT);
7478
}
7579

80+
public void testDeactivateWatch() throws Exception {
81+
// Deactivate a watch that exists
82+
String watchId = randomAlphaOfLength(10);
83+
createWatch(watchId);
84+
DeactivateWatchResponse response = highLevelClient().watcher().deactivateWatch(
85+
new DeactivateWatchRequest(watchId), RequestOptions.DEFAULT);
86+
assertThat(response.getStatus().state().isActive(), is(false));
87+
}
88+
public void testDeactivateWatch404() throws Exception {
89+
// Deactivate a watch that does not exist
90+
String watchId = randomAlphaOfLength(10);
91+
ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class,
92+
() -> highLevelClient().watcher().deactivateWatch(new DeactivateWatchRequest(watchId), RequestOptions.DEFAULT));
93+
assertEquals(RestStatus.NOT_FOUND, exception.status());
94+
95+
}
96+
7697
public void testDeleteWatch() throws Exception {
7798
// delete watch that exists
7899
{

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.http.client.methods.HttpDelete;
2323
import org.apache.http.client.methods.HttpPost;
2424
import org.apache.http.client.methods.HttpPut;
25+
import org.elasticsearch.client.watcher.DeactivateWatchRequest;
2526
import org.elasticsearch.client.watcher.ActivateWatchRequest;
2627
import org.elasticsearch.client.watcher.AckWatchRequest;
2728
import org.elasticsearch.client.watcher.StartWatchServiceRequest;
@@ -83,6 +84,15 @@ public void testPutWatch() throws Exception {
8384
assertThat(bos.toString("UTF-8"), is(body));
8485
}
8586

87+
public void testDeactivateWatch() {
88+
String watchId = randomAlphaOfLength(10);
89+
DeactivateWatchRequest deactivateWatchRequest = new DeactivateWatchRequest(watchId);
90+
Request request = WatcherRequestConverters.deactivateWatch(deactivateWatchRequest);
91+
92+
assertEquals(HttpPut.METHOD_NAME, request.getMethod());
93+
assertEquals("/_xpack/watcher/watch/" + watchId + "/_deactivate", request.getEndpoint());
94+
}
95+
8696
public void testDeleteWatch() {
8797
DeleteWatchRequest deleteWatchRequest = new DeleteWatchRequest();
8898
String watchId = randomAlphaOfLength(10);

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.elasticsearch.client.watcher.AckWatchResponse;
3333
import org.elasticsearch.client.watcher.ActionStatus;
3434
import org.elasticsearch.client.watcher.ActionStatus.AckStatus;
35+
import org.elasticsearch.client.watcher.DeactivateWatchRequest;
36+
import org.elasticsearch.client.watcher.DeactivateWatchResponse;
3537
import org.elasticsearch.client.watcher.StartWatchServiceRequest;
3638
import org.elasticsearch.client.watcher.StopWatchServiceRequest;
3739
import org.elasticsearch.client.watcher.WatchStatus;
@@ -47,6 +49,8 @@
4749
import java.util.concurrent.CountDownLatch;
4850
import java.util.concurrent.TimeUnit;
4951

52+
import static org.hamcrest.Matchers.is;
53+
5054
public class WatcherDocumentationIT extends ESRestHighLevelClientTestCase {
5155

5256
public void testStartStopWatchService() throws Exception {
@@ -297,6 +301,57 @@ public void onFailure(Exception e) {
297301
}
298302
}
299303

304+
public void testDeactivateWatch() throws Exception {
305+
RestHighLevelClient client = highLevelClient();
306+
307+
{
308+
BytesReference watch = new BytesArray("{ \n" +
309+
" \"trigger\": { \"schedule\": { \"interval\": \"10h\" } },\n" +
310+
" \"input\": { \"simple\": { \"foo\" : \"bar\" } },\n" +
311+
" \"actions\": { \"logme\": { \"logging\": { \"text\": \"{{ctx.payload}}\" } } }\n" +
312+
"}");
313+
PutWatchRequest putWatchRequest = new PutWatchRequest("my_watch_id", watch, XContentType.JSON);
314+
client.watcher().putWatch(putWatchRequest, RequestOptions.DEFAULT);
315+
}
316+
317+
{
318+
//tag::deactivate-watch-execute
319+
DeactivateWatchRequest request = new DeactivateWatchRequest("my_watch_id");
320+
DeactivateWatchResponse response = client.watcher().deactivateWatch(request, RequestOptions.DEFAULT);
321+
//end::deactivate-watch-execute
322+
323+
assertThat(response.getStatus().state().isActive(), is(false));
324+
}
325+
326+
{
327+
DeactivateWatchRequest request = new DeactivateWatchRequest("my_watch_id");
328+
// tag::deactivate-watch-execute-listener
329+
ActionListener<DeactivateWatchResponse> listener = new ActionListener<DeactivateWatchResponse>() {
330+
@Override
331+
public void onResponse(DeactivateWatchResponse response) {
332+
// <1>
333+
}
334+
335+
@Override
336+
public void onFailure(Exception e) {
337+
// <2>
338+
}
339+
};
340+
// end::deactivate-watch-execute-listener
341+
342+
// For testing, replace the empty listener by a blocking listener.
343+
final CountDownLatch latch = new CountDownLatch(1);
344+
listener = new LatchedActionListener<>(listener, latch);
345+
346+
// tag::deactivate-watch-execute-async
347+
client.watcher().deactivateWatchAsync(request, RequestOptions.DEFAULT, listener); // <1>
348+
// end::deactivate-watch-execute-async
349+
350+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
351+
}
352+
}
353+
354+
300355
public void testActivateWatch() throws Exception {
301356
RestHighLevelClient client = highLevelClient();
302357

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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.test.ESTestCase;
23+
24+
import static org.hamcrest.Matchers.is;
25+
26+
public class DeactivateWatchRequestTests extends ESTestCase {
27+
28+
public void testNullId() {
29+
NullPointerException actual = expectThrows(NullPointerException.class, () -> new DeactivateWatchRequest(null));
30+
assertNotNull(actual);
31+
assertThat(actual.getMessage(), is("watch id is missing"));
32+
}
33+
34+
public void testInvalidId() {
35+
IllegalArgumentException actual = expectThrows(IllegalArgumentException.class,
36+
() -> new DeactivateWatchRequest("Watch id has spaces"));
37+
assertNotNull(actual);
38+
assertThat(actual.getMessage(), is("watch id contains whitespace"));
39+
}
40+
41+
}

0 commit comments

Comments
 (0)