-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Adds custom action parsing logic Signed-off-by: Robert Downs <[email protected]>
- Loading branch information
Showing
16 changed files
with
416 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -429,6 +429,10 @@ | |
} | ||
} | ||
} | ||
}, | ||
"custom": { | ||
"enabled": false, | ||
"type": "object" | ||
} | ||
} | ||
}, | ||
|
76 changes: 76 additions & 0 deletions
76
...in/org/opensearch/indexmanagement/indexstatemanagement/extension/ISMActionsParserTests.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.indexmanagement.indexstatemanagement.extension | ||
|
||
import org.junit.After | ||
import org.opensearch.common.xcontent.LoggingDeprecationHandler | ||
import org.opensearch.common.xcontent.ToXContent | ||
import org.opensearch.common.xcontent.XContentFactory | ||
import org.opensearch.common.xcontent.XContentType | ||
import org.opensearch.indexmanagement.indexstatemanagement.ISMActionsParser | ||
import org.opensearch.indexmanagement.opensearchapi.convertToMap | ||
import org.opensearch.indexmanagement.opensearchapi.string | ||
import org.opensearch.test.OpenSearchTestCase | ||
import kotlin.test.assertFailsWith | ||
|
||
class ISMActionsParserTests : OpenSearchTestCase() { | ||
|
||
/* | ||
* If any tests added the custom action parser, it should be removed from the static instance to not impact other tests | ||
*/ | ||
@After | ||
@Suppress("UnusedPrivateMember") | ||
private fun removeCustomActionParser() { | ||
ISMActionsParser.instance.parsers.removeIf { it.getActionType() == SampleCustomActionParser.SampleCustomAction.name } | ||
} | ||
|
||
fun `test duplicate action names fail`() { | ||
val customActionParser = SampleCustomActionParser() | ||
customActionParser.customAction = true | ||
// Duplicate custom parser names should fail | ||
ISMActionsParser.instance.addParser(customActionParser) | ||
assertFailsWith<IllegalArgumentException>("Expected IllegalArgumentException for duplicate action names") { | ||
ISMActionsParser.instance.addParser(customActionParser) | ||
} | ||
// Adding any duplicate parser should fail | ||
assertFailsWith<IllegalArgumentException>("Expected IllegalArgumentException for duplicate action names") { | ||
val randomExistingParser = ISMActionsParser.instance.parsers.random() | ||
ISMActionsParser.instance.addParser(randomExistingParser) | ||
} | ||
} | ||
|
||
fun `test custom action parsing`() { | ||
val customActionParser = SampleCustomActionParser() | ||
customActionParser.customAction = true | ||
ISMActionsParser.instance.addParser(customActionParser) | ||
val customAction = SampleCustomActionParser.SampleCustomAction(randomInt(), 0) | ||
val builder = XContentFactory.jsonBuilder() | ||
|
||
val customActionString = customAction.toXContent(builder, ToXContent.EMPTY_PARAMS).string() | ||
val parser = XContentType.JSON.xContent().createParser(xContentRegistry(), LoggingDeprecationHandler.INSTANCE, customActionString) | ||
parser.nextToken() | ||
val parsedCustomAction = ISMActionsParser.instance.parse(parser, 1) | ||
assertTrue("Action was not set to be custom after parsing", parsedCustomAction.customAction) | ||
customAction.customAction = true | ||
assertEquals("Round tripping custom action doesn't work", customAction.convertToMap(), parsedCustomAction.convertToMap()) | ||
} | ||
|
||
fun `test parsing custom action without custom flag`() { | ||
val customActionParser = SampleCustomActionParser() | ||
customActionParser.customAction = true | ||
ISMActionsParser.instance.addParser(customActionParser) | ||
val customAction = SampleCustomActionParser.SampleCustomAction(randomInt(), 0) | ||
customAction.customAction = true | ||
|
||
val customActionString = "{\"retry\":{\"count\":3,\"backoff\":\"exponential\",\"delay\":\"1m\"},\"some_custom_action\":{\"some_int_field\":${customAction.someInt}}}" | ||
val parser = XContentType.JSON.xContent().createParser(xContentRegistry(), LoggingDeprecationHandler.INSTANCE, customActionString) | ||
parser.nextToken() | ||
val parsedCustomAction = ISMActionsParser.instance.parse(parser, 1) | ||
assertTrue("Action was not set to be custom after parsing", parsedCustomAction.customAction) | ||
assertEquals("Round tripping custom action doesn't work", customAction.convertToMap(), parsedCustomAction.convertToMap()) | ||
assertTrue("Custom action did not have custom keyword after parsing", parsedCustomAction.convertToMap().containsKey("custom")) | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
...org/opensearch/indexmanagement/indexstatemanagement/extension/SampleCustomActionParser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.indexmanagement.indexstatemanagement.extension | ||
|
||
import org.opensearch.common.io.stream.StreamInput | ||
import org.opensearch.common.io.stream.StreamOutput | ||
import org.opensearch.common.xcontent.ToXContent | ||
import org.opensearch.common.xcontent.XContentBuilder | ||
import org.opensearch.common.xcontent.XContentParser | ||
import org.opensearch.common.xcontent.XContentParserUtils | ||
import org.opensearch.indexmanagement.spi.indexstatemanagement.Action | ||
import org.opensearch.indexmanagement.spi.indexstatemanagement.ActionParser | ||
import org.opensearch.indexmanagement.spi.indexstatemanagement.Step | ||
import org.opensearch.indexmanagement.spi.indexstatemanagement.model.ManagedIndexMetaData | ||
import org.opensearch.indexmanagement.spi.indexstatemanagement.model.StepContext | ||
import org.opensearch.indexmanagement.spi.indexstatemanagement.model.StepMetaData | ||
|
||
class SampleCustomActionParser : ActionParser() { | ||
override fun fromStreamInput(sin: StreamInput): Action { | ||
val someInt = sin.readInt() | ||
val index = sin.readInt() | ||
return SampleCustomAction(someInt, index) | ||
} | ||
|
||
override fun fromXContent(xcp: XContentParser, index: Int): Action { | ||
var someInt: Int? = null | ||
|
||
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp) | ||
while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { | ||
val fieldName = xcp.currentName() | ||
xcp.nextToken() | ||
|
||
when (fieldName) { | ||
SampleCustomAction.SOME_INT_FIELD -> someInt = xcp.intValue() | ||
else -> throw IllegalArgumentException("Invalid field: [$fieldName] found in SampleCustomAction.") | ||
} | ||
} | ||
return SampleCustomAction(someInt = requireNotNull(someInt) { "SomeInt field must be specified" }, index) | ||
} | ||
|
||
override fun getActionType(): String { | ||
return SampleCustomAction.name | ||
} | ||
class SampleCustomAction(val someInt: Int, index: Int) : Action(name, index) { | ||
|
||
private val sampleCustomStep = SampleCustomStep() | ||
private val steps = listOf(sampleCustomStep) | ||
|
||
override fun getStepToExecute(context: StepContext): Step = sampleCustomStep | ||
|
||
override fun getSteps(): List<Step> = steps | ||
|
||
override fun populateAction(builder: XContentBuilder, params: ToXContent.Params) { | ||
builder.startObject(type) | ||
builder.field(SOME_INT_FIELD, someInt) | ||
builder.endObject() | ||
} | ||
|
||
override fun populateAction(out: StreamOutput) { | ||
out.writeInt(someInt) | ||
out.writeInt(actionIndex) | ||
} | ||
|
||
companion object { | ||
const val name = "some_custom_action" | ||
const val SOME_INT_FIELD = "some_int_field" | ||
} | ||
} | ||
class SampleCustomStep : Step(name) { | ||
private var stepStatus = StepStatus.STARTING | ||
|
||
override suspend fun execute(): Step { | ||
stepStatus = StepStatus.COMPLETED | ||
return this | ||
} | ||
|
||
override fun getUpdatedManagedIndexMetadata(currentMetadata: ManagedIndexMetaData): ManagedIndexMetaData { | ||
return currentMetadata.copy( | ||
stepMetaData = StepMetaData(name, getStepStartTime(currentMetadata).toEpochMilli(), stepStatus), | ||
transitionTo = null, | ||
info = null | ||
) | ||
} | ||
|
||
override fun isIdempotent(): Boolean = true | ||
|
||
companion object { | ||
const val name = "some_custom_step" | ||
} | ||
} | ||
} |
Oops, something went wrong.