Skip to content

Commit

Permalink
Add delete autoscaling policy API (elastic#54601)
Browse files Browse the repository at this point in the history
This commit adds an API for deleting autoscaling policies.
  • Loading branch information
jasontedor authored Apr 2, 2020
1 parent cdd07c5 commit 6d0bd25
Show file tree
Hide file tree
Showing 10 changed files with 517 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/reference/autoscaling/apis/autoscaling-apis.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ You can use the following APIs to perform autoscaling operations.
=== Top-Level

* <<autoscaling-get-autoscaling-decision,Get autoscaling decision>>
* <<autoscaling-delete-autoscaling-policy,Delete autoscaling policy>>
* <<autoscaling-put-autoscaling-policy,Put autoscaling policy>>

// top-level
include::get-autoscaling-decision.asciidoc[]
include::delete-autoscaling-policy.asciidoc[]
include::put-autoscaling-policy.asciidoc[]
64 changes: 64 additions & 0 deletions docs/reference/autoscaling/apis/delete-autoscaling-policy.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
[role="xpack"]
[testenv="platinum"]
[[autoscaling-delete-autoscaling-policy]]
=== Delete autoscaling policy API
++++
<titleabbrev>Delete autoscaling policy</titleabbrev>
++++

Delete autoscaling policy.

[[autoscaling-delete-autoscaling-policy-request]]
==== {api-request-title}

[source,console]
--------------------------------------------------
PUT /_autoscaling/policy/my_autoscaling_policy
{
"policy": {
"deciders": {
"always": {
}
}
}
}
--------------------------------------------------
// TESTSETUP

[source,console]
--------------------------------------------------
DELETE /_autoscaling/policy/<name>
--------------------------------------------------
// TEST[s/<name>/my_autoscaling_policy/]

[[autoscaling-delete-autoscaling-policy-prereqs]]
==== {api-prereq-title}

* If the {es} {security-features} are enabled, you must have
`manage_autoscaling` cluster privileges. For more information, see
<<security-privileges>>.

[[autoscaling-delete-autoscaling-policy-desc]]
==== {api-description-title}

This API deletes an autoscaling policy with the provided name.

[[autoscaling-delete-autoscaling-policy-examples]]
==== {api-examples-title}

This example deletes an autoscaling policy named `my_autosaling_policy`.

[source,console]
--------------------------------------------------
DELETE /_autoscaling/policy/my_autoscaling_policy
--------------------------------------------------
// TEST

The API returns the following result:

[source,console-result]
--------------------------------------------------
{
"acknowledged": true
}
--------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
"Test delete autoscaling policy":
- do:
autoscaling.put_autoscaling_policy:
name: hot
body:
policy:
deciders:
always: {}

- match: { "acknowledged": true }

- do:
autoscaling.delete_autoscaling_policy:
name: hot

# TODO: add validation that the policy is removed after we have a get policy API

- do:
catch: bad_request
autoscaling.delete_autoscaling_policy:
name: does_not_exist
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestHandler;
import org.elasticsearch.xpack.autoscaling.action.DeleteAutoscalingPolicyAction;
import org.elasticsearch.xpack.autoscaling.action.GetAutoscalingDecisionAction;
import org.elasticsearch.xpack.autoscaling.action.PutAutoscalingPolicyAction;
import org.elasticsearch.xpack.autoscaling.action.TransportDeleteAutoscalingPolicyAction;
import org.elasticsearch.xpack.autoscaling.action.TransportGetAutoscalingDecisionAction;
import org.elasticsearch.xpack.autoscaling.action.TransportPutAutoscalingPolicyAction;
import org.elasticsearch.xpack.autoscaling.decision.AlwaysAutoscalingDecider;
import org.elasticsearch.xpack.autoscaling.decision.AutoscalingDecider;
import org.elasticsearch.xpack.autoscaling.rest.RestDeleteAutoscalingPolicyActionHandler;
import org.elasticsearch.xpack.autoscaling.rest.RestGetAutoscalingDecisionHandler;
import org.elasticsearch.xpack.autoscaling.rest.RestPutAutoscalingPolicyHandler;
import org.elasticsearch.xpack.core.XPackPlugin;
Expand Down Expand Up @@ -99,6 +102,7 @@ boolean isSnapshot() {
if (enabled) {
return List.of(
new ActionHandler<>(GetAutoscalingDecisionAction.INSTANCE, TransportGetAutoscalingDecisionAction.class),
new ActionHandler<>(DeleteAutoscalingPolicyAction.INSTANCE, TransportDeleteAutoscalingPolicyAction.class),
new ActionHandler<>(PutAutoscalingPolicyAction.INSTANCE, TransportPutAutoscalingPolicyAction.class)
);
} else {
Expand All @@ -117,7 +121,11 @@ public List<RestHandler> getRestHandlers(
final Supplier<DiscoveryNodes> nodesInCluster
) {
if (enabled) {
return List.of(new RestGetAutoscalingDecisionHandler(), new RestPutAutoscalingPolicyHandler());
return List.of(
new RestGetAutoscalingDecisionHandler(),
new RestDeleteAutoscalingPolicyActionHandler(),
new RestPutAutoscalingPolicyHandler()
);
} else {
return List.of();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.autoscaling.action;

import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;

import java.io.IOException;
import java.util.Objects;

public class DeleteAutoscalingPolicyAction extends ActionType<AcknowledgedResponse> {

public static final DeleteAutoscalingPolicyAction INSTANCE = new DeleteAutoscalingPolicyAction();
public static final String NAME = "cluster:admin/autoscaling/delete_autoscaling_policy";

private DeleteAutoscalingPolicyAction() {
super(NAME, AcknowledgedResponse::new);
}

public static class Request extends AcknowledgedRequest<DeleteAutoscalingPolicyAction.Request> implements ToXContentObject {

private final String name;

public String name() {
return name;
}

public Request(final String name) {
this.name = Objects.requireNonNull(name);
}

public Request(final StreamInput in) throws IOException {
super(in);
name = in.readString();
}

@Override
public void writeTo(final StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(name);
}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
builder.startObject();
{

}
builder.endObject();
return builder;
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.autoscaling.action;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.autoscaling.AutoscalingMetadata;
import org.elasticsearch.xpack.autoscaling.policy.AutoscalingPolicyMetadata;

import java.io.IOException;
import java.util.SortedMap;
import java.util.TreeMap;

public class TransportDeleteAutoscalingPolicyAction extends TransportMasterNodeAction<
DeleteAutoscalingPolicyAction.Request,
AcknowledgedResponse> {

private static final Logger logger = LogManager.getLogger(TransportPutAutoscalingPolicyAction.class);

@Inject
public TransportDeleteAutoscalingPolicyAction(
final TransportService transportService,
final ClusterService clusterService,
final ThreadPool threadPool,
final ActionFilters actionFilters,
final IndexNameExpressionResolver indexNameExpressionResolver
) {
super(
DeleteAutoscalingPolicyAction.NAME,
transportService,
clusterService,
threadPool,
actionFilters,
DeleteAutoscalingPolicyAction.Request::new,
indexNameExpressionResolver
);
}

@Override
protected String executor() {
return ThreadPool.Names.SAME;
}

@Override
protected AcknowledgedResponse read(final StreamInput in) throws IOException {
return new AcknowledgedResponse(in);
}

@Override
protected void masterOperation(
final Task task,
final DeleteAutoscalingPolicyAction.Request request,
final ClusterState state,
final ActionListener<AcknowledgedResponse> listener
) {
clusterService.submitStateUpdateTask("delete-autoscaling-policy", new AckedClusterStateUpdateTask<>(request, listener) {

@Override
protected AcknowledgedResponse newResponse(final boolean acknowledged) {
return new AcknowledgedResponse(acknowledged);
}

@Override
public ClusterState execute(final ClusterState currentState) {
return deleteAutoscalingPolicy(currentState, request.name(), logger);
}

});
}

@Override
protected ClusterBlockException checkBlock(final DeleteAutoscalingPolicyAction.Request request, final ClusterState state) {
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
}

static ClusterState deleteAutoscalingPolicy(final ClusterState currentState, final String name, final Logger logger) {
final ClusterState.Builder builder = ClusterState.builder(currentState);
final AutoscalingMetadata currentMetadata;
if (currentState.metadata().custom(AutoscalingMetadata.NAME) != null) {
currentMetadata = currentState.metadata().custom(AutoscalingMetadata.NAME);
} else {
// we will reject the request below when we try to look up the policy by name
currentMetadata = AutoscalingMetadata.EMPTY;
}
if (currentMetadata.policies().containsKey(name) == false) {
throw new IllegalArgumentException("autoscaling policy with name [" + name + "] does not exist");
}
final SortedMap<String, AutoscalingPolicyMetadata> newPolicies = new TreeMap<>(currentMetadata.policies());
final AutoscalingPolicyMetadata policy = newPolicies.remove(name);
assert policy != null : name;
logger.info("deleting autoscaling policy [{}]", name);
final AutoscalingMetadata newMetadata = new AutoscalingMetadata(newPolicies);
builder.metadata(Metadata.builder(currentState.getMetadata()).putCustom(AutoscalingMetadata.NAME, newMetadata).build());
return builder.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

package org.elasticsearch.xpack.autoscaling.rest;

import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.xpack.autoscaling.action.DeleteAutoscalingPolicyAction;

import java.util.List;

import static org.elasticsearch.rest.RestRequest.Method.DELETE;

public class RestDeleteAutoscalingPolicyActionHandler extends BaseRestHandler {

@Override
public List<Route> routes() {
return List.of(new Route(DELETE, "/_autoscaling/policy/{name}"));
}

@Override
public String getName() {
return "delete_autoscaling_policy";
}

@Override
protected RestChannelConsumer prepareRequest(final RestRequest restRequest, final NodeClient client) {
final String name = restRequest.param("name");
final DeleteAutoscalingPolicyAction.Request request = new DeleteAutoscalingPolicyAction.Request(name);
return channel -> client.execute(DeleteAutoscalingPolicyAction.INSTANCE, request, new RestToXContentListener<>(channel));
}

}
Loading

0 comments on commit 6d0bd25

Please sign in to comment.