Skip to content

Commit 54ecb00

Browse files
committed
Add delete autoscaling policy API (#54601)
This commit adds an API for deleting autoscaling policies.
1 parent b4feda8 commit 54ecb00

File tree

10 files changed

+518
-1
lines changed

10 files changed

+518
-1
lines changed

docs/reference/autoscaling/apis/autoscaling-apis.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ You can use the following APIs to perform autoscaling operations.
1010
=== Top-Level
1111

1212
* <<autoscaling-get-autoscaling-decision,Get autoscaling decision>>
13+
* <<autoscaling-delete-autoscaling-policy,Delete autoscaling policy>>
1314
* <<autoscaling-put-autoscaling-policy,Put autoscaling policy>>
1415

1516
// top-level
1617
include::get-autoscaling-decision.asciidoc[]
18+
include::delete-autoscaling-policy.asciidoc[]
1719
include::put-autoscaling-policy.asciidoc[]
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
[role="xpack"]
2+
[testenv="platinum"]
3+
[[autoscaling-delete-autoscaling-policy]]
4+
=== Delete autoscaling policy API
5+
++++
6+
<titleabbrev>Delete autoscaling policy</titleabbrev>
7+
++++
8+
9+
Delete autoscaling policy.
10+
11+
[[autoscaling-delete-autoscaling-policy-request]]
12+
==== {api-request-title}
13+
14+
[source,console]
15+
--------------------------------------------------
16+
PUT /_autoscaling/policy/my_autoscaling_policy
17+
{
18+
"policy": {
19+
"deciders": {
20+
"always": {
21+
}
22+
}
23+
}
24+
}
25+
--------------------------------------------------
26+
// TESTSETUP
27+
28+
[source,console]
29+
--------------------------------------------------
30+
DELETE /_autoscaling/policy/<name>
31+
--------------------------------------------------
32+
// TEST[s/<name>/my_autoscaling_policy/]
33+
34+
[[autoscaling-delete-autoscaling-policy-prereqs]]
35+
==== {api-prereq-title}
36+
37+
* If the {es} {security-features} are enabled, you must have
38+
`manage_autoscaling` cluster privileges. For more information, see
39+
<<security-privileges>>.
40+
41+
[[autoscaling-delete-autoscaling-policy-desc]]
42+
==== {api-description-title}
43+
44+
This API deletes an autoscaling policy with the provided name.
45+
46+
[[autoscaling-delete-autoscaling-policy-examples]]
47+
==== {api-examples-title}
48+
49+
This example deletes an autoscaling policy named `my_autosaling_policy`.
50+
51+
[source,console]
52+
--------------------------------------------------
53+
DELETE /_autoscaling/policy/my_autoscaling_policy
54+
--------------------------------------------------
55+
// TEST
56+
57+
The API returns the following result:
58+
59+
[source,console-result]
60+
--------------------------------------------------
61+
{
62+
"acknowledged": true
63+
}
64+
--------------------------------------------------
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
"Test delete autoscaling policy":
3+
- do:
4+
autoscaling.put_autoscaling_policy:
5+
name: hot
6+
body:
7+
policy:
8+
deciders:
9+
always: {}
10+
11+
- match: { "acknowledged": true }
12+
13+
- do:
14+
autoscaling.delete_autoscaling_policy:
15+
name: hot
16+
17+
# TODO: add validation that the policy is removed after we have a get policy API
18+
19+
- do:
20+
catch: bad_request
21+
autoscaling.delete_autoscaling_policy:
22+
name: does_not_exist

x-pack/plugin/autoscaling/src/main/java/org/elasticsearch/xpack/autoscaling/Autoscaling.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
import org.elasticsearch.plugins.Plugin;
2727
import org.elasticsearch.rest.RestController;
2828
import org.elasticsearch.rest.RestHandler;
29+
import org.elasticsearch.xpack.autoscaling.action.DeleteAutoscalingPolicyAction;
2930
import org.elasticsearch.xpack.autoscaling.action.GetAutoscalingDecisionAction;
3031
import org.elasticsearch.xpack.autoscaling.action.PutAutoscalingPolicyAction;
32+
import org.elasticsearch.xpack.autoscaling.action.TransportDeleteAutoscalingPolicyAction;
3133
import org.elasticsearch.xpack.autoscaling.action.TransportGetAutoscalingDecisionAction;
3234
import org.elasticsearch.xpack.autoscaling.action.TransportPutAutoscalingPolicyAction;
3335
import org.elasticsearch.xpack.autoscaling.decision.AlwaysAutoscalingDecider;
3436
import org.elasticsearch.xpack.autoscaling.decision.AutoscalingDecider;
37+
import org.elasticsearch.xpack.autoscaling.rest.RestDeleteAutoscalingPolicyActionHandler;
3538
import org.elasticsearch.xpack.autoscaling.rest.RestGetAutoscalingDecisionHandler;
3639
import org.elasticsearch.xpack.autoscaling.rest.RestPutAutoscalingPolicyHandler;
3740
import org.elasticsearch.xpack.core.XPackPlugin;
@@ -99,6 +102,7 @@ boolean isSnapshot() {
99102
if (enabled) {
100103
return org.elasticsearch.common.collect.List.of(
101104
new ActionHandler<>(GetAutoscalingDecisionAction.INSTANCE, TransportGetAutoscalingDecisionAction.class),
105+
new ActionHandler<>(DeleteAutoscalingPolicyAction.INSTANCE, TransportDeleteAutoscalingPolicyAction.class),
102106
new ActionHandler<>(PutAutoscalingPolicyAction.INSTANCE, TransportPutAutoscalingPolicyAction.class)
103107
);
104108
} else {
@@ -117,7 +121,11 @@ public List<RestHandler> getRestHandlers(
117121
final Supplier<DiscoveryNodes> nodesInCluster
118122
) {
119123
if (enabled) {
120-
return org.elasticsearch.common.collect.List.of(new RestGetAutoscalingDecisionHandler(), new RestPutAutoscalingPolicyHandler());
124+
return org.elasticsearch.common.collect.List.of(
125+
new RestGetAutoscalingDecisionHandler(),
126+
new RestDeleteAutoscalingPolicyActionHandler(),
127+
new RestPutAutoscalingPolicyHandler()
128+
);
121129
} else {
122130
return org.elasticsearch.common.collect.List.of();
123131
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.autoscaling.action;
8+
9+
import org.elasticsearch.action.ActionRequestValidationException;
10+
import org.elasticsearch.action.ActionType;
11+
import org.elasticsearch.action.support.master.AcknowledgedRequest;
12+
import org.elasticsearch.action.support.master.AcknowledgedResponse;
13+
import org.elasticsearch.common.io.stream.StreamInput;
14+
import org.elasticsearch.common.io.stream.StreamOutput;
15+
import org.elasticsearch.common.xcontent.ToXContentObject;
16+
import org.elasticsearch.common.xcontent.XContentBuilder;
17+
18+
import java.io.IOException;
19+
import java.util.Objects;
20+
21+
public class DeleteAutoscalingPolicyAction extends ActionType<AcknowledgedResponse> {
22+
23+
public static final DeleteAutoscalingPolicyAction INSTANCE = new DeleteAutoscalingPolicyAction();
24+
public static final String NAME = "cluster:admin/autoscaling/delete_autoscaling_policy";
25+
26+
private DeleteAutoscalingPolicyAction() {
27+
super(NAME, AcknowledgedResponse::new);
28+
}
29+
30+
public static class Request extends AcknowledgedRequest<DeleteAutoscalingPolicyAction.Request> implements ToXContentObject {
31+
32+
private final String name;
33+
34+
public String name() {
35+
return name;
36+
}
37+
38+
public Request(final String name) {
39+
this.name = Objects.requireNonNull(name);
40+
}
41+
42+
public Request(final StreamInput in) throws IOException {
43+
super(in);
44+
name = in.readString();
45+
}
46+
47+
@Override
48+
public void writeTo(final StreamOutput out) throws IOException {
49+
super.writeTo(out);
50+
out.writeString(name);
51+
}
52+
53+
@Override
54+
public ActionRequestValidationException validate() {
55+
return null;
56+
}
57+
58+
@Override
59+
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
60+
builder.startObject();
61+
{
62+
63+
}
64+
builder.endObject();
65+
return builder;
66+
}
67+
68+
}
69+
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.autoscaling.action;
8+
9+
import org.apache.logging.log4j.LogManager;
10+
import org.apache.logging.log4j.Logger;
11+
import org.elasticsearch.action.ActionListener;
12+
import org.elasticsearch.action.support.ActionFilters;
13+
import org.elasticsearch.action.support.master.AcknowledgedResponse;
14+
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
15+
import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
16+
import org.elasticsearch.cluster.ClusterState;
17+
import org.elasticsearch.cluster.block.ClusterBlockException;
18+
import org.elasticsearch.cluster.block.ClusterBlockLevel;
19+
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
20+
import org.elasticsearch.cluster.metadata.Metadata;
21+
import org.elasticsearch.cluster.service.ClusterService;
22+
import org.elasticsearch.common.inject.Inject;
23+
import org.elasticsearch.common.io.stream.StreamInput;
24+
import org.elasticsearch.threadpool.ThreadPool;
25+
import org.elasticsearch.transport.TransportService;
26+
import org.elasticsearch.xpack.autoscaling.AutoscalingMetadata;
27+
import org.elasticsearch.xpack.autoscaling.policy.AutoscalingPolicyMetadata;
28+
29+
import java.io.IOException;
30+
import java.util.SortedMap;
31+
import java.util.TreeMap;
32+
33+
public class TransportDeleteAutoscalingPolicyAction extends TransportMasterNodeAction<
34+
DeleteAutoscalingPolicyAction.Request,
35+
AcknowledgedResponse> {
36+
37+
private static final Logger logger = LogManager.getLogger(TransportPutAutoscalingPolicyAction.class);
38+
39+
@Inject
40+
public TransportDeleteAutoscalingPolicyAction(
41+
final TransportService transportService,
42+
final ClusterService clusterService,
43+
final ThreadPool threadPool,
44+
final ActionFilters actionFilters,
45+
final IndexNameExpressionResolver indexNameExpressionResolver
46+
) {
47+
super(
48+
DeleteAutoscalingPolicyAction.NAME,
49+
transportService,
50+
clusterService,
51+
threadPool,
52+
actionFilters,
53+
DeleteAutoscalingPolicyAction.Request::new,
54+
indexNameExpressionResolver
55+
);
56+
}
57+
58+
@Override
59+
protected String executor() {
60+
return ThreadPool.Names.SAME;
61+
}
62+
63+
@Override
64+
protected AcknowledgedResponse read(final StreamInput in) throws IOException {
65+
return new AcknowledgedResponse(in);
66+
}
67+
68+
@Override
69+
protected void masterOperation(
70+
final DeleteAutoscalingPolicyAction.Request request,
71+
final ClusterState state,
72+
final ActionListener<AcknowledgedResponse> listener
73+
) {
74+
clusterService.submitStateUpdateTask(
75+
"delete-autoscaling-policy",
76+
new AckedClusterStateUpdateTask<AcknowledgedResponse>(request, listener) {
77+
78+
@Override
79+
protected AcknowledgedResponse newResponse(final boolean acknowledged) {
80+
return new AcknowledgedResponse(acknowledged);
81+
}
82+
83+
@Override
84+
public ClusterState execute(final ClusterState currentState) {
85+
return deleteAutoscalingPolicy(currentState, request.name(), logger);
86+
}
87+
88+
}
89+
);
90+
}
91+
92+
@Override
93+
protected ClusterBlockException checkBlock(final DeleteAutoscalingPolicyAction.Request request, final ClusterState state) {
94+
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
95+
}
96+
97+
static ClusterState deleteAutoscalingPolicy(final ClusterState currentState, final String name, final Logger logger) {
98+
final ClusterState.Builder builder = ClusterState.builder(currentState);
99+
final AutoscalingMetadata currentMetadata;
100+
if (currentState.metadata().custom(AutoscalingMetadata.NAME) != null) {
101+
currentMetadata = currentState.metadata().custom(AutoscalingMetadata.NAME);
102+
} else {
103+
// we will reject the request below when we try to look up the policy by name
104+
currentMetadata = AutoscalingMetadata.EMPTY;
105+
}
106+
if (currentMetadata.policies().containsKey(name) == false) {
107+
throw new IllegalArgumentException("autoscaling policy with name [" + name + "] does not exist");
108+
}
109+
final SortedMap<String, AutoscalingPolicyMetadata> newPolicies = new TreeMap<>(currentMetadata.policies());
110+
final AutoscalingPolicyMetadata policy = newPolicies.remove(name);
111+
assert policy != null : name;
112+
logger.info("deleting autoscaling policy [{}]", name);
113+
final AutoscalingMetadata newMetadata = new AutoscalingMetadata(newPolicies);
114+
builder.metadata(Metadata.builder(currentState.getMetadata()).putCustom(AutoscalingMetadata.NAME, newMetadata).build());
115+
return builder.build();
116+
}
117+
118+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.autoscaling.rest;
8+
9+
import org.elasticsearch.client.node.NodeClient;
10+
import org.elasticsearch.rest.BaseRestHandler;
11+
import org.elasticsearch.rest.RestRequest;
12+
import org.elasticsearch.rest.action.RestToXContentListener;
13+
import org.elasticsearch.xpack.autoscaling.action.DeleteAutoscalingPolicyAction;
14+
15+
import java.util.List;
16+
17+
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
18+
19+
public class RestDeleteAutoscalingPolicyActionHandler extends BaseRestHandler {
20+
21+
@Override
22+
public List<Route> routes() {
23+
return org.elasticsearch.common.collect.List.of(new Route(DELETE, "/_autoscaling/policy/{name}"));
24+
}
25+
26+
@Override
27+
public String getName() {
28+
return "delete_autoscaling_policy";
29+
}
30+
31+
@Override
32+
protected RestChannelConsumer prepareRequest(final RestRequest restRequest, final NodeClient client) {
33+
final String name = restRequest.param("name");
34+
final DeleteAutoscalingPolicyAction.Request request = new DeleteAutoscalingPolicyAction.Request(name);
35+
return channel -> client.execute(DeleteAutoscalingPolicyAction.INSTANCE, request, new RestToXContentListener<>(channel));
36+
}
37+
38+
}

0 commit comments

Comments
 (0)