Introduce autoscaling decisions (#53934)
This is the first in a series of commits that will introduce the autoscaling deciders framework. This commit introduces the basic framework for representing autoscaling decisions.
This commit is contained in:
parent
c1c9f7a735
commit
e3ca124537
|
@ -47,6 +47,6 @@ The API returns the following result:
|
||||||
[source,console-result]
|
[source,console-result]
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
{
|
{
|
||||||
|
decisions: []
|
||||||
}
|
}
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an autoscaling decision.
|
||||||
|
*/
|
||||||
|
public class AutoscalingDecision implements ToXContent, Writeable {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AutoscalingDecisionType type;
|
||||||
|
|
||||||
|
public AutoscalingDecisionType type() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String reason;
|
||||||
|
|
||||||
|
public String reason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoscalingDecision(final String name, final AutoscalingDecisionType type, final String reason) {
|
||||||
|
this.name = Objects.requireNonNull(name);
|
||||||
|
this.type = Objects.requireNonNull(type);
|
||||||
|
this.reason = Objects.requireNonNull(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoscalingDecision(final StreamInput in) throws IOException {
|
||||||
|
this.name = in.readString();
|
||||||
|
this.type = AutoscalingDecisionType.readFrom(in);
|
||||||
|
this.reason = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(final StreamOutput out) throws IOException {
|
||||||
|
out.writeString(name);
|
||||||
|
type.writeTo(out);
|
||||||
|
out.writeString(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(final XContentBuilder builder, final ToXContent.Params params) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
builder.field("name", name);
|
||||||
|
builder.field("type", type);
|
||||||
|
builder.field("reason", reason);
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final AutoscalingDecision that = (AutoscalingDecision) o;
|
||||||
|
return name.equals(that.name) && type == that.type && reason.equals(that.reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, type, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.common.xcontent.ToXContentFragment;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the type of an autoscaling decision: to indicating if a scale down, no scaling event, or a scale up is needed.
|
||||||
|
*/
|
||||||
|
public enum AutoscalingDecisionType implements Writeable, ToXContentFragment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that a scale down event is needed.
|
||||||
|
*/
|
||||||
|
SCALE_DOWN((byte) 0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that no scaling event is needed.
|
||||||
|
*/
|
||||||
|
NO_SCALE((byte) 1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that a scale up event is needed.
|
||||||
|
*/
|
||||||
|
SCALE_UP((byte) 2);
|
||||||
|
|
||||||
|
private final byte id;
|
||||||
|
|
||||||
|
byte id() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoscalingDecisionType(final byte id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AutoscalingDecisionType readFrom(final StreamInput in) throws IOException {
|
||||||
|
final byte id = in.readByte();
|
||||||
|
switch (id) {
|
||||||
|
case 0:
|
||||||
|
return SCALE_DOWN;
|
||||||
|
case 1:
|
||||||
|
return NO_SCALE;
|
||||||
|
case 2:
|
||||||
|
return SCALE_UP;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("unexpected value [" + id + "] for autoscaling decision type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(final StreamOutput out) throws IOException {
|
||||||
|
out.writeByte(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
|
||||||
|
builder.value(name().toLowerCase(Locale.ROOT));
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a collection of individual autoscaling decisions that can be aggregated into a single autoscaling decision.
|
||||||
|
*/
|
||||||
|
public class AutoscalingDecisions implements ToXContent, Writeable {
|
||||||
|
|
||||||
|
private final Collection<AutoscalingDecision> decisions;
|
||||||
|
|
||||||
|
public AutoscalingDecisions(final Collection<AutoscalingDecision> decisions) {
|
||||||
|
Objects.requireNonNull(decisions);
|
||||||
|
if (decisions.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("decisions can not be empty");
|
||||||
|
}
|
||||||
|
this.decisions = decisions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoscalingDecisions(final StreamInput in) throws IOException {
|
||||||
|
this.decisions = in.readList(AutoscalingDecision::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(final StreamOutput out) throws IOException {
|
||||||
|
out.writeCollection(decisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
|
||||||
|
for (final AutoscalingDecision decision : decisions) {
|
||||||
|
decision.toXContent(builder, params);
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoscalingDecisionType type() {
|
||||||
|
if (decisions.stream().anyMatch(p -> p.type() == AutoscalingDecisionType.SCALE_UP)) {
|
||||||
|
// if any deciders say to scale up
|
||||||
|
return AutoscalingDecisionType.SCALE_UP;
|
||||||
|
} else if (decisions.stream().allMatch(p -> p.type() == AutoscalingDecisionType.SCALE_DOWN)) {
|
||||||
|
// if all deciders say to scale down
|
||||||
|
return AutoscalingDecisionType.SCALE_DOWN;
|
||||||
|
} else {
|
||||||
|
// otherwise, do not scale
|
||||||
|
return AutoscalingDecisionType.NO_SCALE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final org.elasticsearch.xpack.autoscaling.AutoscalingDecisions that = (org.elasticsearch.xpack.autoscaling.AutoscalingDecisions) o;
|
||||||
|
return decisions.equals(that.decisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(decisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,8 +14,13 @@ import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.xpack.autoscaling.AutoscalingDecisions;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
public class GetAutoscalingDecisionAction extends ActionType<GetAutoscalingDecisionAction.Response> {
|
public class GetAutoscalingDecisionAction extends ActionType<GetAutoscalingDecisionAction.Response> {
|
||||||
|
|
||||||
|
@ -60,24 +65,37 @@ public class GetAutoscalingDecisionAction extends ActionType<GetAutoscalingDecis
|
||||||
|
|
||||||
public static class Response extends ActionResponse implements ToXContentObject {
|
public static class Response extends ActionResponse implements ToXContentObject {
|
||||||
|
|
||||||
public Response() {
|
private final SortedMap<String, AutoscalingDecisions> decisions;
|
||||||
|
|
||||||
|
public Response(final SortedMap<String, AutoscalingDecisions> decisions) {
|
||||||
|
this.decisions = Objects.requireNonNull(decisions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response(final StreamInput in) throws IOException {
|
public Response(final StreamInput in) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
|
decisions = new TreeMap<>(in.readMap(StreamInput::readString, AutoscalingDecisions::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(final StreamOutput out) {
|
public void writeTo(final StreamOutput out) throws IOException {
|
||||||
|
out.writeMap(decisions, StreamOutput::writeString, (o, decision) -> decision.writeTo(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
|
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
{
|
{
|
||||||
|
builder.startArray("decisions");
|
||||||
|
{
|
||||||
|
for (final Map.Entry<String, AutoscalingDecisions> decision : decisions.entrySet()) {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
builder.field(decision.getKey(), decision.getValue());
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
}
|
}
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
return builder;
|
return builder;
|
||||||
|
|
|
@ -19,6 +19,8 @@ import org.elasticsearch.threadpool.ThreadPool;
|
||||||
import org.elasticsearch.transport.TransportService;
|
import org.elasticsearch.transport.TransportService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
public class TransportGetAutoscalingDecisionAction extends TransportMasterNodeAction<
|
public class TransportGetAutoscalingDecisionAction extends TransportMasterNodeAction<
|
||||||
GetAutoscalingDecisionAction.Request,
|
GetAutoscalingDecisionAction.Request,
|
||||||
|
@ -59,7 +61,7 @@ public class TransportGetAutoscalingDecisionAction extends TransportMasterNodeAc
|
||||||
final ClusterState state,
|
final ClusterState state,
|
||||||
final ActionListener<GetAutoscalingDecisionAction.Response> listener
|
final ActionListener<GetAutoscalingDecisionAction.Response> listener
|
||||||
) {
|
) {
|
||||||
listener.onResponse(new GetAutoscalingDecisionAction.Response());
|
listener.onResponse(new GetAutoscalingDecisionAction.Response(Collections.unmodifiableSortedMap(new TreeMap<>())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
public class AutoscalingDecisionTests extends AutoscalingTestCase {
|
||||||
|
|
||||||
|
public void testAutoscalingDecisionType() {
|
||||||
|
final AutoscalingDecisionType type = randomFrom(AutoscalingDecisionType.values());
|
||||||
|
final AutoscalingDecision decision = randomAutoscalingDecisionOfType(type);
|
||||||
|
assertThat(decision.type(), equalTo(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAutoscalingDecisionTypeSerialization() throws IOException {
|
||||||
|
final AutoscalingDecisionType before = randomFrom(AutoscalingDecisionType.values());
|
||||||
|
final BytesStreamOutput out = new BytesStreamOutput();
|
||||||
|
before.writeTo(out);
|
||||||
|
final AutoscalingDecisionType after = AutoscalingDecisionType.readFrom(out.bytes().streamInput());
|
||||||
|
assertThat(after, equalTo(before));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
public class AutoscalingDecisionTypeWireSerializingTests extends AbstractWireSerializingTestCase<AutoscalingDecisionType> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<AutoscalingDecisionType> instanceReader() {
|
||||||
|
return AutoscalingDecisionType::readFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AutoscalingDecisionType createTestInstance() {
|
||||||
|
return randomFrom(AutoscalingDecisionType.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void assertEqualInstances(final AutoscalingDecisionType expectedInstance, final AutoscalingDecisionType newInstance) {
|
||||||
|
assertSame(expectedInstance, newInstance);
|
||||||
|
assertEquals(expectedInstance, newInstance);
|
||||||
|
assertEquals(expectedInstance.hashCode(), newInstance.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInvalidAutoscalingDecisionTypeSerialization() throws IOException {
|
||||||
|
final BytesStreamOutput out = new BytesStreamOutput();
|
||||||
|
final Set<Byte> values = Arrays.stream(AutoscalingDecisionType.values())
|
||||||
|
.map(AutoscalingDecisionType::id)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
final byte value = randomValueOtherThanMany(values::contains, ESTestCase::randomByte);
|
||||||
|
out.writeByte(value);
|
||||||
|
final IllegalArgumentException e = expectThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() -> AutoscalingDecisionType.readFrom(out.bytes().streamInput())
|
||||||
|
);
|
||||||
|
assertThat(e.getMessage(), equalTo("unexpected value [" + value + "] for autoscaling decision type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
|
|
||||||
|
public class AutoscalingDecisionWireSerializingTests extends AbstractWireSerializingTestCase<AutoscalingDecision> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<AutoscalingDecision> instanceReader() {
|
||||||
|
return AutoscalingDecision::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AutoscalingDecision createTestInstance() {
|
||||||
|
return AutoscalingTestCase.randomAutoscalingDecision();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
public class AutoscalingDecisionsTests extends AutoscalingTestCase {
|
||||||
|
|
||||||
|
public void testAutoscalingDecisionsRejectsEmptyDecisions() {
|
||||||
|
final IllegalArgumentException e = expectThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() -> new AutoscalingDecisions(Collections.emptyList())
|
||||||
|
);
|
||||||
|
assertThat(e.getMessage(), equalTo("decisions can not be empty"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAutoscalingDecisionsTypeDown() {
|
||||||
|
final AutoscalingDecisions decisions = randomAutoscalingDecisions(randomIntBetween(1, 8), 0, 0);
|
||||||
|
assertThat(decisions.type(), equalTo(AutoscalingDecisionType.SCALE_DOWN));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAutoscalingDecisionsTypeNo() {
|
||||||
|
final AutoscalingDecisions decision = randomAutoscalingDecisions(randomIntBetween(0, 8), randomIntBetween(1, 8), 0);
|
||||||
|
assertThat(decision.type(), equalTo(AutoscalingDecisionType.NO_SCALE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAutoscalingDecisionsTypeUp() {
|
||||||
|
final AutoscalingDecisions decision = randomAutoscalingDecisions(0, 0, randomIntBetween(1, 8));
|
||||||
|
assertThat(decision.type(), equalTo(AutoscalingDecisionType.SCALE_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
|
|
||||||
|
public class AutoscalingDecisionsWireSerializingTests extends AbstractWireSerializingTestCase<AutoscalingDecisions> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<AutoscalingDecisions> instanceReader() {
|
||||||
|
return AutoscalingDecisions::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AutoscalingDecisions createTestInstance() {
|
||||||
|
return AutoscalingTestCase.randomAutoscalingDecisions();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.common.Randomness;
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AutoscalingTestCase extends ESTestCase {
|
||||||
|
|
||||||
|
static AutoscalingDecision randomAutoscalingDecision() {
|
||||||
|
return randomAutoscalingDecisionOfType(randomFrom(AutoscalingDecisionType.values()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static AutoscalingDecision randomAutoscalingDecisionOfType(final AutoscalingDecisionType type) {
|
||||||
|
return new AutoscalingDecision(randomAlphaOfLength(8), type, randomAlphaOfLength(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
static AutoscalingDecisions randomAutoscalingDecisions() {
|
||||||
|
final int numberOfDecisions = 1 + randomIntBetween(1, 8);
|
||||||
|
final List<AutoscalingDecision> decisions = new ArrayList<>(numberOfDecisions);
|
||||||
|
for (int i = 0; i < numberOfDecisions; i++) {
|
||||||
|
decisions.add(randomAutoscalingDecisionOfType(AutoscalingDecisionType.SCALE_DOWN));
|
||||||
|
}
|
||||||
|
final int numberOfDownDecisions = randomIntBetween(0, 8);
|
||||||
|
final int numberOfNoDecisions = randomIntBetween(0, 8);
|
||||||
|
final int numberOfUpDecisions = randomIntBetween(numberOfDownDecisions + numberOfNoDecisions == 0 ? 1 : 0, 8);
|
||||||
|
return randomAutoscalingDecisions(numberOfDownDecisions, numberOfNoDecisions, numberOfUpDecisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
static AutoscalingDecisions randomAutoscalingDecisions(
|
||||||
|
final int numberOfDownDecisions,
|
||||||
|
final int numberOfNoDecisions,
|
||||||
|
final int numberOfUpDecisions
|
||||||
|
) {
|
||||||
|
final List<AutoscalingDecision> decisions = new ArrayList<>(numberOfDownDecisions + numberOfNoDecisions + numberOfUpDecisions);
|
||||||
|
for (int i = 0; i < numberOfDownDecisions; i++) {
|
||||||
|
decisions.add(randomAutoscalingDecisionOfType(AutoscalingDecisionType.SCALE_DOWN));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < numberOfNoDecisions; i++) {
|
||||||
|
decisions.add(randomAutoscalingDecisionOfType(AutoscalingDecisionType.NO_SCALE));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < numberOfUpDecisions; i++) {
|
||||||
|
decisions.add(randomAutoscalingDecisionOfType(AutoscalingDecisionType.SCALE_UP));
|
||||||
|
}
|
||||||
|
Randomness.shuffle(decisions);
|
||||||
|
return new AutoscalingDecisions(decisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue