From cffa376436084b5fb5b993c1e3cacc04537d6c21 Mon Sep 17 00:00:00 2001 From: skkosuri-amzn Date: Wed, 9 Sep 2020 15:49:15 -0700 Subject: [PATCH 1/5] Fix 1/ IllegalStateException warn messages, 2/ location header in destination response, 3/ handle null in GetMonitorRequest --- .../alerting/action/GetMonitorRequest.kt | 11 ++++++-- .../resthandler/RestIndexDestinationAction.kt | 2 +- .../TransportExecuteMonitorAction.kt | 1 + .../transport/TransportGetMonitorAction.kt | 1 + .../TransportIndexDestinationAction.kt | 18 ++++++++++--- .../transport/TransportIndexMonitorAction.kt | 19 +++++++++++--- .../alerting/AlertingRestTestCase.kt | 2 +- .../alerting/action/GetMonitorRequestTests.kt | 15 +++++++++++ .../resthandler/DestinationRestApiIT.kt | 26 +++++++++++++++++-- 9 files changed, 81 insertions(+), 14 deletions(-) diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt index ebf46c71..783fd000 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt @@ -46,7 +46,9 @@ class GetMonitorRequest : ActionRequest { sin.readString(), // monitorId sin.readLong(), // version sin.readEnum(RestRequest.Method::class.java), // method - FetchSourceContext(sin) // srcContext + if (sin.readBoolean()) { + FetchSourceContext(sin) // srcContext + } else null ) override fun validate(): ActionRequestValidationException? { @@ -58,6 +60,11 @@ class GetMonitorRequest : ActionRequest { out.writeString(monitorId) out.writeLong(version) out.writeEnum(method) - srcContext?.writeTo(out) + if (srcContext != null) { + out.writeBoolean(true) + srcContext?.writeTo(out) + } else { + out.writeBoolean(false) + } } } diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/RestIndexDestinationAction.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/RestIndexDestinationAction.kt index 39b1b840..913edab6 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/RestIndexDestinationAction.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/RestIndexDestinationAction.kt @@ -101,7 +101,7 @@ class RestIndexDestinationAction( val restResponse = BytesRestResponse(returnStatus, response.toXContent(channel.newBuilder(), ToXContent.EMPTY_PARAMS)) if (returnStatus == RestStatus.CREATED) { - val location = AlertingPlugin.DESTINATION_BASE_URI + response.id + val location = "${AlertingPlugin.DESTINATION_BASE_URI}/${response.id}" restResponse.addHeader("Location", location) } return restResponse diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportExecuteMonitorAction.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportExecuteMonitorAction.kt index c73c8188..d7a4c27a 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportExecuteMonitorAction.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportExecuteMonitorAction.kt @@ -69,6 +69,7 @@ class TransportExecuteMonitorAction @Inject constructor( actionListener.onFailure( ElasticsearchStatusException("Can't find monitor with id: ${response.id}", RestStatus.NOT_FOUND) ) + return } if (!response.isSourceEmpty) { XContentHelper.createParser(xContentRegistry, LoggingDeprecationHandler.INSTANCE, diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportGetMonitorAction.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportGetMonitorAction.kt index 1fd0e8b2..d1580dd1 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportGetMonitorAction.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportGetMonitorAction.kt @@ -58,6 +58,7 @@ class TransportGetMonitorAction @Inject constructor( override fun onResponse(response: GetResponse) { if (!response.isExists) { actionListener.onFailure(ElasticsearchStatusException("Monitor not found.", RestStatus.NOT_FOUND)) + return } var monitor: Monitor? = null diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexDestinationAction.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexDestinationAction.kt index 052893d6..b06795e4 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexDestinationAction.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexDestinationAction.kt @@ -97,7 +97,11 @@ class TransportIndexDestinationAction @Inject constructor( client.index(indexRequest, object : ActionListener { override fun onResponse(response: IndexResponse) { - checkShardsFailure(response) + val failureReasons = checkShardsFailure(response) + if (failureReasons != null) { + actionListener.onFailure(ElasticsearchStatusException(failureReasons.toString(), response.status())) + return + } actionListener.onResponse(IndexDestinationResponse(response.id, response.version, response.seqNo, response.primaryTerm, RestStatus.CREATED, destination)) } @@ -155,6 +159,7 @@ class TransportIndexDestinationAction @Inject constructor( if (!response.isExists) { actionListener.onFailure( ElasticsearchStatusException("Destination with ${request.destinationId} is not found", RestStatus.NOT_FOUND)) + return } val destination = request.destination.copy(schemaVersion = IndexUtils.scheduledJobIndexSchemaVersion) @@ -168,7 +173,11 @@ class TransportIndexDestinationAction @Inject constructor( client.index(indexRequest, object : ActionListener { override fun onResponse(response: IndexResponse) { - checkShardsFailure(response) + val failureReasons = checkShardsFailure(response) + if (failureReasons != null) { + actionListener.onFailure(ElasticsearchStatusException(failureReasons.toString(), response.status())) + return + } actionListener.onResponse(IndexDestinationResponse(response.id, response.version, response.seqNo, response.primaryTerm, RestStatus.CREATED, destination)) } @@ -178,14 +187,15 @@ class TransportIndexDestinationAction @Inject constructor( }) } - private fun checkShardsFailure(response: IndexResponse) { + private fun checkShardsFailure(response: IndexResponse): String? { var failureReasons = StringBuilder() if (response.shardInfo.failed > 0) { response.shardInfo.failures.forEach { entry -> failureReasons.append(entry.reason()) } - actionListener.onFailure(ElasticsearchStatusException(failureReasons.toString(), response.status())) + return failureReasons.toString() } + return null } } } diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexMonitorAction.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexMonitorAction.kt index dc405fa5..96842307 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexMonitorAction.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/transport/TransportIndexMonitorAction.kt @@ -133,6 +133,7 @@ class TransportIndexMonitorAction @Inject constructor( validateActionThrottle(request.monitor, maxActionThrottle, TimeValue.timeValueMinutes(1)) } catch (e: RuntimeException) { actionListener.onFailure(e) + return } if (request.method == RestRequest.Method.PUT) return updateMonitor() @@ -221,7 +222,11 @@ class TransportIndexMonitorAction @Inject constructor( .timeout(indexTimeout) client.index(indexRequest, object : ActionListener { override fun onResponse(response: IndexResponse) { - checkShardsFailure(response) + val failureReasons = checkShardsFailure(response) + if (failureReasons != null) { + actionListener.onFailure(ElasticsearchStatusException(failureReasons.toString(), response.status())) + return + } actionListener.onResponse(IndexMonitorResponse(response.id, response.version, response.seqNo, response.primaryTerm, RestStatus.CREATED, request.monitor)) } @@ -247,6 +252,7 @@ class TransportIndexMonitorAction @Inject constructor( if (!response.isExists) { actionListener.onFailure( ElasticsearchStatusException("Monitor with ${request.monitorId} is not found", RestStatus.NOT_FOUND)) + return } val xcp = XContentHelper.createParser(xContentRegistry, LoggingDeprecationHandler.INSTANCE, @@ -268,7 +274,11 @@ class TransportIndexMonitorAction @Inject constructor( client.index(indexRequest, object : ActionListener { override fun onResponse(response: IndexResponse) { - checkShardsFailure(response) + val failureReasons = checkShardsFailure(response) + if (failureReasons != null) { + actionListener.onFailure(ElasticsearchStatusException(failureReasons.toString(), response.status())) + return + } actionListener.onResponse( IndexMonitorResponse(response.id, response.version, response.seqNo, response.primaryTerm, RestStatus.CREATED, request.monitor) @@ -280,14 +290,15 @@ class TransportIndexMonitorAction @Inject constructor( }) } - private fun checkShardsFailure(response: IndexResponse) { + private fun checkShardsFailure(response: IndexResponse): String? { var failureReasons = StringBuilder() if (response.shardInfo.failed > 0) { response.shardInfo.failures.forEach { entry -> failureReasons.append(entry.reason()) } - actionListener.onFailure(ElasticsearchStatusException(failureReasons.toString(), response.status())) + return failureReasons.toString() } + return null } } } diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt index cc977b5a..b45934d0 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt @@ -282,7 +282,7 @@ abstract class AlertingRestTestCase : ODFERestTestCase() { return shuffleXContent(toXContent(builder)).string() } - private fun Destination.toHttpEntity(): HttpEntity { + protected fun Destination.toHttpEntity(): HttpEntity { return StringEntity(toJsonString(), APPLICATION_JSON) } diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequestTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequestTests.kt index 2b627f3c..17d147af 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequestTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequestTests.kt @@ -38,6 +38,21 @@ class GetMonitorRequestTests : ESTestCase() { assertEquals(FetchSourceContext.FETCH_SOURCE, newReq.srcContext) } + fun `test get monitor request withou src context`() { + + val req = GetMonitorRequest("1234", 1L, RestRequest.Method.GET, null) + assertNotNull(req) + + val out = BytesStreamOutput() + req.writeTo(out) + val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes) + val newReq = GetMonitorRequest(sin) + assertEquals("1234", newReq.monitorId) + assertEquals(1L, newReq.version) + assertEquals(RestRequest.Method.GET, newReq.method) + assertEquals(null, newReq.srcContext) + } + fun `test head monitor request`() { val req = GetMonitorRequest("1234", 2L, RestRequest.Method.HEAD, FetchSourceContext.FETCH_SOURCE) diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt index 2b0fbbde..183ad615 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt @@ -15,13 +15,13 @@ package com.amazon.opendistroforelasticsearch.alerting.resthandler -import com.amazon.opendistroforelasticsearch.alerting.DESTINATION_BASE_URI import com.amazon.opendistroforelasticsearch.alerting.AlertingRestTestCase +import com.amazon.opendistroforelasticsearch.alerting.DESTINATION_BASE_URI +import com.amazon.opendistroforelasticsearch.alerting.makeRequest import com.amazon.opendistroforelasticsearch.alerting.model.destination.Chime import com.amazon.opendistroforelasticsearch.alerting.model.destination.CustomWebhook import com.amazon.opendistroforelasticsearch.alerting.model.destination.Destination import com.amazon.opendistroforelasticsearch.alerting.model.destination.Slack -import com.amazon.opendistroforelasticsearch.alerting.makeRequest import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType import org.elasticsearch.rest.RestStatus import org.elasticsearch.test.junit.annotations.TestLogging @@ -149,6 +149,28 @@ class DestinationRestApiIT : AlertingRestTestCase() { assertEquals("Incorrect destination url after update", "abc.com", updatedDestination.customWebhook?.host) } + @Throws(Exception::class) + fun `test creating a destination`() { + val chime = Chime("http://abc.com") + val destination = Destination( + type = DestinationType.CHIME, + name = "test", + lastUpdateTime = Instant.now(), + chime = chime, + slack = null, + customWebhook = null) + + val createResponse = client().makeRequest("POST", DESTINATION_BASE_URI, emptyMap(), destination.toHttpEntity()) + + assertEquals("Create destination failed", RestStatus.CREATED, createResponse.restStatus()) + val responseBody = createResponse.asMap() + val createdId = responseBody["_id"] as String + val createdVersion = responseBody["_version"] as Int + assertNotEquals("response is missing Id", Destination.NO_ID, createdId) + assertTrue("incorrect version", createdVersion > 0) + assertEquals("Incorrect Location header", "$DESTINATION_BASE_URI/$createdId", createResponse.getHeader("Location")) + } + fun `test delete destination`() { val destination = createDestination() val deletedDestinationResponse = client().makeRequest("DELETE", "$DESTINATION_BASE_URI/${destination.id}") From ff14293af73abf16b5900cf287f55ad8b4f4726b Mon Sep 17 00:00:00 2001 From: skkosuri-amzn Date: Wed, 23 Sep 2020 13:52:50 -0700 Subject: [PATCH 2/5] Add User details to Monitor and Destination --- .../alerting/action/GetMonitorRequest.kt | 2 +- .../alerting/model/Monitor.kt | 26 +++++- .../alerting/model/User.kt | 92 +++++++++++++++++++ .../alerting/model/destination/Destination.kt | 23 +++++ .../alerting/AlertingRestTestCase.kt | 1 + .../alerting/TestHelpers.kt | 28 +++++- .../action/GetMonitorResponseTests.kt | 3 +- .../action/IndexDestinationRequestTests.kt | 3 + .../action/IndexDestinationResponseTests.kt | 3 +- .../action/IndexMonitorResponseTests.kt | 3 +- .../alerting/alerts/AlertIndicesIT.kt | 2 +- .../alerting/model/DestinationTests.kt | 23 ++++- .../alerting/model/WriteableTests.kt | 20 ++++ .../alerting/model/XContentTests.kt | 27 ++++++ .../resthandler/DestinationRestApiIT.kt | 6 ++ .../alerting/core/model/ScheduledJob.kt | 3 +- .../resources/mappings/scheduled-jobs.json | 76 ++++++++++++++- .../alerting/core/model/MockScheduledJob.kt | 7 ++ 18 files changed, 336 insertions(+), 12 deletions(-) create mode 100644 alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/User.kt diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt index 783fd000..e4fd1031 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt @@ -62,7 +62,7 @@ class GetMonitorRequest : ActionRequest { out.writeEnum(method) if (srcContext != null) { out.writeBoolean(true) - srcContext?.writeTo(out) + srcContext.writeTo(out) } else { out.writeBoolean(false) } diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt index 360301b8..ac1342a8 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt @@ -52,6 +52,7 @@ data class Monitor( override val schedule: Schedule, override val lastUpdateTime: Instant, override val enabledTime: Instant?, + val user: User?, val schemaVersion: Int = NO_SCHEMA_VERSION, val inputs: List, val triggers: List, @@ -81,9 +82,12 @@ data class Monitor( sin.readLong(), // version sin.readString(), // name sin.readBoolean(), // enabled - Schedule.readFrom(sin), + Schedule.readFrom(sin), // schedule sin.readInstant(), // lastUpdateTime sin.readOptionalInstant(), // enabledTime + if (sin.readBoolean()) { + User.readFrom(sin) // user + } else null, sin.readInt(), // schemaVersion sin.readList(::SearchInput), // inputs sin.readList(::Trigger), // triggers @@ -104,6 +108,7 @@ data class Monitor( builder.field(TYPE_FIELD, type) .field(SCHEMA_VERSION_FIELD, schemaVersion) .field(NAME_FIELD, name) + .optionalUserField(user) .field(ENABLED_FIELD, enabled) .optionalTimeField(ENABLED_TIME_FIELD, enabledTime) .field(SCHEDULE_FIELD, schedule) @@ -117,8 +122,15 @@ data class Monitor( override fun fromDocument(id: String, version: Long): Monitor = copy(id = id, version = version) + private fun XContentBuilder.optionalUserField(user: User?): XContentBuilder { + if (user == null) { + return nullField(USER_FIELD) + } + return this.field(USER_FIELD, user) + } + @Throws(IOException::class) - fun writeTo(out: StreamOutput) { + override fun writeTo(out: StreamOutput) { out.writeString(id) out.writeLong(version) out.writeString(name) @@ -131,6 +143,12 @@ data class Monitor( schedule.writeTo(out) out.writeInstant(lastUpdateTime) out.writeOptionalInstant(enabledTime) + if (user != null) { + out.writeBoolean(true) + user.writeTo(out) + } else { + out.writeBoolean(false) + } out.writeInt(schemaVersion) out.writeCollection(inputs) out.writeCollection(triggers) @@ -142,6 +160,7 @@ data class Monitor( const val TYPE_FIELD = "type" const val SCHEMA_VERSION_FIELD = "schema_version" const val NAME_FIELD = "name" + const val USER_FIELD = "user" const val ENABLED_FIELD = "enabled" const val SCHEDULE_FIELD = "schedule" const val TRIGGERS_FIELD = "triggers" @@ -163,6 +182,7 @@ data class Monitor( @Throws(IOException::class) fun parse(xcp: XContentParser, id: String = NO_ID, version: Long = NO_VERSION): Monitor { lateinit var name: String + var user: User? = null lateinit var schedule: Schedule var lastUpdateTime: Instant? = null var enabledTime: Instant? = null @@ -180,6 +200,7 @@ data class Monitor( when (fieldName) { SCHEMA_VERSION_FIELD -> schemaVersion = xcp.intValue() NAME_FIELD -> name = xcp.text() + USER_FIELD -> user = User.parse(xcp) ENABLED_FIELD -> enabled = xcp.booleanValue() SCHEDULE_FIELD -> schedule = Schedule.parse(xcp) INPUTS_FIELD -> { @@ -215,6 +236,7 @@ data class Monitor( requireNotNull(schedule) { "Monitor schedule is null" }, lastUpdateTime ?: Instant.now(), enabledTime, + user, schemaVersion, inputs.toList(), triggers.toList(), diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/User.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/User.kt new file mode 100644 index 00000000..df3b86c1 --- /dev/null +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/User.kt @@ -0,0 +1,92 @@ +package com.amazon.opendistroforelasticsearch.alerting.model + +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.ToXContentObject +import org.elasticsearch.common.xcontent.XContentBuilder +import org.elasticsearch.common.xcontent.XContentParser +import org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken +import java.io.IOException + +data class User( + val name: String, + val backendRoles: List, + val roles: List, + val customAttNames: List +) : Writeable, ToXContentObject { + + @Throws(IOException::class) + constructor(sin: StreamInput): this( + sin.readString(), // name + sin.readStringList(), // backendRoles + sin.readStringList(), // roles + sin.readStringList() // customAttNames + ) + + override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { + builder.startObject() + .field(NAME_FIELD, name) + .field(BACKEND_ROLES_FIELD, backendRoles) + .field(ROLES_FIELD, roles) + .field(CUSTOM_ATTRIBUTE_NAMES_FIELD, customAttNames) + return builder.endObject() + } + @Throws(IOException::class) + override fun writeTo(out: StreamOutput) { + out.writeString(name) + out.writeStringCollection(backendRoles) + out.writeStringCollection(roles) + out.writeStringCollection(customAttNames) + } + + companion object { + const val NAME_FIELD = "name" + const val BACKEND_ROLES_FIELD = "backend_roles" + const val ROLES_FIELD = "roles" + const val CUSTOM_ATTRIBUTE_NAMES_FIELD = "custom_attribute_names" + + @JvmStatic + @Throws(IOException::class) + fun parse(xcp: XContentParser): User { + var name = "" + val backendRoles: MutableList = mutableListOf() + val roles: MutableList = mutableListOf() + val customAttNames: MutableList = mutableListOf() + + while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = xcp.currentName() + xcp.nextToken() + when (fieldName) { + NAME_FIELD -> name = xcp.text() + ROLES_FIELD -> { + ensureExpectedToken(XContentParser.Token.START_ARRAY, xcp.currentToken(), xcp::getTokenLocation) + while (xcp.nextToken() != XContentParser.Token.END_ARRAY) { + roles.add(xcp.text()) + } + } + BACKEND_ROLES_FIELD -> { + ensureExpectedToken(XContentParser.Token.START_ARRAY, xcp.currentToken(), xcp::getTokenLocation) + while (xcp.nextToken() != XContentParser.Token.END_ARRAY) { + backendRoles.add(xcp.text()) + } + } + CUSTOM_ATTRIBUTE_NAMES_FIELD -> { + ensureExpectedToken(XContentParser.Token.START_ARRAY, xcp.currentToken(), xcp::getTokenLocation) + while (xcp.nextToken() != XContentParser.Token.END_ARRAY) { + customAttNames.add(xcp.text()) + } + } + } + } + return User(name, backendRoles, roles, customAttNames) + } + + @JvmStatic + @Throws(IOException::class) + fun readFrom(sin: StreamInput): User { + return User(sin) + } + } +} diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt index da55e8e5..404b6d4c 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt @@ -24,6 +24,7 @@ import com.amazon.opendistroforelasticsearch.alerting.destination.response.Desti import com.amazon.opendistroforelasticsearch.alerting.elasticapi.convertToMap import com.amazon.opendistroforelasticsearch.alerting.elasticapi.instant import com.amazon.opendistroforelasticsearch.alerting.elasticapi.optionalTimeField +import com.amazon.opendistroforelasticsearch.alerting.model.User import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType import com.amazon.opendistroforelasticsearch.alerting.util.IndexUtils.Companion.NO_SCHEMA_VERSION import org.apache.logging.log4j.LogManager @@ -46,6 +47,7 @@ data class Destination( val schemaVersion: Int = NO_SCHEMA_VERSION, val type: DestinationType, val name: String, + val user: User?, val lastUpdateTime: Instant, val chime: Chime?, val slack: Slack?, @@ -57,6 +59,7 @@ data class Destination( if (params.paramAsBoolean("with_type", false)) builder.startObject(DESTINATION) builder.field(TYPE_FIELD, type.value) .field(NAME_FIELD, name) + .optionalUserField(user) .field(SCHEMA_VERSION, schemaVersion) .optionalTimeField(LAST_UPDATE_TIME_FIELD, lastUpdateTime) .field(type.value, constructResponseForDestinationType(type)) @@ -68,6 +71,13 @@ data class Destination( return toXContent(builder, ToXContent.EMPTY_PARAMS) } + private fun XContentBuilder.optionalUserField(user: User?): XContentBuilder { + if (user == null) { + return nullField(USER_FIELD) + } + return this.field(USER_FIELD, user) + } + @Throws(IOException::class) fun writeTo(out: StreamOutput) { out.writeString(id) @@ -75,6 +85,12 @@ data class Destination( out.writeInt(schemaVersion) out.writeEnum(type) out.writeString(name) + if (user != null) { + out.writeBoolean(true) + user.writeTo(out) + } else { + out.writeBoolean(false) + } out.writeInstant(lastUpdateTime) if (chime != null) { out.writeBoolean(true) @@ -100,6 +116,7 @@ data class Destination( const val DESTINATION = "destination" const val TYPE_FIELD = "type" const val NAME_FIELD = "name" + const val USER_FIELD = "user" const val NO_ID = "" const val NO_VERSION = 1L const val SCHEMA_VERSION = "schema_version" @@ -117,6 +134,7 @@ data class Destination( @Throws(IOException::class) fun parse(xcp: XContentParser, id: String = NO_ID, version: Long = NO_VERSION): Destination { lateinit var name: String + var user: User? = null lateinit var type: String var slack: Slack? = null var chime: Chime? = null @@ -131,6 +149,7 @@ data class Destination( when (fieldName) { NAME_FIELD -> name = xcp.text() + USER_FIELD -> user = User.parse(xcp) TYPE_FIELD -> { type = xcp.text() val allowedTypes = DestinationType.values().map { it.value } @@ -164,6 +183,7 @@ data class Destination( schemaVersion, DestinationType.valueOf(type.toUpperCase(Locale.ROOT)), requireNotNull(name) { "Destination name is null" }, + user, lastUpdateTime ?: Instant.now(), chime, slack, @@ -179,6 +199,9 @@ data class Destination( sin.readInt(), // schemaVersion sin.readEnum(DestinationType::class.java), // type sin.readString(), // name + if (sin.readBoolean()) { + User.readFrom(sin) // user + } else null, sin.readInstant(), // lastUpdateTime Chime.readFrom(sin), // chime Slack.readFrom(sin), // slack diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt index b45934d0..67c6a6ce 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/AlertingRestTestCase.kt @@ -113,6 +113,7 @@ abstract class AlertingRestTestCase : ODFERestTestCase() { return Destination( type = DestinationType.TEST_ACTION, name = "test", + user = randomUser(), lastUpdateTime = Instant.now(), chime = null, slack = null, diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt index 304b2d43..40744405 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt @@ -28,6 +28,7 @@ import com.amazon.opendistroforelasticsearch.alerting.model.ActionRunResult import com.amazon.opendistroforelasticsearch.alerting.model.InputRunResults import com.amazon.opendistroforelasticsearch.alerting.model.MonitorRunResult import com.amazon.opendistroforelasticsearch.alerting.model.TriggerRunResult +import com.amazon.opendistroforelasticsearch.alerting.model.User import com.amazon.opendistroforelasticsearch.alerting.model.action.Throttle import org.apache.http.Header import org.apache.http.HttpEntity @@ -57,6 +58,7 @@ import java.time.temporal.ChronoUnit fun randomMonitor( name: String = ESRestTestCase.randomAlphaOfLength(10), + user: User = randomUser(), inputs: List = listOf(SearchInput(emptyList(), SearchSourceBuilder().query(QueryBuilders.matchAllQuery()))), schedule: Schedule = IntervalSchedule(interval = 5, unit = ChronoUnit.MINUTES), enabled: Boolean = ESTestCase.randomBoolean(), @@ -67,7 +69,23 @@ fun randomMonitor( ): Monitor { return Monitor(name = name, enabled = enabled, inputs = inputs, schedule = schedule, triggers = triggers, enabledTime = enabledTime, lastUpdateTime = lastUpdateTime, - uiMetadata = if (withMetadata) mapOf("foo" to "bar") else mapOf()) + user = user, uiMetadata = if (withMetadata) mapOf("foo" to "bar") else mapOf()) +} + +// Monitor of older versions without security. +fun randomMonitorWithoutUser( + name: String = ESRestTestCase.randomAlphaOfLength(10), + inputs: List = listOf(SearchInput(emptyList(), SearchSourceBuilder().query(QueryBuilders.matchAllQuery()))), + schedule: Schedule = IntervalSchedule(interval = 5, unit = ChronoUnit.MINUTES), + enabled: Boolean = ESTestCase.randomBoolean(), + triggers: List = (1..randomInt(10)).map { randomTrigger() }, + enabledTime: Instant? = if (enabled) Instant.now().truncatedTo(ChronoUnit.MILLIS) else null, + lastUpdateTime: Instant = Instant.now().truncatedTo(ChronoUnit.MILLIS), + withMetadata: Boolean = false +): Monitor { + return Monitor(name = name, enabled = enabled, inputs = inputs, schedule = schedule, triggers = triggers, + enabledTime = enabledTime, lastUpdateTime = lastUpdateTime, + user = null, uiMetadata = if (withMetadata) mapOf("foo" to "bar") else mapOf()) } fun randomTrigger( @@ -164,6 +182,14 @@ fun Monitor.toJsonString(): String { return this.toXContent(builder).string() } +fun randomUser(): User { + return User("joe", listOf("ops", "backup"), listOf("all_access"), listOf("test_attr=test")) +} + +fun randomUserEmpty(): User { + return User("", listOf(), listOf(), listOf()) +} + /** * Wrapper for [RestClient.performRequest] which was deprecated in ES 6.5 and is used in tests. This provides * a single place to suppress deprecation warnings. This will probably need further work when the API is removed entirely diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorResponseTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorResponseTests.kt index a572b4ee..bed60350 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorResponseTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorResponseTests.kt @@ -17,6 +17,7 @@ package com.amazon.opendistroforelasticsearch.alerting.action import com.amazon.opendistroforelasticsearch.alerting.core.model.CronSchedule import com.amazon.opendistroforelasticsearch.alerting.model.Monitor +import com.amazon.opendistroforelasticsearch.alerting.randomUser import org.elasticsearch.common.io.stream.BytesStreamOutput import org.elasticsearch.common.io.stream.StreamInput import org.elasticsearch.rest.RestStatus @@ -47,7 +48,7 @@ class GetMonitorResponseTests : ESTestCase() { val cronSchedule = CronSchedule(cronExpression, ZoneId.of("Asia/Kolkata"), testInstance) val req = GetMonitorResponse("1234", 1L, 2L, 0L, RestStatus.OK, Monitor("123", 0L, "test-monitor", true, cronSchedule, Instant.now(), - Instant.now(), 0, mutableListOf(), mutableListOf(), mutableMapOf())) + Instant.now(), randomUser(), 0, mutableListOf(), mutableListOf(), mutableMapOf())) assertNotNull(req) val out = BytesStreamOutput() diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationRequestTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationRequestTests.kt index 57ce57a7..d4e0ad52 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationRequestTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationRequestTests.kt @@ -17,6 +17,7 @@ package com.amazon.opendistroforelasticsearch.alerting.action import com.amazon.opendistroforelasticsearch.alerting.model.destination.Chime import com.amazon.opendistroforelasticsearch.alerting.model.destination.Destination +import com.amazon.opendistroforelasticsearch.alerting.randomUser import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType import org.elasticsearch.action.support.WriteRequest import org.elasticsearch.common.io.stream.BytesStreamOutput @@ -41,6 +42,7 @@ class IndexDestinationRequestTests : ESTestCase() { 1, DestinationType.CHIME, "TestChimeDest", + randomUser(), Instant.now(), Chime("test.com"), null, @@ -76,6 +78,7 @@ class IndexDestinationRequestTests : ESTestCase() { 1, DestinationType.CHIME, "TestChimeDest", + randomUser(), Instant.now(), Chime("test.com"), null, diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationResponseTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationResponseTests.kt index b30d4b33..29d4cfd5 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationResponseTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexDestinationResponseTests.kt @@ -17,6 +17,7 @@ package com.amazon.opendistroforelasticsearch.alerting.action import com.amazon.opendistroforelasticsearch.alerting.model.destination.Chime import com.amazon.opendistroforelasticsearch.alerting.model.destination.Destination +import com.amazon.opendistroforelasticsearch.alerting.randomUser import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType import org.elasticsearch.common.io.stream.BytesStreamOutput import org.elasticsearch.common.io.stream.StreamInput @@ -30,7 +31,7 @@ class IndexDestinationResponseTests : ESTestCase() { val req = IndexDestinationResponse("1234", 0L, 1L, 2L, RestStatus.CREATED, Destination("1234", 0L, 1, DestinationType.CHIME, "TestChimeDest", - Instant.now(), Chime("test.com"), null, null)) + randomUser(), Instant.now(), Chime("test.com"), null, null)) assertNotNull(req) diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexMonitorResponseTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexMonitorResponseTests.kt index f0148a6a..4452a87f 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexMonitorResponseTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/IndexMonitorResponseTests.kt @@ -17,6 +17,7 @@ package com.amazon.opendistroforelasticsearch.alerting.action import com.amazon.opendistroforelasticsearch.alerting.core.model.CronSchedule import com.amazon.opendistroforelasticsearch.alerting.model.Monitor +import com.amazon.opendistroforelasticsearch.alerting.randomUser import org.elasticsearch.common.io.stream.BytesStreamOutput import org.elasticsearch.common.io.stream.StreamInput import org.elasticsearch.rest.RestStatus @@ -33,7 +34,7 @@ class IndexMonitorResponseTests : ESTestCase() { val cronSchedule = CronSchedule(cronExpression, ZoneId.of("Asia/Kolkata"), testInstance) val req = IndexMonitorResponse("1234", 1L, 2L, 0L, RestStatus.OK, Monitor("123", 0L, "test-monitor", true, cronSchedule, Instant.now(), - Instant.now(), 0, mutableListOf(), mutableListOf(), mutableMapOf())) + Instant.now(), randomUser(), 0, mutableListOf(), mutableListOf(), mutableMapOf())) assertNotNull(req) val out = BytesStreamOutput() diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt index 1d9519f5..5c9cdf68 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt @@ -53,7 +53,7 @@ class AlertIndicesIT : AlertingRestTestCase() { executeMonitor(createRandomMonitor()) assertIndexExists(AlertIndices.ALERT_INDEX) assertIndexExists(AlertIndices.HISTORY_WRITE_INDEX) - verifyIndexSchemaVersion(ScheduledJob.SCHEDULED_JOBS_INDEX, 1) + verifyIndexSchemaVersion(ScheduledJob.SCHEDULED_JOBS_INDEX, 2) verifyIndexSchemaVersion(AlertIndices.ALERT_INDEX, 1) verifyIndexSchemaVersion(AlertIndices.HISTORY_WRITE_INDEX, 1) } diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/DestinationTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/DestinationTests.kt index c8d86572..f0d84356 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/DestinationTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/DestinationTests.kt @@ -19,6 +19,8 @@ import com.amazon.opendistroforelasticsearch.alerting.model.destination.Chime import com.amazon.opendistroforelasticsearch.alerting.model.destination.CustomWebhook import com.amazon.opendistroforelasticsearch.alerting.model.destination.Destination import com.amazon.opendistroforelasticsearch.alerting.model.destination.Slack +import com.amazon.opendistroforelasticsearch.alerting.parser +import com.amazon.opendistroforelasticsearch.alerting.randomUser import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType import org.elasticsearch.common.io.stream.BytesStreamOutput import org.elasticsearch.common.io.stream.StreamInput @@ -82,7 +84,7 @@ class DestinationTests : ESTestCase() { fun `test chime destination create using stream`() { val chimeDest = Destination("1234", 0L, 1, DestinationType.CHIME, "TestChimeDest", - Instant.now(), Chime("test.com"), null, null) + randomUser(), Instant.now(), Chime("test.com"), null, null) val out = BytesStreamOutput() chimeDest.writeTo(out) @@ -103,7 +105,7 @@ class DestinationTests : ESTestCase() { fun `test slack destination create using stream`() { val chimeDest = Destination("2345", 1L, 2, DestinationType.SLACK, "TestSlackDest", - Instant.now(), null, Slack("mytest.com"), null) + randomUser(), Instant.now(), null, Slack("mytest.com"), null) val out = BytesStreamOutput() chimeDest.writeTo(out) @@ -129,6 +131,7 @@ class DestinationTests : ESTestCase() { 2, DestinationType.SLACK, "TestSlackDest", + randomUser(), Instant.now(), null, null, @@ -168,6 +171,7 @@ class DestinationTests : ESTestCase() { 2, DestinationType.SLACK, "TestSlackDest", + randomUser(), Instant.now(), null, null, @@ -199,4 +203,19 @@ class DestinationTests : ESTestCase() { assertNull(newDest.slack) assertNotNull(newDest.customWebhook) } + + fun `test chime destination without user`() { + val userString = "{\"type\":\"chime\",\"name\":\"TestChimeDest\",\"schema_version\":1," + + "\"last_update_time\":1600063313658,\"chime\":{\"url\":\"test.com\"}}" + val parsedDest = Destination.parse(parser(userString)) + assertNull(parsedDest.user) + } + + fun `test chime destination with user`() { + val userString = "{\"type\":\"chime\",\"name\":\"TestChimeDest\",\"user\":{\"name\":\"joe\",\"backend_roles\"" + + ":[\"ops\",\"backup\"],\"roles\":[\"ops_role, backup_role\"],\"custom_attribute_names\":[\"test_attr=test\"]}," + + "\"schema_version\":1,\"last_update_time\":1600063313658,\"chime\":{\"url\":\"test.com\"}}" + val parsedDest = Destination.parse(parser(userString)) + assertNotNull(parsedDest.user) + } } diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt index 98a719d4..b84957e9 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt @@ -26,6 +26,8 @@ import com.amazon.opendistroforelasticsearch.alerting.randomMonitorRunResult import com.amazon.opendistroforelasticsearch.alerting.randomThrottle import com.amazon.opendistroforelasticsearch.alerting.randomTrigger import com.amazon.opendistroforelasticsearch.alerting.randomTriggerRunResult +import com.amazon.opendistroforelasticsearch.alerting.randomUser +import com.amazon.opendistroforelasticsearch.alerting.randomUserEmpty import org.elasticsearch.common.io.stream.BytesStreamOutput import org.elasticsearch.common.io.stream.StreamInput import org.elasticsearch.search.builder.SearchSourceBuilder @@ -140,4 +142,22 @@ class WriteableTests : ESTestCase() { val newInput = SearchInput(sin) assertEquals("Round tripping MonitorRunResult doesn't work", input, newInput) } + + fun `test user as stream`() { + val user = randomUser() + val out = BytesStreamOutput() + user.writeTo(out) + val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes) + val newUser = User(sin) + assertEquals("Round tripping User doesn't work", user, newUser) + } + + fun `test empty user as stream`() { + val user = randomUserEmpty() + val out = BytesStreamOutput() + user.writeTo(out) + val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes) + val newUser = User(sin) + assertEquals("Round tripping User doesn't work", user, newUser) + } } diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt index b753494a..6363249e 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt @@ -26,6 +26,8 @@ import com.amazon.opendistroforelasticsearch.alerting.randomAlert import com.amazon.opendistroforelasticsearch.alerting.randomMonitor import com.amazon.opendistroforelasticsearch.alerting.randomThrottle import com.amazon.opendistroforelasticsearch.alerting.randomTrigger +import com.amazon.opendistroforelasticsearch.alerting.randomUser +import com.amazon.opendistroforelasticsearch.alerting.randomUserEmpty import com.amazon.opendistroforelasticsearch.alerting.toJsonString import org.elasticsearch.common.xcontent.ToXContent import org.elasticsearch.test.ESTestCase @@ -126,4 +128,29 @@ class XContentTests : ESTestCase() { } catch (ignored: IllegalArgumentException) { } } + + fun `test user parsing`() { + val user = randomUser() + val userString = user.toXContent(builder(), ToXContent.EMPTY_PARAMS).string() + val parsedUser = User.parse(parser(userString)) + assertEquals("Round tripping user doesn't work", user, parsedUser) + } + + fun `test empty user parsing`() { + val user = randomUserEmpty() + val userString = user.toXContent(builder(), ToXContent.EMPTY_PARAMS).string() + + val parsedUser = User.parse(parser(userString)) + assertEquals("Round tripping user doesn't work", user, parsedUser) + assertEquals("", parsedUser.name) + assertEquals(0, parsedUser.roles.size) + } + + fun `test monitor parsing without user`() { + val prevVersionMonitorStr = "{\"type\":\"monitor\",\"schema_version\":0,\"name\":\"bkHIMJSbfj\",\"enabled\":true,\"enabled_time" + + "\":1600052622174,\"schedule\":{\"period\":{\"interval\":5,\"unit\":\"MINUTES\"}},\"inputs\":[{\"search\":{\"indices\"" + + ":[],\"query\":{\"query\":{\"match_all\":{\"boost\":1.0}}}}}],\"triggers\":[],\"last_update_time\":1600052622174}" + val parsedMonitor = Monitor.parse(parser(prevVersionMonitorStr)) + assertNull(parsedMonitor.user) + } } diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt index 183ad615..9694c6d7 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/resthandler/DestinationRestApiIT.kt @@ -22,6 +22,7 @@ import com.amazon.opendistroforelasticsearch.alerting.model.destination.Chime import com.amazon.opendistroforelasticsearch.alerting.model.destination.CustomWebhook import com.amazon.opendistroforelasticsearch.alerting.model.destination.Destination import com.amazon.opendistroforelasticsearch.alerting.model.destination.Slack +import com.amazon.opendistroforelasticsearch.alerting.randomUser import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType import org.elasticsearch.rest.RestStatus import org.elasticsearch.test.junit.annotations.TestLogging @@ -37,6 +38,7 @@ class DestinationRestApiIT : AlertingRestTestCase() { val destination = Destination( type = DestinationType.CHIME, name = "test", + user = randomUser(), lastUpdateTime = Instant.now(), chime = chime, slack = null, @@ -67,6 +69,7 @@ class DestinationRestApiIT : AlertingRestTestCase() { val destination = Destination( type = DestinationType.SLACK, name = "test", + user = randomUser(), lastUpdateTime = Instant.now(), chime = null, slack = slack, @@ -97,6 +100,7 @@ class DestinationRestApiIT : AlertingRestTestCase() { val destination = Destination( type = DestinationType.CUSTOM_WEBHOOK, name = "test", + user = randomUser(), lastUpdateTime = Instant.now(), chime = null, slack = null, @@ -113,6 +117,7 @@ class DestinationRestApiIT : AlertingRestTestCase() { val destination = Destination( type = DestinationType.CUSTOM_WEBHOOK, name = "test", + user = randomUser(), lastUpdateTime = Instant.now(), chime = null, slack = null, @@ -155,6 +160,7 @@ class DestinationRestApiIT : AlertingRestTestCase() { val destination = Destination( type = DestinationType.CHIME, name = "test", + user = randomUser(), lastUpdateTime = Instant.now(), chime = chime, slack = null, diff --git a/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/ScheduledJob.kt b/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/ScheduledJob.kt index 297df59c..a2c2fd12 100644 --- a/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/ScheduledJob.kt +++ b/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/ScheduledJob.kt @@ -18,6 +18,7 @@ package com.amazon.opendistroforelasticsearch.alerting.core.model import com.amazon.opendistroforelasticsearch.alerting.core.model.ScheduledJob.Companion.NO_ID import com.amazon.opendistroforelasticsearch.alerting.core.model.ScheduledJob.Companion.NO_VERSION import com.amazon.opendistroforelasticsearch.alerting.core.model.ScheduledJob.Companion.SCHEDULED_JOBS_INDEX +import org.elasticsearch.common.io.stream.Writeable import org.elasticsearch.common.xcontent.ToXContent import org.elasticsearch.common.xcontent.ToXContentObject import org.elasticsearch.common.xcontent.XContentBuilder @@ -38,7 +39,7 @@ import java.time.Instant * Like all documents in Elasticsearch [ScheduledJob]s also have an [id] and a [version]. Jobs that have not been * persisted in the cluster should use the special sentinel values [NO_ID] and [NO_VERSION] for these fields. */ -interface ScheduledJob : ToXContentObject { +interface ScheduledJob : Writeable, ToXContentObject { fun toXContentWithType(builder: XContentBuilder): XContentBuilder = toXContent(builder, XCONTENT_WITH_TYPE) diff --git a/core/src/main/resources/mappings/scheduled-jobs.json b/core/src/main/resources/mappings/scheduled-jobs.json index fc135eb5..615e2d16 100644 --- a/core/src/main/resources/mappings/scheduled-jobs.json +++ b/core/src/main/resources/mappings/scheduled-jobs.json @@ -1,6 +1,6 @@ { "_meta" : { - "schema_version": 1 + "schema_version": 2 }, "properties": { "monitor": { @@ -18,6 +18,43 @@ } } }, + "user": { + "properties": { + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "backend_roles": { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "text" + } + } + }, + "roles": { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "text" + } + } + }, + "custom_attribute_names": { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "text" + } + } + } + } + }, "type": { "type": "keyword" }, @@ -158,6 +195,43 @@ } } }, + "user": { + "properties": { + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "backend_roles": { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "text" + } + } + }, + "roles": { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "text" + } + } + }, + "custom_attribute_names": { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "text" + } + } + } + } + }, "type": { "type": "keyword" }, diff --git a/core/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/MockScheduledJob.kt b/core/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/MockScheduledJob.kt index 41f12581..22ca884b 100644 --- a/core/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/MockScheduledJob.kt +++ b/core/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/MockScheduledJob.kt @@ -15,8 +15,10 @@ package com.amazon.opendistroforelasticsearch.alerting.core.model +import org.elasticsearch.common.io.stream.StreamOutput import org.elasticsearch.common.xcontent.ToXContent import org.elasticsearch.common.xcontent.XContentBuilder +import java.io.IOException import java.time.Instant class MockScheduledJob( @@ -36,4 +38,9 @@ class MockScheduledJob( override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { TODO("not implemented") } + + @Throws(IOException::class) + override fun writeTo(out: StreamOutput) { + TODO("not implemented") + } } From 39411a0f54a00e0f668b240e2d931e96518383b2 Mon Sep 17 00:00:00 2001 From: skkosuri-amzn Date: Thu, 24 Sep 2020 23:36:20 -0700 Subject: [PATCH 3/5] refacted --- alerting/build.gradle | 3 + .../alerting/action/GetMonitorRequest.kt | 8 +-- .../alerting/model/Monitor.kt | 45 +++++------- .../alerting/model/destination/Destination.kt | 68 +++++++------------ .../alerting/TestHelpers.kt | 9 ++- .../alerting/model/WriteableTests.kt | 1 + .../alerting/model/XContentTests.kt | 1 + .../alerting/core}/model/User.kt | 25 +++++-- .../alerting/elasticapi/ElasticExtensions.kt | 8 +++ .../resources/mappings/scheduled-jobs.json | 12 ++-- 10 files changed, 89 insertions(+), 91 deletions(-) rename {alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting => core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core}/model/User.kt (80%) diff --git a/alerting/build.gradle b/alerting/build.gradle index 853c3c22..1637ba26 100644 --- a/alerting/build.gradle +++ b/alerting/build.gradle @@ -79,6 +79,9 @@ dependencies { compile project(":alerting-notification") testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" + testImplementation "org.apache.commons:commons-lang3:3.11" + testImplementation "org.apache.commons:commons-text:1.9" + } javadoc.enabled = false // turn off javadoc as it barfs on Kotlin code diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt index e4fd1031..f15738c7 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/action/GetMonitorRequest.kt @@ -60,11 +60,7 @@ class GetMonitorRequest : ActionRequest { out.writeString(monitorId) out.writeLong(version) out.writeEnum(method) - if (srcContext != null) { - out.writeBoolean(true) - srcContext.writeTo(out) - } else { - out.writeBoolean(false) - } + out.writeBoolean(srcContext != null) + srcContext?.writeTo(out) } } diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt index ac1342a8..5c9d209a 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/Monitor.kt @@ -20,8 +20,10 @@ import com.amazon.opendistroforelasticsearch.alerting.core.model.Input import com.amazon.opendistroforelasticsearch.alerting.core.model.Schedule import com.amazon.opendistroforelasticsearch.alerting.core.model.ScheduledJob import com.amazon.opendistroforelasticsearch.alerting.core.model.SearchInput +import com.amazon.opendistroforelasticsearch.alerting.core.model.User import com.amazon.opendistroforelasticsearch.alerting.elasticapi.instant import com.amazon.opendistroforelasticsearch.alerting.elasticapi.optionalTimeField +import com.amazon.opendistroforelasticsearch.alerting.elasticapi.optionalUserField import com.amazon.opendistroforelasticsearch.alerting.settings.AlertingSettings.Companion.MONITOR_MAX_INPUTS import com.amazon.opendistroforelasticsearch.alerting.settings.AlertingSettings.Companion.MONITOR_MAX_TRIGGERS import com.amazon.opendistroforelasticsearch.alerting.util.IndexUtils.Companion.NO_SCHEMA_VERSION @@ -78,20 +80,20 @@ data class Monitor( @Throws(IOException::class) constructor(sin: StreamInput): this( - sin.readString(), // id - sin.readLong(), // version - sin.readString(), // name - sin.readBoolean(), // enabled - Schedule.readFrom(sin), // schedule - sin.readInstant(), // lastUpdateTime - sin.readOptionalInstant(), // enabledTime - if (sin.readBoolean()) { - User.readFrom(sin) // user + id = sin.readString(), + version = sin.readLong(), + name = sin.readString(), + enabled = sin.readBoolean(), + schedule = Schedule.readFrom(sin), + lastUpdateTime = sin.readInstant(), + enabledTime = sin.readOptionalInstant(), + user = if (sin.readBoolean()) { + User.readFrom(sin) } else null, - sin.readInt(), // schemaVersion - sin.readList(::SearchInput), // inputs - sin.readList(::Trigger), // triggers - suppressWarning(sin.readMap()) // uiMetadata + schemaVersion = sin.readInt(), + inputs = sin.readList(::SearchInput), + triggers = sin.readList(::Trigger), + uiMetadata = suppressWarning(sin.readMap()) ) fun toXContent(builder: XContentBuilder): XContentBuilder { return toXContent(builder, ToXContent.EMPTY_PARAMS) @@ -108,7 +110,7 @@ data class Monitor( builder.field(TYPE_FIELD, type) .field(SCHEMA_VERSION_FIELD, schemaVersion) .field(NAME_FIELD, name) - .optionalUserField(user) + .optionalUserField(USER_FIELD, user) .field(ENABLED_FIELD, enabled) .optionalTimeField(ENABLED_TIME_FIELD, enabledTime) .field(SCHEDULE_FIELD, schedule) @@ -122,13 +124,6 @@ data class Monitor( override fun fromDocument(id: String, version: Long): Monitor = copy(id = id, version = version) - private fun XContentBuilder.optionalUserField(user: User?): XContentBuilder { - if (user == null) { - return nullField(USER_FIELD) - } - return this.field(USER_FIELD, user) - } - @Throws(IOException::class) override fun writeTo(out: StreamOutput) { out.writeString(id) @@ -143,12 +138,8 @@ data class Monitor( schedule.writeTo(out) out.writeInstant(lastUpdateTime) out.writeOptionalInstant(enabledTime) - if (user != null) { - out.writeBoolean(true) - user.writeTo(out) - } else { - out.writeBoolean(false) - } + out.writeBoolean(user != null) + user?.writeTo(out) out.writeInt(schemaVersion) out.writeCollection(inputs) out.writeCollection(triggers) diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt index 404b6d4c..73603474 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt +++ b/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/destination/Destination.kt @@ -24,7 +24,8 @@ import com.amazon.opendistroforelasticsearch.alerting.destination.response.Desti import com.amazon.opendistroforelasticsearch.alerting.elasticapi.convertToMap import com.amazon.opendistroforelasticsearch.alerting.elasticapi.instant import com.amazon.opendistroforelasticsearch.alerting.elasticapi.optionalTimeField -import com.amazon.opendistroforelasticsearch.alerting.model.User +import com.amazon.opendistroforelasticsearch.alerting.core.model.User +import com.amazon.opendistroforelasticsearch.alerting.elasticapi.optionalUserField import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType import com.amazon.opendistroforelasticsearch.alerting.util.IndexUtils.Companion.NO_SCHEMA_VERSION import org.apache.logging.log4j.LogManager @@ -59,7 +60,7 @@ data class Destination( if (params.paramAsBoolean("with_type", false)) builder.startObject(DESTINATION) builder.field(TYPE_FIELD, type.value) .field(NAME_FIELD, name) - .optionalUserField(user) + .optionalUserField(USER_FIELD, user) .field(SCHEMA_VERSION, schemaVersion) .optionalTimeField(LAST_UPDATE_TIME_FIELD, lastUpdateTime) .field(type.value, constructResponseForDestinationType(type)) @@ -71,13 +72,6 @@ data class Destination( return toXContent(builder, ToXContent.EMPTY_PARAMS) } - private fun XContentBuilder.optionalUserField(user: User?): XContentBuilder { - if (user == null) { - return nullField(USER_FIELD) - } - return this.field(USER_FIELD, user) - } - @Throws(IOException::class) fun writeTo(out: StreamOutput) { out.writeString(id) @@ -85,31 +79,15 @@ data class Destination( out.writeInt(schemaVersion) out.writeEnum(type) out.writeString(name) - if (user != null) { - out.writeBoolean(true) - user.writeTo(out) - } else { - out.writeBoolean(false) - } + out.writeBoolean(user != null) + user?.writeTo(out) out.writeInstant(lastUpdateTime) - if (chime != null) { - out.writeBoolean(true) - chime.writeTo(out) - } else { - out.writeBoolean(false) - } - if (slack != null) { - out.writeBoolean(true) - slack.writeTo(out) - } else { - out.writeBoolean(false) - } - if (customWebhook != null) { - out.writeBoolean(true) - customWebhook.writeTo(out) - } else { - out.writeBoolean(false) - } + out.writeBoolean(chime != null) + chime?.writeTo(out) + out.writeBoolean(slack != null) + slack?.writeTo(out) + out.writeBoolean(customWebhook != null) + customWebhook?.writeTo(out) } companion object { @@ -194,18 +172,18 @@ data class Destination( @Throws(IOException::class) fun readFrom(sin: StreamInput): Destination { return Destination( - sin.readString(), // id - sin.readLong(), // version - sin.readInt(), // schemaVersion - sin.readEnum(DestinationType::class.java), // type - sin.readString(), // name - if (sin.readBoolean()) { - User.readFrom(sin) // user - } else null, - sin.readInstant(), // lastUpdateTime - Chime.readFrom(sin), // chime - Slack.readFrom(sin), // slack - CustomWebhook.readFrom(sin) // customWebhook + id = sin.readString(), + version = sin.readLong(), + schemaVersion = sin.readInt(), + type = sin.readEnum(DestinationType::class.java), + name = sin.readString(), + user = if (sin.readBoolean()) { + User.readFrom(sin) + } else null, + lastUpdateTime = sin.readInstant(), + chime = Chime.readFrom(sin), + slack = Slack.readFrom(sin), + customWebhook = CustomWebhook.readFrom(sin) ) } } diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt index 40744405..22c2739a 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt @@ -28,8 +28,9 @@ import com.amazon.opendistroforelasticsearch.alerting.model.ActionRunResult import com.amazon.opendistroforelasticsearch.alerting.model.InputRunResults import com.amazon.opendistroforelasticsearch.alerting.model.MonitorRunResult import com.amazon.opendistroforelasticsearch.alerting.model.TriggerRunResult -import com.amazon.opendistroforelasticsearch.alerting.model.User +import com.amazon.opendistroforelasticsearch.alerting.core.model.User import com.amazon.opendistroforelasticsearch.alerting.model.action.Throttle +import org.apache.commons.text.RandomStringGenerator import org.apache.http.Header import org.apache.http.HttpEntity import org.elasticsearch.client.Request @@ -183,7 +184,11 @@ fun Monitor.toJsonString(): String { } fun randomUser(): User { - return User("joe", listOf("ops", "backup"), listOf("all_access"), listOf("test_attr=test")) + val ranStrGen = RandomStringGenerator.Builder().build() + val randomUser = ranStrGen.generate(5) + val bckEndRole1 = ranStrGen.generate(10) + val bckEndRole2 = ranStrGen.generate(10) + return User(randomUser, listOf(bckEndRole1, bckEndRole2), listOf("all_access"), listOf("test_attr=test")) } fun randomUserEmpty(): User { diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt index b84957e9..efdf6c8c 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/WriteableTests.kt @@ -16,6 +16,7 @@ package com.amazon.opendistroforelasticsearch.alerting.model import com.amazon.opendistroforelasticsearch.alerting.core.model.SearchInput +import com.amazon.opendistroforelasticsearch.alerting.core.model.User import com.amazon.opendistroforelasticsearch.alerting.model.action.Action import com.amazon.opendistroforelasticsearch.alerting.model.action.Throttle import com.amazon.opendistroforelasticsearch.alerting.randomAction diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt index 6363249e..1fa08203 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/XContentTests.kt @@ -16,6 +16,7 @@ package com.amazon.opendistroforelasticsearch.alerting.model import com.amazon.opendistroforelasticsearch.alerting.builder +import com.amazon.opendistroforelasticsearch.alerting.core.model.User import com.amazon.opendistroforelasticsearch.alerting.elasticapi.string import com.amazon.opendistroforelasticsearch.alerting.model.action.Action import com.amazon.opendistroforelasticsearch.alerting.model.action.Throttle diff --git a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/User.kt b/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/User.kt similarity index 80% rename from alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/User.kt rename to core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/User.kt index df3b86c1..5d0e30ff 100644 --- a/alerting/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/model/User.kt +++ b/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/core/model/User.kt @@ -1,4 +1,19 @@ -package com.amazon.opendistroforelasticsearch.alerting.model +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.amazon.opendistroforelasticsearch.alerting.core.model import org.elasticsearch.common.io.stream.StreamInput import org.elasticsearch.common.io.stream.StreamOutput @@ -19,10 +34,10 @@ data class User( @Throws(IOException::class) constructor(sin: StreamInput): this( - sin.readString(), // name - sin.readStringList(), // backendRoles - sin.readStringList(), // roles - sin.readStringList() // customAttNames + name = sin.readString(), + backendRoles = sin.readStringList(), + roles = sin.readStringList(), + customAttNames = sin.readStringList() ) override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { diff --git a/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/elasticapi/ElasticExtensions.kt b/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/elasticapi/ElasticExtensions.kt index 5cb766ce..9cf3312c 100644 --- a/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/elasticapi/ElasticExtensions.kt +++ b/core/src/main/kotlin/com/amazon/opendistroforelasticsearch/alerting/elasticapi/ElasticExtensions.kt @@ -15,6 +15,7 @@ package com.amazon.opendistroforelasticsearch.alerting.elasticapi +import com.amazon.opendistroforelasticsearch.alerting.core.model.User import kotlinx.coroutines.delay import org.apache.logging.log4j.Logger import org.elasticsearch.ElasticsearchException @@ -131,6 +132,13 @@ fun XContentBuilder.optionalTimeField(name: String, instant: Instant?): XContent return this.timeField(name, name, instant.toEpochMilli()) } +fun XContentBuilder.optionalUserField(name: String, user: User?): XContentBuilder { + if (user == null) { + return nullField(name) + } + return this.field(name, user) +} + /** * Extension function for ES 6.3 and above that duplicates the ES 6.2 XContentBuilder.string() method. */ diff --git a/core/src/main/resources/mappings/scheduled-jobs.json b/core/src/main/resources/mappings/scheduled-jobs.json index 615e2d16..7f51fc01 100644 --- a/core/src/main/resources/mappings/scheduled-jobs.json +++ b/core/src/main/resources/mappings/scheduled-jobs.json @@ -33,7 +33,7 @@ "type" : "text", "fields" : { "keyword" : { - "type" : "text" + "type" : "keyword" } } }, @@ -41,7 +41,7 @@ "type" : "text", "fields" : { "keyword" : { - "type" : "text" + "type" : "keyword" } } }, @@ -49,7 +49,7 @@ "type" : "text", "fields" : { "keyword" : { - "type" : "text" + "type" : "keyword" } } } @@ -210,7 +210,7 @@ "type" : "text", "fields" : { "keyword" : { - "type" : "text" + "type" : "keyword" } } }, @@ -218,7 +218,7 @@ "type" : "text", "fields" : { "keyword" : { - "type" : "text" + "type" : "keyword" } } }, @@ -226,7 +226,7 @@ "type" : "text", "fields" : { "keyword" : { - "type" : "text" + "type" : "keyword" } } } From c8c476cd80dbe6d007794e7573d19fa6774b6425 Mon Sep 17 00:00:00 2001 From: skkosuri-amzn Date: Fri, 25 Sep 2020 08:36:49 -0700 Subject: [PATCH 4/5] Increase schema version --- .../alerting/alerts/AlertIndicesIT.kt | 2 +- core/src/main/resources/mappings/scheduled-jobs.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt index 5c9cdf68..073b4fdb 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/alerts/AlertIndicesIT.kt @@ -53,7 +53,7 @@ class AlertIndicesIT : AlertingRestTestCase() { executeMonitor(createRandomMonitor()) assertIndexExists(AlertIndices.ALERT_INDEX) assertIndexExists(AlertIndices.HISTORY_WRITE_INDEX) - verifyIndexSchemaVersion(ScheduledJob.SCHEDULED_JOBS_INDEX, 2) + verifyIndexSchemaVersion(ScheduledJob.SCHEDULED_JOBS_INDEX, 3) verifyIndexSchemaVersion(AlertIndices.ALERT_INDEX, 1) verifyIndexSchemaVersion(AlertIndices.HISTORY_WRITE_INDEX, 1) } diff --git a/core/src/main/resources/mappings/scheduled-jobs.json b/core/src/main/resources/mappings/scheduled-jobs.json index 30af77a2..af013e01 100644 --- a/core/src/main/resources/mappings/scheduled-jobs.json +++ b/core/src/main/resources/mappings/scheduled-jobs.json @@ -1,6 +1,6 @@ { "_meta" : { - "schema_version": 2 + "schema_version": 3 }, "properties": { "monitor": { From 8e1092fe304dec2ff002181cbc3d9ac0ef8554c7 Mon Sep 17 00:00:00 2001 From: skkosuri-amzn Date: Fri, 25 Sep 2020 14:06:20 -0700 Subject: [PATCH 5/5] Use ESRestTestCase.randomAlphaOfLength for random str --- alerting/build.gradle | 3 --- .../opendistroforelasticsearch/alerting/TestHelpers.kt | 8 ++------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/alerting/build.gradle b/alerting/build.gradle index 1637ba26..853c3c22 100644 --- a/alerting/build.gradle +++ b/alerting/build.gradle @@ -79,9 +79,6 @@ dependencies { compile project(":alerting-notification") testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" - testImplementation "org.apache.commons:commons-lang3:3.11" - testImplementation "org.apache.commons:commons-text:1.9" - } javadoc.enabled = false // turn off javadoc as it barfs on Kotlin code diff --git a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt index 99fe1380..7caaf2ba 100644 --- a/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt +++ b/alerting/src/test/kotlin/com/amazon/opendistroforelasticsearch/alerting/TestHelpers.kt @@ -30,7 +30,6 @@ import com.amazon.opendistroforelasticsearch.alerting.model.MonitorRunResult import com.amazon.opendistroforelasticsearch.alerting.model.TriggerRunResult import com.amazon.opendistroforelasticsearch.alerting.core.model.User import com.amazon.opendistroforelasticsearch.alerting.model.action.Throttle -import org.apache.commons.text.RandomStringGenerator import com.amazon.opendistroforelasticsearch.alerting.model.destination.email.EmailAccount import com.amazon.opendistroforelasticsearch.alerting.model.destination.email.EmailEntry import com.amazon.opendistroforelasticsearch.alerting.model.destination.email.EmailGroup @@ -221,11 +220,8 @@ fun Monitor.toJsonString(): String { } fun randomUser(): User { - val ranStrGen = RandomStringGenerator.Builder().build() - val randomUser = ranStrGen.generate(5) - val bckEndRole1 = ranStrGen.generate(10) - val bckEndRole2 = ranStrGen.generate(10) - return User(randomUser, listOf(bckEndRole1, bckEndRole2), listOf("all_access"), listOf("test_attr=test")) + return User(ESRestTestCase.randomAlphaOfLength(10), listOf(ESRestTestCase.randomAlphaOfLength(10), + ESRestTestCase.randomAlphaOfLength(10)), listOf("all_access"), listOf("test_attr=test")) } fun randomUserEmpty(): User {