Add autoscaling API skelton (#51564)
The main purpose of this commit is to add a single autoscaling REST endpoint skeleton, for the purpose of starting to build out the build and testing infrastructure that will surround it. For example, rather than commiting a fully-functioning autoscaling API, we introduce here the skeleton so that we can start wiring up the build and testing infrastructure, establish security roles/permissions, an so on. This way, in a forthcoming PR that introduces actual functionality, that PR will be smaller and have less distractions around that sort of infrastructure.
This commit is contained in:
parent
488944f4a1
commit
25daf5f1e1
|
@ -318,6 +318,7 @@ public final class Role {
|
||||||
public static final String MANAGE_OIDC = "manage_oidc";
|
public static final String MANAGE_OIDC = "manage_oidc";
|
||||||
public static final String MANAGE_TOKEN = "manage_token";
|
public static final String MANAGE_TOKEN = "manage_token";
|
||||||
public static final String MANAGE_PIPELINE = "manage_pipeline";
|
public static final String MANAGE_PIPELINE = "manage_pipeline";
|
||||||
|
public static final String MANAGE_AUTOSCALING = "manage_autoscaling";
|
||||||
public static final String MANAGE_CCR = "manage_ccr";
|
public static final String MANAGE_CCR = "manage_ccr";
|
||||||
public static final String READ_CCR = "read_ccr";
|
public static final String READ_CCR = "read_ccr";
|
||||||
public static final String MANAGE_ILM = "manage_ilm";
|
public static final String MANAGE_ILM = "manage_ilm";
|
||||||
|
@ -326,8 +327,8 @@ public final class Role {
|
||||||
public static final String[] ALL_ARRAY = new String[] { NONE, ALL, MONITOR, MONITOR_TRANSFORM_DEPRECATED, MONITOR_TRANSFORM,
|
public static final String[] ALL_ARRAY = new String[] { NONE, ALL, MONITOR, MONITOR_TRANSFORM_DEPRECATED, MONITOR_TRANSFORM,
|
||||||
MONITOR_ML, MONITOR_WATCHER, MONITOR_ROLLUP, MANAGE, MANAGE_TRANSFORM_DEPRECATED, MANAGE_TRANSFORM,
|
MONITOR_ML, MONITOR_WATCHER, MONITOR_ROLLUP, MANAGE, MANAGE_TRANSFORM_DEPRECATED, MANAGE_TRANSFORM,
|
||||||
MANAGE_ML, MANAGE_WATCHER, MANAGE_ROLLUP, MANAGE_INDEX_TEMPLATES, MANAGE_INGEST_PIPELINES, TRANSPORT_CLIENT,
|
MANAGE_ML, MANAGE_WATCHER, MANAGE_ROLLUP, MANAGE_INDEX_TEMPLATES, MANAGE_INGEST_PIPELINES, TRANSPORT_CLIENT,
|
||||||
MANAGE_SECURITY, MANAGE_SAML, MANAGE_OIDC, MANAGE_TOKEN, MANAGE_PIPELINE, MANAGE_CCR, READ_CCR, MANAGE_ILM, READ_ILM,
|
MANAGE_SECURITY, MANAGE_SAML, MANAGE_OIDC, MANAGE_TOKEN, MANAGE_PIPELINE, MANAGE_AUTOSCALING, MANAGE_CCR, READ_CCR,
|
||||||
MANAGE_ENRICH };
|
MANAGE_ILM, READ_ILM, MANAGE_ENRICH };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
[role="xpack"]
|
||||||
|
[testenv="platinum"]
|
||||||
|
[[autoscaling-apis]]
|
||||||
|
== Autoscaling APIs
|
||||||
|
|
||||||
|
You can use the following APIs to perform autoscaling operations.
|
||||||
|
|
||||||
|
[float]
|
||||||
|
[[autoscaling-api-top-level]]
|
||||||
|
=== Top-Level
|
||||||
|
|
||||||
|
* <<autoscaling-get-autoscaling-decision,Get autoscaling decision>>
|
||||||
|
|
||||||
|
// top-level
|
||||||
|
include::get-autoscaling-decision.asciidoc[]
|
|
@ -0,0 +1,52 @@
|
||||||
|
[role="xpack"]
|
||||||
|
[testenv="platinum"]
|
||||||
|
[[autoscaling-get-autoscaling-decision]]
|
||||||
|
=== Get autoscaling decision API
|
||||||
|
++++
|
||||||
|
<titleabbrev>Get autoscaling decision</titleabbrev>
|
||||||
|
++++
|
||||||
|
|
||||||
|
Get autoscaling decision.
|
||||||
|
|
||||||
|
[[autoscaling-get-autoscaling-decision-request]]
|
||||||
|
==== {api-request-title}
|
||||||
|
|
||||||
|
[source,console]
|
||||||
|
--------------------------------------------------
|
||||||
|
GET /_autoscaling/decision/
|
||||||
|
--------------------------------------------------
|
||||||
|
// TEST
|
||||||
|
|
||||||
|
[[autoscaling-get-autoscaling-decision-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-get-autoscaling-decision-desc]]
|
||||||
|
==== {api-description-title}
|
||||||
|
|
||||||
|
This API gets the current autoscaling decision based on the configured
|
||||||
|
autoscaling policy. This API will return whether or not autoscaling is
|
||||||
|
needed.
|
||||||
|
|
||||||
|
[[autoscaling-get-autoscaling-decision-examples]]
|
||||||
|
==== {api-examples-title}
|
||||||
|
|
||||||
|
This example retrieves the current autoscaling decision.
|
||||||
|
|
||||||
|
[source,console]
|
||||||
|
--------------------------------------------------
|
||||||
|
GET /_autoscaling/decision
|
||||||
|
--------------------------------------------------
|
||||||
|
// TEST
|
||||||
|
|
||||||
|
The API returns the following result:
|
||||||
|
|
||||||
|
[source,console-result]
|
||||||
|
--------------------------------------------------
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
--------------------------------------------------
|
|
@ -35,6 +35,7 @@ not be included yet.
|
||||||
--
|
--
|
||||||
|
|
||||||
include::{es-repo-dir}/api-conventions.asciidoc[]
|
include::{es-repo-dir}/api-conventions.asciidoc[]
|
||||||
|
include::{es-repo-dir}/autoscaling/apis/autoscaling-apis.asciidoc[]
|
||||||
include::{es-repo-dir}/cat.asciidoc[]
|
include::{es-repo-dir}/cat.asciidoc[]
|
||||||
include::{es-repo-dir}/cluster.asciidoc[]
|
include::{es-repo-dir}/cluster.asciidoc[]
|
||||||
include::{es-repo-dir}/ccr/apis/ccr-apis.asciidoc[]
|
include::{es-repo-dir}/ccr/apis/ccr-apis.asciidoc[]
|
||||||
|
|
|
@ -66,6 +66,7 @@ A successful call returns an object with "cluster" and "index" fields.
|
||||||
"delegate_pki",
|
"delegate_pki",
|
||||||
"manage",
|
"manage",
|
||||||
"manage_api_key",
|
"manage_api_key",
|
||||||
|
"manage_autoscaling",
|
||||||
"manage_ccr",
|
"manage_ccr",
|
||||||
"manage_data_frame_transforms",
|
"manage_data_frame_transforms",
|
||||||
"manage_enrich",
|
"manage_enrich",
|
||||||
|
|
|
@ -18,3 +18,12 @@ dependencies {
|
||||||
compileOnly project(path: xpackModule('core'), configuration: 'default')
|
compileOnly project(path: xpackModule('core'), configuration: 'default')
|
||||||
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
|
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add all sub-projects of the qa sub-project
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
project.subprojects
|
||||||
|
.find { it.path == project.path + ":qa" }
|
||||||
|
.subprojects
|
||||||
|
.findAll { it.path.startsWith(project.path + ":qa") }
|
||||||
|
.each { check.dependsOn it.check }
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import org.elasticsearch.gradle.test.RestIntegTestTask
|
||||||
|
|
||||||
|
apply plugin: 'elasticsearch.build'
|
||||||
|
test.enabled = false
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':test:framework')
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
project.tasks.withType(RestIntegTestTask) {
|
||||||
|
final File xPackResources = new File(xpackProject('plugin').projectDir, 'src/test/resources')
|
||||||
|
project.copyRestSpec.from(xPackResources) {
|
||||||
|
include 'rest-api-spec/api/**'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
autoscaling:
|
||||||
|
cluster:
|
||||||
|
- manage_autoscaling
|
|
@ -0,0 +1,25 @@
|
||||||
|
import org.elasticsearch.gradle.test.RestIntegTestTask
|
||||||
|
|
||||||
|
apply plugin: 'elasticsearch.testclusters'
|
||||||
|
apply plugin: 'elasticsearch.standalone-test'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
|
||||||
|
testCompile project(path: xpackModule('autoscaling'), configuration: 'runtime')
|
||||||
|
}
|
||||||
|
|
||||||
|
task restTest(type: RestIntegTestTask) {
|
||||||
|
mustRunAfter(precommit)
|
||||||
|
}
|
||||||
|
|
||||||
|
testClusters.restTest {
|
||||||
|
testDistribution = 'DEFAULT'
|
||||||
|
setting 'xpack.autoscaling.enabled', 'true'
|
||||||
|
setting 'xpack.security.enabled', 'true'
|
||||||
|
extraConfigFile 'roles.yml', file('autoscaling-roles.yml')
|
||||||
|
user username: 'autoscaling-admin', password: 'autoscaling-admin-password', role: 'superuser'
|
||||||
|
user username: 'autoscaling-user', password: 'autoscaling-user-password', role: 'autoscaling'
|
||||||
|
}
|
||||||
|
|
||||||
|
check.dependsOn restTest
|
||||||
|
test.enabled = false
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||||
|
import org.elasticsearch.common.settings.SecureString;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||||
|
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||||
|
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||||
|
|
||||||
|
import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||||
|
|
||||||
|
public class AutoscalingRestIT extends ESClientYamlSuiteTestCase {
|
||||||
|
|
||||||
|
public AutoscalingRestIT(final ClientYamlTestCandidate testCandidate) {
|
||||||
|
super(testCandidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParametersFactory
|
||||||
|
public static Iterable<Object[]> parameters() throws Exception {
|
||||||
|
return ESClientYamlSuiteTestCase.createParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Settings restAdminSettings() {
|
||||||
|
final String value = basicAuthHeaderValue("autoscaling-admin", new SecureString("autoscaling-admin-password".toCharArray()));
|
||||||
|
return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", value).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Settings restClientSettings() {
|
||||||
|
final String value = basicAuthHeaderValue("autoscaling-user", new SecureString("autoscaling-user-password".toCharArray()));
|
||||||
|
return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", value).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
"Test get autoscaling decision":
|
||||||
|
- do:
|
||||||
|
autoscaling.get_autoscaling_decision: {}
|
|
@ -7,16 +7,31 @@
|
||||||
package org.elasticsearch.xpack.autoscaling;
|
package org.elasticsearch.xpack.autoscaling;
|
||||||
|
|
||||||
import org.elasticsearch.Build;
|
import org.elasticsearch.Build;
|
||||||
|
import org.elasticsearch.action.ActionRequest;
|
||||||
|
import org.elasticsearch.action.ActionResponse;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
|
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||||
|
import org.elasticsearch.common.settings.ClusterSettings;
|
||||||
|
import org.elasticsearch.common.settings.IndexScopedSettings;
|
||||||
import org.elasticsearch.common.settings.Setting;
|
import org.elasticsearch.common.settings.Setting;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.settings.SettingsFilter;
|
||||||
|
import org.elasticsearch.plugins.ActionPlugin;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
import org.elasticsearch.rest.RestController;
|
||||||
|
import org.elasticsearch.rest.RestHandler;
|
||||||
|
import org.elasticsearch.xpack.autoscaling.action.GetAutoscalingDecisionAction;
|
||||||
|
import org.elasticsearch.xpack.autoscaling.action.TransportGetAutoscalingDecisionAction;
|
||||||
|
import org.elasticsearch.xpack.autoscaling.rest.RestGetAutoscalingDecisionHandler;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container class for autoscaling functionality.
|
* Container class for autoscaling functionality.
|
||||||
*/
|
*/
|
||||||
public class Autoscaling extends Plugin {
|
public class Autoscaling extends Plugin implements ActionPlugin {
|
||||||
|
|
||||||
public static final Setting<Boolean> AUTOSCALING_ENABLED_SETTING = Setting.boolSetting(
|
public static final Setting<Boolean> AUTOSCALING_ENABLED_SETTING = Setting.boolSetting(
|
||||||
"xpack.autoscaling.enabled",
|
"xpack.autoscaling.enabled",
|
||||||
|
@ -24,6 +39,12 @@ public class Autoscaling extends Plugin {
|
||||||
Setting.Property.NodeScope
|
Setting.Property.NodeScope
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
public Autoscaling(final Settings settings) {
|
||||||
|
this.enabled = AUTOSCALING_ENABLED_SETTING.get(settings);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings defined by autoscaling.
|
* The settings defined by autoscaling.
|
||||||
*
|
*
|
||||||
|
@ -38,6 +59,34 @@ public class Autoscaling extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions() {
|
||||||
|
if (enabled) {
|
||||||
|
return Collections.singletonList(
|
||||||
|
new ActionHandler<>(GetAutoscalingDecisionAction.INSTANCE, TransportGetAutoscalingDecisionAction.class)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RestHandler> getRestHandlers(
|
||||||
|
final Settings settings,
|
||||||
|
final RestController controller,
|
||||||
|
final ClusterSettings clusterSettings,
|
||||||
|
final IndexScopedSettings indexScopedSettings,
|
||||||
|
final SettingsFilter settingsFilter,
|
||||||
|
final IndexNameExpressionResolver indexNameExpressionResolver,
|
||||||
|
final Supplier<DiscoveryNodes> nodesInCluster
|
||||||
|
) {
|
||||||
|
if (enabled) {
|
||||||
|
return Collections.singletonList(new RestGetAutoscalingDecisionHandler(controller));
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean isSnapshot() {
|
boolean isSnapshot() {
|
||||||
return Build.CURRENT.isSnapshot();
|
return Build.CURRENT.isSnapshot();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.ActionResponse;
|
||||||
|
import org.elasticsearch.action.ActionType;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedRequest;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class GetAutoscalingDecisionAction extends ActionType<GetAutoscalingDecisionAction.Response> {
|
||||||
|
|
||||||
|
public static final GetAutoscalingDecisionAction INSTANCE = new GetAutoscalingDecisionAction();
|
||||||
|
public static final String NAME = "cluster:admin/autoscaling/get_autoscaling_decision";
|
||||||
|
|
||||||
|
private GetAutoscalingDecisionAction() {
|
||||||
|
super(NAME, Response::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Request extends AcknowledgedRequest<GetAutoscalingDecisionAction.Request> implements ToXContentObject {
|
||||||
|
|
||||||
|
public Request() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request(final StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(final StreamOutput out) throws IOException {
|
||||||
|
super.writeTo(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionRequestValidationException validate() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Response extends ActionResponse implements ToXContentObject {
|
||||||
|
|
||||||
|
public Response() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response(final StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(final StreamOutput out) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.ActionListener;
|
||||||
|
import org.elasticsearch.action.support.ActionFilters;
|
||||||
|
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
|
import org.elasticsearch.transport.TransportService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class TransportGetAutoscalingDecisionAction extends TransportMasterNodeAction<
|
||||||
|
GetAutoscalingDecisionAction.Request,
|
||||||
|
GetAutoscalingDecisionAction.Response> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TransportGetAutoscalingDecisionAction(
|
||||||
|
final TransportService transportService,
|
||||||
|
final ClusterService clusterService,
|
||||||
|
final ThreadPool threadPool,
|
||||||
|
final ActionFilters actionFilters,
|
||||||
|
final IndexNameExpressionResolver indexNameExpressionResolver
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
GetAutoscalingDecisionAction.NAME,
|
||||||
|
transportService,
|
||||||
|
clusterService,
|
||||||
|
threadPool,
|
||||||
|
actionFilters,
|
||||||
|
GetAutoscalingDecisionAction.Request::new,
|
||||||
|
indexNameExpressionResolver
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String executor() {
|
||||||
|
return ThreadPool.Names.SAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GetAutoscalingDecisionAction.Response read(final StreamInput in) throws IOException {
|
||||||
|
return new GetAutoscalingDecisionAction.Response(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void masterOperation(
|
||||||
|
final GetAutoscalingDecisionAction.Request request,
|
||||||
|
final ClusterState state,
|
||||||
|
final ActionListener<GetAutoscalingDecisionAction.Response> listener
|
||||||
|
) {
|
||||||
|
listener.onResponse(new GetAutoscalingDecisionAction.Response());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClusterBlockException checkBlock(final GetAutoscalingDecisionAction.Request request, final ClusterState state) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.RestController;
|
||||||
|
import org.elasticsearch.rest.RestRequest;
|
||||||
|
import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
import org.elasticsearch.xpack.autoscaling.action.GetAutoscalingDecisionAction;
|
||||||
|
|
||||||
|
public class RestGetAutoscalingDecisionHandler extends BaseRestHandler {
|
||||||
|
|
||||||
|
public RestGetAutoscalingDecisionHandler(final RestController controller) {
|
||||||
|
controller.registerHandler(RestRequest.Method.GET, "/_autoscaling/decision", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "get_autoscaling_decision";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RestChannelConsumer prepareRequest(final RestRequest restRequest, final NodeClient client) {
|
||||||
|
final GetAutoscalingDecisionAction.Request request = new GetAutoscalingDecisionAction.Request();
|
||||||
|
return channel -> client.execute(GetAutoscalingDecisionAction.INSTANCE, request, new RestToXContentListener<>(channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.xpack.autoscaling;
|
package org.elasticsearch.xpack.autoscaling;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
@ -14,7 +15,7 @@ import static org.hamcrest.Matchers.not;
|
||||||
public class AutoscalingTests extends ESTestCase {
|
public class AutoscalingTests extends ESTestCase {
|
||||||
|
|
||||||
public void testEnabledSettingRegisteredInSnapshotBuilds() {
|
public void testEnabledSettingRegisteredInSnapshotBuilds() {
|
||||||
final Autoscaling plugin = new Autoscaling() {
|
final Autoscaling plugin = new Autoscaling(Settings.EMPTY) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSnapshot() {
|
protected boolean isSnapshot() {
|
||||||
|
@ -26,7 +27,7 @@ public class AutoscalingTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEnabledSettingNotRegisteredInNonSnapshotBuilds() {
|
public void testEnabledSettingNotRegisteredInNonSnapshotBuilds() {
|
||||||
final Autoscaling plugin = new Autoscaling() {
|
final Autoscaling plugin = new Autoscaling(Settings.EMPTY) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSnapshot() {
|
protected boolean isSnapshot() {
|
||||||
|
|
|
@ -120,6 +120,9 @@ public class ClusterPrivilegeResolver {
|
||||||
public static final NamedClusterPrivilege MANAGE_API_KEY = new ActionClusterPrivilege("manage_api_key", MANAGE_API_KEY_PATTERN);
|
public static final NamedClusterPrivilege MANAGE_API_KEY = new ActionClusterPrivilege("manage_api_key", MANAGE_API_KEY_PATTERN);
|
||||||
public static final NamedClusterPrivilege MANAGE_PIPELINE = new ActionClusterPrivilege("manage_pipeline",
|
public static final NamedClusterPrivilege MANAGE_PIPELINE = new ActionClusterPrivilege("manage_pipeline",
|
||||||
Collections.singleton("cluster:admin/ingest/pipeline/*"));
|
Collections.singleton("cluster:admin/ingest/pipeline/*"));
|
||||||
|
public static final NamedClusterPrivilege MANAGE_AUTOSCALING = new ActionClusterPrivilege(
|
||||||
|
"manage_autoscaling",
|
||||||
|
Collections.singleton("cluster:admin/autoscaling/*"));
|
||||||
public static final NamedClusterPrivilege MANAGE_CCR = new ActionClusterPrivilege("manage_ccr", MANAGE_CCR_PATTERN);
|
public static final NamedClusterPrivilege MANAGE_CCR = new ActionClusterPrivilege("manage_ccr", MANAGE_CCR_PATTERN);
|
||||||
public static final NamedClusterPrivilege READ_CCR = new ActionClusterPrivilege("read_ccr", READ_CCR_PATTERN);
|
public static final NamedClusterPrivilege READ_CCR = new ActionClusterPrivilege("read_ccr", READ_CCR_PATTERN);
|
||||||
public static final NamedClusterPrivilege CREATE_SNAPSHOT = new ActionClusterPrivilege("create_snapshot", CREATE_SNAPSHOT_PATTERN);
|
public static final NamedClusterPrivilege CREATE_SNAPSHOT = new ActionClusterPrivilege("create_snapshot", CREATE_SNAPSHOT_PATTERN);
|
||||||
|
@ -159,6 +162,7 @@ public class ClusterPrivilegeResolver {
|
||||||
MANAGE_API_KEY,
|
MANAGE_API_KEY,
|
||||||
MANAGE_PIPELINE,
|
MANAGE_PIPELINE,
|
||||||
MANAGE_ROLLUP,
|
MANAGE_ROLLUP,
|
||||||
|
MANAGE_AUTOSCALING,
|
||||||
MANAGE_CCR,
|
MANAGE_CCR,
|
||||||
READ_CCR,
|
READ_CCR,
|
||||||
CREATE_SNAPSHOT,
|
CREATE_SNAPSHOT,
|
||||||
|
|
|
@ -174,6 +174,10 @@ public class PrivilegeTests extends ESTestCase {
|
||||||
assertThat(predicate.test("indices:admin/settings/foo"), is(false));
|
assertThat(predicate.test("indices:admin/settings/foo"), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testManageAutoscalingPrivilege() {
|
||||||
|
verifyClusterActionAllowed(ClusterPrivilegeResolver.MANAGE_AUTOSCALING, "cluster:admin/autoscaling/get_decision");
|
||||||
|
}
|
||||||
|
|
||||||
public void testManageCcrPrivilege() {
|
public void testManageCcrPrivilege() {
|
||||||
verifyClusterActionAllowed(ClusterPrivilegeResolver.MANAGE_CCR, "cluster:admin/xpack/ccr/follow_index",
|
verifyClusterActionAllowed(ClusterPrivilegeResolver.MANAGE_CCR, "cluster:admin/xpack/ccr/follow_index",
|
||||||
"cluster:admin/xpack/ccr/unfollow_index", "cluster:admin/xpack/ccr/brand_new_api");
|
"cluster:admin/xpack/ccr/unfollow_index", "cluster:admin/xpack/ccr/brand_new_api");
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"autoscaling.get_autoscaling_decision":{
|
||||||
|
"documentation":{
|
||||||
|
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/current/autoscaling-get-autoscaling-decision.html"
|
||||||
|
},
|
||||||
|
"stability":"experimental",
|
||||||
|
"url":{
|
||||||
|
"paths":[
|
||||||
|
{
|
||||||
|
"path":"/_autoscaling/decision",
|
||||||
|
"methods":[
|
||||||
|
"GET"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,5 +15,5 @@ setup:
|
||||||
# This is fragile - it needs to be updated every time we add a new cluster/index privilege
|
# This is fragile - it needs to be updated every time we add a new cluster/index privilege
|
||||||
# I would much prefer we could just check that specific entries are in the array, but we don't have
|
# I would much prefer we could just check that specific entries are in the array, but we don't have
|
||||||
# an assertion for that
|
# an assertion for that
|
||||||
- length: { "cluster" : 34 }
|
- length: { "cluster" : 35 }
|
||||||
- length: { "index" : 18 }
|
- length: { "index" : 18 }
|
||||||
|
|
Loading…
Reference in New Issue