diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 00000000..e711a04d --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,12 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "75...100" + status: + project: + default: + target: 75% # the required coverage value + threshold: 1% # the leniency in hitting the target \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..b57ed5c8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# This should match the owning team set up in https://github.com/orgs/opensearch-project/teams +* @opensearch-project/common-utils \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8af6ebb5..29eddb95 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,33 +1,31 @@ --- name: 🐛 Bug report about: Create a report to help us improve -title: "[BUG]" -labels: 'bug, untriaged, Beta' +title: '[BUG]' +labels: 'bug, untriaged' assignees: '' --- -**Describe the bug** -A clear and concise description of what the bug is. +**What is the bug?** +A clear and concise description of the bug. -**To Reproduce** +**How can one reproduce the bug?** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** +**What is the expected behavior?** A clear and concise description of what you expected to happen. -**Plugins** -Please list all plugins currently enabled. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Host/Environment (please complete the following information):** +**What is your host/environment?** - OS: [e.g. iOS] - Version [e.g. 22] + - Plugins + +**Do you have any screenshots?** +If applicable, add screenshots to help explain your problem. -**Additional context** -Add any other context about the problem here. \ No newline at end of file +**Do you have any additional context?** +Add any other context about the problem. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..a8199a10 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - name: OpenSearch Community Support + url: https://discuss.opendistrocommunity.dev/ + about: Please ask and answer questions here. + - name: AWS/Amazon Security + url: https://aws.amazon.com/security/vulnerability-reporting/ + about: Please report security vulnerabilities here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 2791b808..6198f338 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,19 +1,18 @@ --- name: 🎆 Feature request -about: Suggest an idea for this project -title: '' -labels: enhancement +about: Request a feature in this project +title: '[FEATURE]' +labels: 'enhancement, untriaged' assignees: '' --- +**Is your feature request related to a problem?** +A clear and concise description of what the problem is, e.g. _I'm always frustrated when [...]_ -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** +**What solution would you like?** A clear and concise description of what you want to happen. -**Describe alternatives you've considered** +**What alternatives have you considered?** A clear and concise description of any alternative solutions or features you've considered. -**Additional context** +**Do you have any additional context?** Add any other context or screenshots about the feature request here. \ No newline at end of file diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 00000000..e3f96a44 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,29 @@ + +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + +jobs: + backport: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + name: Backport + steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + + - name: Backport + uses: VachaShah/backport@v1.1.4 + with: + github_token: ${{ steps.github_app_token.outputs.token }} + branch_name: backport/backport-${{ github.event.number }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f49c13b9..0bcc5e2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,9 @@ jobs: build: strategy: matrix: - java: [14] + java: + - 11 + - 17 name: Build and Test runs-on: ubuntu-latest @@ -25,29 +27,16 @@ jobs: with: java-version: ${{ matrix.java }} - # dependencies: OpenSearch - - name: Checkout OpenSearch - uses: actions/checkout@v2 - with: - repository: 'opensearch-project/OpenSearch' - path: OpenSearch - ref: '1.0' - - name: Build OpenSearch - working-directory: ./OpenSearch - run: ./gradlew publishToMavenLocal -Dbuild.snapshot=false - - # common-utils - name: Build and Test run: | - ./gradlew build -Dopensearch.version=1.0.0 + ./gradlew build - name: Publish to Maven Local run: | - ./gradlew publishToMavenLocal -Dopensearch.version=1.0.0 + ./gradlew publishToMavenLocal - name: Upload Coverage Report uses: codecov/codecov-action@v1 with: - file: ./build/reports/jacoco/test/jacocoTestReport.xml - flags: plugin + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/delete_backport_branch.yml b/.github/workflows/delete_backport_branch.yml new file mode 100644 index 00000000..f24f022b --- /dev/null +++ b/.github/workflows/delete_backport_branch.yml @@ -0,0 +1,15 @@ +name: Delete merged branch of the backport PRs +on: + pull_request: + types: + - closed + +jobs: + delete-branch: + runs-on: ubuntu-latest + if: startsWith(github.event.pull_request.head.ref,'backport/') + steps: + - name: Delete merged branch + uses: SvanBoxel/delete-merged-branch@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/push-common-utils-jar.yml b/.github/workflows/push-common-utils-jar.yml deleted file mode 100644 index 6a4bc703..00000000 --- a/.github/workflows/push-common-utils-jar.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Upload Common-Utils Jar to Maven - -on: - push: - tags: - - v* -jobs: - upload-common-utils-jar: - runs-on: [ubuntu-16.04] - name: Upload common-utils Jar to Maven - steps: - - name: Checkout Repo - uses: actions/checkout@v2 - - - name: Configure AWS CLI - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-1 - - - name: Setup Java - uses: actions/setup-java@v1 - with: - java-version: '14' - - - name: Upload common-utils Jar to Maven - env: - passphrase: ${{ secrets.PASSPHRASE }} - run: | - cd .. - export JAVA14_HOME=$JAVA_HOME - aws s3 cp s3://opendistro-docs/github-actions/pgp-public-key . - aws s3 cp s3://opendistro-docs/github-actions/pgp-private-key . - - gpg --import pgp-public-key - gpg --allow-secret-key-import --import pgp-private-key - - mkdir /home/runner/.gradle - aws s3 cp s3://opendistro-docs/github-actions/gradle.properties /home/runner/.gradle/ - - cd common-utils - - ./gradlew publishShadowPublicationToSonatype-stagingRepository -Dcompiler.java=14 -Dbuild.snapshot=false -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml new file mode 100644 index 00000000..6c96199a --- /dev/null +++ b/.github/workflows/version.yml @@ -0,0 +1,53 @@ +name: Increment Version + +on: + push: + tags: + - '*.*.*.*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + + - uses: actions/checkout@v2 + - name: Fetch Tag and Version Information + run: | + TAG=$(echo "${GITHUB_REF#refs/*/}") + CURRENT_VERSION_ARRAY=($(echo "$TAG" | tr . '\n')) + BASE=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:2}") + CURRENT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + CURRENT_VERSION_ARRAY[2]=$((CURRENT_VERSION_ARRAY[2]+1)) + NEXT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + echo "TAG=$TAG" >> $GITHUB_ENV + echo "BASE=$BASE" >> $GITHUB_ENV + echo "CURRENT_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV + echo "NEXT_VERSION=$NEXT_VERSION" >> $GITHUB_ENV + - uses: actions/checkout@v2 + with: + ref: ${{ env.BASE }} + token: ${{ steps.github_app_token.outputs.token }} + + - name: Increment Version + run: | + echo Incrementing $CURRENT_VERSION to $NEXT_VERSION + sed -i "s/$CURRENT_VERSION-SNAPSHOT/$NEXT_VERSION-SNAPSHOT/g" build.gradle + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ steps.github_app_token.outputs.token }} + base: ${{ env.BASE }} + commit-message: Incremented version to ${{ env.NEXT_VERSION }} + signoff: true + delete-branch: true + title: '[AUTO] Incremented version to ${{ env.NEXT_VERSION }}.' + body: | + I've noticed that a new tag ${{ env.TAG }} was pushed, and incremented the version from ${{ env.CURRENT_VERSION }} to ${{ env.NEXT_VERSION }}. diff --git a/.whitesource b/.whitesource new file mode 100644 index 00000000..db4b0fec --- /dev/null +++ b/.whitesource @@ -0,0 +1,15 @@ +{ + "scanSettings": { + "configMode": "AUTO", + "configExternalURL": "", + "projectToken": "", + "baseBranches": [] + }, + "checkRunSettings": { + "vulnerableCheckRunConclusionLevel": "failure", + "displayMode": "diff" + }, + "issueSettings": { + "minSeverityLevel": "LOW" + } +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c970f9d3..c25787ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,51 @@ ## Contributing to this Project OpenSearch is a community project that is built and maintained by people just like **you**. -[This document](https://github.com/opensearch-project/.github/blob/main/CONTRIBUTING.md) explains how you can contribute to this and related projects. \ No newline at end of file +[This document](https://github.com/opensearch-project/.github/blob/main/CONTRIBUTING.md) explains how you can contribute to this and related projects. + +## Developer Certificate of Origin + +OpenSearch is an open source product released under the Apache 2.0 license (see either [the Apache site](https://www.apache.org/licenses/LICENSE-2.0) or the [LICENSE.txt file](LICENSE.txt)). The Apache 2.0 license allows you to freely use, modify, distribute, and sell your own products that include Apache 2.0 licensed software. + +We respect intellectual property rights of others and we want to make sure all incoming contributions are correctly attributed and licensed. A Developer Certificate of Origin (DCO) is a lightweight mechanism to do that. + +The DCO is a declaration attached to every contribution made by every developer. In the commit message of the contribution, the developer simply adds a `Signed-off-by` statement and thereby agrees to the DCO, which you can find below or at [DeveloperCertificate.org](http://developercertificate.org/). + +``` +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the + best of my knowledge, is covered under an appropriate open + source license and I have the right under that license to + submit that work with modifications, whether created in whole + or in part by me, under the same open source license (unless + I am permitted to submit under a different license), as + Indicated in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including + all personal information I submit with it, including my + sign-off) is maintained indefinitely and may be redistributed + consistent with this project or the open source license(s) + involved. + ``` + +We require that every contribution to OpenSearch is signed with a Developer Certificate of Origin. Additionally, please use your real name. We do not accept anonymous contributors nor those utilizing pseudonyms. + +Each commit must include a DCO which looks like this + +``` +Signed-off-by: Jane Smith +``` + +You may type this line on your own when writing your commit messages. However, if your user.name and user.email are set in your git configs, you can use `-s` or `– – signoff` to add the `Signed-off-by` line to the end of the commit message. \ No newline at end of file diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index d162eccb..d4a44c46 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -1,7 +1,7 @@ - [Developer Guide](#developer-guide) - [Forking and Cloning](#forking-and-cloning) - [Install Prerequisites](#install-prerequisites) - - [JDK 14](#jdk-14) + - [JDK 11](#jdk-11) - [Building](#building) - [Using IntelliJ IDEA](#using-intellij-idea) - [Submitting Changes](#submitting-changes) @@ -16,9 +16,9 @@ Fork this repository on GitHub, and clone locally with `git clone`. ### Install Prerequisites -#### JDK 14 +#### JDK 11 -OpenSearch components build using Java 14 at a minimum. This means you must have a JDK 14 installed with the environment variable `JAVA_HOME` referencing the path to Java home for your JDK 14 installation, e.g. `JAVA_HOME=/usr/lib/jvm/jdk-14`. +OpenSearch components build using Java 11 at a minimum. This means you must have a JDK 11 installed with the environment variable `JAVA_HOME` referencing the path to Java home for your JDK 11 installation, e.g. `JAVA_HOME=/usr/lib/jvm/jdk-11`. ### Building @@ -36,4 +36,8 @@ Launch Intellij IDEA, choose **Import Project**, and select the `settings.gradle ### Submitting Changes -See [CONTRIBUTING](CONTRIBUTING.md). \ No newline at end of file +See [CONTRIBUTING](CONTRIBUTING.md). + +### Backport + +- [Link to backport documentation](https://github.com/opensearch-project/opensearch-plugins/blob/main/BACKPORT.md) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index c50082af..3802e32b 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,13 +1,14 @@ ## Maintainers -| Maintainer | GitHub ID | Affiliation | -| --------------- | --------- | ----------- | -| Ashish Agrawal | [lezzago](https://github.com/lezzago) | Amazon | -| Mohammad Qureshi | [qreshi](https://github.com/qreshi) | Amazon | -| Sriram Kosuri | [skkosuri-amzn](https://github.com/skkosuri-amzn) | Amazon | -| Bowen Lan | [bowenlan-amzn](https://github.com/bowenlan-amzn) | Amazon | -| Rishabh Maurya | [rishabhmaurya](https://github.com/rishabhmaurya) | Amazon | -| Tianli Feng | [tlfeng](https://github.com/tlfeng) | Amazon | -| Annie Lee | [leeyun-amzn](https://github.com/leeyun-amzn) | Amazon | +| Maintainer | GitHub ID | Affiliation | +|------------------|---------------------------------------------------| ----------- | +| Ashish Agrawal | [lezzago](https://github.com/lezzago) | Amazon | +| Mohammad Qureshi | [qreshi](https://github.com/qreshi) | Amazon | +| Sriram Kosuri | [skkosuri-amzn](https://github.com/skkosuri-amzn) | Amazon | +| Bowen Lan | [bowenlan-amzn](https://github.com/bowenlan-amzn) | Amazon | +| Rishabh Maurya | [rishabhmaurya](https://github.com/rishabhmaurya) | Amazon | +| Tianli Feng | [tlfeng](https://github.com/tlfeng) | Amazon | +| Annie Lee | [leeyun-amzn](https://github.com/leeyun-amzn) | Amazon | +| Saurabh Singh | [getsaurabh02](https://github.com/getsaurabh02) | Amazon | [This document](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md) explains what maintainers do in this repo, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). diff --git a/NOTICE b/NOTICE index be83767d..6c7dc983 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ -OpenSearch -Copyright 2021 OpenSearch Contributors +OpenSearch (https://opensearch.org/) +Copyright OpenSearch Contributors This product includes software developed by Elasticsearch (http://www.elastic.co). diff --git a/README.md b/README.md index 237509c1..98ee4ce2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ - +[![codecov](https://codecov.io/gh/opensearch-project/common-utils/branch/main/graph/badge.svg)](https://codecov.io/gh/opensearch-project/common-utils) + + - [OpenSearch Common Utils](#opensearch-common-utils) - [Contributing](#contributing) @@ -44,4 +46,4 @@ This project is licensed under the [Apache v2.0 License](LICENSE.txt). ## Copyright -Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright OpenSearch Contributors. See [NOTICE](NOTICE.txt) for details. diff --git a/build-tools/opensearchplugin-coverage.gradle b/build-tools/opensearchplugin-coverage.gradle new file mode 100644 index 00000000..2b4d21c0 --- /dev/null +++ b/build-tools/opensearchplugin-coverage.gradle @@ -0,0 +1,49 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * OpenSearch Plugin build tools don't work with the Gradle Jacoco Plugin to report coverage out of the box. + * https://github.com/elastic/elasticsearch/issues/28867. + * + * This code sets up coverage reporting manually for OpenSearch plugin tests. This is complicated because: + * 1. The OpenSearch integTest Task doesn't implement Gradle's JavaForkOptions so we have to manually start the jacoco agent with the test JVM + * 2. The cluster nodes are stopped using 'kill -9' which means jacoco can't dump it's execution output to a file on VM shutdown + * 3. The Java Security Manager prevents JMX from writing execution output to the file. + * + * To workaround these we start the cluster with jmx enabled and then use Jacoco's JMX MBean to get the execution data before the + * cluster is stopped and dump it to a file. Luckily our current security policy seems to allow this. This will also probably + * break if there are multiple nodes in the integTestCluster. But for now... it sorta works. + */ +apply plugin: 'jacoco' + +// Get gradle to generate the required jvm agent arg for us using a dummy tasks of type Test. Unfortunately Elastic's +// testing tasks don't derive from Test so the jacoco plugin can't do this automatically. +def jacocoDir = "${buildDir}/jacoco" +task dummyTest(type: Test) { + enabled = false + workingDir = file("/") // Force absolute path to jacoco agent jar + jacoco { + destinationFile = file("${jacocoDir}/test.exec") + destinationFile.parentFile.mkdirs() + jmx = true + } +} + +jacocoTestReport { + dependsOn test + executionData dummyTest.jacoco.destinationFile + getSourceDirectories().from(sourceSets.main.allSource) + getClassDirectories().from(sourceSets.main.output) + reports { + html.enabled = true // human readable + xml.enabled = true // for coverlay + } +} + +project.gradle.projectsEvaluated { + jacocoTestReport.dependsOn test +} + +check.dependsOn jacocoTestReport diff --git a/build.gradle b/build.gradle index 2d955951..86051f92 100644 --- a/build.gradle +++ b/build.gradle @@ -1,33 +1,29 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ buildscript { ext { opensearch_group = "org.opensearch" - opensearch_version = System.getProperty("opensearch.version", "1.0.0") - kotlin_version = System.getProperty("kotlin.version", "1.4.32") + opensearch_version = System.getProperty("opensearch.version", "2.3.1-SNAPSHOT") + isSnapshot = "true" == System.getProperty("build.snapshot", "true") + buildVersionQualifier = System.getProperty("build.version_qualifier", "") + kotlin_version = System.getProperty("kotlin.version", "1.6.10") } repositories { mavenLocal() mavenCentral() maven { url "https://plugins.gradle.org/m2/" } - jcenter() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } dependencies { classpath "${opensearch_group}.gradle:build-tools:${opensearch_version}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}" classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlin_version}" - classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.17.1" +// classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.20.0-RC1" } } @@ -41,24 +37,37 @@ repositories { mavenLocal() mavenCentral() maven { url "https://plugins.gradle.org/m2/" } - jcenter() + maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" } } -group 'org.opensearch.commons' +allprojects { + group 'org.opensearch.commons' + version = opensearch_version.tokenize('-')[0] + '.0' + if (buildVersionQualifier) { + version += "-${buildVersionQualifier}" + } + if (isSnapshot) { + version += "-SNAPSHOT" + } +} -sourceCompatibility = 1.8 +targetCompatibility = JavaVersion.VERSION_11 +sourceCompatibility = JavaVersion.VERSION_11 apply plugin: 'java' apply plugin: 'jacoco' apply plugin: 'signing' apply plugin: 'maven-publish' apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: 'io.gitlab.arturbosch.detekt' +// apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'org.jetbrains.kotlin.jvm' apply plugin: 'org.jetbrains.kotlin.plugin.allopen' +apply plugin: 'opensearch.repositories' +apply from: 'build-tools/opensearchplugin-coverage.gradle' configurations { ktlint + all*.exclude group: 'org.yaml', module: 'snakeyaml' } dependencies { @@ -66,15 +75,15 @@ dependencies { compileOnly "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" compileOnly "org.jetbrains.kotlin:kotlin-stdlib-common:${kotlin_version}" compileOnly "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3" // ${kotlin_version} does not work for coroutines - testCompile "org.opensearch.test:framework:${opensearch_version}" - testCompile "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" - testCompile "org.mockito:mockito-core:3.10.0" + testImplementation "org.opensearch.test:framework:${opensearch_version}" + testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" + testImplementation "org.mockito:mockito-core:3.10.0" testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' testImplementation 'org.mockito:mockito-junit-jupiter:3.10.0' testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' - ktlint "com.pinterest:ktlint:0.41.0" + ktlint "com.pinterest:ktlint:0.44.0" } test { @@ -95,10 +104,12 @@ spotless { eclipse().configFile rootProject.file('.eclipseformat.xml') } } -detekt { + +// TODO: enable detekt only when snakeyaml vulnerability is fixed +/*detekt { config = files("detekt.yml") buildUponDefaultConfig = true -} +}*/ task ktlint(type: JavaExec, group: "verification") { description = "Check Kotlin code style." @@ -122,13 +133,13 @@ task ktlintFormat(type: JavaExec, group: "formatting") { compileKotlin { kotlinOptions { freeCompilerArgs = ['-Xjsr305=strict'] - jvmTarget = "1.8" + jvmTarget = "11" } } compileTestKotlin { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "11" } } @@ -145,10 +156,13 @@ task javadocJar(type: Jar) { classifier = 'javadoc' from javadoc.destinationDir } - -version '1.0.0.0' - publishing { + repositories { + maven { + name = 'staging' + url = "${rootProject.buildDir}/local-staging-repo" + } + } publications { shadow(MavenPublication) { project.shadow.component(it) @@ -187,9 +201,16 @@ publishing { gradle.startParameter.setShowStacktrace(ShowStacktrace.ALWAYS) gradle.startParameter.setLogLevel(LogLevel.DEBUG) +} - signing { - required { gradle.taskGraph.hasTask("publishShadowPublicationToSonatype-stagingRepository") } - sign publishing.publications.shadow +// updateVersion: Task to auto increment to the next development iteration +task updateVersion { + onlyIf { System.getProperty('newVersion') } + doLast { + ext.newVersion = System.getProperty('newVersion') + println "Setting version to ${newVersion}." + // String tokenization to support -SNAPSHOT + // Include the required files that needs to be updated with new Version + ant.replaceregexp(file:'build.gradle', match: '"opensearch.version", "\\d.*"', replace: '"opensearch.version", "' + newVersion.tokenize('-')[0] + '-SNAPSHOT"', flags:'g', byline:true) } -} +} \ No newline at end of file diff --git a/detekt.yml b/detekt.yml index 34ed3c1e..251da688 100644 --- a/detekt.yml +++ b/detekt.yml @@ -1,14 +1,8 @@ --- # +# Copyright OpenSearch Contributors # SPDX-License-Identifier: Apache-2.0 # -# The OpenSearch Contributors require contributions made to -# this file be licensed under the Apache-2.0 license or a -# compatible open source license. -# -# Modifications Copyright OpenSearch Contributors. See -# GitHub history for details. -# style: ForbiddenComment: diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 28861d27..41d9927a 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 21a8fe40..aa991fce 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-all.zip diff --git a/gradlew b/gradlew index cccdd3d5..1b6c7873 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md new file mode 100644 index 00000000..71d1a7db --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.0.0.0.md @@ -0,0 +1,29 @@ +## Version 1.0.0.0 2021-07-01 + +Compatible with OpenSearch 1.0.0 + +### Enhancements + + * Notification plugin interface and models ([#31](https://github.com/opensearch-project/common-utils/pull/31)) + +### Infrastructure + + * Support for kotlin and JUnit5 with mockito ([#29](https://github.com/opensearch-project/common-utils/pull/29)) + * Removing Kotlin Runtime library bundled into library ([#30](https://github.com/opensearch-project/common-utils/pull/30)) + * Bump to version 1.0.0.0 #34 ([#34](https://github.com/opensearch-project/common-utils/pull/34)) + +### Documentation + + * Update OpenSearch branch to 1.0 ([#28](https://github.com/opensearch-project/common-utils/pull/28)) + * Cleanup READMEs. ([#32](https://github.com/opensearch-project/common-utils/pull/32)) + +### Maintainence + + * Update issue template with multiple labels ([#18](https://github.com/opensearch-project/common-utils/pull/18)) + * Rename namespaces from OpenDistro to OpenSearch ([#20](https://github.com/opensearch-project/common-utils/pull/20)) + * Rename classes, variables, methods to incorporate OpenSearch ([#21](https://github.com/opensearch-project/common-utils/pull/21)) + * Rename remaining identifiers to OpenSearch ([#23](https://github.com/opensearch-project/common-utils/pull/23)) + * Version changed to rc1 #24 ([#24](https://github.com/opensearch-project/common-utils/pull/24)) + * Rename consts as per changes in security plugin ([#25](https://github.com/opensearch-project/common-utils/pull/25)) + * Move workflow tags to rc1 ([#26](https://github.com/opensearch-project/common-utils/pull/26)) + * Add rc1 release notes ([#27](https://github.com/opensearch-project/common-utils/pull/27)) diff --git a/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md new file mode 100644 index 00000000..afb92873 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.2.0.0.md @@ -0,0 +1,14 @@ +## Version 1.2.0.0 2021-11-05 + +Compatible with OpenSearch 1.2.0 + +### Infrastructure + + * Updates common-utils version to 1.2 ([#77](https://github.com/opensearch-project/common-utils/pull/77)) + * Update maven publication to include cksums. ([#91](https://github.com/opensearch-project/common-utils/pull/91)) + +### Documentation + + * Add themed logo to README ([#41](https://github.com/opensearch-project/common-utils/pull/41)) + * Update copyright notice ([#90](https://github.com/opensearch-project/common-utils/pull/90)) + * Add release notes for version 1.2.0.0 ([#92](https://github.com/opensearch-project/common-utils/pull/92)) \ No newline at end of file diff --git a/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md b/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md new file mode 100644 index 00000000..4f210951 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-1.3.0.0.md @@ -0,0 +1,14 @@ +## Version 1.3.0.0 2022-03-11 + +Compatible with OpenSearch 1.3.0 + +### Infrastructure + + * Updates common-utils version to 1.3 ([#99](https://github.com/opensearch-project/common-utils/pull/99)) + * Update build.sh script to include optional platform param. ([#95](https://github.com/opensearch-project/common-utils/pull/95)) + * Update copyright notice and add DCO check workflow. ([#94](https://github.com/opensearch-project/common-utils/pull/94)) + +### Documentation + + * Update copyright headers ([#117](https://github.com/opensearch-project/common-utils/pull/117)) + * Add release notes for version 1.3.0.0 ([#132](https://github.com/opensearch-project/common-utils/pull/132)) \ No newline at end of file diff --git a/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md b/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md new file mode 100644 index 00000000..84418524 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.0.0.0-rc1.md @@ -0,0 +1,29 @@ +## Version 2.0.0.0-rc1 2022-04-25 + +Compatible with OpenSearch 2.0.0-rc1 + +### Enhancements + + * Add SQL/PPL transport request/response models for SQL plugin ([#155](https://github.com/opensearch-project/common-utils/pull/155)) + * Support sending email message via Notifications pass-through API ([#158](https://github.com/opensearch-project/common-utils/pull/158)) + +### Infrastructure + + * Upgrade gradle artifacts to 7.3.3 ([#135](https://github.com/opensearch-project/common-utils/pull/135) + * Update common-utils to depend on the OpenSearch repositories plugin ([#137](https://github.com/opensearch-project/common-utils/pull/137)) + * Add sign-off option for version workflow PR ([#143](https://github.com/opensearch-project/common-utils/pull/143)) + * Add qualifier default to alpha1 in build.gradle ([#151](https://github.com/opensearch-project/common-utils/pull/151)) + * Update issue templates from github for bugs and features ([#154](https://github.com/opensearch-project/common-utils/pull/154)) + * Remove support for JDK 14 ([#159](https://github.com/opensearch-project/common-utils/pull/159)) + +### Refactoring + + * Remove feature and feature_list usage for Notifications ([#136](https://github.com/opensearch-project/common-utils/pull/136)) + * Rename references for Get Channels API for Notifications ([#140](https://github.com/opensearch-project/common-utils/pull/140)) + * Remove allowedConfigFeatureList from GetPluginFeaturesResponse for Notifications ([#144](https://github.com/opensearch-project/common-utils/pull/144)) + * Remove NotificationEvent Request, Response and SearchResults ([#153](https://github.com/opensearch-project/common-utils/pull/153)) + * Add NotificationEvent to SendNotificationResponse and Removal of NotificationID ([#156](https://github.com/opensearch-project/common-utils/pull/156)) + +### Documentation + + * Add release notes for version 2.0.0-rc1 ([#162](https://github.com/opensearch-project/common-utils/pull/162)) diff --git a/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md new file mode 100644 index 00000000..70295ccc --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.0.0.0.md @@ -0,0 +1,32 @@ +## Version 2.0.0.0 2022-05-18 + +Compatible with OpenSearch 2.0.0 + +### Enhancements + + * Add SQL/PPL transport request/response models for SQL plugin ([#155](https://github.com/opensearch-project/common-utils/pull/155)) + * Support sending email message via Notifications pass-through API ([#158](https://github.com/opensearch-project/common-utils/pull/158)) + +### Infrastructure + + * Upgrade gradle artifacts to 7.3.3 ([#135](https://github.com/opensearch-project/common-utils/pull/135) + * Update common-utils to depend on the OpenSearch repositories plugin ([#137](https://github.com/opensearch-project/common-utils/pull/137)) + * Add sign-off option for version workflow PR ([#143](https://github.com/opensearch-project/common-utils/pull/143)) + * Add qualifier default to alpha1 in build.gradle ([#151](https://github.com/opensearch-project/common-utils/pull/151)) + * Update issue templates from github for bugs and features ([#154](https://github.com/opensearch-project/common-utils/pull/154)) + * Remove support for JDK 14 ([#159](https://github.com/opensearch-project/common-utils/pull/159)) + * Remove RC1 as the qualifier from Common Utils ([#168](https://github.com/opensearch-project/common-utils/pull/168)) + +### Refactoring + + * Remove feature and feature_list usage for Notifications ([#136](https://github.com/opensearch-project/common-utils/pull/136)) + * Rename references for Get Channels API for Notifications ([#140](https://github.com/opensearch-project/common-utils/pull/140)) + * Remove allowedConfigFeatureList from GetPluginFeaturesResponse for Notifications ([#144](https://github.com/opensearch-project/common-utils/pull/144)) + * Remove NotificationEvent Request, Response and SearchResults ([#153](https://github.com/opensearch-project/common-utils/pull/153)) + * Add NotificationEvent to SendNotificationResponse and Removal of NotificationID ([#156](https://github.com/opensearch-project/common-utils/pull/156)) + * Change BaseModel to extend ToXContentObject instead of ToXContent ([#173](https://github.com/opensearch-project/common-utils/pull/173)) + +### Documentation + + * Add release notes for version 2.0.0-rc1 ([#162](https://github.com/opensearch-project/common-utils/pull/162)) + * Add release notes for version 2.0.0.0 ([#177](https://github.com/opensearch-project/common-utils/pull/177)) diff --git a/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md new file mode 100644 index 00000000..3bf4465f --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.1.0.0.md @@ -0,0 +1,10 @@ +## Version 2.1.0.0 2022-07-06 + +Compatible with OpenSearch 2.1.0 + +### Maintenance +* Upgrade gradle to 7.4.2. ([#191](https://github.com/opensearch-project/common-utils/pull/191)) +* Bump up the version to 2.1. ([#190](https://github.com/opensearch-project/common-utils/pull/190)) + +### Documentation +* Added 2.1 release notes. ([#194](https://github.com/opensearch-project/common-utils/pull/194)) \ No newline at end of file diff --git a/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md new file mode 100644 index 00000000..b77f7244 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.2.0.0.md @@ -0,0 +1,10 @@ +## Version 2.2.0.0 2022-08-09 + +Compatible with OpenSearch 2.2.0 + +### Infrastructure +* Execute version auto increment in staging ([#200](https://github.com/opensearch-project/common-utils/pull/200)) +* Bump up the version to 2.2. ([#204](https://github.com/opensearch-project/common-utils/pull/204)) + +### Documentation +* Added 2.2 release notes. ([#212](https://github.com/opensearch-project/common-utils/pull/212)) \ No newline at end of file diff --git a/release-notes/opensearch-common-utils.release-notes-2.3.0.0.md b/release-notes/opensearch-common-utils.release-notes-2.3.0.0.md new file mode 100644 index 00000000..f6fdf7f7 --- /dev/null +++ b/release-notes/opensearch-common-utils.release-notes-2.3.0.0.md @@ -0,0 +1,10 @@ +## Version 2.3.0.0 2022-09-12 + +Compatible with OpenSearch 2.3.0 + +### Infrastructure +* fix snakeyaml vulnerability issue by disabling detekt ([#241](https://github.com/opensearch-project/common-utils/pull/241)) +* Upgrade version to 2.3. ([#223](https://github.com/opensearch-project/common-utils/pull/223)) + +### Documentation +* Adds 2.3 release notes. ([#248](https://github.com/opensearch-project/common-utils/pull/248)) \ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 00000000..e0495d4a --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# Copyright OpenSearch Contributors. +# SPDX-License-Identifier: Apache-2.0 + +set -ex + +function usage() { + echo "Usage: $0 [args]" + echo "" + echo "Arguments:" + echo -e "-v VERSION\t[Required] OpenSearch version." + echo -e "-q QUALIFIER\t[Optional] Version qualifier." + echo -e "-s SNAPSHOT\t[Optional] Build a snapshot, default is 'false'." + echo -e "-p PLATFORM\t[Optional] Platform, ignored." + echo -e "-a ARCHITECTURE\t[Optional] Build architecture, ignored." + echo -e "-o OUTPUT\t[Optional] Output path, default is 'artifacts'." + echo -e "-h help" +} + +while getopts ":h:v:q:s:o:p:a:" arg; do + case $arg in + h) + usage + exit 1 + ;; + v) + VERSION=$OPTARG + ;; + q) + QUALIFIER=$OPTARG + ;; + s) + SNAPSHOT=$OPTARG + ;; + o) + OUTPUT=$OPTARG + ;; + p) + PLATFORM=$OPTARG + ;; + a) + ARCHITECTURE=$OPTARG + ;; + :) + echo "Error: -${OPTARG} requires an argument" + usage + exit 1 + ;; + ?) + echo "Invalid option: -${arg}" + exit 1 + ;; + esac +done + +if [ -z "$VERSION" ]; then + echo "Error: You must specify the OpenSearch version" + usage + exit 1 +fi + +[[ ! -z "$QUALIFIER" ]] && VERSION=$VERSION-$QUALIFIER +[[ "$SNAPSHOT" == "true" ]] && VERSION=$VERSION-SNAPSHOT +[ -z "$OUTPUT" ] && OUTPUT=artifacts + +./gradlew build -x test -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew publishShadowPublicationToMavenLocal -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +./gradlew publishShadowPublicationToStagingRepository -Dopensearch.version=$VERSION -Dbuild.snapshot=$SNAPSHOT -Dbuild.version_qualifier=$QUALIFIER +mkdir -p $OUTPUT/maven/org/opensearch +cp -r ./build/local-staging-repo/org/opensearch/. $OUTPUT/maven/org/opensearch diff --git a/settings.gradle b/settings.gradle index 7fa821ef..59d3dd1c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,12 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ rootProject.name = 'common-utils' \ No newline at end of file diff --git a/spotless.license.java b/spotless.license.java index 01b9ea6c..9e182dcd 100644 --- a/spotless.license.java +++ b/spotless.license.java @@ -1,26 +1,5 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. */ diff --git a/src/main/java/org/opensearch/commons/ConfigConstants.java b/src/main/java/org/opensearch/commons/ConfigConstants.java index d7516dbc..6fc6e362 100644 --- a/src/main/java/org/opensearch/commons/ConfigConstants.java +++ b/src/main/java/org/opensearch/commons/ConfigConstants.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons; diff --git a/src/main/java/org/opensearch/commons/InjectSecurity.java b/src/main/java/org/opensearch/commons/InjectSecurity.java index ab4f0323..f2644c29 100644 --- a/src/main/java/org/opensearch/commons/InjectSecurity.java +++ b/src/main/java/org/opensearch/commons/InjectSecurity.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons; @@ -160,6 +139,23 @@ public void injectRoles(final List roles) { } } + /** + * Allows one to set the property in threadContext if possible to the value provided. If not possible returns false. + * @param property + * @param value + * @return boolean + */ + public boolean injectProperty(final String property, final Object value) { + if (Strings.isNullOrEmpty(property) || value == null || threadContext.getTransient(property) != null) { + log.debug("{}, InjectSecurity - cannot inject property: {}", Thread.currentThread().getName(), id); + return false; + } else { + threadContext.putTransient(property, value); + log.debug("{}, InjectSecurity - inject property: {}", Thread.currentThread().getName(), id); + return true; + } + } + @Override public void close() { if (ctx != null) { diff --git a/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java b/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java index c4b32e5f..32602744 100644 --- a/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java +++ b/src/main/java/org/opensearch/commons/authuser/AuthUserRequestBuilder.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.authuser; diff --git a/src/main/java/org/opensearch/commons/authuser/User.java b/src/main/java/org/opensearch/commons/authuser/User.java index 017405e9..f698d36b 100644 --- a/src/main/java/org/opensearch/commons/authuser/User.java +++ b/src/main/java/org/opensearch/commons/authuser/User.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.authuser; diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java new file mode 100644 index 00000000..96bd06ba --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyBaseMessage.java @@ -0,0 +1,107 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; + +import org.apache.http.client.utils.URIBuilder; +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +/** + * This class holds the generic parameters required for a + * message. + */ +public abstract class LegacyBaseMessage implements Writeable { + + private final LegacyDestinationType destinationType; + protected String destinationName; + protected String url; + private final String content; + + LegacyBaseMessage(final LegacyDestinationType destinationType, final String destinationName, final String content) { + if (destinationType == null) { + throw new IllegalArgumentException("Channel type must be defined"); + } + if (!Strings.hasLength(destinationName)) { + throw new IllegalArgumentException("Channel name must be defined"); + } + this.destinationType = destinationType; + this.destinationName = destinationName; + this.content = content; + } + + LegacyBaseMessage(final LegacyDestinationType destinationType, final String destinationName, final String content, final String url) { + this(destinationType, destinationName, content); + if (url == null) { + throw new IllegalArgumentException("url is invalid or empty"); + } + this.url = url; + } + + LegacyBaseMessage(StreamInput streamInput) throws IOException { + this.destinationType = streamInput.readEnum(LegacyDestinationType.class); + this.destinationName = streamInput.readString(); + this.url = streamInput.readOptionalString(); + this.content = streamInput.readString(); + } + + public void setUrl(String url) { + this.url = url; + } + + public LegacyDestinationType getChannelType() { + return destinationType; + } + + public String getChannelName() { + return destinationName; + } + + public String getMessageContent() { + return content; + } + + public String getUrl() { + return url; + } + + public URI getUri() { + return buildUri(getUrl().trim(), null, null, -1, null, null); + } + + protected URI buildUri(String endpoint, String scheme, String host, int port, String path, Map queryParams) { + try { + if (Strings.isNullOrEmpty(endpoint)) { + if (Strings.isNullOrEmpty(scheme)) { + scheme = "https"; + } + URIBuilder uriBuilder = new URIBuilder(); + if (queryParams != null) { + for (Map.Entry e : queryParams.entrySet()) + uriBuilder.addParameter(e.getKey(), e.getValue()); + } + return uriBuilder.setScheme(scheme).setHost(host).setPort(port).setPath(path).build(); + } + return new URIBuilder(endpoint).build(); + } catch (URISyntaxException exception) { + throw new IllegalStateException("Error creating URI"); + } + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeEnum(destinationType); + streamOutput.writeString(destinationName); + streamOutput.writeOptionalString(url); + streamOutput.writeString(content); + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java new file mode 100644 index 00000000..31b45d1f --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyChimeMessage.java @@ -0,0 +1,70 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; + +/** + * This class holds the contents of an Chime message + */ +public class LegacyChimeMessage extends LegacyBaseMessage { + private final String message; + + private LegacyChimeMessage(final String destinationName, final String url, final String message) { + super(LegacyDestinationType.LEGACY_CHIME, destinationName, message, url); + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.message = message; + } + + public LegacyChimeMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + } + + @Override + public String toString() { + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + } + + public static class Builder { + private String message; + private final String destinationName; + private String url; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyChimeMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyChimeMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacyChimeMessage build() { + return new LegacyChimeMessage(this.destinationName, this.url, this.message); + } + } + + public String getMessage() { + return message; + } + + public String getUrl() { + return url; + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java new file mode 100644 index 00000000..dbc4b7df --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessage.java @@ -0,0 +1,254 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; + +/** + * This class holds the content of an CustomWebhook message + */ +public class LegacyCustomWebhookMessage extends LegacyBaseMessage { + + private final String message; + private final String url; + private final String scheme; + private final String host; + private final String method; + private final int port; + private String path; + private final Map queryParams; + private Map headerParams; + + private LegacyCustomWebhookMessage( + final String destinationName, + final String url, + final String scheme, + final String host, + final Integer port, + final String path, + final String method, + final Map queryParams, + final Map headerParams, + final String message + ) { + super(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, destinationName, message); + + if (!Strings.isNullOrEmpty(url)) { + setUrl(url.trim()); + } + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.scheme = Strings.isNullOrEmpty(scheme) ? "https" : scheme; + this.port = port == null ? -1 : port; + + if (!Strings.isNullOrEmpty(path)) { + if (!path.startsWith("/")) { + this.path = "/" + path; + } + } + + if (Strings.isNullOrEmpty(url) && Strings.isNullOrEmpty(host)) { + throw new IllegalArgumentException("Either fully qualified URL or host name should be provided"); + } + + if (Strings.isNullOrEmpty(method)) { + // Default to POST for backwards compatibility + this.method = "POST"; + } else if (!HttpPost.METHOD_NAME.equals(method) && !HttpPut.METHOD_NAME.equals(method) && !HttpPatch.METHOD_NAME.equals(method)) { + throw new IllegalArgumentException("Invalid method supplied. Only POST, PUT and PATCH are allowed"); + } else { + this.method = method; + } + + this.message = message; + this.url = url; + this.host = host; + this.queryParams = queryParams; + this.headerParams = headerParams; + } + + public LegacyCustomWebhookMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + this.url = streamInput.readOptionalString(); + this.scheme = null; + this.host = null; + this.method = streamInput.readOptionalString(); + this.port = -1; + this.path = null; + this.queryParams = null; + if (streamInput.readBoolean()) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) streamInput.readMap(); + this.headerParams = headerParams; + } + } + + @Override + public String toString() { + return "DestinationType: " + + getChannelType() + + ", DestinationName:" + + destinationName + + ", Url: " + + url + + ", scheme: " + + scheme + + ", Host: " + + host + + ", Port: " + + port + + ", Path: " + + path + + ", Method: " + + method + + ", Message: <...>"; + } + + public static class Builder { + private String message; + private final String destinationName; + private String url; + private String scheme; + private String host; + private Integer port; + private String path; + private String method; + private Map queryParams; + private Map headerParams; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyCustomWebhookMessage.Builder withScheme(String scheme) { + this.scheme = scheme; + return this; + } + + public LegacyCustomWebhookMessage.Builder withHost(String host) { + this.host = host; + return this; + } + + public LegacyCustomWebhookMessage.Builder withPort(Integer port) { + this.port = port; + return this; + } + + public LegacyCustomWebhookMessage.Builder withPath(String path) { + this.path = path; + return this; + } + + public LegacyCustomWebhookMessage.Builder withMethod(String method) { + this.method = method; + return this; + } + + public LegacyCustomWebhookMessage.Builder withQueryParams(Map queryParams) { + this.queryParams = queryParams; + return this; + } + + public LegacyCustomWebhookMessage.Builder withHeaderParams(Map headerParams) { + this.headerParams = headerParams; + return this; + } + + public LegacyCustomWebhookMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyCustomWebhookMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacyCustomWebhookMessage build() { + return new LegacyCustomWebhookMessage( + this.destinationName, + this.url, + this.scheme, + this.host, + this.port, + this.path, + this.method, + this.queryParams, + this.headerParams, + this.message + ); + } + } + + public String getScheme() { + return scheme; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } + + public Map getQueryParams() { + return queryParams; + } + + public Map getHeaderParams() { + return headerParams; + } + + public URI getUri() { + return buildUri(getUrl(), getScheme(), getHost(), getPort(), getPath(), getQueryParams()); + } + + public String getMessage() { + return message; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + // Making LegacyCustomWebhookMessage streamable is purely to support the new pass through API from Alerting/ISM -> Notification + // plugin + // and it only supports LegacyCustomWebhookMessage when the url is already constructed by Alerting/ISM. + if (Strings.isNullOrEmpty(getUrl())) { + throw new IllegalStateException("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url."); + } + streamOutput.writeOptionalString(url); + streamOutput.writeOptionalString(method); + streamOutput.writeBoolean(headerParams != null); + if (headerParams != null) { + @SuppressWarnings("unchecked") + Map headerParams = (Map) (Map) this.headerParams; + streamOutput.writeMap(headerParams); + } + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java new file mode 100644 index 00000000..f5086c27 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyDestinationType.java @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +/** + * Supported legacy notification destinations for Alerting and Index Management + */ +public enum LegacyDestinationType { + LEGACY_CHIME, + LEGACY_SLACK, + LEGACY_CUSTOM_WEBHOOK, + LEGACY_EMAIL +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java new file mode 100644 index 00000000..01810868 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacyEmailMessage.java @@ -0,0 +1,234 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; +import java.net.URI; +import java.util.List; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.commons.notifications.model.MethodType; + +/** + * This class holds the content of an CustomWebhook message + */ +public class LegacyEmailMessage extends LegacyBaseMessage { + + private final String accountName; + private final String host; + private final int port; + private final String method; + private final String from; + private final List recipients; + private final String subject; + private final String message; + + private LegacyEmailMessage( + final String destinationName, + final String accountName, + final String host, + final Integer port, + final String method, + final String from, + final List recipients, + final String subject, + final String message + ) { + super(LegacyDestinationType.LEGACY_EMAIL, destinationName, message); + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + if (Strings.isNullOrEmpty(accountName)) { + throw new IllegalArgumentException("Account name should be provided"); + } + + if (Strings.isNullOrEmpty(host)) { + throw new IllegalArgumentException("Host name should be provided"); + } + + if (Strings.isNullOrEmpty(from)) { + throw new IllegalArgumentException("From address should be provided"); + } + + if (recipients == null || recipients.isEmpty()) { + throw new IllegalArgumentException("List of recipients should be provided"); + } + + this.message = message; + this.accountName = accountName; + this.host = host; + this.port = port == null ? 25 : port; + + if (Strings.isNullOrEmpty(method)) { + // Default to "none" + this.method = "none"; + } else if (!MethodType.NONE.toString().equals(method) + && !MethodType.SSL.toString().equals(method) + && !MethodType.START_TLS.toString().equals(method)) { + throw new IllegalArgumentException("Invalid method supplied. Only none, ssl and start_tls are allowed"); + } else { + this.method = method; + } + + this.from = from; + this.recipients = recipients; + this.subject = Strings.isNullOrEmpty(subject) ? destinationName : subject; + } + + public LegacyEmailMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + this.accountName = streamInput.readString(); + this.host = streamInput.readString(); + this.port = streamInput.readInt(); + this.method = streamInput.readString(); + this.from = streamInput.readString(); + this.recipients = streamInput.readStringList(); + this.subject = streamInput.readString(); + } + + @Override + public String toString() { + return "DestinationType: " + + getChannelType() + + ", DestinationName:" + + destinationName + + ", AccountName:" + + accountName + + ", From: " + + from + + ", Host: " + + host + + ", Port: " + + port + + ", Method: " + + method + + ", Subject: <...>" + + ", Message: <...>"; + } + + public static class Builder { + private final String destinationName; + private String accountName; + private String host; + private Integer port; + private String method; + private String from; + private List recipients; + private String subject; + private String message; + + public Builder(String destinationName) { + this.destinationName = destinationName; + } + + public LegacyEmailMessage.Builder withAccountName(String accountName) { + this.accountName = accountName; + return this; + } + + public LegacyEmailMessage.Builder withHost(String host) { + this.host = host; + return this; + } + + public LegacyEmailMessage.Builder withPort(Integer port) { + this.port = port; + return this; + } + + public LegacyEmailMessage.Builder withMethod(String method) { + this.method = method; + return this; + } + + public LegacyEmailMessage.Builder withFrom(String from) { + this.from = from; + return this; + } + + public LegacyEmailMessage.Builder withRecipients(List recipients) { + this.recipients = recipients; + return this; + } + + public LegacyEmailMessage.Builder withSubject(String subject) { + this.subject = subject; + return this; + } + + public LegacyEmailMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacyEmailMessage build() { + return new LegacyEmailMessage( + this.destinationName, + this.accountName, + this.host, + this.port, + this.method, + this.from, + this.recipients, + this.subject, + this.message + ); + } + } + + public String getAccountName() { + return accountName; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getMethod() { + return method; + } + + public String getFrom() { + return from; + } + + public List getRecipients() { + return recipients; + } + + public String getSubject() { + return subject; + } + + public String getMessage() { + return message; + } + + public URI getUri() { + return buildUri(null, null, host, port, null, null); + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + streamOutput.writeString(accountName); + streamOutput.writeString(host); + streamOutput.writeInt(port); + streamOutput.writeString(method); + streamOutput.writeString(from); + streamOutput.writeStringCollection(recipients); + streamOutput.writeString(subject); + } +} diff --git a/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java new file mode 100644 index 00000000..02d30bb4 --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/message/LegacySlackMessage.java @@ -0,0 +1,74 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import java.io.IOException; + +import org.opensearch.common.Strings; +import org.opensearch.common.io.stream.StreamInput; + +/** + * This class holds the content of an Slack message + */ +public class LegacySlackMessage extends LegacyBaseMessage { + private final String message; + + private LegacySlackMessage(final String destinationName, final String url, final String message) { + super(LegacyDestinationType.LEGACY_SLACK, destinationName, message, url); + + if (Strings.isNullOrEmpty(url)) { // add URL validation + throw new IllegalArgumentException("Fully qualified URL is missing/invalid: " + url); + } + + if (Strings.isNullOrEmpty(message)) { + throw new IllegalArgumentException("Message content is missing"); + } + + this.message = message; + } + + public LegacySlackMessage(StreamInput streamInput) throws IOException { + super(streamInput); + this.message = super.getMessageContent(); + } + + @Override + public String toString() { + return "DestinationType: " + getChannelType() + ", DestinationName:" + destinationName + ", Url: " + url + ", Message: <...>"; + } + + public static class Builder { + private String message; + private String destinationName; + private String url; + + public Builder(String channelName) { + this.destinationName = channelName; + } + + public LegacySlackMessage.Builder withMessage(String message) { + this.message = message; + return this; + } + + public LegacySlackMessage.Builder withUrl(String url) { + this.url = url; + return this; + } + + public LegacySlackMessage build() { + return new LegacySlackMessage(this.destinationName, this.url, this.message); + } + } + + public String getMessage() { + return message; + } + + public String getUrl() { + return url; + } +} diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java new file mode 100644 index 00000000..4d34b67f --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyBaseResponse.java @@ -0,0 +1,39 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.response; + +import java.io.IOException; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; + +/** + * This class holds the generic response attributes + */ +public abstract class LegacyBaseResponse implements Writeable { + protected Integer statusCode; + + LegacyBaseResponse(final Integer statusCode) { + if (statusCode == null) { + throw new IllegalArgumentException("status code is invalid"); + } + this.statusCode = statusCode; + } + + public LegacyBaseResponse(StreamInput streamInput) throws IOException { + this.statusCode = streamInput.readInt(); + } + + public int getStatusCode() { + return statusCode; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + streamOutput.writeInt(statusCode); + } +} diff --git a/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java new file mode 100644 index 00000000..d55f5f3d --- /dev/null +++ b/src/main/java/org/opensearch/commons/destination/response/LegacyDestinationResponse.java @@ -0,0 +1,61 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.response; + +import java.io.IOException; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; + +/** + * This class is a place holder for destination response metadata + */ +public class LegacyDestinationResponse extends LegacyBaseResponse { + + private final String responseContent; + + private LegacyDestinationResponse(final String responseString, final Integer statusCode) { + super(statusCode); + if (responseString == null) { + throw new IllegalArgumentException("Response is missing"); + } + this.responseContent = responseString; + } + + public LegacyDestinationResponse(StreamInput streamInput) throws IOException { + super(streamInput); + this.responseContent = streamInput.readString(); + } + + public static class Builder { + private String responseContent; + private Integer statusCode; + + public LegacyDestinationResponse.Builder withResponseContent(String responseContent) { + this.responseContent = responseContent; + return this; + } + + public LegacyDestinationResponse.Builder withStatusCode(Integer statusCode) { + this.statusCode = statusCode; + return this; + } + + public LegacyDestinationResponse build() { + return new LegacyDestinationResponse(responseContent, statusCode); + } + } + + public String getResponseContent() { + return this.responseContent; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + super.writeTo(streamOutput); + streamOutput.writeString(responseContent); + } +} diff --git a/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java b/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java index 109809a8..96af1540 100644 --- a/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java +++ b/src/main/java/org/opensearch/commons/rest/SecureRestClientBuilder.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.rest; diff --git a/src/main/java/org/opensearch/commons/rest/TrustStore.java b/src/main/java/org/opensearch/commons/rest/TrustStore.java index 95f23796..52832b32 100644 --- a/src/main/java/org/opensearch/commons/rest/TrustStore.java +++ b/src/main/java/org/opensearch/commons/rest/TrustStore.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.rest; diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 344cf0b8..74fcc600 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -36,22 +36,23 @@ object NotificationConstants { const val NAME_TAG = "name" const val DESCRIPTION_TAG = "description" const val IS_ENABLED_TAG = "is_enabled" - const val FEATURE_LIST_TAG = "feature_list" const val TITLE_TAG = "title" const val SEVERITY_TAG = "severity" const val TAGS_TAG = "tags" const val URL_TAG = "url" const val HEADER_PARAMS_TAG = "header_params" + const val TOPIC_ARN_TAG = "topic_arn" + const val ROLE_ARN_TAG = "role_arn" + const val REGION_TAG = "region" const val HOST_TAG = "host" const val PORT_TAG = "port" const val METHOD_TAG = "method" const val FROM_ADDRESS_TAG = "from_address" const val UPDATED_TIME_TAG = "last_updated_time_ms" const val CREATED_TIME_TAG = "created_time_ms" - const val TENANT_TAG = "tenant" const val CONFIG_LIST_TAG = "config_list" const val EVENT_LIST_TAG = "event_list" - const val FEATURE_CONFIG_LIST_TAG = "feature_channel_list" + const val CHANNEL_LIST_TAG = "channel_list" const val DELETE_RESPONSE_LIST_TAG = "delete_response_list" const val FROM_INDEX_TAG = "from_index" const val MAX_ITEMS_TAG = "max_items" @@ -64,7 +65,7 @@ object NotificationConstants { const val TOTAL_HIT_RELATION_TAG = "total_hit_relation" const val QUERY_TAG = "query" const val COMPACT_TAG = "compact" - const val CONFIG_TYPE_LIST_TAG = "config_type_list" + const val ALLOWED_CONFIG_TYPE_LIST_TAG = "allowed_config_type_list" const val PLUGIN_FEATURES_TAG = "plugin_features" const val DEFAULT_MAX_ITEMS = 1000 diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt index e82aaba8..c3baa938 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterface.kt @@ -1,52 +1,33 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications import org.opensearch.action.ActionListener +import org.opensearch.action.ActionResponse import org.opensearch.client.node.NodeClient +import org.opensearch.common.io.stream.Writeable import org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT +import org.opensearch.commons.notifications.action.BaseResponse import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetFeatureChannelListRequest -import org.opensearch.commons.notifications.action.GetFeatureChannelListResponse +import org.opensearch.commons.notifications.action.GetChannelListRequest +import org.opensearch.commons.notifications.action.GetChannelListResponse import org.opensearch.commons.notifications.action.GetNotificationConfigRequest import org.opensearch.commons.notifications.action.GetNotificationConfigResponse -import org.opensearch.commons.notifications.action.GetNotificationEventRequest -import org.opensearch.commons.notifications.action.GetNotificationEventResponse import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest +import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse import org.opensearch.commons.notifications.action.NotificationsActions.CREATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.DELETE_NOTIFICATION_CONFIG_ACTION_TYPE -import org.opensearch.commons.notifications.action.NotificationsActions.GET_FEATURE_CHANNEL_LIST_ACTION_TYPE +import org.opensearch.commons.notifications.action.NotificationsActions.GET_CHANNEL_LIST_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_CONFIG_ACTION_TYPE -import org.opensearch.commons.notifications.action.NotificationsActions.GET_NOTIFICATION_EVENT_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.GET_PLUGIN_FEATURES_ACTION_TYPE +import org.opensearch.commons.notifications.action.NotificationsActions.LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.SEND_NOTIFICATION_ACTION_TYPE import org.opensearch.commons.notifications.action.NotificationsActions.UPDATE_NOTIFICATION_CONFIG_ACTION_TYPE import org.opensearch.commons.notifications.action.SendNotificationRequest @@ -56,6 +37,7 @@ import org.opensearch.commons.notifications.action.UpdateNotificationConfigRespo import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.utils.SecureClientWrapper +import org.opensearch.commons.utils.recreateObject /** * All the transport action plugin interfaces for the Notification plugin @@ -76,7 +58,7 @@ object NotificationsPluginInterface { client.execute( CREATE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { CreateNotificationConfigResponse(it) } } ) } @@ -94,7 +76,7 @@ object NotificationsPluginInterface { client.execute( UPDATE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { UpdateNotificationConfigResponse(it) } } ) } @@ -112,7 +94,7 @@ object NotificationsPluginInterface { client.execute( DELETE_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { DeleteNotificationConfigResponse(it) } } ) } @@ -130,25 +112,7 @@ object NotificationsPluginInterface { client.execute( GET_NOTIFICATION_CONFIG_ACTION_TYPE, request, - listener - ) - } - - /** - * Get notification events. - * @param client Node client for making transport action - * @param request The request object - * @param listener The listener for getting response - */ - fun getNotificationEvent( - client: NodeClient, - request: GetNotificationEventRequest, - listener: ActionListener - ) { - client.execute( - GET_NOTIFICATION_EVENT_ACTION_TYPE, - request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetNotificationConfigResponse(it) } } ) } @@ -166,25 +130,25 @@ object NotificationsPluginInterface { client.execute( GET_PLUGIN_FEATURES_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetPluginFeaturesResponse(it) } } ) } /** - * Get notification channel configuration enabled for a feature. + * Get notification channel configuration. * @param client Node client for making transport action * @param request The request object * @param listener The listener for getting response */ - fun getFeatureChannelList( + fun getChannelList( client: NodeClient, - request: GetFeatureChannelListRequest, - listener: ActionListener + request: GetChannelListRequest, + listener: ActionListener ) { client.execute( - GET_FEATURE_CHANNEL_LIST_ACTION_TYPE, + GET_CHANNEL_LIST_ACTION_TYPE, request, - listener + wrapActionListener(listener) { response -> recreateObject(response) { GetChannelListResponse(it) } } ) } @@ -209,7 +173,49 @@ object NotificationsPluginInterface { wrapper.execute( SEND_NOTIFICATION_ACTION_TYPE, SendNotificationRequest(eventSource, channelMessage, channelIds, threadContext), - listener + wrapActionListener(listener) { response -> recreateObject(response) { SendNotificationResponse(it) } } ) } + + /** + * Publishes a notification API using the legacy notification implementation. No REST API. + * Internal API only for the Alerting and Index Management plugin, other consumers should use [sendNotification]. + * @param client Node client for making transport action + * @param request The legacy publish notification request + * @param listener The listener for getting response + */ + fun publishLegacyNotification( + client: NodeClient, + request: LegacyPublishNotificationRequest, + listener: ActionListener + ) { + client.execute( + LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE, + request, + wrapActionListener(listener) { response -> recreateObject(response) { LegacyPublishNotificationResponse(it) } } + ) + } + + /** + * Wrap action listener on concrete response class by a new created one on ActionResponse. + * This is required because the response may be loaded by different classloader across plugins. + * The onResponse(ActionResponse) avoids type cast exception and give a chance to recreate + * the response object. + */ + @Suppress("UNCHECKED_CAST") + private fun wrapActionListener( + listener: ActionListener, + recreate: (Writeable) -> Response + ): ActionListener { + return object : ActionListener { + override fun onResponse(response: ActionResponse) { + val recreated = response as? Response ?: recreate(response) + listener.onResponse(recreated) + } + + override fun onFailure(exception: java.lang.Exception) { + listener.onFailure(exception) + } + } as ActionListener + } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt index 4bfa2271..e0659e8f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/BaseResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt index e62e92dd..dfbd1b95 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt index 742e7be5..e8bce5af 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt index 3699369f..1bcd355a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt index e701daa2..efb68005 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt similarity index 53% rename from src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt rename to src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt index 17e4f6fb..96a54eb2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -36,27 +14,23 @@ import org.opensearch.common.xcontent.ToXContentObject import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_TAG -import org.opensearch.commons.notifications.model.Feature +import org.opensearch.commons.notifications.NotificationConstants.COMPACT_TAG import org.opensearch.commons.utils.logger import java.io.IOException /** * This request is plugin-only call. i.e. REST interface is not exposed. - * Also the library will remove the user context while making this call - * so that user making this call need not have to set permission to this API. - * Hence the request also contains tenant info for space isolation. */ -class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { - val feature: Feature +class GetChannelListRequest : ActionRequest, ToXContentObject { + val compact: Boolean // Dummy request parameter for transport request companion object { - private val log by logger(GetFeatureChannelListRequest::class.java) + private val log by logger(GetChannelListRequest::class.java) /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { GetFeatureChannelListRequest(it) } + val reader = Writeable.Reader { GetChannelListRequest(it) } /** * Creator used in REST communication. @@ -64,8 +38,8 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): GetFeatureChannelListRequest { - var feature: Feature? = null + fun parse(parser: XContentParser): GetChannelListRequest { + var compact = false XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -76,24 +50,32 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - FEATURE_TAG -> feature = Feature.fromTagOrDefault(parser.text()) + COMPACT_TAG -> compact = parser.booleanValue() else -> { parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing GetFeatureChannelListRequest") + log.info("Unexpected field: $fieldName, while parsing GetChannelListRequest") } } } - feature ?: throw IllegalArgumentException("$FEATURE_TAG field absent") - return GetFeatureChannelListRequest(feature) + return GetChannelListRequest() } } + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + return builder!!.startObject() + .field(COMPACT_TAG, compact) + .endObject() + } + /** * constructor for creating the class - * @param feature the caller plugin feature + * @param compact Dummy request parameter for transport request */ - constructor(feature: Feature) { - this.feature = feature + constructor(compact: Boolean = false) { + this.compact = compact } /** @@ -101,7 +83,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - feature = input.readEnum(Feature::class.java) + compact = input.readBoolean() } /** @@ -110,17 +92,7 @@ class GetFeatureChannelListRequest : ActionRequest, ToXContentObject { @Throws(IOException::class) override fun writeTo(output: StreamOutput) { super.writeTo(output) - output.writeEnum(feature) - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(FEATURE_TAG, feature) - .endObject() + output.writeBoolean(compact) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt similarity index 52% rename from src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt rename to src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt index 455109fc..89623ed0 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -32,21 +10,21 @@ import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.model.FeatureChannelList +import org.opensearch.commons.notifications.model.ChannelList import java.io.IOException /** * Action Response for creating new configuration. */ -class GetFeatureChannelListResponse : BaseResponse { - val searchResult: FeatureChannelList +class GetChannelListResponse : BaseResponse { + val searchResult: ChannelList companion object { /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { GetFeatureChannelListResponse(it) } + val reader = Writeable.Reader { GetChannelListResponse(it) } /** * Creator used in REST communication. @@ -54,8 +32,8 @@ class GetFeatureChannelListResponse : BaseResponse { */ @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): GetFeatureChannelListResponse { - return GetFeatureChannelListResponse(FeatureChannelList(parser)) + fun parse(parser: XContentParser): GetChannelListResponse { + return GetChannelListResponse(ChannelList(parser)) } } @@ -63,7 +41,7 @@ class GetFeatureChannelListResponse : BaseResponse { * constructor for creating the class * @param searchResult the notification configuration list */ - constructor(searchResult: FeatureChannelList) { + constructor(searchResult: ChannelList) { this.searchResult = searchResult } @@ -72,7 +50,7 @@ class GetFeatureChannelListResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - searchResult = FeatureChannelList(input) + searchResult = ChannelList(input) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt index a410fe7e..a78d0d51 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt index a810759b..1825ccca 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt deleted file mode 100644 index 27e20554..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequest.kt +++ /dev/null @@ -1,193 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action - -import org.opensearch.action.ActionRequest -import org.opensearch.action.ActionRequestValidationException -import org.opensearch.action.ValidateActions -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.ToXContentObject -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.common.xcontent.XContentParserUtils -import org.opensearch.commons.notifications.NotificationConstants.DEFAULT_MAX_ITEMS -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_LIST_TAG -import org.opensearch.commons.notifications.NotificationConstants.FILTER_PARAM_LIST_TAG -import org.opensearch.commons.notifications.NotificationConstants.FROM_INDEX_TAG -import org.opensearch.commons.notifications.NotificationConstants.MAX_ITEMS_TAG -import org.opensearch.commons.notifications.NotificationConstants.SORT_FIELD_TAG -import org.opensearch.commons.notifications.NotificationConstants.SORT_ORDER_TAG -import org.opensearch.commons.utils.STRING_READER -import org.opensearch.commons.utils.STRING_WRITER -import org.opensearch.commons.utils.enumReader -import org.opensearch.commons.utils.fieldIfNotNull -import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList -import org.opensearch.search.sort.SortOrder -import java.io.IOException - -/** - * Action Request for getting notification event. - */ -class GetNotificationEventRequest : ActionRequest, ToXContentObject { - val eventIds: Set - val fromIndex: Int - val maxItems: Int - val sortField: String? - val sortOrder: SortOrder? - val filterParams: Map - - companion object { - private val log by logger(GetNotificationEventRequest::class.java) - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { GetNotificationEventRequest(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): GetNotificationEventRequest { - var eventIds: Set = setOf() - var fromIndex = 0 - var maxItems = DEFAULT_MAX_ITEMS - var sortField: String? = null - var sortOrder: SortOrder? = null - var filterParams: Map = mapOf() - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_LIST_TAG -> eventIds = parser.stringList().toSet() - FROM_INDEX_TAG -> fromIndex = parser.intValue() - MAX_ITEMS_TAG -> maxItems = parser.intValue() - SORT_FIELD_TAG -> sortField = parser.textOrNull() - SORT_ORDER_TAG -> sortOrder = SortOrder.fromString(parser.text()) - FILTER_PARAM_LIST_TAG -> filterParams = parser.mapStrings() - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing GetNotificationEventRequest") - } - } - } - return GetNotificationEventRequest(eventIds, fromIndex, maxItems, sortField, sortOrder, filterParams) - } - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - return builder!!.startObject() - .field(EVENT_ID_LIST_TAG, eventIds) - .field(FROM_INDEX_TAG, fromIndex) - .field(MAX_ITEMS_TAG, maxItems) - .fieldIfNotNull(SORT_FIELD_TAG, sortField) - .fieldIfNotNull(SORT_ORDER_TAG, sortOrder) - .field(FILTER_PARAM_LIST_TAG, filterParams) - .endObject() - } - - /** - * constructor for creating the class - * @param eventIds the ids of the notification events (other parameters are not relevant if ids are present) - * @param fromIndex the starting index for paginated response - * @param maxItems the maximum number of items to return for paginated response - * @param sortField the sort field if response has many items - * @param sortOrder the sort order if response has many items - * @param filterParams the filter parameters - */ - constructor( - eventIds: Set = setOf(), - fromIndex: Int = 0, - maxItems: Int = DEFAULT_MAX_ITEMS, - sortField: String? = null, - sortOrder: SortOrder? = null, - filterParams: Map = mapOf() - ) { - this.eventIds = eventIds - this.fromIndex = fromIndex - this.maxItems = maxItems - this.sortField = sortField - this.sortOrder = sortOrder - this.filterParams = filterParams - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - constructor(input: StreamInput) : super(input) { - eventIds = input.readStringList().toSet() - fromIndex = input.readInt() - maxItems = input.readInt() - sortField = input.readOptionalString() - sortOrder = input.readOptionalWriteable(enumReader(SortOrder::class.java)) - filterParams = input.readMap(STRING_READER, STRING_READER) - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - override fun writeTo(output: StreamOutput) { - super.writeTo(output) - output.writeStringCollection(eventIds) - output.writeInt(fromIndex) - output.writeInt(maxItems) - output.writeOptionalString(sortField) - output.writeOptionalWriteable(sortOrder) - output.writeMap(filterParams, STRING_WRITER, STRING_WRITER) - } - - /** - * {@inheritDoc} - */ - override fun validate(): ActionRequestValidationException? { - var validationException: ActionRequestValidationException? = null - if (fromIndex < 0) { - validationException = ValidateActions.addValidationError("fromIndex is -ve", validationException) - } - if (maxItems <= 0) { - validationException = ValidateActions.addValidationError("maxItems is not +ve", validationException) - } - return validationException - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt deleted file mode 100644 index 176d95ea..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponse.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action - -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent -import org.opensearch.common.xcontent.XContentBuilder -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.model.NotificationEventSearchResult -import java.io.IOException - -/** - * Action Response for getting notification event. - */ -class GetNotificationEventResponse : BaseResponse { - val searchResult: NotificationEventSearchResult - - companion object { - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { GetNotificationEventResponse(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): GetNotificationEventResponse { - return GetNotificationEventResponse(NotificationEventSearchResult(parser)) - } - } - - /** - * constructor for creating the class - * @param searchResult the notification event list - */ - constructor(searchResult: NotificationEventSearchResult) { - this.searchResult = searchResult - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - constructor(input: StreamInput) : super(input) { - searchResult = NotificationEventSearchResult(input) - } - - /** - * {@inheritDoc} - */ - @Throws(IOException::class) - override fun writeTo(output: StreamOutput) { - searchResult.writeTo(output) - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - return searchResult.toXContent(builder, params) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt index 8b9b81b4..9437f376 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt index 681b943e..73db57a0 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -33,7 +11,7 @@ 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.commons.notifications.NotificationConstants.CONFIG_TYPE_LIST_TAG +import org.opensearch.commons.notifications.NotificationConstants.ALLOWED_CONFIG_TYPE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.PLUGIN_FEATURES_TAG import org.opensearch.commons.utils.STRING_READER import org.opensearch.commons.utils.STRING_WRITER @@ -45,7 +23,7 @@ import java.io.IOException * Action Response for getting notification plugin features. */ class GetPluginFeaturesResponse : BaseResponse { - val configTypeList: List + val allowedConfigTypeList: List val pluginFeatures: Map companion object { @@ -63,7 +41,7 @@ class GetPluginFeaturesResponse : BaseResponse { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): GetPluginFeaturesResponse { - var configTypeList: List? = null + var allowedConfigTypeList: List? = null var pluginFeatures: Map? = null XContentParserUtils.ensureExpectedToken( @@ -75,7 +53,7 @@ class GetPluginFeaturesResponse : BaseResponse { val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - CONFIG_TYPE_LIST_TAG -> configTypeList = parser.stringList() + ALLOWED_CONFIG_TYPE_LIST_TAG -> allowedConfigTypeList = parser.stringList() PLUGIN_FEATURES_TAG -> pluginFeatures = parser.mapStrings() else -> { parser.skipChildren() @@ -83,9 +61,9 @@ class GetPluginFeaturesResponse : BaseResponse { } } } - configTypeList ?: throw IllegalArgumentException("$CONFIG_TYPE_LIST_TAG field absent") + allowedConfigTypeList ?: throw IllegalArgumentException("$ALLOWED_CONFIG_TYPE_LIST_TAG field absent") pluginFeatures ?: throw IllegalArgumentException("$PLUGIN_FEATURES_TAG field absent") - return GetPluginFeaturesResponse(configTypeList, pluginFeatures) + return GetPluginFeaturesResponse(allowedConfigTypeList, pluginFeatures) } } @@ -94,18 +72,21 @@ class GetPluginFeaturesResponse : BaseResponse { */ override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { return builder!!.startObject() - .field(CONFIG_TYPE_LIST_TAG, configTypeList) + .field(ALLOWED_CONFIG_TYPE_LIST_TAG, allowedConfigTypeList) .field(PLUGIN_FEATURES_TAG, pluginFeatures) .endObject() } /** * constructor for creating the class - * @param configTypeList the list of config types supported by plugin + * @param allowedConfigTypeList the list of config types supported by plugin * @param pluginFeatures the map of plugin features supported to its value */ - constructor(configTypeList: List, pluginFeatures: Map) { - this.configTypeList = configTypeList + constructor( + allowedConfigTypeList: List, + pluginFeatures: Map + ) { + this.allowedConfigTypeList = allowedConfigTypeList this.pluginFeatures = pluginFeatures } @@ -114,7 +95,7 @@ class GetPluginFeaturesResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - configTypeList = input.readStringList() + allowedConfigTypeList = input.readStringList() pluginFeatures = input.readMap(STRING_READER, STRING_READER) } @@ -123,7 +104,7 @@ class GetPluginFeaturesResponse : BaseResponse { */ @Throws(IOException::class) override fun writeTo(output: StreamOutput) { - output.writeStringCollection(configTypeList) + output.writeStringCollection(allowedConfigTypeList) output.writeMap(pluginFeatures, STRING_WRITER, STRING_WRITER) } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt new file mode 100644 index 00000000..211e2076 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequest.kt @@ -0,0 +1,72 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.action + +import org.opensearch.action.ActionRequest +import org.opensearch.action.ActionRequestValidationException +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.commons.destination.message.LegacyBaseMessage +import org.opensearch.commons.destination.message.LegacyChimeMessage +import org.opensearch.commons.destination.message.LegacyCustomWebhookMessage +import org.opensearch.commons.destination.message.LegacyDestinationType +import org.opensearch.commons.destination.message.LegacyEmailMessage +import org.opensearch.commons.destination.message.LegacySlackMessage +import java.io.IOException + +/** + * Action Request to publish notification. This is a legacy implementation. + * This should not be used going forward, instead use [SendNotificationRequest]. + */ +class LegacyPublishNotificationRequest : ActionRequest { + val baseMessage: LegacyBaseMessage + + companion object { + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { LegacyPublishNotificationRequest(it) } + } + + /** + * constructor for creating the class + * @param baseMessage the base message to send + */ + constructor( + baseMessage: LegacyBaseMessage + ) { + this.baseMessage = baseMessage + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + constructor(input: StreamInput) : super(input) { + baseMessage = when (requireNotNull(input.readEnum(LegacyDestinationType::class.java)) { "Destination type cannot be null" }) { + LegacyDestinationType.LEGACY_CHIME -> LegacyChimeMessage(input) + LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK -> LegacyCustomWebhookMessage(input) + LegacyDestinationType.LEGACY_SLACK -> LegacySlackMessage(input) + LegacyDestinationType.LEGACY_EMAIL -> LegacyEmailMessage(input) + } + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + override fun writeTo(output: StreamOutput) { + super.writeTo(output) + output.writeEnum(baseMessage.channelType) + baseMessage.writeTo(output) + } + + /** + * {@inheritDoc} + */ + override fun validate(): ActionRequestValidationException? = null +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt new file mode 100644 index 00000000..f7311da2 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponse.kt @@ -0,0 +1,57 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.action + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.commons.destination.response.LegacyDestinationResponse +import java.io.IOException + +/** + * Action Response for legacy publish notification. + */ +class LegacyPublishNotificationResponse : BaseResponse { + val destinationResponse: LegacyDestinationResponse + + companion object { + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { LegacyPublishNotificationResponse(it) } + } + + /** + * constructor for creating the class + * @param destinationResponse the response of the published notification + */ + constructor(destinationResponse: LegacyDestinationResponse) { + this.destinationResponse = destinationResponse + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + constructor(input: StreamInput) : super(input) { + destinationResponse = LegacyDestinationResponse(input) + } + + /** + * {@inheritDoc} + */ + @Throws(IOException::class) + override fun writeTo(output: StreamOutput) { + destinationResponse.writeTo(output) + } + + // This class is only used across transport wire and does not need to implement toXContent + override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { + throw IllegalStateException("Legacy notification response is not intended for REST or persistence and does not support XContent.") + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt index fe7457d0..e4a8cfe5 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/NotificationsActions.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -52,11 +30,6 @@ object NotificationsActions { */ const val GET_NOTIFICATION_CONFIG_NAME = "cluster:admin/opensearch/notifications/configs/get" - /** - * Get notification events transport action name. - */ - const val GET_NOTIFICATION_EVENT_NAME = "cluster:admin/opensearch/notifications/events/get" - /** * Get notification plugin features transport action name. */ @@ -65,13 +38,19 @@ object NotificationsActions { /** * Get Config List for feature. Internal only - Inter plugin communication. */ - const val GET_FEATURE_CHANNEL_LIST_NAME = "cluster:admin/opensearch/notifications/feature/channels/get" + const val GET_CHANNEL_LIST_NAME = "cluster:admin/opensearch/notifications/channels/get" /** * Send notification message. Internal only - Inter plugin communication. */ const val SEND_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/send" + /** + * Publish legacy notification message. Internal only - Inter plugin communication. + * Only for the Alerting and Index Management plugins. + */ + const val LEGACY_PUBLISH_NOTIFICATION_NAME = "cluster:admin/opensearch/notifications/feature/publish" + /** * Create notification configuration transport action type. */ @@ -96,12 +75,6 @@ object NotificationsActions { val GET_NOTIFICATION_CONFIG_ACTION_TYPE = ActionType(GET_NOTIFICATION_CONFIG_NAME, ::GetNotificationConfigResponse) - /** - * Get notification events transport action type. - */ - val GET_NOTIFICATION_EVENT_ACTION_TYPE = - ActionType(GET_NOTIFICATION_EVENT_NAME, ::GetNotificationEventResponse) - /** * Get notification plugin features transport action type. */ @@ -109,14 +82,21 @@ object NotificationsActions { ActionType(GET_PLUGIN_FEATURES_NAME, ::GetPluginFeaturesResponse) /** - * Get Config List for feature transport action type. + * Get notification channel List transport action type. */ - val GET_FEATURE_CHANNEL_LIST_ACTION_TYPE = - ActionType(GET_FEATURE_CHANNEL_LIST_NAME, ::GetFeatureChannelListResponse) + val GET_CHANNEL_LIST_ACTION_TYPE = + ActionType(GET_CHANNEL_LIST_NAME, ::GetChannelListResponse) /** * Send notification transport action type. Internal only - Inter plugin communication. */ val SEND_NOTIFICATION_ACTION_TYPE = ActionType(SEND_NOTIFICATION_NAME, ::SendNotificationResponse) + + /** + * Send legacy notification transport action type. Internal only - Inter plugin communication. + * Only for the Alerting and Index Management plugins. + */ + val LEGACY_PUBLISH_NOTIFICATION_ACTION_TYPE = + ActionType(LEGACY_PUBLISH_NOTIFICATION_NAME, ::LegacyPublishNotificationResponse) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt index 9943ed57..9f4d3159 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt index 38338fc5..8967bdd9 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -32,19 +10,16 @@ import org.opensearch.common.io.stream.Writeable 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.commons.notifications.NotificationConstants.EVENT_ID_TAG -import org.opensearch.commons.utils.logger +import org.opensearch.commons.notifications.model.NotificationEvent import java.io.IOException /** * Action Response for send notification. */ class SendNotificationResponse : BaseResponse { - val notificationId: String + val notificationEvent: NotificationEvent companion object { - private val log by logger(SendNotificationResponse::class.java) /** * reader to create instance of class from writable. @@ -58,35 +33,16 @@ class SendNotificationResponse : BaseResponse { @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): SendNotificationResponse { - var notificationId: String? = null - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_TAG -> notificationId = parser.text() - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing SendNotificationResponse") - } - } - } - notificationId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") - return SendNotificationResponse(notificationId) + return SendNotificationResponse(NotificationEvent.parse(parser)) } } /** * constructor for creating the class - * @param configId the id of the created notification configuration + * @param notificationEvent the id of the created notification configuration */ - constructor(configId: String) { - this.notificationId = configId + constructor(notificationEvent: NotificationEvent) { + this.notificationEvent = notificationEvent } /** @@ -94,7 +50,7 @@ class SendNotificationResponse : BaseResponse { */ @Throws(IOException::class) constructor(input: StreamInput) : super(input) { - notificationId = input.readString() + notificationEvent = NotificationEvent(input) } /** @@ -102,16 +58,13 @@ class SendNotificationResponse : BaseResponse { */ @Throws(IOException::class) override fun writeTo(output: StreamOutput) { - output.writeString(notificationId) + notificationEvent.writeTo(output) } /** * {@inheritDoc} */ override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(EVENT_ID_TAG, notificationId) - .endObject() + return notificationEvent.toXContent(builder, params) } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt index dcba7b71..765533be 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequest.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt index 0e15a69b..7de2e58c 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponse.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt index 282781f0..7768273d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Attachment.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt index a766d3e0..1b8e59bf 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseConfigData.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt index bdc13931..056fcc6e 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/BaseModel.kt @@ -1,35 +1,13 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model import org.opensearch.common.io.stream.Writeable -import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.ToXContentObject /** * interface for representing objects. */ -interface BaseModel : Writeable, ToXContent +interface BaseModel : Writeable, ToXContentObject diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt similarity index 78% rename from src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt rename to src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt index a108d2ff..a235d974 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannel.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Channel.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -43,9 +21,9 @@ import org.opensearch.commons.utils.logger import java.io.IOException /** - * Data class representing Notification config for exposed for other plugins. + * Data class representing Notification config exposed for other plugins. */ -data class FeatureChannel( +data class Channel( val configId: String, val name: String, val description: String, @@ -59,12 +37,12 @@ data class FeatureChannel( } companion object { - private val log by logger(FeatureChannel::class.java) + private val log by logger(Channel::class.java) /** * reader to create instance of class from writable. */ - val reader = Writeable.Reader { FeatureChannel(it) } + val reader = Writeable.Reader { Channel(it) } /** * Creator used in REST communication. @@ -73,7 +51,7 @@ data class FeatureChannel( @Suppress("ComplexMethod") @JvmStatic @Throws(IOException::class) - fun parse(parser: XContentParser): FeatureChannel { + fun parse(parser: XContentParser): Channel { var configId: String? = null var name: String? = null var description = "" @@ -96,14 +74,14 @@ data class FeatureChannel( IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing FeatureChannel") + log.info("Unexpected field: $fieldName, while parsing Channel") } } } configId ?: throw IllegalArgumentException("$CONFIG_ID_TAG field absent") name ?: throw IllegalArgumentException("$NAME_TAG field absent") configType ?: throw IllegalArgumentException("$CONFIG_TYPE_TAG field absent") - return FeatureChannel( + return Channel( configId, name, description, diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt new file mode 100644 index 00000000..7cb25c3a --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelList.kt @@ -0,0 +1,71 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.model + +import org.apache.lucene.search.TotalHits +import org.opensearch.action.search.SearchResponse +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.xcontent.XContentParser +import org.opensearch.commons.notifications.NotificationConstants.CHANNEL_LIST_TAG + +/** + * Channel search results + */ +class ChannelList : SearchResults { + + /** + * single item result constructor + */ + constructor(objectItem: Channel) : super(CHANNEL_LIST_TAG, objectItem) + + /** + * multiple items result constructor + */ + constructor(objectList: List) : this( + 0, + objectList.size.toLong(), + TotalHits.Relation.EQUAL_TO, + objectList + ) + + /** + * all param constructor + */ + constructor( + startIndex: Long, + totalHits: Long, + totalHitRelation: TotalHits.Relation, + objectList: List + ) : super(startIndex, totalHits, totalHitRelation, CHANNEL_LIST_TAG, objectList) + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : super(input, Channel.reader) + + /** + * Construct object from XContentParser + */ + constructor(parser: XContentParser) : super(parser, CHANNEL_LIST_TAG) + + /** + * Construct object from SearchResponse + */ + constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( + from, + response, + searchHitParser, + CHANNEL_LIST_TAG + ) + + /** + * {@inheritDoc} + */ + override fun parseItem(parser: XContentParser): Channel { + return Channel.parse(parser) + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt index 5f70efa7..18a65d39 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ChannelMessage.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt index 2ffb0fd0..f39a3f7a 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt index 0dbe70a6..e9888e2b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/ConfigType.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -57,6 +35,16 @@ enum class ConfigType(val tag: String) { return tag } }, + SNS("sns") { + override fun toString(): String { + return tag + } + }, + SES_ACCOUNT("ses_account") { + override fun toString(): String { + return tag + } + }, SMTP_ACCOUNT("smtp_account") { override fun toString(): String { return tag diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt index e824242b..41009ba7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/DeliveryStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt index c8da0f85..07c055d6 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Email.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -38,8 +16,8 @@ import org.opensearch.commons.notifications.NotificationConstants.EMAIL_ACCOUNT_ import org.opensearch.commons.notifications.NotificationConstants.EMAIL_GROUP_ID_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_LIST_TAG import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.objectList import org.opensearch.commons.utils.stringList -import org.opensearch.commons.utils.validateEmail import java.io.IOException /** @@ -47,15 +25,12 @@ import java.io.IOException */ data class Email( val emailAccountID: String, - val recipients: List, + val recipients: List, val emailGroupIds: List ) : BaseConfigData { init { require(!Strings.isNullOrEmpty(emailAccountID)) { "emailAccountID is null or empty" } - recipients.forEach { - validateEmail(it) - } } companion object { @@ -79,7 +54,7 @@ data class Email( @Throws(IOException::class) fun parse(parser: XContentParser): Email { var emailAccountID: String? = null - var recipients: List = listOf() + var recipients: List = listOf() var emailGroupIds: List = listOf() XContentParserUtils.ensureExpectedToken( @@ -92,7 +67,7 @@ data class Email( parser.nextToken() when (fieldName) { EMAIL_ACCOUNT_ID_TAG -> emailAccountID = parser.text() - RECIPIENT_LIST_TAG -> recipients = parser.stringList() + RECIPIENT_LIST_TAG -> recipients = parser.objectList { EmailRecipient.parse(it) } EMAIL_GROUP_ID_LIST_TAG -> emailGroupIds = parser.stringList() else -> { parser.skipChildren() @@ -111,7 +86,7 @@ data class Email( */ constructor(input: StreamInput) : this( emailAccountID = input.readString(), - recipients = input.readStringList(), + recipients = input.readList(EmailRecipient.reader), emailGroupIds = input.readStringList() ) @@ -120,7 +95,7 @@ data class Email( */ override fun writeTo(output: StreamOutput) { output.writeString(emailAccountID) - output.writeStringCollection(recipients) + output.writeList(recipients) output.writeStringCollection(emailGroupIds) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt index f3beecd8..c286b66e 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailGroup.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -35,23 +13,16 @@ import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.RECIPIENT_LIST_TAG import org.opensearch.commons.utils.logger -import org.opensearch.commons.utils.stringList -import org.opensearch.commons.utils.validateEmail +import org.opensearch.commons.utils.objectList import java.io.IOException /** * Data class representing Email group. */ data class EmailGroup( - val recipients: List + val recipients: List ) : BaseConfigData { - init { - recipients.forEach { - validateEmail(it) - } - } - companion object { private val log by logger(EmailGroup::class.java) @@ -72,7 +43,7 @@ data class EmailGroup( @JvmStatic @Throws(IOException::class) fun parse(parser: XContentParser): EmailGroup { - var recipients: List? = null + var recipients: List? = null XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -83,7 +54,7 @@ data class EmailGroup( val fieldName = parser.currentName() parser.nextToken() when (fieldName) { - RECIPIENT_LIST_TAG -> recipients = parser.stringList() + RECIPIENT_LIST_TAG -> recipients = parser.objectList { EmailRecipient.parse(it) } else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing EmailGroup") @@ -100,14 +71,14 @@ data class EmailGroup( * @param input StreamInput stream to deserialize data from. */ constructor(input: StreamInput) : this( - recipients = input.readStringList() + recipients = input.readList(EmailRecipient.reader) ) /** * {@inheritDoc} */ override fun writeTo(output: StreamOutput) { - output.writeStringCollection(recipients) + output.writeList(recipients) } /** diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt new file mode 100644 index 00000000..aa523346 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipient.kt @@ -0,0 +1,97 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.commons.notifications.model + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +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.commons.notifications.NotificationConstants.RECIPIENT_TAG +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateEmail +import java.io.IOException + +/** + * Data class representing Email recipient. + */ +data class EmailRecipient( + val recipient: String +) : BaseConfigData { + + init { + validateEmail(recipient) + } + + companion object { + private val log by logger(EmailRecipient::class.java) + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { EmailRecipient(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + /** + * Creator used in REST communication. + * @param parser XContentParser to deserialize data from. + */ + @JvmStatic + @Throws(IOException::class) + fun parse(parser: XContentParser): EmailRecipient { + var recipient: String? = null + + XContentParserUtils.ensureExpectedToken( + XContentParser.Token.START_OBJECT, + parser.currentToken(), + parser + ) + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = parser.currentName() + parser.nextToken() + when (fieldName) { + RECIPIENT_TAG -> recipient = parser.text() + else -> { + parser.skipChildren() + log.info("Unexpected field: $fieldName, while parsing EmailRecipient") + } + } + } + recipient ?: throw IllegalArgumentException("$RECIPIENT_TAG field absent") + return EmailRecipient(recipient) + } + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + recipient = input.readString() + ) + + /** + * {@inheritDoc} + */ + override fun writeTo(output: StreamOutput) { + output.writeString(recipient) + } + + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + builder!! + return builder.startObject() + .field(RECIPIENT_TAG, recipient) + .endObject() + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt index a65224de..12774764 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt index caf86dcd..10bf04e3 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventSource.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -34,7 +12,6 @@ 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.commons.notifications.NotificationConstants.FEATURE_TAG import org.opensearch.commons.notifications.NotificationConstants.REFERENCE_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.SEVERITY_TAG import org.opensearch.commons.notifications.NotificationConstants.TAGS_TAG @@ -49,7 +26,6 @@ import java.io.IOException data class EventSource( val title: String, val referenceId: String, - val feature: Feature, val severity: SeverityType = SeverityType.INFO, val tags: List = listOf() ) : BaseModel { @@ -75,7 +51,6 @@ data class EventSource( fun parse(parser: XContentParser): EventSource { var title: String? = null var referenceId: String? = null - var feature: Feature? = null var severity: SeverityType = SeverityType.INFO var tags: List = emptyList() @@ -90,7 +65,6 @@ data class EventSource( when (fieldName) { TITLE_TAG -> title = parser.text() REFERENCE_ID_TAG -> referenceId = parser.text() - FEATURE_TAG -> feature = Feature.fromTagOrDefault(parser.text()) SEVERITY_TAG -> severity = SeverityType.fromTagOrDefault(parser.text()) TAGS_TAG -> tags = parser.stringList() else -> { @@ -101,12 +75,10 @@ data class EventSource( } title ?: throw IllegalArgumentException("$TITLE_TAG field absent") referenceId ?: throw IllegalArgumentException("$REFERENCE_ID_TAG field absent") - feature ?: throw IllegalArgumentException("$FEATURE_TAG field absent") return EventSource( title, referenceId, - feature, severity, tags ) @@ -121,7 +93,6 @@ data class EventSource( return builder.startObject() .field(TITLE_TAG, title) .field(REFERENCE_ID_TAG, referenceId) - .field(FEATURE_TAG, feature.tag) .field(SEVERITY_TAG, severity.tag) .field(TAGS_TAG, tags) .endObject() @@ -134,7 +105,6 @@ data class EventSource( constructor(input: StreamInput) : this( title = input.readString(), referenceId = input.readString(), - feature = input.readEnum(Feature::class.java), severity = input.readEnum(SeverityType::class.java), tags = input.readStringList() ) @@ -145,7 +115,6 @@ data class EventSource( override fun writeTo(output: StreamOutput) { output.writeString(title) output.writeString(referenceId) - output.writeEnum(feature) output.writeEnum(severity) output.writeStringCollection(tags) } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt index 1233a997..b322e401 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/EventStatus.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -64,6 +42,7 @@ data class EventStatus( ConfigType.WEBHOOK -> requireNotNull(deliveryStatus) ConfigType.SLACK -> requireNotNull(deliveryStatus) ConfigType.EMAIL -> require(emailRecipientStatus.isNotEmpty()) + ConfigType.SNS -> requireNotNull(deliveryStatus) ConfigType.NONE -> log.info("Some config field not recognized") else -> { log.info("non-allowed config type for Status") diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt deleted file mode 100644 index 84b37139..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Feature.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model - -import org.opensearch.commons.utils.EnumParser - -/** - * Features using notification plugin - */ -enum class Feature(val tag: String) { - NONE("none") { - override fun toString(): String { - return tag - } - }, - ALERTING("alerting") { - override fun toString(): String { - return tag - } - }, - INDEX_MANAGEMENT("index_management") { - override fun toString(): String { - return tag - } - }, - REPORTS("reports") { - override fun toString(): String { - return tag - } - }; - - companion object { - private val tagMap = values().associateBy { it.tag } - - val enumParser = EnumParser { fromTagOrDefault(it) } - - /** - * Get Feature from tag or NONE if not found - * @param tag the tag - * @return Feature corresponding to tag. NONE if invalid tag. - */ - fun fromTagOrDefault(tag: String): Feature { - return tagMap[tag] ?: NONE - } - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt deleted file mode 100644 index 6fc57b22..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/FeatureChannelList.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model - -import org.apache.lucene.search.TotalHits -import org.opensearch.action.search.SearchResponse -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_CONFIG_LIST_TAG - -/** - * FeatureChannel search results - */ -class FeatureChannelList : SearchResults { - - /** - * single item result constructor - */ - constructor(objectItem: FeatureChannel) : super(FEATURE_CONFIG_LIST_TAG, objectItem) - - /** - * multiple items result constructor - */ - constructor(objectList: List) : this( - 0, - objectList.size.toLong(), - TotalHits.Relation.EQUAL_TO, - objectList - ) - - /** - * all param constructor - */ - constructor( - startIndex: Long, - totalHits: Long, - totalHitRelation: TotalHits.Relation, - objectList: List - ) : super(startIndex, totalHits, totalHitRelation, FEATURE_CONFIG_LIST_TAG, objectList) - - /** - * Constructor used in transport action communication. - * @param input StreamInput stream to deserialize data from. - */ - constructor(input: StreamInput) : super(input, FeatureChannel.reader) - - /** - * Construct object from XContentParser - */ - constructor(parser: XContentParser) : super(parser, FEATURE_CONFIG_LIST_TAG) - - /** - * Construct object from SearchResponse - */ - constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( - from, - response, - searchHitParser, - FEATURE_CONFIG_LIST_TAG - ) - - /** - * {@inheritDoc} - */ - override fun parseItem(parser: XContentParser): FeatureChannel { - return FeatureChannel.parse(parser) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt new file mode 100644 index 00000000..8485e4fd --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/HttpMethodType.kt @@ -0,0 +1,36 @@ +package org.opensearch.commons.notifications.model + +import org.opensearch.commons.utils.EnumParser + +enum class HttpMethodType(val tag: String) { + POST("POST") { + override fun toString(): String { + return tag + } + }, + PUT("PUT") { + override fun toString(): String { + return tag + } + }, + PATCH("PATCH") { + override fun toString(): String { + return tag + } + }; + + companion object { + private val tagMap = values().associateBy { it.tag } + + val enumParser = EnumParser { fromTagOrDefault(it) } + + /** + * Get HttpMethodType from tag or POST if not found + * @param tag the tag + * @return MethodType corresponding to tag. POST if invalid tag. + */ + fun fromTagOrDefault(tag: String): HttpMethodType { + return tagMap[tag] ?: POST + } + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt index 30d72147..f490e8b1 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfig.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -36,17 +14,14 @@ import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TYPE_TAG import org.opensearch.commons.notifications.NotificationConstants.DESCRIPTION_TAG -import org.opensearch.commons.notifications.NotificationConstants.FEATURE_LIST_TAG import org.opensearch.commons.notifications.NotificationConstants.IS_ENABLED_TAG import org.opensearch.commons.notifications.NotificationConstants.NAME_TAG import org.opensearch.commons.notifications.model.config.ConfigDataProperties.createConfigData import org.opensearch.commons.notifications.model.config.ConfigDataProperties.getReaderForConfigType import org.opensearch.commons.notifications.model.config.ConfigDataProperties.validateConfigData -import org.opensearch.commons.utils.enumSet import org.opensearch.commons.utils.fieldIfNotNull import org.opensearch.commons.utils.logger import java.io.IOException -import java.util.EnumSet /** * Data class representing Notification config. @@ -55,7 +30,6 @@ data class NotificationConfig( val name: String, val description: String, val configType: ConfigType, - val features: EnumSet, val configData: BaseConfigData?, val isEnabled: Boolean = true ) : BaseModel { @@ -89,7 +63,6 @@ data class NotificationConfig( var name: String? = null var description = "" var configType: ConfigType? = null - var features: EnumSet? = null var isEnabled = true var configData: BaseConfigData? = null XContentParserUtils.ensureExpectedToken( @@ -104,7 +77,6 @@ data class NotificationConfig( NAME_TAG -> name = parser.text() DESCRIPTION_TAG -> description = parser.text() CONFIG_TYPE_TAG -> configType = ConfigType.fromTagOrDefault(parser.text()) - FEATURE_LIST_TAG -> features = parser.enumSet(Feature.enumParser) IS_ENABLED_TAG -> isEnabled = parser.booleanValue() else -> { val configTypeForTag = ConfigType.fromTagOrDefault(fieldName) @@ -119,12 +91,10 @@ data class NotificationConfig( } name ?: throw IllegalArgumentException("$NAME_TAG field absent") configType ?: throw IllegalArgumentException("$CONFIG_TYPE_TAG field absent") - features ?: throw IllegalArgumentException("$FEATURE_LIST_TAG field absent") return NotificationConfig( name, description, configType, - features, configData, isEnabled ) @@ -140,7 +110,6 @@ data class NotificationConfig( .field(NAME_TAG, name) .field(DESCRIPTION_TAG, description) .field(CONFIG_TYPE_TAG, configType.tag) - .field(FEATURE_LIST_TAG, features) .field(IS_ENABLED_TAG, isEnabled) .fieldIfNotNull(configType.tag, configData) .endObject() @@ -154,7 +123,6 @@ data class NotificationConfig( name = input.readString(), description = input.readString(), configType = input.readEnum(ConfigType::class.java), - features = input.readEnumSet(Feature::class.java), isEnabled = input.readBoolean(), configData = input.readOptionalWriteable(getReaderForConfigType(input.readEnum(ConfigType::class.java))) ) @@ -166,7 +134,6 @@ data class NotificationConfig( output.writeString(name) output.writeString(description) output.writeEnum(configType) - output.writeEnumSet(features) output.writeBoolean(isEnabled) // Reading config types multiple times in constructor output.writeEnum(configType) diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt index 7a949bbb..7867a2d2 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfo.kt @@ -1,29 +1,8 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. */ -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model import org.opensearch.common.Strings @@ -37,7 +16,6 @@ import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.CONFIG_ID_TAG import org.opensearch.commons.notifications.NotificationConstants.CONFIG_TAG import org.opensearch.commons.notifications.NotificationConstants.CREATED_TIME_TAG -import org.opensearch.commons.notifications.NotificationConstants.TENANT_TAG import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG import org.opensearch.commons.utils.logger import java.io.IOException @@ -50,7 +28,6 @@ data class NotificationConfigInfo( val configId: String, val lastUpdatedTime: Instant, val createdTime: Instant, - val tenant: String, val notificationConfig: NotificationConfig ) : BaseModel { @@ -76,7 +53,6 @@ data class NotificationConfigInfo( var configId: String? = null var lastUpdatedTime: Instant? = null var createdTime: Instant? = null - var tenant: String? = null var notificationConfig: NotificationConfig? = null XContentParserUtils.ensureExpectedToken( @@ -91,7 +67,6 @@ data class NotificationConfigInfo( CONFIG_ID_TAG -> configId = parser.text() UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - TENANT_TAG -> tenant = parser.text() CONFIG_TAG -> notificationConfig = NotificationConfig.parse(parser) else -> { parser.skipChildren() @@ -102,13 +77,11 @@ data class NotificationConfigInfo( configId ?: throw IllegalArgumentException("$CONFIG_ID_TAG field absent") lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - tenant = tenant ?: "" notificationConfig ?: throw IllegalArgumentException("$CONFIG_TAG field absent") return NotificationConfigInfo( configId, lastUpdatedTime, createdTime, - tenant, notificationConfig ) } @@ -122,7 +95,6 @@ data class NotificationConfigInfo( configId = input.readString(), lastUpdatedTime = input.readInstant(), createdTime = input.readInstant(), - tenant = input.readString(), notificationConfig = NotificationConfig.reader.read(input) ) @@ -133,7 +105,6 @@ data class NotificationConfigInfo( output.writeString(configId) output.writeInstant(lastUpdatedTime) output.writeInstant(createdTime) - output.writeString(tenant) notificationConfig.writeTo(output) } @@ -146,7 +117,6 @@ data class NotificationConfigInfo( .field(CONFIG_ID_TAG, configId) .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(TENANT_TAG, tenant) .field(CONFIG_TAG, notificationConfig) .endObject() } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt index 48952335..579a16cb 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResult.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt index c6bf6928..2ab5426b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEvent.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -30,9 +8,12 @@ import org.opensearch.common.io.stream.StreamInput import org.opensearch.common.io.stream.StreamOutput import org.opensearch.common.io.stream.Writeable import org.opensearch.common.xcontent.ToXContent +import org.opensearch.common.xcontent.ToXContent.EMPTY_PARAMS import org.opensearch.common.xcontent.XContentBuilder +import org.opensearch.common.xcontent.XContentHelper import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils +import org.opensearch.common.xcontent.XContentType import org.opensearch.commons.notifications.NotificationConstants.EVENT_SOURCE_TAG import org.opensearch.commons.notifications.NotificationConstants.STATUS_LIST_TAG import org.opensearch.commons.utils.logger @@ -124,4 +105,14 @@ data class NotificationEvent( .field(STATUS_LIST_TAG, statusList) .endObject() } + + // Overriding toString so consuming plugins can log/output this from the sendNotification response if needed + override fun toString(): String { + return try { + XContentHelper.toXContent(this, XContentType.JSON, EMPTY_PARAMS, true).utf8ToString() + } catch (e: IOException) { + log.debug("Failed to convert NotificationEvent to string", e) + super.toString() + " threw " + e.toString() + } + } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt deleted file mode 100644 index 27f9d0ad..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfo.kt +++ /dev/null @@ -1,153 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model - -import org.opensearch.common.Strings -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.io.stream.StreamOutput -import org.opensearch.common.io.stream.Writeable -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.commons.notifications.NotificationConstants.CREATED_TIME_TAG -import org.opensearch.commons.notifications.NotificationConstants.EVENT_ID_TAG -import org.opensearch.commons.notifications.NotificationConstants.EVENT_TAG -import org.opensearch.commons.notifications.NotificationConstants.TENANT_TAG -import org.opensearch.commons.notifications.NotificationConstants.UPDATED_TIME_TAG -import org.opensearch.commons.utils.logger -import java.io.IOException -import java.time.Instant - -/** - * Data class representing Notification event with information. - */ -data class NotificationEventInfo( - val eventId: String, - val lastUpdatedTime: Instant, - val createdTime: Instant, - val tenant: String, - val notificationEvent: NotificationEvent -) : BaseModel { - - init { - require(!Strings.isNullOrEmpty(eventId)) { "event id is null or empty" } - } - - companion object { - private val log by logger(NotificationEventInfo::class.java) - - /** - * reader to create instance of class from writable. - */ - val reader = Writeable.Reader { NotificationEventInfo(it) } - - /** - * Creator used in REST communication. - * @param parser XContentParser to deserialize data from. - */ - @JvmStatic - @Throws(IOException::class) - fun parse(parser: XContentParser): NotificationEventInfo { - var eventId: String? = null - var lastUpdatedTime: Instant? = null - var createdTime: Instant? = null - var tenant: String? = null - var notificationEvent: NotificationEvent? = null - - XContentParserUtils.ensureExpectedToken( - XContentParser.Token.START_OBJECT, - parser.currentToken(), - parser - ) - while (parser.nextToken() != XContentParser.Token.END_OBJECT) { - val fieldName = parser.currentName() - parser.nextToken() - when (fieldName) { - EVENT_ID_TAG -> eventId = parser.text() - UPDATED_TIME_TAG -> lastUpdatedTime = Instant.ofEpochMilli(parser.longValue()) - CREATED_TIME_TAG -> createdTime = Instant.ofEpochMilli(parser.longValue()) - TENANT_TAG -> tenant = parser.text() - EVENT_TAG -> notificationEvent = NotificationEvent.parse(parser) - else -> { - parser.skipChildren() - log.info("Unexpected field: $fieldName, while parsing event info") - } - } - } - eventId ?: throw IllegalArgumentException("$EVENT_ID_TAG field absent") - lastUpdatedTime ?: throw IllegalArgumentException("$UPDATED_TIME_TAG field absent") - createdTime ?: throw IllegalArgumentException("$CREATED_TIME_TAG field absent") - tenant = tenant ?: "" - notificationEvent ?: throw IllegalArgumentException("$EVENT_TAG field absent") - return NotificationEventInfo( - eventId, - lastUpdatedTime, - createdTime, - tenant, - notificationEvent - ) - } - } - - /** - * {@inheritDoc} - */ - override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { - builder!! - return builder.startObject() - .field(EVENT_ID_TAG, eventId) - .field(UPDATED_TIME_TAG, lastUpdatedTime.toEpochMilli()) - .field(CREATED_TIME_TAG, createdTime.toEpochMilli()) - .field(TENANT_TAG, tenant) - .field(EVENT_TAG, notificationEvent) - .endObject() - } - - /** - * Constructor used in transport action communication. - * @param input StreamInput stream to deserialize data from. - */ - constructor(input: StreamInput) : this( - eventId = input.readString(), - lastUpdatedTime = input.readInstant(), - createdTime = input.readInstant(), - tenant = input.readString(), - notificationEvent = NotificationEvent.reader.read(input) - ) - - /** - * {@inheritDoc} - */ - override fun writeTo(output: StreamOutput) { - output.writeString(eventId) - output.writeInstant(lastUpdatedTime) - output.writeInstant(createdTime) - output.writeString(tenant) - notificationEvent.writeTo(output) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt deleted file mode 100644 index 71ed1ba5..00000000 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResult.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model - -import org.apache.lucene.search.TotalHits -import org.opensearch.action.search.SearchResponse -import org.opensearch.common.io.stream.StreamInput -import org.opensearch.common.xcontent.XContentParser -import org.opensearch.commons.notifications.NotificationConstants.EVENT_LIST_TAG - -/** - * Notification Event search results - */ -class NotificationEventSearchResult : SearchResults { - - /** - * single item result constructor - */ - constructor(objectItem: NotificationEventInfo) : super(EVENT_LIST_TAG, objectItem) - - /** - * multiple items result constructor - */ - constructor(objectList: List) : this( - 0, - objectList.size.toLong(), - TotalHits.Relation.EQUAL_TO, - objectList - ) - - /** - * all param constructor - */ - constructor( - startIndex: Long, - totalHits: Long, - totalHitRelation: TotalHits.Relation, - objectList: List - ) : super(startIndex, totalHits, totalHitRelation, EVENT_LIST_TAG, objectList) - - /** - * Constructor used in transport action communication. - * @param input StreamInput stream to deserialize data from. - */ - constructor(input: StreamInput) : super(input, NotificationEventInfo.reader) - - /** - * Construct object from XContentParser - */ - constructor(parser: XContentParser) : super(parser, EVENT_LIST_TAG) - - /** - * Construct object from SearchResponse - */ - constructor(from: Long, response: SearchResponse, searchHitParser: SearchHitParser) : super( - from, - response, - searchHitParser, - EVENT_LIST_TAG - ) - - /** - * {@inheritDoc} - */ - override fun parseItem(parser: XContentParser): NotificationEventInfo { - return NotificationEventInfo.parse(parser) - } -} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt index 868cfebe..226f8d5d 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SearchResults.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt new file mode 100644 index 00000000..4aea8eb4 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SesAccount.kt @@ -0,0 +1,119 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.model + +import org.opensearch.common.Strings +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +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.commons.notifications.NotificationConstants.FROM_ADDRESS_TAG +import org.opensearch.commons.notifications.NotificationConstants.REGION_TAG +import org.opensearch.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.utils.fieldIfNotNull +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateEmail +import org.opensearch.commons.utils.validateIamRoleArn +import java.io.IOException + +/** + * Data class representing SES account channel. + */ +data class SesAccount( + val awsRegion: String, + val roleArn: String?, + val fromAddress: String +) : BaseConfigData { + + init { + require(!Strings.isNullOrEmpty(awsRegion)) { "awsRegion is null or empty" } + validateEmail(fromAddress) + if (roleArn != null) { + validateIamRoleArn(roleArn) + } + } + + companion object { + private val log by logger(SesAccount::class.java) + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { SesAccount(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + @JvmStatic + @Throws(IOException::class) + fun parse(parser: XContentParser): SesAccount { + var awsRegion: String? = null + var roleArn: String? = null + var fromAddress: String? = null + + XContentParserUtils.ensureExpectedToken( + XContentParser.Token.START_OBJECT, + parser.currentToken(), + parser + ) + while (parser.nextToken() != XContentParser.Token.END_OBJECT) { + val fieldName = parser.currentName() + parser.nextToken() + when (fieldName) { + REGION_TAG -> awsRegion = parser.text() + ROLE_ARN_TAG -> roleArn = parser.textOrNull() + FROM_ADDRESS_TAG -> fromAddress = parser.text() + else -> { + parser.skipChildren() + log.info("Unexpected field: $fieldName, while parsing SesAccount") + } + } + } + awsRegion ?: throw IllegalArgumentException("$REGION_TAG field absent") + fromAddress ?: throw IllegalArgumentException("$FROM_ADDRESS_TAG field absent") + return SesAccount( + awsRegion, + roleArn, + fromAddress + ) + } + } + + /** + * {@inheritDoc} + */ + override fun toXContent(builder: XContentBuilder?, params: ToXContent.Params?): XContentBuilder { + return builder!!.startObject() + .field(REGION_TAG, awsRegion) + .fieldIfNotNull(ROLE_ARN_TAG, roleArn) + .field(FROM_ADDRESS_TAG, fromAddress) + .endObject() + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + awsRegion = input.readString(), + roleArn = input.readOptionalString(), + fromAddress = input.readString() + ) + + /** + * {@inheritDoc} + */ + override fun writeTo(out: StreamOutput) { + out.writeString(awsRegion) + out.writeOptionalString(roleArn) + out.writeString(fromAddress) + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt index 6f84f07b..0fa8a427 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SeverityType.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt index e5d3c3f6..f022470b 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt index 21e2155e..6022a913 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/SmtpAccount.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt new file mode 100644 index 00000000..583aec49 --- /dev/null +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Sns.kt @@ -0,0 +1,96 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.model + +import org.opensearch.common.io.stream.StreamInput +import org.opensearch.common.io.stream.StreamOutput +import org.opensearch.common.io.stream.Writeable +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.commons.notifications.NotificationConstants.ROLE_ARN_TAG +import org.opensearch.commons.notifications.NotificationConstants.TOPIC_ARN_TAG +import org.opensearch.commons.utils.fieldIfNotNull +import org.opensearch.commons.utils.logger +import org.opensearch.commons.utils.validateIamRoleArn +import java.io.IOException +import java.util.regex.Pattern + +/** + * SNS notification data model + */ +data class Sns(val topicArn: String, val roleArn: String?) : BaseConfigData { + + init { + require(SNS_ARN_REGEX.matcher(topicArn).find()) { "Invalid AWS SNS topic ARN: $topicArn" } + if (roleArn != null) { + validateIamRoleArn(roleArn) + } + } + + override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder { + return builder.startObject() + .field(TOPIC_ARN_TAG, topicArn) + .fieldIfNotNull(ROLE_ARN_TAG, roleArn) + .endObject() + } + + /** + * Constructor used in transport action communication. + * @param input StreamInput stream to deserialize data from. + */ + constructor(input: StreamInput) : this( + topicArn = input.readString(), + roleArn = input.readOptionalString() + ) + + @Throws(IOException::class) + override fun writeTo(out: StreamOutput) { + out.writeString(topicArn) + out.writeOptionalString(roleArn) + } + + companion object { + private val log by logger(Sns::class.java) + + private val SNS_ARN_REGEX = + Pattern.compile("^arn:aws(-[^:]+)?:sns:([a-zA-Z0-9-]+):([0-9]{12}):([a-zA-Z0-9-_]+)$") + + /** + * reader to create instance of class from writable. + */ + val reader = Writeable.Reader { Sns(it) } + + /** + * Parser to parse xContent + */ + val xParser = XParser { parse(it) } + + @JvmStatic + @Throws(IOException::class) + fun parse(xcp: XContentParser): Sns { + var topicArn: String? = null + var roleArn: String? = 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) { + TOPIC_ARN_TAG -> topicArn = xcp.textOrNull() + ROLE_ARN_TAG -> roleArn = xcp.textOrNull() + else -> { + xcp.skipChildren() + log.info("Unexpected field: $fieldName, while parsing SNS destination") + } + } + } + topicArn ?: throw IllegalArgumentException("$TOPIC_ARN_TAG field absent") + return Sns(topicArn, roleArn) + } + } +} diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt index 55a4cb3e..710a9594 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -35,6 +13,7 @@ import org.opensearch.common.xcontent.XContentBuilder import org.opensearch.common.xcontent.XContentParser import org.opensearch.common.xcontent.XContentParserUtils import org.opensearch.commons.notifications.NotificationConstants.HEADER_PARAMS_TAG +import org.opensearch.commons.notifications.NotificationConstants.METHOD_TAG import org.opensearch.commons.notifications.NotificationConstants.URL_TAG import org.opensearch.commons.utils.STRING_READER import org.opensearch.commons.utils.STRING_WRITER @@ -47,7 +26,8 @@ import java.io.IOException */ data class Webhook( val url: String, - val headerParams: Map = mapOf() + val headerParams: Map = mapOf(), + val method: HttpMethodType = HttpMethodType.POST ) : BaseConfigData { init { @@ -77,6 +57,7 @@ data class Webhook( fun parse(parser: XContentParser): Webhook { var url: String? = null var headerParams: Map = mapOf() + var method = HttpMethodType.POST XContentParserUtils.ensureExpectedToken( XContentParser.Token.START_OBJECT, @@ -89,6 +70,7 @@ data class Webhook( when (fieldName) { URL_TAG -> url = parser.text() HEADER_PARAMS_TAG -> headerParams = parser.mapStrings() + METHOD_TAG -> method = HttpMethodType.fromTagOrDefault(parser.text()) else -> { parser.skipChildren() log.info("Unexpected field: $fieldName, while parsing Webhook destination") @@ -96,7 +78,7 @@ data class Webhook( } } url ?: throw IllegalArgumentException("$URL_TAG field absent") - return Webhook(url, headerParams) + return Webhook(url, headerParams, method) } } @@ -108,6 +90,7 @@ data class Webhook( return builder.startObject() .field(URL_TAG, url) .field(HEADER_PARAMS_TAG, headerParams) + .field(METHOD_TAG, method.tag) .endObject() } @@ -117,7 +100,8 @@ data class Webhook( */ constructor(input: StreamInput) : this( url = input.readString(), - headerParams = input.readMap(STRING_READER, STRING_READER) + headerParams = input.readMap(STRING_READER, STRING_READER), + method = input.readEnum(HttpMethodType::class.java) ) /** @@ -126,5 +110,6 @@ data class Webhook( override fun writeTo(output: StreamOutput) { output.writeString(url) output.writeMap(headerParams, STRING_WRITER, STRING_WRITER) + output.writeEnum(method) } } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt index 894b21a9..e019acd7 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/XParser.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt index 1500879c..7fb4327f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/config/ConfigDataProperties.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model.config @@ -33,8 +11,10 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.SesAccount import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount +import org.opensearch.commons.notifications.model.Sns import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.notifications.model.XParser @@ -53,6 +33,8 @@ internal object ConfigDataProperties { Pair(ConfigType.CHIME, ConfigProperty(Chime.reader, Chime.xParser)), Pair(ConfigType.WEBHOOK, ConfigProperty(Webhook.reader, Webhook.xParser)), Pair(ConfigType.EMAIL, ConfigProperty(Email.reader, Email.xParser)), + Pair(ConfigType.SNS, ConfigProperty(Sns.reader, Sns.xParser)), + Pair(ConfigType.SES_ACCOUNT, ConfigProperty(SesAccount.reader, SesAccount.xParser)), Pair(ConfigType.EMAIL_GROUP, ConfigProperty(EmailGroup.reader, EmailGroup.xParser)), Pair(ConfigType.SMTP_ACCOUNT, ConfigProperty(SmtpAccount.reader, SmtpAccount.xParser)) ) @@ -78,6 +60,8 @@ internal object ConfigDataProperties { ConfigType.EMAIL_GROUP -> configData is EmailGroup ConfigType.SMTP_ACCOUNT -> configData is SmtpAccount ConfigType.CHIME -> configData is Chime + ConfigType.SNS -> configData is Sns + ConfigType.SES_ACCOUNT -> configData is SesAccount ConfigType.NONE -> true } } diff --git a/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt index 3a18407e..39db7949 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/EnumHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt b/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt index 2a678f1f..b327d53c 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/EnumParser.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt b/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt index ae08c1d0..c31f0cab 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/Helpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt b/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt index ccbd1536..1549e2e5 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/OpenForTesting.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt b/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt index 45fa29bd..bc0f0596 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/SecureClientWrapper.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt index 4763a48a..049dabdc 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/TransportHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt index 93bcdc77..ab9f7409 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/ValidationHelpers.kt @@ -1,42 +1,18 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils import java.net.URL +import java.util.regex.Pattern // Valid ID characters = (All Base64 chars + "_-") to support UUID format and Base64 encoded IDs private val VALID_ID_CHARS: Set = (('a'..'z') + ('A'..'Z') + ('0'..'9') + '+' + '/' + '_' + '-').toSet() fun validateUrl(urlString: String) { require(isValidUrl(urlString)) { "Invalid URL or unsupported" } - val url = URL(urlString) - require("https" == url.protocol) // Support only HTTPS. HTTP and other protocols not supported - // TODO : Add hosts deny list } fun validateEmail(email: String) { @@ -49,8 +25,7 @@ fun validateId(idString: String) { fun isValidUrl(urlString: String): Boolean { val url = URL(urlString) // throws MalformedURLException if URL is invalid - // TODO : Add hosts deny list - return ("https" == url.protocol) // Support only HTTPS. HTTP and other protocols not supported + return ("https" == url.protocol || "http" == url.protocol) // Support only http/https, other protocols not supported } /** @@ -73,3 +48,8 @@ fun isValidEmail(email: String): Boolean { fun isValidId(idString: String): Boolean { return idString.isNotBlank() && idString.all { VALID_ID_CHARS.contains(it) } } + +fun validateIamRoleArn(roleArn: String) { + val roleArnRegex = Pattern.compile("^arn:aws(-[^:]+)?:iam::([0-9]{12}):([a-zA-Z_0-9+=,.@\\-_/]+)$") + require(roleArnRegex.matcher(roleArn).find()) { "Invalid AWS role ARN: $roleArn " } +} diff --git a/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt b/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt index 92dee033..e4af6007 100644 --- a/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt +++ b/src/main/kotlin/org/opensearch/commons/utils/XContentHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/test/java/org/opensearch/commons/InjectSecurityTest.java b/src/test/java/org/opensearch/commons/InjectSecurityTest.java index 0f6e0c83..818aa9c7 100644 --- a/src/test/java/org/opensearch/commons/InjectSecurityTest.java +++ b/src/test/java/org/opensearch/commons/InjectSecurityTest.java @@ -1,39 +1,21 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opensearch.commons.ConfigConstants.INJECTED_USER; import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_INJECTED_ROLES; import static org.opensearch.commons.ConfigConstants.OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS; import java.util.Arrays; +import java.util.HashMap; import org.junit.jupiter.api.Test; import org.opensearch.common.settings.Settings; @@ -102,4 +84,63 @@ public void testInjectUser() { assertEquals("plugin", threadContext.getTransient("ctx.name")); assertNull(threadContext.getTransient(INJECTED_USER)); } + + @Test + public void testInjectProperty() { + Settings settings = Settings.builder().put(OPENSEARCH_SECURITY_USE_INJECTED_USER_FOR_PLUGINS, false).build(); + Settings headerSettings = Settings.builder().put("request.headers.default", "1").build(); + ThreadContext threadContext = new ThreadContext(headerSettings); + threadContext.putHeader("name", "opendistro"); + threadContext.putTransient("ctx.name", "plugin"); + + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + + try (InjectSecurity helper = new InjectSecurity("test-name", settings, threadContext)) { + helper.inject("joe", Arrays.asList("ops-role", "logs-role")); + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + assertNotNull(threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + // cannot inject property that is already set + assertFalse(helper.injectProperty(OPENSEARCH_SECURITY_INJECTED_ROLES, "new value")); + assertEquals("plugin|ops-role,logs-role", threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + // cannot inject invalid property/value + assertFalse(helper.injectProperty("", "new value")); + assertFalse(helper.injectProperty(null, "new value")); + assertFalse(helper.injectProperty("property", null)); + // can inject non-set valid properties + assertTrue(helper.injectProperty("property1", true)); + assertTrue(helper.injectProperty("property2", "some value")); + assertTrue(helper.injectProperty("property3", "")); + assertTrue(helper.injectProperty("property4", new HashMap() { + { + put("key", "value"); + } + })); + // verify the set properties are not null and equal to what was set + assertNull(threadContext.getTransient("property")); + assertNotNull(threadContext.getTransient("property1")); + assertEquals(true, threadContext.getTransient("property1")); + assertNotNull(threadContext.getTransient("property2")); + assertEquals("some value", threadContext.getTransient("property2")); + assertNotNull(threadContext.getTransient("property3")); + assertEquals("", threadContext.getTransient("property3")); + assertNotNull(threadContext.getTransient("property4")); + assertEquals(new HashMap() { + { + put("key", "value"); + } + }, threadContext.getTransient("property4")); + } + assertEquals("1", threadContext.getHeader("default")); + assertEquals("opendistro", threadContext.getHeader("name")); + assertEquals("plugin", threadContext.getTransient("ctx.name")); + assertNull(threadContext.getTransient(OPENSEARCH_SECURITY_INJECTED_ROLES)); + assertNull(threadContext.getTransient("property1")); + assertNull(threadContext.getTransient("property2")); + assertNull(threadContext.getTransient("property3")); + assertNull(threadContext.getTransient("property4")); + } } diff --git a/src/test/java/org/opensearch/commons/authuser/UserTest.java b/src/test/java/org/opensearch/commons/authuser/UserTest.java index ca727e6d..4df30a44 100644 --- a/src/test/java/org/opensearch/commons/authuser/UserTest.java +++ b/src/test/java/org/opensearch/commons/authuser/UserTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.authuser; diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java new file mode 100644 index 00000000..191fef30 --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyChimeMessageTest.java @@ -0,0 +1,79 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyChimeMessageTest { + + @Test + public void testBuildingLegacyChimeMessage() { + LegacyChimeMessage message = new LegacyChimeMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_CHIME, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.url); + } + + @Test + public void testRoundTrippingLegacyChimeMessage() throws IOException { + LegacyChimeMessage message = new LegacyChimeMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyChimeMessage newMessage = new LegacyChimeMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.url, message.url); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyChimeMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy chime message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testUrlMissingMessage() { + try { + new LegacyChimeMessage.Builder("custom_webhook").withMessage("Hello world").build(); + fail("Building legacy chime message without url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("url is invalid or empty", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyChimeMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy chime message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java new file mode 100644 index 00000000..7443d060 --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyCustomWebhookMessageTest.java @@ -0,0 +1,156 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyCustomWebhookMessageTest { + + @Test + public void testBuildingLegacyCustomWebhookMessage() { + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_CUSTOM_WEBHOOK, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.getUrl()); + } + + @Test + public void testRoundTrippingLegacyCustomWebhookMessageWithUrl() throws IOException { + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyCustomWebhookMessage newMessage = new LegacyCustomWebhookMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.getUrl(), message.getUrl()); + } + + @Test + public void testRoundTrippingLegacyCustomWebhookMessageWithHostFails() throws IOException { + Map queryParams = new HashMap(); + queryParams.put("token", "sometoken"); + Map headers = new HashMap(); + headers.put("x-token", "sometoken"); + LegacyCustomWebhookMessage message = new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withHost("hooks.chime.aws") + .withPath("incomingwebhooks/abc") + .withMethod(HttpPost.METHOD_NAME) + .withQueryParams(queryParams) + .withHeaderParams(headers) + .withPort(8000) + .withScheme("https") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + try { + message.writeTo(out); + fail("Writing LegacyCustomWebhookMessage with host instead of url to stream output should fail"); + } catch (IllegalStateException e) { + assertEquals("Cannot use LegacyCustomWebhookMessage across transport wire without defining full url.", e.getMessage()); + } + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy custom webhook message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyCustomWebhookMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy custom webhook message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUnsupportedHttpMethods() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with unsupported http methods should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid method supplied. Only POST, PUT and PATCH are allowed", e.getMessage()); + } + } + + @Test + public void testURLandHostNameMissingOrEmpty() { + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook").withMessage("Hello world").withMethod(HttpGet.METHOD_NAME).build(); + fail("Building legacy custom webhook message missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withHost("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + + try { + new LegacyCustomWebhookMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("") + .withHost("") + .withMethod(HttpGet.METHOD_NAME) + .build(); + fail("Building legacy custom webhook message with missing or empty url and host name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Either fully qualified URL or host name should be provided", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java new file mode 100644 index 00000000..06625053 --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacyEmailMessageTest.java @@ -0,0 +1,295 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyEmailMessageTest { + + @Test + public void testBuildingLegacyEmailMessage() { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + + assertEquals("email", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_EMAIL, message.getChannelType()); + assertEquals("test_email", message.getAccountName()); + assertEquals("smtp.test.com", message.getHost()); + assertEquals(123, message.getPort()); + assertEquals("none", message.getMethod()); + assertEquals("test@email.com", message.getFrom()); + assertEquals(Arrays.asList("test2@email.com", "test3@email.com"), message.getRecipients()); + assertEquals("Test Subject", message.getSubject()); + assertEquals("Hello world", message.getMessage()); + } + + @Test + public void testRoundTrippingLegacyEmailMessage() throws IOException { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyEmailMessage newMessage = new LegacyEmailMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getAccountName(), message.getAccountName()); + assertEquals(newMessage.getHost(), message.getHost()); + assertEquals(newMessage.getPort(), message.getPort()); + assertEquals(newMessage.getMethod(), message.getMethod()); + assertEquals(newMessage.getFrom(), message.getFrom()); + assertEquals(newMessage.getRecipients(), message.getRecipients()); + assertEquals(newMessage.getSubject(), message.getSubject()); + assertEquals(newMessage.getMessage(), message.getMessage()); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .build(); + fail("Building legacy email message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacyEmailMessage.Builder(null) + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUnsupportedMethods() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("unsupported") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with unsupported method should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid method supplied. Only none, ssl and start_tls are allowed", e.getMessage()); + } + } + + @Test + public void testAccountNameMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing account name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Account name should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty account name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Account name should be provided", e.getMessage()); + } + } + + @Test + public void testHostMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing host should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Host name should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty host should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Host name should be provided", e.getMessage()); + } + } + + @Test + public void testFromMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing from should fail"); + } catch (IllegalArgumentException e) { + assertEquals("From address should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty from should fail"); + } catch (IllegalArgumentException e) { + assertEquals("From address should be provided", e.getMessage()); + } + } + + @Test + public void testRecipientsMissingOrEmpty() { + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with missing recipients should fail"); + } catch (IllegalArgumentException e) { + assertEquals("List of recipients should be provided", e.getMessage()); + } + + try { + new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(List.of()) + .withSubject("Test Subject") + .withMessage("Hello world") + .build(); + fail("Building legacy email message with empty recipients should fail"); + } catch (IllegalArgumentException e) { + assertEquals("List of recipients should be provided", e.getMessage()); + } + } + + @Test + public void testSubjectDefaultsToDestinationNameWhenMissingOrEmpty() { + LegacyEmailMessage message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withMessage("Hello world") + .build(); + + assertEquals("email", message.getSubject()); + + message = new LegacyEmailMessage.Builder("email") + .withAccountName("test_email") + .withHost("smtp.test.com") + .withPort(123) + .withMethod("none") + .withFrom("test@email.com") + .withRecipients(Arrays.asList("test2@email.com", "test3@email.com")) + .withSubject("") + .withMessage("Hello world") + .build(); + + assertEquals("email", message.getSubject()); + } +} diff --git a/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java new file mode 100644 index 00000000..6b04d651 --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/message/LegacySlackMessageTest.java @@ -0,0 +1,89 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacySlackMessageTest { + + @Test + public void testBuildingLegacySlackMessage() { + LegacySlackMessage message = new LegacySlackMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + + assertEquals("custom_webhook", message.destinationName); + assertEquals(LegacyDestinationType.LEGACY_SLACK, message.getChannelType()); + assertEquals("Hello world", message.getMessageContent()); + assertEquals("https://amazon.com", message.url); + } + + @Test + public void testRoundTrippingLegacySlackMessage() throws IOException { + LegacySlackMessage message = new LegacySlackMessage.Builder("custom_webhook") + .withMessage("Hello world") + .withUrl("https://amazon.com") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + message.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacySlackMessage newMessage = new LegacySlackMessage(in); + + assertEquals(newMessage.destinationName, message.destinationName); + assertEquals(newMessage.getChannelType(), message.getChannelType()); + assertEquals(newMessage.getMessageContent(), message.getMessageContent()); + assertEquals(newMessage.url, message.url); + } + + @Test + public void testContentMissingMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withUrl("https://amazon.com").build(); + fail("Building legacy slack message without message should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Message content is missing", e.getMessage()); + } + } + + @Test + public void testUrlMissingMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withMessage("Hello world").build(); + fail("Building legacy slack message without url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("url is invalid or empty", e.getMessage()); + } + } + + @Test + public void testMissingDestinationName() { + try { + new LegacySlackMessage.Builder(null).withMessage("Hello world").withUrl("https://amazon.com").build(); + fail("Building legacy slack message with null destination name should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Channel name must be defined", e.getMessage()); + } + } + + @Test + public void testUrlEmptyMessage() { + try { + new LegacySlackMessage.Builder("custom_webhook").withMessage("Hello world").withUrl("").build(); + fail("Building legacy slack message with empty url should fail"); + } catch (IllegalArgumentException e) { + assertEquals("Fully qualified URL is missing/invalid: ", e.getMessage()); + } + } +} diff --git a/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java new file mode 100644 index 00000000..e9189d24 --- /dev/null +++ b/src/test/java/org/opensearch/commons/destination/response/LegacyDestinationResponseTest.java @@ -0,0 +1,61 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.destination.response; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; + +public class LegacyDestinationResponseTest { + + @Test + public void testBuildingLegacyDestinationResponse() { + LegacyDestinationResponse res = new LegacyDestinationResponse.Builder() + .withStatusCode(200) + .withResponseContent("Hello world") + .build(); + + assertEquals(200, res.statusCode); + assertEquals("Hello world", res.getResponseContent()); + } + + @Test + public void testRoundTrippingLegacyDestinationResponse() throws IOException { + LegacyDestinationResponse res = new LegacyDestinationResponse.Builder() + .withStatusCode(200) + .withResponseContent("Hello world") + .build(); + BytesStreamOutput out = new BytesStreamOutput(); + res.writeTo(out); + + StreamInput in = StreamInput.wrap(out.bytes().toBytesRef().bytes); + LegacyDestinationResponse newRes = new LegacyDestinationResponse(in); + + assertEquals(res.statusCode, newRes.statusCode, "Round tripping doesn't work"); + assertEquals(res.getResponseContent(), newRes.getResponseContent(), "Round tripping doesn't work"); + } + + @Test + public void testMissingLegacyDestinationResponse() { + try { + new LegacyDestinationResponse.Builder().withStatusCode(200).build(); + fail("Creating LegacyDestinationResponse without response content should fail"); + } catch (IllegalArgumentException ignored) {} + } + + @Test + public void testMissingLegacyDestinationStatusCode() { + try { + new LegacyDestinationResponse.Builder().withResponseContent("Hello world").build(); + fail("Creating LegacyDestinationResponse without status code should fail"); + } catch (IllegalArgumentException ignored) {} + } +} diff --git a/src/test/java/org/opensearch/commons/rest/IntegrationTests.java b/src/test/java/org/opensearch/commons/rest/IntegrationTests.java index ee465086..0c6b7cfe 100644 --- a/src/test/java/org/opensearch/commons/rest/IntegrationTests.java +++ b/src/test/java/org/opensearch/commons/rest/IntegrationTests.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.rest; diff --git a/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java b/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java index 1fe5a51e..4a034f7e 100644 --- a/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java +++ b/src/test/java/org/opensearch/commons/rest/SecureRestClientBuilderTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.rest; diff --git a/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java b/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java index bea767d0..108a9e8d 100644 --- a/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java +++ b/src/test/java/org/opensearch/commons/rest/TrustStoreTest.java @@ -1,27 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 org.opensearch.commons.rest; diff --git a/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt new file mode 100644 index 00000000..61cbca7a --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/NotificationsPluginInterfaceTests.kt @@ -0,0 +1,242 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications + +import com.nhaarman.mockitokotlin2.whenever +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.Answers +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.mock +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.junit.jupiter.MockitoExtension +import org.opensearch.action.ActionListener +import org.opensearch.action.ActionType +import org.opensearch.client.node.NodeClient +import org.opensearch.commons.destination.response.LegacyDestinationResponse +import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest +import org.opensearch.commons.notifications.action.CreateNotificationConfigResponse +import org.opensearch.commons.notifications.action.DeleteNotificationConfigRequest +import org.opensearch.commons.notifications.action.DeleteNotificationConfigResponse +import org.opensearch.commons.notifications.action.GetChannelListRequest +import org.opensearch.commons.notifications.action.GetChannelListResponse +import org.opensearch.commons.notifications.action.GetNotificationConfigRequest +import org.opensearch.commons.notifications.action.GetNotificationConfigResponse +import org.opensearch.commons.notifications.action.GetPluginFeaturesRequest +import org.opensearch.commons.notifications.action.GetPluginFeaturesResponse +import org.opensearch.commons.notifications.action.LegacyPublishNotificationRequest +import org.opensearch.commons.notifications.action.LegacyPublishNotificationResponse +import org.opensearch.commons.notifications.action.SendNotificationResponse +import org.opensearch.commons.notifications.action.UpdateNotificationConfigRequest +import org.opensearch.commons.notifications.action.UpdateNotificationConfigResponse +import org.opensearch.commons.notifications.model.Channel +import org.opensearch.commons.notifications.model.ChannelList +import org.opensearch.commons.notifications.model.ChannelMessage +import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus +import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus +import org.opensearch.commons.notifications.model.NotificationConfig +import org.opensearch.commons.notifications.model.NotificationConfigInfo +import org.opensearch.commons.notifications.model.NotificationConfigSearchResult +import org.opensearch.commons.notifications.model.NotificationEvent +import org.opensearch.commons.notifications.model.SeverityType +import org.opensearch.commons.notifications.model.Slack +import org.opensearch.rest.RestStatus +import java.time.Instant + +@Suppress("UNCHECKED_CAST") +@ExtendWith(MockitoExtension::class) +internal class NotificationsPluginInterfaceTests { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private lateinit var client: NodeClient + + @Test + fun createNotificationConfig() { + val request = mock(CreateNotificationConfigRequest::class.java) + val response = CreateNotificationConfigResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.createNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun updateNotificationConfig() { + val request = mock(UpdateNotificationConfigRequest::class.java) + val response = UpdateNotificationConfigResponse("configId") + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.updateNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun deleteNotificationConfig() { + val request = mock(DeleteNotificationConfigRequest::class.java) + val response = DeleteNotificationConfigResponse(mapOf(Pair("sample_config_id", RestStatus.OK))) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.deleteNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getNotificationConfig() { + val request = mock(GetNotificationConfigRequest::class.java) + val response = mockGetNotificationConfigResponse() + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getNotificationConfig(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getPluginFeatures() { + val request = mock(GetPluginFeaturesRequest::class.java) + val response = GetPluginFeaturesResponse( + listOf("config_type_1", "config_type_2", "config_type_3"), + mapOf( + Pair("FeatureKey1", "FeatureValue1"), + Pair("FeatureKey2", "FeatureValue2"), + Pair("FeatureKey3", "FeatureValue3") + ) + ) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getPluginFeatures(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun getChannelList() { + val sampleConfig = Channel( + "config_id", + "name", + "description", + ConfigType.SLACK + ) + + val request = mock(GetChannelListRequest::class.java) + val response = GetChannelListResponse(ChannelList(sampleConfig)) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.getChannelList(client, request, listener) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun sendNotification() { + val notificationInfo = EventSource( + "title", + "reference_id", + SeverityType.HIGH, + listOf("tag1", "tag2") + ) + val channelMessage = ChannelMessage( + "text_description", + "htmlDescription", + null + ) + + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + + val sampleEvent = NotificationEvent(notificationInfo, listOf(sampleStatus)) + + val response = SendNotificationResponse(sampleEvent) + val listener: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(response) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.sendNotification( + client, notificationInfo, channelMessage, listOf("channelId1", "channelId2"), listener + ) + verify(listener, times(1)).onResponse(eq(response)) + } + + @Test + fun publishLegacyNotification() { + val request = mock(LegacyPublishNotificationRequest::class.java) + val res = LegacyPublishNotificationResponse(LegacyDestinationResponse.Builder().withStatusCode(200).withResponseContent("Nice!").build()) + val l: ActionListener = + mock(ActionListener::class.java) as ActionListener + + doAnswer { + (it.getArgument(2) as ActionListener) + .onResponse(res) + }.whenever(client).execute(any(ActionType::class.java), any(), any()) + + NotificationsPluginInterface.publishLegacyNotification(client, request, l) + verify(l, times(1)).onResponse(eq(res)) + } + + private fun mockGetNotificationConfigResponse(): GetNotificationConfigResponse { + val sampleSlack = Slack("https://domain.com/sample_url#1234567890") + val sampleConfig = NotificationConfig( + "name", + "description", + ConfigType.SLACK, + configData = sampleSlack + ) + val configInfo = NotificationConfigInfo( + "config_id", + Instant.now(), + Instant.now(), + sampleConfig + ) + return GetNotificationConfigResponse(NotificationConfigSearchResult(configInfo)) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt index 679ded46..24f389e2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -35,7 +13,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.Feature +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -44,7 +22,6 @@ import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class CreateNotificationConfigRequestTests { @@ -54,9 +31,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) } @@ -66,9 +42,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) } @@ -78,37 +53,34 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) } private fun createEmailGroupContentConfigObject(): NotificationConfig { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) return NotificationConfig( "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) } private fun createEmailContentConfigObject(): NotificationConfig { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) return NotificationConfig( "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) } @@ -123,9 +95,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) } @@ -286,9 +257,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -297,7 +267,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } @@ -314,9 +283,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ @@ -325,7 +293,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"webhook", - "feature_list":["index_management"], "is_enabled":true, "webhook":{"url":"https://domain.com/sample_webhook_url#1234567890"} } @@ -342,9 +309,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) val jsonString = """ @@ -354,7 +320,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"chime", - "feature_list":["index_management"], "is_enabled":true, "chime":{"url":"https://domain.com/sample_chime_url#1234567890"} } @@ -366,14 +331,13 @@ internal class CreateNotificationConfigRequestTests { @Test fun `Create config should deserialize json object using parser Email Group`() { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) val config = NotificationConfig( "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) val jsonString = """ @@ -383,9 +347,8 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"email_group", - "feature_list":["index_management"], "is_enabled":true, - "email_group":{"recipient_list":["dummy@company.com"]} + "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } } """.trimIndent() @@ -397,16 +360,15 @@ internal class CreateNotificationConfigRequestTests { fun `Update config should deserialize json object using parser Email`() { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) val config = NotificationConfig( "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) val jsonString = """ @@ -416,10 +378,12 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"email", - "feature_list":["index_management"], "is_enabled":true, - "email":{"email_account_id":"sample_1@dummy.com","recipient_list":["sample_2@dummy.com"], - "email_group_id_list":["sample_3@dummy.com"] } + "email":{ + "email_account_id":"sample_1@dummy.com", + "recipient_list":[{"recipient":"sample_2@dummy.com"}], + "email_group_id_list":["sample_3@dummy.com"] + } } } """.trimIndent() @@ -439,9 +403,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) val jsonString = """ @@ -451,7 +414,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"smtp_account", - "feature_list":["index_management"], "is_enabled":true, "smtp_account":{"host":"http://dummy.com", "port":11,"method": "ssl", "from_address": "sample@dummy.com" } } @@ -482,7 +444,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"chime", - "feature_list":["index_management"], "is_enabled":true, "chime":{"url":"https://domain.com/sample_chime_url#1234567890"} } @@ -507,9 +468,8 @@ internal class CreateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -518,7 +478,6 @@ internal class CreateNotificationConfigRequestTests { "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"}, "extra_field_1":["extra", "value"], diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt index b9f0f4e1..0f580fcd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/CreateNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt index 4c0c016d..c44d1458 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt index 5c479b47..fb574114 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/DeleteNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt new file mode 100644 index 00000000..aaa29e21 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListRequestTests.kt @@ -0,0 +1,60 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.commons.notifications.action + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class GetChannelListRequestTests { + + private fun assertGetRequestEquals( + expected: GetChannelListRequest, + actual: GetChannelListRequest + ) { + assertEquals(expected.compact, actual.compact) + } + + @Test + fun `Get request serialize and deserialize transport object should be equal`() { + val configRequest = GetChannelListRequest() + val recreatedObject = recreateObject(configRequest) { GetChannelListRequest(it) } + assertGetRequestEquals(configRequest, recreatedObject) + } + + @Test + fun `Get request serialize and deserialize using json object should be equal`() { + val configRequest = GetChannelListRequest() + val jsonString = getJsonString(configRequest) + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } + assertGetRequestEquals(configRequest, recreatedObject) + } + + @Test + fun `Get request should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows { + createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } + } + } + + @Test + fun `Get request should safely ignore extra field in json object`() { + val configRequest = GetChannelListRequest() + val jsonString = """ + { + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListRequest.parse(it) } + assertGetRequestEquals(configRequest, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt similarity index 66% rename from src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt index 149e966f..eb4023dd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetChannelListResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -30,18 +8,18 @@ import org.apache.lucene.search.TotalHits import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opensearch.commons.notifications.model.Channel +import org.opensearch.commons.notifications.model.ChannelList import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.FeatureChannel -import org.opensearch.commons.notifications.model.FeatureChannelList import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class GetFeatureChannelListResponseTests { +internal class GetChannelListResponseTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -52,112 +30,112 @@ internal class GetFeatureChannelListResponseTests { @Test fun `Get Response serialize and deserialize with config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val searchResult = FeatureChannelList(sampleConfig) - val getResponse = GetFeatureChannelListResponse(searchResult) - val recreatedObject = recreateObject(getResponse) { GetFeatureChannelListResponse(it) } + val searchResult = ChannelList(sampleConfig) + val getResponse = GetChannelListResponse(searchResult) + val recreatedObject = recreateObject(getResponse) { GetChannelListResponse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val getResponse = GetFeatureChannelListResponse(searchResult) - val recreatedObject = recreateObject(getResponse) { GetFeatureChannelListResponse(it) } + val getResponse = GetChannelListResponse(searchResult) + val recreatedObject = recreateObject(getResponse) { GetChannelListResponse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize using json config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL_GROUP ) - val searchResult = FeatureChannelList(sampleConfig) - val getResponse = GetFeatureChannelListResponse(searchResult) + val searchResult = ChannelList(sampleConfig) + val getResponse = GetChannelListResponse(searchResult) val jsonString = getJsonString(getResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response serialize and deserialize using json with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val getResponse = GetFeatureChannelListResponse(searchResult) + val getResponse = GetChannelListResponse(searchResult) val jsonString = getJsonString(getResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should use isEnabled=true if absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL, true ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -167,25 +145,25 @@ internal class GetFeatureChannelListResponseTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -199,22 +177,22 @@ internal class GetFeatureChannelListResponseTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test fun `Get Response should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -225,12 +203,12 @@ internal class GetFeatureChannelListResponseTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } assertSearchResultEquals(searchResult, recreatedObject.searchResult) } @Test - fun `Get Response should throw exception if featureChannelList is absent in json`() { + fun `Get Response should throw exception if channelList is absent in json`() { val jsonString = """ { "start_index":"0", @@ -239,7 +217,7 @@ internal class GetFeatureChannelListResponseTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetFeatureChannelListResponse.parse(it) } + createObjectFromJsonString(jsonString) { GetChannelListResponse.parse(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt deleted file mode 100644 index c9788a80..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetFeatureChannelListRequestTests.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action - -import com.fasterxml.jackson.core.JsonParseException -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.notifications.model.Feature -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject - -internal class GetFeatureChannelListRequestTests { - - private fun assertGetRequestEquals( - expected: GetFeatureChannelListRequest, - actual: GetFeatureChannelListRequest - ) { - assertEquals(expected.feature, actual.feature) - } - - @Test - fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetFeatureChannelListRequest(Feature.REPORTS) - val recreatedObject = recreateObject(configRequest) { GetFeatureChannelListRequest(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetFeatureChannelListRequest(Feature.INDEX_MANAGEMENT) - val jsonString = getJsonString(configRequest) - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request should throw exception when invalid json object is passed`() { - val jsonString = "sample message" - assertThrows { - createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } - } - } - - @Test - fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetFeatureChannelListRequest(Feature.ALERTING) - val jsonString = """ - { - "feature":"${configRequest.feature}", - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request should throw exception if feature field is absent in json object`() { - val jsonString = """ - { - } - """.trimIndent() - assertThrows { - createObjectFromJsonString(jsonString) { GetFeatureChannelListRequest.parse(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt index cf892209..8873202d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt index a2e14b40..3cfccfcb 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -32,7 +10,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult @@ -41,7 +18,6 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class GetNotificationConfigResponseTests { @@ -63,14 +39,12 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -85,28 +59,24 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -129,14 +99,12 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -154,28 +122,24 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( "config_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( "config_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -199,15 +163,13 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -221,12 +183,10 @@ internal class GetNotificationConfigResponseTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } @@ -250,15 +210,13 @@ internal class GetNotificationConfigResponseTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -269,12 +227,10 @@ internal class GetNotificationConfigResponseTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", "config_type":"slack", - "feature_list":["index_management"], "is_enabled":true, "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} } @@ -299,8 +255,7 @@ internal class GetNotificationConfigResponseTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt deleted file mode 100644 index 5e12d5f1..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventRequestTests.kt +++ /dev/null @@ -1,280 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action - -import com.fasterxml.jackson.core.JsonParseException -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import org.opensearch.search.sort.SortOrder - -internal class GetNotificationEventRequestTests { - - private fun assertGetRequestEquals( - expected: GetNotificationEventRequest, - actual: GetNotificationEventRequest - ) { - assertEquals(expected.eventIds, actual.eventIds) - assertEquals(expected.fromIndex, actual.fromIndex) - assertEquals(expected.maxItems, actual.maxItems) - assertEquals(expected.sortField, actual.sortField) - assertEquals(expected.sortOrder, actual.sortOrder) - assertEquals(expected.filterParams, actual.filterParams) - } - - @Test - fun `Get request serialize and deserialize transport object should be equal`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 0, - 10, - "sortField", - SortOrder.DESC, - mapOf(Pair("filterKey", "filterValue")) - ) - val recreatedObject = recreateObject(configRequest) { GetNotificationEventRequest(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request serialize and deserialize using json object should be equal`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 0, - 10, - "sortField", - SortOrder.ASC, - mapOf(Pair("filterKey", "filterValue")) - ) - val jsonString = getJsonString(configRequest) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with all field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest( - setOf("sample_event_id"), - 10, - 100, - "sortField", - SortOrder.DESC, - mapOf( - Pair("filterKey1", "filterValue1"), - Pair("filterKey2", "true"), - Pair("filterKey3", "filter,Value,3"), - Pair("filterKey4", "4") - ) - ) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"], - "from_index":"10", - "max_items":"100", - "sort_field":"sortField", - "sort_order":"desc", - "filter_param_list": { - "filterKey1":"filterValue1", - "filterKey2":"true", - "filterKey3":"filter,Value,3", - "filterKey4":"4" - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only event_id field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(eventIds = setOf("sample_event_id")) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only from_index field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(fromIndex = 20) - val jsonString = """ - { - "from_index":"20" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only max_items field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(maxItems = 100) - val jsonString = """ - { - "max_items":"100" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_field field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortField = "sample_sort_field") - val jsonString = """ - { - "sort_field":"sample_sort_field" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=asc field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.ASC) - val jsonString = """ - { - "sort_order":"asc" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=ASC field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.ASC) - val jsonString = """ - { - "sort_order":"ASC" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=desc field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.DESC) - val jsonString = """ - { - "sort_order":"desc" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with only sort_order=DESC field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest(sortOrder = SortOrder.DESC) - val jsonString = """ - { - "sort_order":"DESC" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request with invalid sort_order should throw exception`() { - val jsonString = """ - { - "sort_order":"descending" - } - """.trimIndent() - assertThrows { - createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - } - } - - @Test - fun `Get request with only filter_param_list field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest( - filterParams = mapOf( - Pair("filterKey1", "filterValue1"), - Pair("filterKey2", "true"), - Pair("filterKey3", "filter,Value,3"), - Pair("filterKey4", "4") - ) - ) - val jsonString = """ - { - "filter_param_list": { - "filterKey1":"filterValue1", - "filterKey2":"true", - "filterKey3":"filter,Value,3", - "filterKey4":"4" - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request no field should deserialize json object using parser`() { - val configRequest = GetNotificationEventRequest() - val jsonString = """ - { - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } - - @Test - fun `Get request should throw exception when invalid json object is passed`() { - val jsonString = "sample message" - assertThrows { - createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - } - } - - @Test - fun `Get request should safely ignore extra field in json object`() { - val configRequest = GetNotificationEventRequest(eventIds = setOf("sample_event_id")) - val jsonString = """ - { - "event_id_list":["${configRequest.eventIds.first()}"], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventRequest.parse(it) } - assertGetRequestEquals(configRequest, recreatedObject) - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt deleted file mode 100644 index 4f7d72d1..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetNotificationEventResponseTests.kt +++ /dev/null @@ -1,391 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action - -import org.apache.lucene.search.TotalHits -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.DeliveryStatus -import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.EventStatus -import org.opensearch.commons.notifications.model.Feature -import org.opensearch.commons.notifications.model.NotificationEvent -import org.opensearch.commons.notifications.model.NotificationEventInfo -import org.opensearch.commons.notifications.model.NotificationEventSearchResult -import org.opensearch.commons.notifications.model.SeverityType -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class GetNotificationEventResponseTests { - - private fun assertSearchResultEquals( - expected: NotificationEventSearchResult, - actual: NotificationEventSearchResult - ) { - assertEquals(expected.startIndex, actual.startIndex) - assertEquals(expected.totalHits, actual.totalHits) - assertEquals(expected.totalHitRelation, actual.totalHitRelation) - assertEquals(expected.objectListFieldName, actual.objectListFieldName) - assertEquals(expected.objectList, actual.objectList) - } - - @Test - fun `Search result serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - "tenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val searchResponse = GetNotificationEventResponse(searchResult) - val recreatedObject = recreateObject(searchResponse) { GetNotificationEventResponse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize with multiple event status object should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - Feature.REPORTS, - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val searchResponse = GetNotificationEventResponse(searchResult) - val recreatedObject = recreateObject(searchResponse) { GetNotificationEventResponse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val searchResponse = GetNotificationEventResponse(searchResult) - val jsonString = getJsonString(searchResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result serialize and deserialize using json with multiple event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - Feature.REPORTS, - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - NotificationEvent(eventSource2, listOf(status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2) - ) - val searchResponse = GetNotificationEventResponse(searchResult) - val jsonString = getJsonString(searchResponse) - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "selectedTenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "selectedTenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - assertSearchResultEquals(searchResult, recreatedObject.searchResult) - } - - @Test - fun `Search result should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" - } - ] - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { GetNotificationEventResponse.parse(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt index 3861fdd9..1c85ed70 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt index 3103825f..1aa065a2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/GetPluginFeaturesResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -39,7 +17,7 @@ internal class GetPluginFeaturesResponseTests { expected: GetPluginFeaturesResponse, actual: GetPluginFeaturesResponse ) { - assertEquals(expected.configTypeList, actual.configTypeList) + assertEquals(expected.allowedConfigTypeList, actual.allowedConfigTypeList) assertEquals(expected.pluginFeatures, actual.pluginFeatures) } @@ -84,7 +62,7 @@ internal class GetPluginFeaturesResponseTests { ) val jsonString = """ { - "config_type_list":["config_type_1", "config_type_2", "config_type_3"], + "allowed_config_type_list":["config_type_1", "config_type_2", "config_type_3"], "plugin_features":{ "FeatureKey1":"FeatureValue1", "FeatureKey2":"FeatureValue2", @@ -100,7 +78,7 @@ internal class GetPluginFeaturesResponseTests { } @Test - fun `Get Response should throw exception if config_type_list is absent in json`() { + fun `Get Response should throw exception if allowed_config_type_list is absent in json`() { val jsonString = """ { "plugin_features":{ diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt new file mode 100644 index 00000000..e4b990a5 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationRequestTests.kt @@ -0,0 +1,34 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.action + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Test +import org.opensearch.commons.destination.message.LegacyChimeMessage +import org.opensearch.commons.utils.recreateObject + +internal class LegacyPublishNotificationRequestTests { + + private fun assertRequestEquals( + expected: LegacyPublishNotificationRequest, + actual: LegacyPublishNotificationRequest + ) { + assertEquals(expected.baseMessage.channelName, actual.baseMessage.channelName) + assertEquals(expected.baseMessage.channelType, actual.baseMessage.channelType) + assertEquals(expected.baseMessage.messageContent, actual.baseMessage.messageContent) + assertEquals(expected.baseMessage.url, actual.baseMessage.url) + assertNull(actual.validate()) + } + + @Test + fun `publish request serialize and deserialize transport object should be equal`() { + val baseMessage = LegacyChimeMessage.Builder("chime_message").withMessage("Hello world").withUrl("https://amazon.com").build() + val request = LegacyPublishNotificationRequest(baseMessage) + val recreatedObject = recreateObject(request) { LegacyPublishNotificationRequest(it) } + assertRequestEquals(request, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt new file mode 100644 index 00000000..4a75a82e --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/LegacyPublishNotificationResponseTests.kt @@ -0,0 +1,23 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.action + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.opensearch.commons.destination.response.LegacyDestinationResponse +import org.opensearch.commons.utils.recreateObject + +internal class LegacyPublishNotificationResponseTests { + + @Test + fun `Create response serialize and deserialize transport object should be equal`() { + val res = LegacyDestinationResponse.Builder().withStatusCode(200).withResponseContent("Hello world").build() + val configResponse = LegacyPublishNotificationResponse(res) + val recreatedObject = recreateObject(configResponse) { LegacyPublishNotificationResponse(it) } + assertEquals(configResponse.destinationResponse.statusCode, recreatedObject.destinationResponse.statusCode) + assertEquals(configResponse.destinationResponse.responseContent, recreatedObject.destinationResponse.responseContent) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt index 9c8bd2b4..70e0bd6c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -34,7 +12,6 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.opensearch.commons.notifications.model.ChannelMessage import org.opensearch.commons.notifications.model.EventSource -import org.opensearch.commons.notifications.model.Feature import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -58,7 +35,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -82,7 +58,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.INDEX_MANAGEMENT, SeverityType.CRITICAL, listOf("tag1", "tag2") ) @@ -115,7 +90,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.ALERTING, SeverityType.HIGH, listOf("tag1", "tag2") ) @@ -135,7 +109,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"${notificationInfo.title}", "reference_id":"${notificationInfo.referenceId}", - "feature":"${notificationInfo.feature}", "severity":"${notificationInfo.severity}", "tags":["tag1", "tag2"] }, @@ -159,7 +132,6 @@ internal class SendNotificationRequestTests { val notificationInfo = EventSource( "title", "reference_id", - Feature.REPORTS, SeverityType.INFO, listOf("tag1", "tag2") ) @@ -179,7 +151,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"${notificationInfo.title}", "reference_id":"${notificationInfo.referenceId}", - "feature":"${notificationInfo.feature}", "severity":"${notificationInfo.severity}", "tags":["tag1", "tag2"] }, @@ -216,7 +187,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, @@ -235,7 +205,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, @@ -256,7 +225,6 @@ internal class SendNotificationRequestTests { "event_source":{ "title":"title", "reference_id":"reference_id", - "feature":"feature", "severity":"High", "tags":["tag1", "tag2"] }, diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt index 511c5760..4d828998 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/SendNotificationResponseTests.kt @@ -1,35 +1,19 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action import com.fasterxml.jackson.core.JsonParseException +import org.junit.Test import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.DeliveryStatus +import org.opensearch.commons.notifications.model.EventSource +import org.opensearch.commons.notifications.model.EventStatus +import org.opensearch.commons.notifications.model.NotificationEvent +import org.opensearch.commons.notifications.model.SeverityType import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject @@ -38,25 +22,29 @@ internal class SendNotificationResponseTests { @Test fun `Create response serialize and deserialize transport object should be equal`() { - val configResponse = SendNotificationResponse("sample_notification_id") - val recreatedObject = recreateObject(configResponse) { SendNotificationResponse(it) } - assertEquals(configResponse.notificationId, recreatedObject.notificationId) + + val sampleEvent = getSampleEvent() + + val recreatedObject = recreateObject(sampleEvent) { SendNotificationResponse(it) } + assertEquals(sampleEvent, recreatedObject) } @Test fun `Create response serialize and deserialize using json object should be equal`() { - val configResponse = SendNotificationResponse("sample_notification_id") - val jsonString = getJsonString(configResponse) + + val sampleEvent = getSampleEvent() + + val jsonString = getJsonString(sampleEvent) val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(configResponse.notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) } @Test fun `Create response should deserialize json object using parser`() { - val notificationId = "sample_notification_id" - val jsonString = "{\"event_id\":\"$notificationId\"}" + val sampleEvent = getSampleEvent() + val jsonString = "{\"event_id\":\"$sampleEvent\"}" val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) } @Test @@ -77,16 +65,32 @@ internal class SendNotificationResponseTests { @Test fun `Create response should safely ignore extra field in json object`() { - val notificationId = "sample_notification_id" + val sampleEvent = getSampleEvent() val jsonString = """ { - "event_id":"$notificationId", + "event_id":"$sampleEvent", "extra_field_1":["extra", "value"], "extra_field_2":{"extra":"value"}, "extra_field_3":"extra value 3" } """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { SendNotificationResponse.parse(it) } - assertEquals(notificationId, recreatedObject.notificationId) + assertEquals(sampleEvent, recreatedObject) + } + + private fun getSampleEvent(): NotificationEvent { + val sampleEventSource = EventSource( + "title", + "reference_id", + severity = SeverityType.INFO + ) + val sampleStatus = EventStatus( + "config_id", + "name", + ConfigType.SLACK, + deliveryStatus = DeliveryStatus("404", "invalid recipient") + ) + + return NotificationEvent(sampleEventSource, listOf(sampleStatus)) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt index 607e8077..a6e0077a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigRequestTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action @@ -35,7 +13,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup -import org.opensearch.commons.notifications.model.Feature +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack @@ -44,7 +22,6 @@ import org.opensearch.commons.notifications.model.Webhook import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class UpdateNotificationConfigRequestTests { @@ -54,9 +31,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) } @@ -66,9 +42,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) } @@ -78,37 +53,34 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) } private fun createEmailGroupContentConfigObject(): NotificationConfig { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) return NotificationConfig( "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) } private fun createEmailContentConfigObject(): NotificationConfig { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) return NotificationConfig( "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) } @@ -123,9 +95,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) } @@ -250,9 +221,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ @@ -280,9 +250,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ @@ -310,9 +279,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleChime + configData = sampleChime, + isEnabled = true ) val jsonString = """ @@ -335,14 +303,13 @@ internal class UpdateNotificationConfigRequestTests { @Test fun `Update config should deserialize json object using parser Email Group`() { - val sampleEmailGroup = EmailGroup(listOf("dummy@company.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("dummy@company.com"))) val config = NotificationConfig( "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmailGroup + configData = sampleEmailGroup, + isEnabled = true ) val jsonString = """ @@ -354,7 +321,7 @@ internal class UpdateNotificationConfigRequestTests { "config_type":"email_group", "feature_list":["index_management"], "is_enabled":true, - "email_group":{"recipient_list":["dummy@company.com"]} + "email_group":{"recipient_list":[{"recipient":"dummy@company.com"}]} } } """.trimIndent() @@ -367,16 +334,15 @@ internal class UpdateNotificationConfigRequestTests { fun `Update config should deserialize json object using parser Email`() { val sampleEmail = Email( emailAccountID = "sample_1@dummy.com", - recipients = listOf("sample_2@dummy.com"), + recipients = listOf(EmailRecipient("sample_2@dummy.com")), emailGroupIds = listOf("sample_3@dummy.com") ) val config = NotificationConfig( "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleEmail + configData = sampleEmail, + isEnabled = true ) val jsonString = """ @@ -388,8 +354,11 @@ internal class UpdateNotificationConfigRequestTests { "config_type":"email", "feature_list":["index_management"], "is_enabled":true, - "email":{"email_account_id":"sample_1@dummy.com","recipient_list":["sample_2@dummy.com"], - "email_group_id_list":["sample_3@dummy.com"] } + "email":{ + "email_account_id":"sample_1@dummy.com", + "recipient_list":[{"recipient":"sample_2@dummy.com"}], + "email_group_id_list":["sample_3@dummy.com"] + } } } """.trimIndent() @@ -410,9 +379,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSmtpAccount + configData = sampleSmtpAccount, + isEnabled = true ) val jsonString = """ @@ -448,9 +416,8 @@ internal class UpdateNotificationConfigRequestTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ diff --git a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt index aa2839c3..ca0b18cc 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/action/UpdateNotificationConfigResponseTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.action diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt index b0873cfe..5aa127fe 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/AttachmentTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt similarity index 59% rename from src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt index 5bd3db62..06387d37 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelListTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -34,11 +12,11 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class FeatureChannelListTests { +internal class ChannelListTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -49,129 +27,129 @@ internal class FeatureChannelListTests { @Test fun `Feature Channel List serialize and deserialize using transport should be equal`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val channelList = ChannelList(channel) + val recreatedObject = recreateObject(channelList) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize multiple object with default values should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList(listOf(featureChannel1, featureChannel2)) - val expectedResult = FeatureChannelList( + val channelList = ChannelList(listOf(channel1, channel2)) + val expectedResult = ChannelList( 0, 2, TotalHits.Relation.EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } + val recreatedObject = recreateObject(channelList) { ChannelList(it) } assertSearchResultEquals(expectedResult, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize with multiple object should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList( + val channelList = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val recreatedObject = recreateObject(featureChannelList) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = recreateObject(channelList) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize using json should be equal`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) - val jsonString = getJsonString(featureChannelList) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val channelList = ChannelList(channel) + val jsonString = getJsonString(channelList) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List serialize and deserialize using json with multiple object should be equal`() { - val featureChannel1 = FeatureChannel( + val channel1 = Channel( "configId1", "name1", "description1", ConfigType.SLACK, true ) - val featureChannel2 = FeatureChannel( + val channel2 = Channel( "configId2", "name2", "description2", ConfigType.CHIME, true ) - val featureChannelList = FeatureChannelList( + val channelList = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(featureChannel1, featureChannel2) + listOf(channel1, channel2) ) - val jsonString = getJsonString(featureChannelList) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val jsonString = getJsonString(channelList) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List should safely ignore extra field in json object`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) + val channelList = ChannelList(channel) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"configId", "name":"name", @@ -185,23 +163,23 @@ internal class FeatureChannelListTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test fun `Feature Channel List should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val featureChannel = FeatureChannel( + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val featureChannelList = FeatureChannelList(featureChannel) + val channelList = ChannelList(channel) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"configId", "name":"name", @@ -212,12 +190,12 @@ internal class FeatureChannelListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } - assertSearchResultEquals(featureChannelList, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } + assertSearchResultEquals(channelList, recreatedObject) } @Test - fun `Feature Channel List should throw exception if feature_channel_list is absent in json`() { + fun `Channel List should throw exception if channel_list is absent in json`() { val jsonString = """ { "start_index":"0", @@ -226,7 +204,7 @@ internal class FeatureChannelListTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + createObjectFromJsonString(jsonString) { ChannelList(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt index 7cda9d66..0a9f3f87 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelMessageTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt similarity index 57% rename from src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt rename to src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt index d2b8f009..3f64cc5a 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureChannelTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChannelTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -33,38 +11,38 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -internal class FeatureChannelTests { +internal class ChannelTests { @Test - fun `FeatureChannel Object serialize and deserialize using transport should be equal`() { - val featureChannel = FeatureChannel( + fun `Channel Object serialize and deserialize using transport should be equal`() { + val channel = Channel( "configId", "name", "description", ConfigType.SLACK, true ) - val recreatedObject = recreateObject(featureChannel) { FeatureChannel(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = recreateObject(channel) { Channel(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Object serialize and deserialize using json should be equal`() { - val featureChannel = FeatureChannel( + fun `Channel Object serialize and deserialize using json should be equal`() { + val channel = Channel( "configId", "name", "description", ConfigType.CHIME, false ) - val jsonString = getJsonString(featureChannel) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val jsonString = getJsonString(channel) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely ignore extra fields`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely ignore extra fields`() { + val channel = Channel( "configId", "name", "description", @@ -83,13 +61,13 @@ internal class FeatureChannelTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely ignore unknown config type`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely ignore unknown config type`() { + val channel = Channel( "configId", "name", "description", @@ -105,13 +83,13 @@ internal class FeatureChannelTests { "is_enabled":true } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely parse if description is absent`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely parse if description is absent`() { + val channel = Channel( "configId", "name", "", @@ -126,13 +104,13 @@ internal class FeatureChannelTests { "is_enabled":true } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should safely parse if is_enabled is absent`() { - val featureChannel = FeatureChannel( + fun `Channel Json parsing should safely parse if is_enabled is absent`() { + val channel = Channel( "configId", "name", "description", @@ -147,12 +125,12 @@ internal class FeatureChannelTests { "config_type":"slack" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } - assertEquals(featureChannel, recreatedObject) + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } + assertEquals(channel, recreatedObject) } @Test - fun `FeatureChannel Json parsing should throw exception if config_id is absent`() { + fun `Channel Json parsing should throw exception if config_id is absent`() { val jsonString = """ { "name":"name", @@ -162,12 +140,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if config_id is empty`() { + fun `Channel Json parsing should throw exception if config_id is empty`() { val jsonString = """ { "config_id":"", @@ -178,12 +156,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if name is absent`() { + fun `Channel Json parsing should throw exception if name is absent`() { val jsonString = """ { "config_id":"configId", @@ -193,12 +171,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if name is empty`() { + fun `Channel Json parsing should throw exception if name is empty`() { val jsonString = """ { "config_id":"configId", @@ -209,12 +187,12 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } @Test - fun `FeatureChannel Json parsing should throw exception if config_type is absent`() { + fun `Channel Json parsing should throw exception if config_type is absent`() { val jsonString = """ { "config_id":"configId", @@ -224,7 +202,7 @@ internal class FeatureChannelTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + createObjectFromJsonString(jsonString) { Channel.parse(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt index f70dc097..8e7f434e 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -89,11 +67,11 @@ internal class ChimeTests { } @Test - fun `Chime should throw exception when url protocol is not https`() { + fun `Chime should throw exception when url protocol is not https or http`() { assertThrows { - Chime("http://domain.com/sample_url#1234567890") + Chime("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Chime.parse(it) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt index 28b1ec7e..6be8d68b 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ConfigTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt index 377d2be9..33c42e99 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/DeliveryStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt index 5146d785..15ab3ade 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailGroupTests.kt @@ -1,35 +1,12 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -37,56 +14,26 @@ import org.opensearch.commons.utils.recreateObject internal class EmailGroupTests { - private fun checkValidEmailAddress(emailAddress: String) { - assertDoesNotThrow("should accept $emailAddress") { - EmailGroup(listOf(emailAddress)) - } - } - - private fun checkInvalidEmailAddress(emailAddress: String) { - assertThrows("Should throw an Exception for invalid email $emailAddress") { - EmailGroup(listOf(emailAddress)) - } - } - - @Test - fun `EmailGroup should accept valid email address`() { - checkValidEmailAddress("email1234@email.com") - checkValidEmailAddress("email+1234@email.com") - checkValidEmailAddress("email-1234@email.com") - checkValidEmailAddress("email_1234@email.com") - checkValidEmailAddress("email.1234@email.com") - checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") - checkValidEmailAddress("email-.+_=#|@domain.com") - checkValidEmailAddress("e@mail.com") - } - - @Test - fun `EmailGroup should throw exception for invalid email address`() { - checkInvalidEmailAddress("email") - checkInvalidEmailAddress("email@") - checkInvalidEmailAddress("email@1234@email.com") - checkInvalidEmailAddress(".email@email.com") - checkInvalidEmailAddress("email.@email.com") - checkInvalidEmailAddress("email..1234@email.com") - checkInvalidEmailAddress("email@email..com") - checkInvalidEmailAddress("email@.com") - checkInvalidEmailAddress("email@email.com.") - checkInvalidEmailAddress("email@.email.com") - checkInvalidEmailAddress("email@email.com-") - checkInvalidEmailAddress("email@email_domain.com") - } - @Test fun `EmailGroup serialize and deserialize transport object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val recreatedObject = recreateObject(sampleEmailGroup) { EmailGroup(it) } assertEquals(sampleEmailGroup, recreatedObject) } @Test fun `EmailGroup serialize and deserialize using json object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = getJsonString(sampleEmailGroup) val recreatedObject = createObjectFromJsonString(jsonString) { EmailGroup.parse(it) } assertEquals(sampleEmailGroup, recreatedObject) @@ -94,12 +41,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should deserialize json object using parser`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = """ { "recipient_list":[ - "${sampleEmailGroup.recipients[0]}", - "${sampleEmailGroup.recipients[1]}" + {"recipient":"${sampleEmailGroup.recipients[0].recipient}"}, + {"recipient":"${sampleEmailGroup.recipients[1].recipient}"} ] }" """.trimIndent() @@ -117,12 +69,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should throw exception when recipients is replaced with recipients2 in json object`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup( + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ) + ) val jsonString = """ { "recipient_list2":[ - "${sampleEmailGroup.recipients[0]}", - "${sampleEmailGroup.recipients[1]}" + {"recipient":"${sampleEmailGroup.recipients[0]}"}, + {"recipient":"${sampleEmailGroup.recipients[1]}"} ] }" """.trimIndent() @@ -133,8 +90,17 @@ internal class EmailGroupTests { @Test fun `EmailGroup should safely ignore extra field in json object`() { - val sampleEmailGroup = EmailGroup(listOf("email@email.com")) - val jsonString = "{\"recipient_list\":[\"${sampleEmailGroup.recipients[0]}\"], \"another\":\"field\"}" + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email1@email.com"))) + val jsonString = """ + { + "recipient_list":[ + {"recipient":"${sampleEmailGroup.recipients[0].recipient}"} + ], + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + }" + """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { EmailGroup.parse(it) } assertEquals(sampleEmailGroup, recreatedObject) } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt index 31bb80bd..c9bd89af 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt new file mode 100644 index 00000000..56a5f752 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailRecipientTests.kt @@ -0,0 +1,120 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class EmailRecipientTests { + + private fun checkValidEmailAddress(emailAddress: String) { + assertDoesNotThrow("should accept $emailAddress") { + EmailRecipient(emailAddress) + } + } + + private fun checkInvalidEmailAddress(emailAddress: String) { + assertThrows("Should throw an Exception for invalid email $emailAddress") { + EmailRecipient(emailAddress) + } + } + + @Test + fun `EmailRecipient should accept valid email address`() { + checkValidEmailAddress("email1234@email.com") + checkValidEmailAddress("email+1234@email.com") + checkValidEmailAddress("email-1234@email.com") + checkValidEmailAddress("email_1234@email.com") + checkValidEmailAddress("email.1234@email.com") + checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") + checkValidEmailAddress("email-.+_=#|@domain.com") + checkValidEmailAddress("e@mail.com") + } + + @Test + fun `EmailRecipient should throw exception for invalid email address`() { + checkInvalidEmailAddress("email") + checkInvalidEmailAddress("email@") + checkInvalidEmailAddress("email@1234@email.com") + checkInvalidEmailAddress(".email@email.com") + checkInvalidEmailAddress("email.@email.com") + checkInvalidEmailAddress("email..1234@email.com") + checkInvalidEmailAddress("email@email..com") + checkInvalidEmailAddress("email@.com") + checkInvalidEmailAddress("email@email.com.") + checkInvalidEmailAddress("email@.email.com") + checkInvalidEmailAddress("email@email.com-") + checkInvalidEmailAddress("email@email_domain.com") + } + + @Test + fun `EmailRecipient serialize and deserialize transport object should be equal`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val recreatedObject = recreateObject(sampleEmailRecipient) { EmailRecipient(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient serialize and deserialize using json object should be equal`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = getJsonString(sampleEmailRecipient) + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient should deserialize json object using parser`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = """ + { + "recipient": "${sampleEmailRecipient.recipient}" + }" + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } + + @Test + fun `EmailRecipient should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows { + createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + } + } + + @Test + fun `EmailRecipient should throw exception when recipients is replaced with recipients2 in json object`() { + val sampleEmailRecipient = EmailRecipient("email1@email.com") + val jsonString = """ + { + "recipient2": "${sampleEmailRecipient.recipient}" + }" + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + } + } + + @Test + fun `EmailRecipient should safely ignore extra field in json object`() { + val sampleEmailRecipient = EmailRecipient("email@email.com") + val jsonString = """ + { + "recipient": "${sampleEmailRecipient.recipient}", + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + }" + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { EmailRecipient.parse(it) } + assertEquals(sampleEmailRecipient, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt index 6590f08e..8624b138 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EmailTests.kt @@ -1,35 +1,12 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model import com.fasterxml.jackson.core.JsonParseException import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString @@ -37,51 +14,14 @@ import org.opensearch.commons.utils.recreateObject internal class EmailTests { - private fun checkValidEmailAddress(emailAddress: String) { - assertDoesNotThrow("should accept $emailAddress") { - Email("sampleId", listOf(emailAddress), listOf()) - } - } - - private fun checkInvalidEmailAddress(emailAddress: String) { - assertThrows("Should throw an Exception for invalid email $emailAddress") { - Email("sampleId", listOf(emailAddress), listOf()) - } - } - - @Test - fun `Email should accept valid email address`() { - checkValidEmailAddress("email1234@email.com") - checkValidEmailAddress("email+1234@email.com") - checkValidEmailAddress("email-1234@email.com") - checkValidEmailAddress("email_1234@email.com") - checkValidEmailAddress("email.1234@email.com") - checkValidEmailAddress("e.ma_il-1+2@test-email-domain.co.uk") - checkValidEmailAddress("email-.+_=#|@domain.com") - checkValidEmailAddress("e@mail.com") - } - - @Test - fun `Email should throw exception for invalid email address`() { - checkInvalidEmailAddress("email") - checkInvalidEmailAddress("email@") - checkInvalidEmailAddress("email@1234@email.com") - checkInvalidEmailAddress(".email@email.com") - checkInvalidEmailAddress("email.@email.com") - checkInvalidEmailAddress("email..1234@email.com") - checkInvalidEmailAddress("email@email..com") - checkInvalidEmailAddress("email@.com") - checkInvalidEmailAddress("email@email.com.") - checkInvalidEmailAddress("email@.email.com") - checkInvalidEmailAddress("email@email.com-") - checkInvalidEmailAddress("email@email_domain.com") - } - @Test fun `Email serialize and deserialize transport object should be equal`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val recreatedObject = recreateObject(sampleEmail) { Email(it) } @@ -92,7 +32,10 @@ internal class EmailTests { fun `Email serialize and deserialize using json object should be equal`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = getJsonString(sampleEmail) @@ -104,15 +47,18 @@ internal class EmailTests { fun `Email should deserialize json object using parser`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = """ { "email_account_id":"${sampleEmail.emailAccountID}", "recipient_list":[ - "${sampleEmail.recipients[0]}", - "${sampleEmail.recipients[1]}" + {"recipient":"${sampleEmail.recipients[0].recipient}"}, + {"recipient":"${sampleEmail.recipients[1].recipient}"} ], "email_group_id_list":[ "${sampleEmail.emailGroupIds[0]}", @@ -136,15 +82,18 @@ internal class EmailTests { fun `Email should throw exception when emailAccountID is replaced with emailAccountID2 in json object`() { val sampleEmail = Email( "sampleAccountId", - listOf("email1@email.com", "email2@email.com"), + listOf( + EmailRecipient("email1@email.com"), + EmailRecipient("email2@email.com") + ), listOf("sample_group_id_1", "sample_group_id_2") ) val jsonString = """ { "email_account_id2":"${sampleEmail.emailAccountID}", "recipient_list":[ - "${sampleEmail.recipients[0]}", - "${sampleEmail.recipients[1]}" + {"recipient":"${sampleEmail.recipients[0]}"}, + {"recipient":"${sampleEmail.recipients[1]}"} ], "email_group_id_list":[ "${sampleEmail.emailGroupIds[0]}", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt index 883c5047..b36a2fc0 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventSourceTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -40,7 +18,6 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, severity = SeverityType.INFO ) val recreatedObject = recreateObject(sampleEventSource) { EventSource(it) } @@ -52,7 +29,6 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, severity = SeverityType.INFO ) @@ -66,9 +42,8 @@ internal class EventSourceTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val jsonString = """ { @@ -87,13 +62,12 @@ internal class EventSourceTests { } @Test - fun `Event source should safely ignore unknown feature type in json object`() { + fun `Event source should safely accepts unknown feature type in json object`() { val sampleEventSource = EventSource( "title", "reference_id", - Feature.NONE, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val jsonString = """ { @@ -114,9 +88,8 @@ internal class EventSourceTests { EventSource( "", "reference_id", - Feature.ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt index e9a1634f..65173cfe 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/EventStatusTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt deleted file mode 100644 index 215c2c2c..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FeatureTests.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.notifications.model.Feature.Companion.enumParser -import org.opensearch.commons.notifications.model.Feature.Companion.fromTagOrDefault - -internal class FeatureTests { - - @Test - fun `toString should return tag`() { - Feature.values().forEach { - assertEquals(it.tag, it.toString()) - } - } - - @Test - fun `fromTagOrDefault should return corresponding enum`() { - Feature.values().forEach { - assertEquals(it, fromTagOrDefault(it.tag)) - } - } - - @Test - fun `EnumParser fromTagOrDefault should return corresponding enum`() { - Feature.values().forEach { - assertEquals(it, enumParser.fromTagOrDefault(it.tag)) - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt index f4ceee7f..de648bcd 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigListTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -37,8 +15,8 @@ import org.opensearch.commons.utils.recreateObject internal class FilterConfigListTests { private fun assertSearchResultEquals( - expected: FeatureChannelList, - actual: FeatureChannelList + expected: ChannelList, + actual: ChannelList ) { assertEquals(expected.startIndex, actual.startIndex) assertEquals(expected.totalHits, actual.totalHits) @@ -49,108 +27,108 @@ internal class FilterConfigListTests { @Test fun `Search result serialize and deserialize with config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val searchResult = FeatureChannelList(sampleConfig) - val recreatedObject = recreateObject(searchResult) { FeatureChannelList(it) } + val searchResult = ChannelList(sampleConfig) + val recreatedObject = recreateObject(searchResult) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) - val recreatedObject = recreateObject(searchResult) { FeatureChannelList(it) } + val recreatedObject = recreateObject(searchResult) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize using json config object should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL_GROUP ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result serialize and deserialize using json with multiple config object should be equal`() { - val sampleConfig1 = FeatureChannel( + val sampleConfig1 = Channel( "config_id1", "name1", "description1", ConfigType.SLACK ) - val sampleConfig2 = FeatureChannel( + val sampleConfig2 = Channel( "config_id2", "name2", "description2", ConfigType.CHIME ) - val sampleConfig3 = FeatureChannel( + val sampleConfig3 = Channel( "config_id3", "name3", "description3", ConfigType.WEBHOOK ) - val searchResult = FeatureChannelList( + val searchResult = ChannelList( 100, 1000, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, listOf(sampleConfig1, sampleConfig2, sampleConfig3) ) val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should use isEnabled=true if absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL, true ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -160,25 +138,25 @@ internal class FilterConfigListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { "start_index":"0", "total_hits":"1", "total_hit_relation":"eq", - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -192,22 +170,22 @@ internal class FilterConfigListTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.EMAIL ) - val searchResult = FeatureChannelList(sampleConfig) + val searchResult = ChannelList(sampleConfig) val jsonString = """ { - "feature_channel_list":[ + "channel_list":[ { "config_id":"config_id", "name":"name", @@ -218,12 +196,12 @@ internal class FilterConfigListTests { ] } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { ChannelList(it) } assertSearchResultEquals(searchResult, recreatedObject) } @Test - fun `Search result should throw exception if featureChannelList is absent in json`() { + fun `Search result should throw exception if channelList is absent in json`() { val jsonString = """ { "start_index":"0", @@ -232,7 +210,7 @@ internal class FilterConfigListTests { } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { FeatureChannelList(it) } + createObjectFromJsonString(jsonString) { ChannelList(it) } } } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt index b5dd66b6..c3557e89 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/FilterConfigTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -37,45 +15,45 @@ internal class FilterConfigTests { @Test fun `Config serialize and deserialize with default isEnabled flag should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.SLACK ) - val recreatedObject = recreateObject(sampleConfig) { FeatureChannel(it) } + val recreatedObject = recreateObject(sampleConfig) { Channel(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize with isEnabled=false should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.CHIME, false ) - val recreatedObject = recreateObject(sampleConfig) { FeatureChannel(it) } + val recreatedObject = recreateObject(sampleConfig) { Channel(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize using json object with default isEnabled flag should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", ConfigType.WEBHOOK ) val jsonString = getJsonString(sampleConfig) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config serialize and deserialize using json object with isEnabled=false should be equal`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -83,13 +61,13 @@ internal class FilterConfigTests { false ) val jsonString = getJsonString(sampleConfig) - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config should safely ignore extra field in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -107,13 +85,13 @@ internal class FilterConfigTests { "extra_field_3":"extra value 3" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config should safely ignore unknown config type in json object`() { - val sampleConfig = FeatureChannel( + val sampleConfig = Channel( "config_id", "name", "description", @@ -127,14 +105,14 @@ internal class FilterConfigTests { "config_type":"NewConfig" } """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { FeatureChannel.parse(it) } + val recreatedObject = createObjectFromJsonString(jsonString) { Channel.parse(it) } assertEquals(sampleConfig, recreatedObject) } @Test fun `Config throw exception if configId is empty`() { Assertions.assertThrows(IllegalArgumentException::class.java) { - FeatureChannel( + Channel( "", "name", "description", @@ -146,7 +124,7 @@ internal class FilterConfigTests { @Test fun `Config throw exception if name is empty`() { Assertions.assertThrows(IllegalArgumentException::class.java) { - FeatureChannel( + Channel( "config_id", "", "description", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt index 75685d53..f9982d7c 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/MethodTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt index 79c1035d..c4e28f33 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigInfoTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -33,7 +11,6 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class NotificationConfigInfoTests { @@ -44,14 +21,12 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val recreatedObject = recreateObject(configInfo) { NotificationConfigInfo(it) } @@ -67,14 +42,12 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val jsonString = getJsonString(configInfo) @@ -82,45 +55,6 @@ internal class NotificationConfigInfoTests { assertEquals(configInfo, recreatedObject) } - @Test - fun `Config info should take default tenant when field is absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") - val sampleConfig = NotificationConfig( - "name", - "description", - ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack - ) - val configInfo = NotificationConfigInfo( - "config-Id", - lastUpdatedTimeMs, - createdTimeMs, - "", // Default tenant - sampleConfig - ) - val jsonString = """ - { - "config_id":"config-Id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "config":{ - "name":"name", - "description":"description", - "config_type":"slack", - "feature_list":["index_management"], - "is_enabled":true, - "slack":{"url":"https://domain.com/sample_slack_url#1234567890"} - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationConfigInfo.parse(it) } - assertEquals(configInfo, recreatedObject) - } - @Test fun `Config info should safely ignore extra field in json object`() { val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) @@ -130,15 +64,13 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val jsonString = """ @@ -146,7 +78,6 @@ internal class NotificationConfigInfoTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -171,7 +102,6 @@ internal class NotificationConfigInfoTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) Assertions.assertThrows(IllegalArgumentException::class.java) { @@ -179,7 +109,6 @@ internal class NotificationConfigInfoTests { "", Instant.now(), Instant.now(), - "tenant", sampleConfig ) } @@ -193,7 +122,6 @@ internal class NotificationConfigInfoTests { { "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -217,7 +145,6 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -240,7 +167,6 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -264,8 +190,7 @@ internal class NotificationConfigInfoTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } """.trimIndent() Assertions.assertThrows(IllegalArgumentException::class.java) { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt index a9543533..06bb3557 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigSearchResultsTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -34,7 +12,6 @@ import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject import java.time.Instant -import java.util.EnumSet internal class NotificationConfigSearchResultsTests { @@ -56,14 +33,12 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( "config_id", Instant.now(), Instant.now(), - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -77,28 +52,24 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult(listOf(configInfo1, configInfo2)) @@ -118,28 +89,24 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( "config_id1", Instant.now(), Instant.now(), - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( "config_id2", Instant.now(), Instant.now(), - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -161,14 +128,12 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val configInfo = NotificationConfigInfo( "config_id", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -185,28 +150,24 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = Slack("https://domain.com/sample_url#1234567890") ) val configInfo1 = NotificationConfigInfo( "config_id1", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig1 ) val sampleConfig2 = NotificationConfig( "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = Chime("https://domain.com/sample_url#1234567890") ) val configInfo2 = NotificationConfigInfo( "config_id2", lastUpdatedTimeMs, createdTimeMs, - "tenant", sampleConfig2 ) val searchResult = NotificationConfigSearchResult( @@ -229,15 +190,13 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -251,7 +210,6 @@ internal class NotificationConfigSearchResultsTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -280,15 +238,13 @@ internal class NotificationConfigSearchResultsTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val configInfo = NotificationConfigInfo( "config-Id", lastUpdatedTimeMs, createdTimeMs, - "selectedTenant", sampleConfig ) val searchResult = NotificationConfigSearchResult(configInfo) @@ -299,7 +255,6 @@ internal class NotificationConfigSearchResultsTests { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", "config":{ "name":"name", "description":"description", @@ -329,8 +284,7 @@ internal class NotificationConfigSearchResultsTests { { "config_id":"config-Id", "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" + "created_time_ms":"${createdTimeMs.toEpochMilli()}" } ] } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt index ab45e2fc..f8aa9e9d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationConfigTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -31,7 +9,6 @@ import org.junit.jupiter.api.Test import org.opensearch.commons.utils.createObjectFromJsonString import org.opensearch.commons.utils.getJsonString import org.opensearch.commons.utils.recreateObject -import java.util.EnumSet internal class NotificationConfigTests { @@ -42,7 +19,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -56,7 +32,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SLACK, - EnumSet.of(Feature.REPORTS), configData = sampleSlack ) val jsonString = getJsonString(sampleConfig) @@ -71,7 +46,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.ALERTING), configData = sampleChime ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -85,7 +59,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.CHIME, - EnumSet.of(Feature.ALERTING), configData = sampleChime ) val jsonString = getJsonString(sampleConfig) @@ -100,7 +73,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = sampleWebhook ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -114,7 +86,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = sampleWebhook ) val jsonString = getJsonString(sampleConfig) @@ -124,12 +95,11 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with email object should be equal`() { - val sampleEmail = Email("id_1234567890", listOf("email@domain.com"), listOf("groupId")) + val sampleEmail = Email("id_1234567890", listOf(EmailRecipient("email@domain.com")), listOf("groupId")) val sampleConfig = NotificationConfig( "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = sampleEmail ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -138,12 +108,11 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with json email object should be equal`() { - val sampleEmail = Email("id_1234567890", listOf("email@domain.com"), listOf("groupId")) + val sampleEmail = Email("id_1234567890", listOf(EmailRecipient("email@domain.com")), listOf("groupId")) val sampleConfig = NotificationConfig( "name", "description", ConfigType.EMAIL, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = sampleEmail ) val jsonString = getJsonString(sampleConfig) @@ -158,7 +127,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = smtpAccount ) val jsonString = getJsonString(sampleConfig) @@ -173,7 +141,6 @@ internal class NotificationConfigTests { "name", "description", ConfigType.SMTP_ACCOUNT, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = sampleSmtpAccount ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -182,12 +149,11 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with json emailGroup object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email@domain.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email@domain.com"))) val sampleConfig = NotificationConfig( "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = sampleEmailGroup ) val jsonString = getJsonString(sampleConfig) @@ -197,12 +163,11 @@ internal class NotificationConfigTests { @Test fun `Config serialize and deserialize with emailGroup object should be equal`() { - val sampleEmailGroup = EmailGroup(listOf("email@domain.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email@domain.com"))) val sampleConfig = NotificationConfig( "name", "description", ConfigType.EMAIL_GROUP, - EnumSet.of(Feature.INDEX_MANAGEMENT), configData = sampleEmailGroup ) val recreatedObject = recreateObject(sampleConfig) { NotificationConfig(it) } @@ -217,9 +182,8 @@ internal class NotificationConfigTests { "name", "description", ConfigType.NONE, - EnumSet.of(Feature.INDEX_MANAGEMENT), - isEnabled = true, - configData = sampleSlack + configData = sampleSlack, + isEnabled = true ) val jsonString = """ { @@ -240,15 +204,14 @@ internal class NotificationConfigTests { } @Test - fun `Config should safely ignore unknown feature type in json object`() { + fun `Config should safely accepts unknown feature type in json object`() { val sampleWebhook = Webhook("https://domain.com/sample_webhook_url#1234567890") val sampleConfig = NotificationConfig( "name", "description", ConfigType.WEBHOOK, - EnumSet.of(Feature.INDEX_MANAGEMENT, Feature.NONE), - isEnabled = true, - configData = sampleWebhook + configData = sampleWebhook, + isEnabled = true ) val jsonString = """ { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt deleted file mode 100644 index e23ca1e0..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventInfoTests.kt +++ /dev/null @@ -1,364 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model - -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class NotificationEventInfoTests { - - @Test - fun `Event info serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - "tenant", - sampleEvent - ) - val recreatedObject = recreateObject(eventInfo) { NotificationEventInfo(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - val jsonString = getJsonString(eventInfo) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info should take default tenant when field is absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"tenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"tenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - }, - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - assertEquals(eventInfo, recreatedObject) - } - - @Test - fun `Event info should throw exception if event_id is empty`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "event_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - Assertions.assertThrows(IllegalArgumentException::class.java) { - NotificationEventInfo( - "", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - } - } - - @Test - fun `Event info should throw exception if event_id is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if lastUpdatedTimeMs is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "event_id":"event_id", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if createdTimeMs is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":["tag1", "tag2"] - }, - "status_list":[ - { - "event_id":"event_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } - - @Test - fun `Event info should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventInfo.parse(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt deleted file mode 100644 index d09fe9d2..00000000 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventSearchResultTests.kt +++ /dev/null @@ -1,445 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model - -import org.apache.lucene.search.TotalHits -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.opensearch.commons.utils.createObjectFromJsonString -import org.opensearch.commons.utils.getJsonString -import org.opensearch.commons.utils.recreateObject -import java.time.Instant - -internal class NotificationEventSearchResultTests { - - private fun assertSearchResultEquals( - expected: NotificationEventSearchResult, - actual: NotificationEventSearchResult - ) { - assertEquals(expected.startIndex, actual.startIndex) - assertEquals(expected.totalHits, actual.totalHits) - assertEquals(expected.totalHitRelation, actual.totalHitRelation) - assertEquals(expected.objectListFieldName, actual.objectListFieldName) - assertEquals(expected.objectList, actual.objectList) - } - - @Test - fun `Search result serialize and deserialize with event object should be equal`() { - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - Instant.now(), - Instant.now(), - "tenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize with multiple event default values should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - Feature.REPORTS, - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val expectedResult = NotificationEventSearchResult( - 0, - 4, - TotalHits.Relation.EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(expectedResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize with multiple event status object should be equal`() { - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - Feature.REPORTS, - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource2, listOf(status2)) - ) - val eventInfo3 = NotificationEventInfo( - "event_id3", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource1, listOf(status1, status2)) - ) - val eventInfo4 = NotificationEventInfo( - "event_id4", - Instant.now(), - Instant.now(), - "tenant", - NotificationEvent(eventSource2, listOf(status1, status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2, eventInfo3, eventInfo4) - ) - val recreatedObject = recreateObject(searchResult) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize using json event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result serialize and deserialize using json with multiple event object should be equal`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val eventSource1 = EventSource( - "title 1", - "reference_id_1", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val eventSource2 = EventSource( - "title 2", - "reference_id_2", - Feature.REPORTS, - severity = SeverityType.HIGH - ) - val status1 = EventStatus( - "config_id1", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val status2 = EventStatus( - "config_id2", - "name", - ConfigType.CHIME, - deliveryStatus = DeliveryStatus("404", "invalid recipient") - ) - val eventInfo1 = NotificationEventInfo( - "event_id1", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - NotificationEvent(eventSource1, listOf(status1)) - ) - val eventInfo2 = NotificationEventInfo( - "event_id2", - lastUpdatedTimeMs, - createdTimeMs, - "tenant", - NotificationEvent(eventSource2, listOf(status2)) - ) - val searchResult = NotificationEventSearchResult( - 100, - 1000, - TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO, - listOf(eventInfo1, eventInfo2) - ) - val jsonString = getJsonString(searchResult) - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should safely ignore extra field in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "selectedTenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ], - "extra_field_1":["extra", "value"], - "extra_field_2":{"extra":"value"}, - "extra_field_3":"extra value 3" - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should safely fallback to default if startIndex, totalHits or totalHitRelation field absent in json object`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val sampleEventSource = EventSource( - "title", - "reference_id", - Feature.ALERTING, - severity = SeverityType.INFO - ) - val sampleStatus = EventStatus( - "config_id", - "name", - ConfigType.SLACK, - deliveryStatus = DeliveryStatus("200", "success") - ) - val sampleEvent = NotificationEvent(sampleEventSource, listOf(sampleStatus)) - val eventInfo = NotificationEventInfo( - "event_id", - lastUpdatedTimeMs, - createdTimeMs, - "selectedTenant", - sampleEvent - ) - val searchResult = NotificationEventSearchResult(eventInfo) - val jsonString = """ - { - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant", - "event":{ - "event_source":{ - "title":"title", - "reference_id":"reference_id", - "feature":"alerting", - "severity":"info", - "tags":[] - }, - "status_list":[ - { - "config_id":"config_id", - "config_type":"slack", - "config_name":"name", - "delivery_status": - { - "status_code":"200", - "status_text":"success" - } - } - ] - } - } - ] - } - """.trimIndent() - val recreatedObject = createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - assertSearchResultEquals(searchResult, recreatedObject) - } - - @Test - fun `Search result should throw exception if event is absent in json`() { - val lastUpdatedTimeMs = Instant.ofEpochMilli(Instant.now().toEpochMilli()) - val createdTimeMs = lastUpdatedTimeMs.minusSeconds(1000) - val jsonString = """ - { - "start_index":"0", - "total_hits":"1", - "total_hit_relation":"eq", - "event_list":[ - { - "event_id":"event_id", - "last_updated_time_ms":"${lastUpdatedTimeMs.toEpochMilli()}", - "created_time_ms":"${createdTimeMs.toEpochMilli()}", - "tenant":"selectedTenant" - } - ] - } - """.trimIndent() - Assertions.assertThrows(IllegalArgumentException::class.java) { - createObjectFromJsonString(jsonString) { NotificationEventSearchResult(it) } - } - } -} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt index 4a135d0c..57df6066 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/NotificationEventTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -40,7 +18,6 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -59,7 +36,6 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.REPORTS, severity = SeverityType.INFO ) val sampleStatus = EventStatus( @@ -79,9 +55,8 @@ internal class NotificationEventTests { val sampleEventSource = EventSource( "title", "reference_id", - Feature.ALERTING, - tags = listOf("tag1", "tag2"), - severity = SeverityType.INFO + severity = SeverityType.INFO, + tags = listOf("tag1", "tag2") ) val status1 = EventStatus( "config_id1", diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt new file mode 100644 index 00000000..e5a52837 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SesAccountTests.kt @@ -0,0 +1,180 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class SesAccountTests { + + @Test + fun `SES should throw exception if empty region`() { + assertThrows { + SesAccount("", null, "from@domain.com") + } + val jsonString = """ + { + "region":"", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception if invalid role ARN`() { + assertThrows { + SesAccount("us-east-1", "arn:aws:iam:us-east-1:0123456789:role-test", "from@domain.com") + } + val jsonString = """ + { + "region":"us-east-1", + "role_arn":"arn:aws:iam:us-east-1:0123456789:role-test", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when email id is invalid`() { + val jsonString = """ + { + "region":"us-east-1", + "from_address":".from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES serialize and deserialize transport object should be equal`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val recreatedObject = recreateObject(sesAccount) { SesAccount(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES serialize and deserialize using json object should be equal`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = getJsonString(sesAccount) + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES serialize and deserialize using json object should be equal with null roleArn`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = getJsonString(sesAccount) + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should deserialize json object using parser`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":"${sesAccount.roleArn}", + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should deserialize json object will null role_arn using parser`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":null, + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should deserialize json object will missing role_arn using parser`() { + val sesAccount = SesAccount("us-east-1", null, "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "from_address":"${sesAccount.fromAddress}" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } + + @Test + fun `SES should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when region is replace with region2 in json object`() { + val jsonString = """ + { + "region2":"us-east-1", + "role_arn":"arn:aws:iam::012345678912:role/iam-test", + "from_address":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should throw exception when from_address is replace with from_address2 in json object`() { + val jsonString = """ + { + "region":"us-east-1", + "role_arn":"arn:aws:iam::012345678912:role/iam-test", + "from_address2":"from@domain.com" + } + """.trimIndent() + assertThrows { + createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + } + } + + @Test + fun `SES should safely ignore extra field in json object`() { + val sesAccount = SesAccount("us-east-1", "arn:aws:iam::012345678912:role/iam-test", "from@domain.com") + val jsonString = """ + { + "region":"${sesAccount.awsRegion}", + "role_arn":"${sesAccount.roleArn}", + "from_address":"${sesAccount.fromAddress}", + "extra_field_1":["extra", "value"], + "extra_field_2":{"extra":"value"}, + "extra_field_3":"extra value 3" + } + """.trimIndent() + val recreatedObject = createObjectFromJsonString(jsonString) { SesAccount.parse(it) } + assertEquals(sesAccount, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt index 71fe1460..35f7b218 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SeverityTypeTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt index b5bf7783..5c64c6ae 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -89,11 +67,11 @@ internal class SlackTests { } @Test - fun `Slack should throw exception when url protocol is not https`() { + fun `Slack should throw exception when url protocol is not https or http`() { assertThrows { - Slack("http://domain.com/sample_url#1234567890") + Slack("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Slack.parse(it) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt index bc924681..ffdf26c7 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SmtpAccountTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt new file mode 100644 index 00000000..494f09e9 --- /dev/null +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SnsTests.kt @@ -0,0 +1,99 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.commons.notifications.model + +import com.fasterxml.jackson.core.JsonParseException +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Assertions.assertThrows +import org.junit.jupiter.api.Test +import org.opensearch.commons.utils.createObjectFromJsonString +import org.opensearch.commons.utils.getJsonString +import org.opensearch.commons.utils.recreateObject + +internal class SnsTests { + + @Test + fun `SNS should throw exception if empty topic`() { + assertThrows(IllegalArgumentException::class.java) { + Sns("", null) + } + val jsonString = "{\"topic_arn\":\"\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { Sns.parse(it) } + } + } + + @Test + fun `SNS should throw exception if invalid topic ARN`() { + assertThrows(IllegalArgumentException::class.java) { + Sns("arn:aws:es:us-east-1:012345678989:test", null) + } + val jsonString = "{\"topic_arn\":\"arn:aws:es:us-east-1:012345678989:test\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { Sns.parse(it) } + } + } + + @Test + fun `SNS should throw exception if invalid role ARN`() { + assertThrows(IllegalArgumentException::class.java) { + Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam:us-east-1:0123456789:role-test") + } + val jsonString = + "{\"topic_arn\":\"arn:aws:sns:us-east-1:012345678912:topic-test\",\"role_arn\":\"arn:aws:iam:us-east-1:0123456789:role-test\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { Sns.parse(it) } + } + } + + @Test + fun `SNS serialize and deserialize transport object should be equal`() { + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val recreatedObject = recreateObject(sampleSns) { Sns(it) } + Assertions.assertEquals(sampleSns, recreatedObject) + } + + @Test + fun `SNS serialize and deserialize using json object should be equal`() { + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = getJsonString(sampleSns) + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) + } + + @Test + fun `SNS should deserialize json object using parser`() { + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn\":\"${sampleSns.topicArn}\",\"role_arn\":\"${sampleSns.roleArn}\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) + } + + @Test + fun `SNS should throw exception when invalid json object is passed`() { + val jsonString = "sample message" + assertThrows(JsonParseException::class.java) { + createObjectFromJsonString(jsonString) { Sns.parse(it) } + } + } + + @Test + fun `SNS should throw exception when arn is replace with arn2 in json object`() { + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", "arn:aws:iam::012345678912:role/iam-test") + val jsonString = "{\"topic_arn2\":\"${sampleSns.topicArn}\",\"role_arn\":\"${sampleSns.roleArn}\"}" + assertThrows(IllegalArgumentException::class.java) { + createObjectFromJsonString(jsonString) { Sns.parse(it) } + } + } + + @Test + fun `SNS should safely ignore extra field in json object`() { + val sampleSns = Sns("arn:aws:sns:us-east-1:012345678912:topic-test", null) + val jsonString = "{\"topic_arn\":\"${sampleSns.topicArn}\", \"another\":\"field\"}" + val recreatedObject = createObjectFromJsonString(jsonString) { Sns.parse(it) } + Assertions.assertEquals(sampleSns, recreatedObject) + } +} diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 9ca39c7c..3272203d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.notifications.model @@ -46,7 +24,11 @@ internal class WebhookTests { @Test fun `Webhook serialize and deserialize using json object should be equal`() { - val sampleWebhook = Webhook("https://domain.com/sample_url#1234567890", mapOf(Pair("key", "value"))) + val sampleWebhook = Webhook( + "http://domain.com/sample_url#1234567890", + mapOf(Pair("key", "value")), + HttpMethodType.PUT + ) val jsonString = getJsonString(sampleWebhook) val recreatedObject = createObjectFromJsonString(jsonString) { Webhook.parse(it) } assertEquals(sampleWebhook, recreatedObject) @@ -54,13 +36,18 @@ internal class WebhookTests { @Test fun `Webhook should deserialize json object using parser`() { - val sampleWebhook = Webhook("https://domain.com/sample_url#1234567890", mapOf(Pair("key", "value"))) + val sampleWebhook = Webhook( + "https://domain.com/sample_url#1234567890", + mapOf(Pair("key", "value")), + HttpMethodType.PATCH + ) val jsonString = """ { "url":"${sampleWebhook.url}", "header_params":{ "key":"value" - } + }, + "method":"PATCH" } """.trimIndent() val recreatedObject = createObjectFromJsonString(jsonString) { Webhook.parse(it) } @@ -96,11 +83,11 @@ internal class WebhookTests { } @Test - fun `Webhook should throw exception when url protocol is not https`() { + fun `Webhook should throw exception when url protocol is not https or http`() { assertThrows { - Webhook("http://domain.com/sample_url#1234567890") + Webhook("ftp://domain.com/sample_url#1234567890") } - val jsonString = "{\"url\":\"http://domain.com/sample_url\"}" + val jsonString = "{\"url\":\"ftp://domain.com/sample_url\"}" assertThrows { createObjectFromJsonString(jsonString) { Webhook.parse(it) } } diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt index 0217c53f..80a20b88 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/config/ConfigPropertiesTests.kt @@ -5,6 +5,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount @@ -72,7 +73,7 @@ internal class ConfigPropertiesTests { @Test fun `Validate config data parse EmailGroup`() { - val sampleEmailGroup = EmailGroup(listOf("email1@email.com", "email2@email.com")) + val sampleEmailGroup = EmailGroup(listOf(EmailRecipient("email1@email.com"), EmailRecipient("email2@email.com"))) val jsonString = getJsonString(sampleEmailGroup) val recreatedObject = createObjectFromJsonString(jsonString) { createConfigData(ConfigType.EMAIL_GROUP, it) } assertEquals(sampleEmailGroup, recreatedObject) diff --git a/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt b/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt index 35f5d3b9..81dc33e0 100644 --- a/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt +++ b/src/test/kotlin/org/opensearch/commons/utils/TestHelpers.kt @@ -1,28 +1,6 @@ /* + * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Copyright 2021 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 org.opensearch.commons.utils diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file