Skip to content

Commit 6d0bd25

Browse files
authored
Add delete autoscaling policy API (#54601)
This commit adds an API for deleting autoscaling policies.
1 parent cdd07c5 commit 6d0bd25

File tree

10 files changed

+517
-1
lines changed

10 files changed

+517
-1
lines changed

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

+2
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[]
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+
--------------------------------------------------
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

+9-1
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 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 List.of(new RestGetAutoscalingDecisionHandler(), new RestPutAutoscalingPolicyHandler());
124+
return List.of(
125+
new RestGetAutoscalingDecisionHandler(),
126+
new RestDeleteAutoscalingPolicyActionHandler(),
127+
new RestPutAutoscalingPolicyHandler()
128+
);
121129
} else {
122130
return List.of();
123131
}
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,117 @@
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.tasks.Task;
25+
import org.elasticsearch.threadpool.ThreadPool;
26+
import org.elasticsearch.transport.TransportService;
27+
import org.elasticsearch.xpack.autoscaling.AutoscalingMetadata;
28+
import org.elasticsearch.xpack.autoscaling.policy.AutoscalingPolicyMetadata;
29+
30+
import java.io.IOException;
31+
import java.util.SortedMap;
32+
import java.util.TreeMap;
33+
34+
public class TransportDeleteAutoscalingPolicyAction extends TransportMasterNodeAction<
35+
DeleteAutoscalingPolicyAction.Request,
36+
AcknowledgedResponse> {
37+
38+
private static final Logger logger = LogManager.getLogger(TransportPutAutoscalingPolicyAction.class);
39+
40+
@Inject
41+
public TransportDeleteAutoscalingPolicyAction(
42+
final TransportService transportService,
43+
final ClusterService clusterService,
44+
final ThreadPool threadPool,
45+
final ActionFilters actionFilters,
46+
final IndexNameExpressionResolver indexNameExpressionResolver
47+
) {
48+
super(
49+
DeleteAutoscalingPolicyAction.NAME,
50+
transportService,
51+
clusterService,
52+
threadPool,
53+
actionFilters,
54+
DeleteAutoscalingPolicyAction.Request::new,
55+
indexNameExpressionResolver
56+
);
57+
}
58+
59+
@Override
60+
protected String executor() {
61+
return ThreadPool.Names.SAME;
62+
}
63+
64+
@Override
65+
protected AcknowledgedResponse read(final StreamInput in) throws IOException {
66+
return new AcknowledgedResponse(in);
67+
}
68+
69+
@Override
70+
protected void masterOperation(
71+
final Task task,
72+
final DeleteAutoscalingPolicyAction.Request request,
73+
final ClusterState state,
74+
final ActionListener<AcknowledgedResponse> listener
75+
) {
76+
clusterService.submitStateUpdateTask("delete-autoscaling-policy", new AckedClusterStateUpdateTask<>(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+
@Override
92+
protected ClusterBlockException checkBlock(final DeleteAutoscalingPolicyAction.Request request, final ClusterState state) {
93+
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
94+
}
95+
96+
static ClusterState deleteAutoscalingPolicy(final ClusterState currentState, final String name, final Logger logger) {
97+
final ClusterState.Builder builder = ClusterState.builder(currentState);
98+
final AutoscalingMetadata currentMetadata;
99+
if (currentState.metadata().custom(AutoscalingMetadata.NAME) != null) {
100+
currentMetadata = currentState.metadata().custom(AutoscalingMetadata.NAME);
101+
} else {
102+
// we will reject the request below when we try to look up the policy by name
103+
currentMetadata = AutoscalingMetadata.EMPTY;
104+
}
105+
if (currentMetadata.policies().containsKey(name) == false) {
106+
throw new IllegalArgumentException("autoscaling policy with name [" + name + "] does not exist");
107+
}
108+
final SortedMap<String, AutoscalingPolicyMetadata> newPolicies = new TreeMap<>(currentMetadata.policies());
109+
final AutoscalingPolicyMetadata policy = newPolicies.remove(name);
110+
assert policy != null : name;
111+
logger.info("deleting autoscaling policy [{}]", name);
112+
final AutoscalingMetadata newMetadata = new AutoscalingMetadata(newPolicies);
113+
builder.metadata(Metadata.builder(currentState.getMetadata()).putCustom(AutoscalingMetadata.NAME, newMetadata).build());
114+
return builder.build();
115+
}
116+
117+
}
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 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)