Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Add logged-on User details to the Monitor and Destination #255

Merged
merged 8 commits into from
Sep 25, 2020
3 changes: 3 additions & 0 deletions alerting/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice!

srcContext?.writeTo(out)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ 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.model.destination.email.Email
import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType
import com.amazon.opendistroforelasticsearch.alerting.util.IndexUtils.Companion.NO_SCHEMA_VERSION
import org.apache.logging.log4j.LogManager
Expand Down Expand Up @@ -61,7 +63,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))
Expand All @@ -73,51 +75,24 @@ 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)
out.writeLong(version)
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)
}
if (email != null) {
out.writeBoolean(true)
email.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)
out.writeBoolean(email != null)
email?.writeTo(out)
}

companion object {
Expand Down Expand Up @@ -209,19 +184,19 @@ 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
id = sin.readString(),
version = sin.readLong(),
schemaVersion = sin.readInt(),
type = sin.readEnum(DestinationType::class.java),
name = sin.readString(),
user = if (sin.readBoolean()) {
User(sin)
} else null,
sin.readInstant(), // lastUpdateTime
Chime.readFrom(sin), // chime
Slack.readFrom(sin), // slack
CustomWebhook.readFrom(sin), // customWebhook
Email.readFrom(sin) // email
lastUpdateTime = sin.readInstant(),
chime = Chime.readFrom(sin),
slack = Slack.readFrom(sin),
customWebhook = CustomWebhook.readFrom(sin),
email = Email.readFrom(sin)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 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
Expand Down Expand Up @@ -220,13 +221,27 @@ 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are already provided helper methods for generating random values, e.g. ESRestTestCase.randomAlphaOfLength(10)

return User(randomUser, listOf(bckEndRole1, bckEndRole2), listOf("all_access"), listOf("test_attr=test"))
}

fun randomUserEmpty(): User {
return User("", listOf(), listOf(), listOf())
}

fun EmailAccount.toJsonString(): String {
val builder = XContentFactory.jsonBuilder()
return this.toXContent(builder).string()
}

fun EmailGroup.toJsonString(): String {
val builder = XContentFactory.jsonBuilder()
return this.toXContent(builder).string()
}

/**
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ class IndexDestinationResponseTests : ESTestCase() {

val req = IndexDestinationResponse("1234", 0L, 1L, 2L, RestStatus.CREATED,
Destination("1234", 0L, 1, DestinationType.CHIME, "TestChimeDest",
randomUser(), Instant.now(), Chime("test.com"), null, null))

randomUser(), Instant.now(), Chime("test.com"), null, null, null))
assertNotNull(req)

val out = BytesStreamOutput()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.amazon.opendistroforelasticsearch.alerting.model.destination.email.Em
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.model.destination.email.Recipient
import com.amazon.opendistroforelasticsearch.alerting.util.DestinationType
import org.elasticsearch.common.io.stream.BytesStreamOutput
import org.elasticsearch.common.io.stream.StreamInput
Expand Down Expand Up @@ -113,7 +114,7 @@ class DestinationTests : ESTestCase() {

fun `test chime destination create using stream`() {
val chimeDest = Destination("1234", 0L, 1, DestinationType.CHIME, "TestChimeDest",
randomUser(), Instant.now(), Chime("test.com"), null, null)
randomUser(), Instant.now(), Chime("test.com"), null, null, null)

val out = BytesStreamOutput()
chimeDest.writeTo(out)
Expand All @@ -135,7 +136,7 @@ class DestinationTests : ESTestCase() {

fun `test slack destination create using stream`() {
val chimeDest = Destination("2345", 1L, 2, DestinationType.SLACK, "TestSlackDest",
randomUser(), Instant.now(), null, Slack("mytest.com"), null)
randomUser(), Instant.now(), null, Slack("mytest.com"), null, null)

val out = BytesStreamOutput()
chimeDest.writeTo(out)
Expand Down Expand Up @@ -253,6 +254,7 @@ class DestinationTests : ESTestCase() {
2,
DestinationType.EMAIL,
"TestEmailDest",
randomUser(),
Instant.now(),
null,
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.model.destination.email.EmailAccount
Expand Down Expand Up @@ -164,4 +165,22 @@ class WriteableTests : ESTestCase() {
val newUser = User(sin)
assertEquals("Round tripping User doesn't work", user, newUser)
}

fun `test emailaccount as stream`() {
val emailAccount = randomEmailAccount()
val out = BytesStreamOutput()
emailAccount.writeTo(out)
val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes)
val newEmailAccount = EmailAccount.readFrom(sin)
assertEquals("Round tripping EmailAccount doesn't work", emailAccount, newEmailAccount)
}

fun `test emailgroup as stream`() {
val emailGroup = randomEmailGroup()
val out = BytesStreamOutput()
emailGroup.writeTo(out)
val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes)
val newEmailGroup = EmailGroup.readFrom(sin)
assertEquals("Round tripping EmailGroup doesn't work", emailGroup, newEmailGroup)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -157,4 +158,20 @@ class XContentTests : ESTestCase() {
val parsedMonitor = Monitor.parse(parser(prevVersionMonitorStr))
assertNull(parsedMonitor.user)
}

fun `test email account parsing`() {
val emailAccount = randomEmailAccount()

val emailAccountString = emailAccount.toJsonString()
val parsedEmailAccount = EmailAccount.parse(parser(emailAccountString))
assertEquals("Round tripping EmailAccount doesn't work", emailAccount, parsedEmailAccount)
}

fun `test email group parsing`() {
val emailGroup = randomEmailGroup()

val emailGroupString = emailGroup.toJsonString()
val parsedEmailGroup = EmailGroup.parse(parser(emailGroupString))
assertEquals("Round tripping EmailGroup doesn't work", emailGroup, parsedEmailGroup)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class DestinationRestApiIT : AlertingRestTestCase() {
val destination = Destination(
type = DestinationType.EMAIL,
name = "test",
user = randomUser(),
lastUpdateTime = Instant.now(),
chime = null,
slack = null,
Expand Down
Loading