Skip to content

Commit

Permalink
Add APIs (GET/PUT) to decommission awareness attribute (opensearch-pr…
Browse files Browse the repository at this point in the history
…oject#4261)

* Add APIs (GET/PUT) to decommission awareness attribute

Signed-off-by: Rishab Nahata <rnnahata@amazon.com>
  • Loading branch information
imRishN authored and sashashura committed Oct 12, 2022
1 parent e70d533 commit a7c157e
Show file tree
Hide file tree
Showing 31 changed files with 1,093 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Further simplification of the ZIP publication implementation ([#4360](https://github.com/opensearch-project/OpenSearch/pull/4360))
- Relax visibility of the HTTP_CHANNEL_KEY and HTTP_SERVER_CHANNEL_KEY to make it possible for the plugins to access associated Netty4HttpChannel / Netty4HttpServerChannel instance ([#4638](https://github.com/opensearch-project/OpenSearch/pull/4638))
- Load the deprecated master role in a dedicated method instead of in setAdditionalRoles() ([#4582](https://github.com/opensearch-project/OpenSearch/pull/4582))
- Add APIs (GET/PUT) to decommission awareness attribute ([#4261](https://github.com/opensearch-project/OpenSearch/pull/4261))

### Deprecated

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,9 @@ public void testApiNamingConventions() throws Exception {
"nodes.reload_secure_settings",
"search_shards",
"remote_store.restore",
"cluster.put_weighted_routing", };
"cluster.put_weighted_routing",
"cluster.put_decommission_awareness",
"cluster.get_decommission_awareness", };
List<String> booleanReturnMethods = Arrays.asList("security.enable_user", "security.disable_user", "security.change_password");
Set<String> deprecatedMethods = new HashSet<>();
deprecatedMethods.add("indices.force_merge");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"cluster.get_decommission_awareness": {
"documentation": {
"url": "https://opensearch.org/docs/latest/opensearch/rest-api/decommission/",
"description": "Get details and status of decommissioned attribute"
},
"stability": "experimental",
"url": {
"paths": [
{
"path": "/_cluster/decommission/awareness/_status",
"methods": [
"GET"
]
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"cluster.put_decommission_awareness": {
"documentation": {
"url": "https://opensearch.org/docs/latest/opensearch/rest-api/decommission/",
"description": "Decommissions an awareness attribute"
},
"stability": "experimental",
"url": {
"paths": [
{
"path": "/_cluster/decommission/awareness/{awareness_attribute_name}/{awareness_attribute_value}",
"methods": [
"PUT"
],
"parts": {
"awareness_attribute_name": {
"type": "string",
"description": "Awareness attribute name"
},
"awareness_attribute_value": {
"type": "string",
"description": "Awareness attribute value"
}
}
}
]
}
}
}
12 changes: 12 additions & 0 deletions server/src/main/java/org/opensearch/action/ActionModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
import org.opensearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsAction;
import org.opensearch.action.admin.cluster.configuration.TransportAddVotingConfigExclusionsAction;
import org.opensearch.action.admin.cluster.configuration.TransportClearVotingConfigExclusionsAction;
import org.opensearch.action.admin.cluster.decommission.awareness.get.GetDecommissionStateAction;
import org.opensearch.action.admin.cluster.decommission.awareness.get.TransportGetDecommissionStateAction;
import org.opensearch.action.admin.cluster.decommission.awareness.put.DecommissionAction;
import org.opensearch.action.admin.cluster.decommission.awareness.put.TransportDecommissionAction;
import org.opensearch.action.admin.cluster.health.ClusterHealthAction;
import org.opensearch.action.admin.cluster.health.TransportClusterHealthAction;
import org.opensearch.action.admin.cluster.node.hotthreads.NodesHotThreadsAction;
Expand Down Expand Up @@ -306,6 +310,7 @@
import org.opensearch.rest.action.admin.cluster.RestDeleteRepositoryAction;
import org.opensearch.rest.action.admin.cluster.RestDeleteSnapshotAction;
import org.opensearch.rest.action.admin.cluster.RestDeleteStoredScriptAction;
import org.opensearch.rest.action.admin.cluster.RestGetDecommissionStateAction;
import org.opensearch.rest.action.admin.cluster.RestGetRepositoriesAction;
import org.opensearch.rest.action.admin.cluster.RestGetScriptContextAction;
import org.opensearch.rest.action.admin.cluster.RestGetScriptLanguageAction;
Expand All @@ -318,6 +323,7 @@
import org.opensearch.rest.action.admin.cluster.RestNodesStatsAction;
import org.opensearch.rest.action.admin.cluster.RestNodesUsageAction;
import org.opensearch.rest.action.admin.cluster.RestPendingClusterTasksAction;
import org.opensearch.rest.action.admin.cluster.RestDecommissionAction;
import org.opensearch.rest.action.admin.cluster.RestPutRepositoryAction;
import org.opensearch.rest.action.admin.cluster.RestPutStoredScriptAction;
import org.opensearch.rest.action.admin.cluster.RestReloadSecureSettingsAction;
Expand Down Expand Up @@ -686,6 +692,10 @@ public <Request extends ActionRequest, Response extends ActionResponse> void reg
// Remote Store
actions.register(RestoreRemoteStoreAction.INSTANCE, TransportRestoreRemoteStoreAction.class);

// Decommission actions
actions.register(DecommissionAction.INSTANCE, TransportDecommissionAction.class);
actions.register(GetDecommissionStateAction.INSTANCE, TransportGetDecommissionStateAction.class);

return unmodifiableMap(actions.getRegistry());
}

Expand Down Expand Up @@ -879,6 +889,8 @@ public void initRestHandlers(Supplier<DiscoveryNodes> nodesInCluster) {
}
}
registerHandler.accept(new RestCatAction(catActions));
registerHandler.accept(new RestDecommissionAction());
registerHandler.accept(new RestGetDecommissionStateAction());

// Remote Store APIs
if (FeatureFlags.isEnabled(FeatureFlags.REMOTE_STORE)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.action.admin.cluster.decommission.awareness.get;

import org.opensearch.action.ActionType;

/**
* Get decommission action
*
* @opensearch.internal
*/
public class GetDecommissionStateAction extends ActionType<GetDecommissionStateResponse> {

public static final GetDecommissionStateAction INSTANCE = new GetDecommissionStateAction();
public static final String NAME = "cluster:admin/decommission/awareness/get";

private GetDecommissionStateAction() {
super(NAME, GetDecommissionStateResponse::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.action.admin.cluster.decommission.awareness.get;

import org.opensearch.action.ActionRequestValidationException;
import org.opensearch.action.support.clustermanager.ClusterManagerNodeReadRequest;
import org.opensearch.common.io.stream.StreamInput;
import org.opensearch.common.io.stream.StreamOutput;

import java.io.IOException;

/**
* Get Decommissioned attribute request
*
* @opensearch.internal
*/
public class GetDecommissionStateRequest extends ClusterManagerNodeReadRequest<GetDecommissionStateRequest> {

public GetDecommissionStateRequest() {}

public GetDecommissionStateRequest(StreamInput in) throws IOException {
super(in);
}

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

@Override
public ActionRequestValidationException validate() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.action.admin.cluster.decommission.awareness.get;

import org.opensearch.action.support.clustermanager.ClusterManagerNodeReadOperationRequestBuilder;
import org.opensearch.client.OpenSearchClient;

/**
* Get decommission request builder
*
* @opensearch.internal
*/
public class GetDecommissionStateRequestBuilder extends ClusterManagerNodeReadOperationRequestBuilder<
GetDecommissionStateRequest,
GetDecommissionStateResponse,
GetDecommissionStateRequestBuilder> {

/**
* Creates new get decommissioned attributes request builder
*/
public GetDecommissionStateRequestBuilder(OpenSearchClient client, GetDecommissionStateAction action) {
super(client, action, new GetDecommissionStateRequest());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.action.admin.cluster.decommission.awareness.get;

import org.opensearch.OpenSearchParseException;
import org.opensearch.action.ActionResponse;
import org.opensearch.cluster.decommission.DecommissionAttribute;
import org.opensearch.cluster.decommission.DecommissionStatus;
import org.opensearch.common.io.stream.StreamInput;
import org.opensearch.common.io.stream.StreamOutput;
import org.opensearch.common.xcontent.ToXContentObject;
import org.opensearch.common.xcontent.XContentBuilder;
import org.opensearch.common.xcontent.XContentParser;

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

import static org.opensearch.common.xcontent.XContentParserUtils.ensureExpectedToken;

/**
* Response for decommission status
*
* @opensearch.internal
*/
public class GetDecommissionStateResponse extends ActionResponse implements ToXContentObject {

private DecommissionAttribute decommissionedAttribute;
private DecommissionStatus status;

GetDecommissionStateResponse() {
this(null, null);
}

GetDecommissionStateResponse(DecommissionAttribute decommissionedAttribute, DecommissionStatus status) {
this.decommissionedAttribute = decommissionedAttribute;
this.status = status;
}

GetDecommissionStateResponse(StreamInput in) throws IOException {
// read decommissioned attribute and status only if it is present
if (in.readBoolean()) {
this.decommissionedAttribute = new DecommissionAttribute(in);
}
if (in.readBoolean()) {
this.status = DecommissionStatus.fromString(in.readString());
}
}

@Override
public void writeTo(StreamOutput out) throws IOException {
// if decommissioned attribute is null, mark absence of decommissioned attribute
if (decommissionedAttribute == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
decommissionedAttribute.writeTo(out);
}

// if status is null, mark absence of status
if (status == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeString(status.status());
}
}

public DecommissionAttribute getDecommissionedAttribute() {
return decommissionedAttribute;
}

public DecommissionStatus getDecommissionStatus() {
return status;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.startObject("awareness");
if (decommissionedAttribute != null) {
builder.field(decommissionedAttribute.attributeName(), decommissionedAttribute.attributeValue());
}
builder.endObject();
if (status != null) {
builder.field("status", status);
}
builder.endObject();
return builder;
}

public static GetDecommissionStateResponse fromXContent(XContentParser parser) throws IOException {
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
String attributeType = "awareness";
XContentParser.Token token;
DecommissionAttribute decommissionAttribute = null;
DecommissionStatus status = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
String currentFieldName = parser.currentName();
if (attributeType.equals(currentFieldName)) {
if (parser.nextToken() != XContentParser.Token.START_OBJECT) {
throw new OpenSearchParseException(
"failed to parse decommission attribute type [{}], expected object",
attributeType
);
}
token = parser.nextToken();
if (token != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
String fieldName = parser.currentName();
String value;
token = parser.nextToken();
if (token == XContentParser.Token.VALUE_STRING) {
value = parser.text();
} else {
throw new OpenSearchParseException(
"failed to parse attribute [{}], expected string for attribute value",
fieldName
);
}
decommissionAttribute = new DecommissionAttribute(fieldName, value);
parser.nextToken();
} else {
throw new OpenSearchParseException("failed to parse attribute type [{}], unexpected type", attributeType);
}
} else {
throw new OpenSearchParseException("failed to parse attribute type [{}]", attributeType);
}
} else if ("status".equals(currentFieldName)) {
if (parser.nextToken() != XContentParser.Token.VALUE_STRING) {
throw new OpenSearchParseException(
"failed to parse status of decommissioning, expected string but found unknown type"
);
}
status = DecommissionStatus.fromString(parser.text().toLowerCase(Locale.ROOT));
} else {
throw new OpenSearchParseException(
"unknown field found [{}], failed to parse the decommission attribute",
currentFieldName
);
}
}
}
return new GetDecommissionStateResponse(decommissionAttribute, status);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GetDecommissionStateResponse that = (GetDecommissionStateResponse) o;
return decommissionedAttribute.equals(that.decommissionedAttribute) && status == that.status;
}

@Override
public int hashCode() {
return Objects.hash(decommissionedAttribute, status);
}
}
Loading

0 comments on commit a7c157e

Please sign in to comment.