From 3ef7642a2bdc32b70464588e475d33acf6622333 Mon Sep 17 00:00:00 2001 From: Joshua Au Date: Tue, 10 Oct 2023 13:05:54 -0400 Subject: [PATCH] Implemented filtering on the ISM eplain API --- .../model/ExplainFilter.kt | 100 ++++++++++++++++++ .../resthandler/RestExplainAction.kt | 21 ++++ .../action/explain/ExplainRequest.kt | 6 ++ .../action/explain/TransportExplainAction.kt | 28 ++--- 4 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/model/ExplainFilter.kt diff --git a/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/model/ExplainFilter.kt b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/model/ExplainFilter.kt new file mode 100644 index 000000000..8fb09d7e7 --- /dev/null +++ b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/model/ExplainFilter.kt @@ -0,0 +1,100 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.indexmanagement.indexstatemanagement.model + +import org.opensearch.core.common.io.stream.StreamInput +import org.opensearch.core.common.io.stream.StreamOutput +import org.opensearch.core.common.io.stream.Writeable +import org.opensearch.core.xcontent.XContentParser +import org.opensearch.core.xcontent.XContentParser.Token +import org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken +import java.io.IOException + +data class ExplainFilter( + val filterPolicyID: String?, + val filterState: String?, + val filterAction: String? +) : Writeable { + + constructor() : this( + filterPolicyID = null, + filterState = null, + filterAction = null + ) + + @Throws(IOException::class) + constructor(sin: StreamInput) : this( + filterPolicyID = sin.readString(), + filterState = sin.readString(), + filterAction = sin.readString() + ) + + @Throws(IOException::class) + override fun writeTo(out: StreamOutput) { + out.writeString(filterPolicyID) + out.writeString(filterState) + out.writeString(filterAction) + } + + fun isValid(managedIndexConfig: ManagedIndexConfig): Boolean { + var valid = true + + if (filterPolicyID != null && filterPolicyID != managedIndexConfig.policyID) { + valid = false + } + + val policy = managedIndexConfig.policy + + if (filterState != null && policy != null && !policy.states.any { it.name == filterState }) { + valid = false + } + + if (filterAction != null && policy != null && !policy.states.any { state -> state.actions.any { it.type == filterAction } }) { + valid = false + } + + return valid + } + + companion object { + const val FILTER_FIELD = "filter" + const val POLICY_ID_FIELD = "policy_id" + const val STATE_FIELD = "state" + const val ACTION_FIELD = "action_type" + + @JvmStatic + @Throws(IOException::class) + fun parse(xcp: XContentParser): ExplainFilter { + var policyID: String? = null + var state: String? = null + var action: String? = null + + ensureExpectedToken(Token.START_OBJECT, xcp.currentToken(), xcp) + while (xcp.nextToken() != Token.END_OBJECT) { + val fieldName = xcp.currentName() + xcp.nextToken() + + when (fieldName) { + FILTER_FIELD -> { + ensureExpectedToken(Token.START_OBJECT, xcp.currentToken(), xcp) + while (xcp.nextToken() != Token.END_OBJECT) { + val filter = xcp.currentName() + xcp.nextToken() + + when (filter) { + POLICY_ID_FIELD -> policyID = xcp.text() + STATE_FIELD -> state = xcp.text() + ACTION_FIELD -> action = xcp.text() + } + } + } + } + } + + return ExplainFilter(policyID, state, action) + } + } +} diff --git a/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/resthandler/RestExplainAction.kt b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/resthandler/RestExplainAction.kt index c9bde8bbf..68f8c353c 100644 --- a/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/resthandler/RestExplainAction.kt +++ b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/resthandler/RestExplainAction.kt @@ -9,8 +9,11 @@ import org.apache.logging.log4j.LogManager import org.opensearch.client.node.NodeClient import org.opensearch.core.common.Strings import org.opensearch.common.logging.DeprecationLogger +import org.opensearch.core.xcontent.XContentParser.Token +import org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken import org.opensearch.indexmanagement.IndexManagementPlugin.Companion.ISM_BASE_URI import org.opensearch.indexmanagement.IndexManagementPlugin.Companion.LEGACY_ISM_BASE_URI +import org.opensearch.indexmanagement.indexstatemanagement.model.ExplainFilter import org.opensearch.indexmanagement.indexstatemanagement.transport.action.explain.ExplainAction import org.opensearch.indexmanagement.indexstatemanagement.transport.action.explain.ExplainRequest import org.opensearch.indexmanagement.indexstatemanagement.util.DEFAULT_EXPLAIN_VALIDATE_ACTION @@ -28,6 +31,7 @@ import org.opensearch.rest.RestHandler.ReplacedRoute import org.opensearch.rest.RestHandler.Route import org.opensearch.rest.RestRequest import org.opensearch.rest.RestRequest.Method.GET +import org.opensearch.rest.RestRequest.Method.POST import org.opensearch.rest.action.RestToXContentListener private val log = LogManager.getLogger(RestExplainAction::class.java) @@ -52,6 +56,14 @@ class RestExplainAction : BaseRestHandler() { ReplacedRoute( GET, "$EXPLAIN_BASE_URI/{index}", GET, "$LEGACY_EXPLAIN_BASE_URI/{index}" + ), + ReplacedRoute( + POST, EXPLAIN_BASE_URI, + POST, LEGACY_EXPLAIN_BASE_URI + ), + ReplacedRoute( + POST, "$EXPLAIN_BASE_URI/{index}", + POST, "$LEGACY_EXPLAIN_BASE_URI/{index}" ) ) } @@ -69,6 +81,14 @@ class RestExplainAction : BaseRestHandler() { val indexType = request.param(TYPE_PARAM_KEY, DEFAULT_INDEX_TYPE) + val explainFilter = if (request.method() == RestRequest.Method.POST) { + val xcp = request.contentParser() + ensureExpectedToken(Token.START_OBJECT, xcp.nextToken(), xcp) + ExplainFilter.parse(xcp) + } else { + ExplainFilter() + } + val clusterManagerTimeout = parseClusterManagerTimeout( request, DeprecationLogger.getLogger(RestExplainAction::class.java), name ) @@ -78,6 +98,7 @@ class RestExplainAction : BaseRestHandler() { request.paramAsBoolean("local", false), clusterManagerTimeout, searchParams, + explainFilter, request.paramAsBoolean(SHOW_POLICY_QUERY_PARAM, DEFAULT_EXPLAIN_SHOW_POLICY), request.paramAsBoolean(SHOW_VALIDATE_ACTION, DEFAULT_EXPLAIN_VALIDATE_ACTION), indexType diff --git a/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/ExplainRequest.kt b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/ExplainRequest.kt index a34ce2020..ba0090442 100644 --- a/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/ExplainRequest.kt +++ b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/ExplainRequest.kt @@ -12,6 +12,7 @@ import org.opensearch.core.common.io.stream.StreamInput import org.opensearch.core.common.io.stream.StreamOutput import org.opensearch.common.unit.TimeValue import org.opensearch.indexmanagement.common.model.rest.SearchParams +import org.opensearch.indexmanagement.indexstatemanagement.model.ExplainFilter import org.opensearch.indexmanagement.indexstatemanagement.util.DEFAULT_INDEX_TYPE import java.io.IOException @@ -21,6 +22,7 @@ class ExplainRequest : ActionRequest { val local: Boolean val clusterManagerTimeout: TimeValue val searchParams: SearchParams + val explainFilter: ExplainFilter val showPolicy: Boolean val validateAction: Boolean val indexType: String @@ -31,6 +33,7 @@ class ExplainRequest : ActionRequest { local: Boolean, clusterManagerTimeout: TimeValue, searchParams: SearchParams, + explainFilter: ExplainFilter, showPolicy: Boolean, validateAction: Boolean, indexType: String @@ -39,6 +42,7 @@ class ExplainRequest : ActionRequest { this.local = local this.clusterManagerTimeout = clusterManagerTimeout this.searchParams = searchParams + this.explainFilter = explainFilter this.showPolicy = showPolicy this.validateAction = validateAction this.indexType = indexType @@ -50,6 +54,7 @@ class ExplainRequest : ActionRequest { local = sin.readBoolean(), clusterManagerTimeout = sin.readTimeValue(), searchParams = SearchParams(sin), + explainFilter = ExplainFilter(sin), showPolicy = sin.readBoolean(), validateAction = sin.readBoolean(), indexType = sin.readString() @@ -72,6 +77,7 @@ class ExplainRequest : ActionRequest { out.writeBoolean(local) out.writeTimeValue(clusterManagerTimeout) searchParams.writeTo(out) + explainFilter.writeTo(out) out.writeBoolean(showPolicy) out.writeBoolean(validateAction) out.writeString(indexType) diff --git a/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/TransportExplainAction.kt b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/TransportExplainAction.kt index ec32bcbd9..d8f140b7b 100644 --- a/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/TransportExplainAction.kt +++ b/src/main/kotlin/org/opensearch/indexmanagement/indexstatemanagement/transport/action/explain/TransportExplainAction.kt @@ -190,19 +190,21 @@ class TransportExplainAction @Inject constructor( } parseSearchHits(response.hits.hits).forEach { managedIndex -> - managedIndices.add(managedIndex.index) - enabledState[managedIndex.index] = managedIndex.enabled - managedIndicesMetaDataMap[managedIndex.index] = mapOf( - "index" to managedIndex.index, - "index_uuid" to managedIndex.indexUuid, - "policy_id" to managedIndex.policyID, - "enabled" to managedIndex.enabled.toString() - ) - if (showPolicy) { - managedIndex.policy?.let { appliedPolicies[managedIndex.index] = it } - } - if (validateAction) { - managedIndex.policy?.let { policiesforValidation[managedIndex.index] = it } + if (request.explainFilter.isValid(managedIndex)) { + managedIndices.add(managedIndex.index) + enabledState[managedIndex.index] = managedIndex.enabled + managedIndicesMetaDataMap[managedIndex.index] = mapOf( + "index" to managedIndex.index, + "index_uuid" to managedIndex.indexUuid, + "policy_id" to managedIndex.policyID, + "enabled" to managedIndex.enabled.toString() + ) + if (showPolicy) { + managedIndex.policy?.let { appliedPolicies[managedIndex.index] = it } + } + if (validateAction) { + managedIndex.policy?.let { policiesforValidation[managedIndex.index] = it } + } } }