diff --git a/airbyte-api/src/main/openapi/config.yaml b/airbyte-api/src/main/openapi/config.yaml index c1cd8f8974b9..f6726d53895f 100644 --- a/airbyte-api/src/main/openapi/config.yaml +++ b/airbyte-api/src/main/openapi/config.yaml @@ -235,7 +235,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Notification" + $ref: "#/components/schemas/NotificationLegacy" required: true responses: "200": @@ -248,6 +248,50 @@ paths: $ref: "#/components/responses/NotFoundResponse" "422": $ref: "#/components/responses/InvalidInputResponse" + /v1/notifications/create: + post: + tags: + - notifications + summary: > + Create a new Notification + operationId: createNotification + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/NotificationCreate" + required: true + responses: + "200": + description: Successful operation + content: + application/json: + schema: + $ref: "#/components/schemas/NotificationRead" + "404": + $ref: "#/components/responses/NotFoundResponse" + /v1/notifications/add_connection: + post: + tags: + - notifications + summary: > + Create a link between a connection and a notification + operationId: createNotificationConnection + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/NotificationConnectionCreate" + required: true + responses: + "200": + description: Successful operation + content: + application/json: + schema: + $ref: "#/components/schemas/NotificationRead" + "404": + $ref: "#/components/responses/NotFoundResponse" /v1/source_definitions/create: post: tags: @@ -1940,10 +1984,61 @@ components: notifications: type: array items: - $ref: "#/components/schemas/Notification" + $ref: "#/components/schemas/NotificationLegacy" displaySetupWizard: type: boolean - Notification: + NotificationCreate: + type: object + required: + - workspaceId + - name + - webhookUrl + - notificationType + properties: + workspaceId: + type: string + format: uuid + name: + type: string + webhookUrl: + type: string + defaultNotification: + type: boolean + default: false + notificationType: + $ref: "#/components/schemas/NotificationType" + tombstone: + type: boolean + default: false + NotificationConnectionCreate: + type: object + required: + - workspaceId + - notificationId + - connectionId + - sendOnSuccess + - sendOnFailure + - tombstone + properties: + workspaceId: + type: string + format: uuid + notificationId: + type: string + format: uuid + connectionId: + type: string + format: uuid + sendOnSuccess: + type: boolean + default: false + sendOnFailure: + type: boolean + default: true + tombstone: + type: boolean + default: false + NotificationLegacy: type: object required: - notificationType @@ -2036,7 +2131,7 @@ components: notifications: type: array items: - $ref: "#/components/schemas/Notification" + $ref: "#/components/schemas/NotificationLegacy" firstCompletedSync: type: boolean feedbackDone: @@ -2078,7 +2173,7 @@ components: notifications: type: array items: - $ref: "#/components/schemas/Notification" + $ref: "#/components/schemas/NotificationLegacy" WorkspaceGiveFeedback: type: object required: diff --git a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderAppTest.java b/airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderAppTest.java index 3ac59ea7f411..5230bcebe050 100644 --- a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderAppTest.java +++ b/airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderAppTest.java @@ -72,7 +72,7 @@ void testBootloaderAppBlankDb() throws Exception { container.getPassword(), container.getJdbcUrl()).getInitialized(); val jobsMigrator = new JobsDatabaseMigrator(jobDatabase, this.getClass().getName()); - assertEquals("0.35.40.001", jobsMigrator.getLatestMigration().getVersion().getVersion()); + assertEquals("0.35.5.001", jobsMigrator.getLatestMigration().getVersion().getVersion()); val configDatabase = new ConfigsDatabaseInstance( mockedConfigs.getConfigDatabaseUser(), @@ -80,7 +80,7 @@ void testBootloaderAppBlankDb() throws Exception { mockedConfigs.getConfigDatabaseUrl()) .getAndInitialize(); val configsMigrator = new ConfigsDatabaseMigrator(configDatabase, this.getClass().getName()); - assertEquals("0.35.56.001", configsMigrator.getLatestMigration().getVersion().getVersion()); + assertEquals("0.35.50.001", configsMigrator.getLatestMigration().getVersion().getVersion()); val jobsPersistence = new DefaultJobPersistence(jobDatabase); assertEquals(version, jobsPersistence.getVersion().get()); diff --git a/airbyte-config/models/src/main/java/io/airbyte/config/ConfigSchema.java b/airbyte-config/models/src/main/java/io/airbyte/config/ConfigSchema.java index 4d2296a0cbde..880df3a72116 100644 --- a/airbyte-config/models/src/main/java/io/airbyte/config/ConfigSchema.java +++ b/airbyte-config/models/src/main/java/io/airbyte/config/ConfigSchema.java @@ -17,6 +17,18 @@ public enum ConfigSchema implements AirbyteConfig { standardWorkspace -> standardWorkspace.getWorkspaceId().toString(), "workspaceId"), + // notification + NOTIFICATION("Notification.yaml", + Notification.class, + Notification -> Notification.getNotificationId().toString(), + "notificationId"), + + // notification connection + NOTIFICATION_CONNECTION("NotificationConnection.yaml", + NotificationConnection.class, + NotificationConnection -> NotificationConnection.getNotificationConnectionId().toString(), + "notificationConnectionId"), + // source STANDARD_SOURCE_DEFINITION("StandardSourceDefinition.yaml", StandardSourceDefinition.class, diff --git a/airbyte-config/models/src/main/resources/types/Notification.yaml b/airbyte-config/models/src/main/resources/types/Notification.yaml index 3214c8cf4835..341fd62841bf 100644 --- a/airbyte-config/models/src/main/resources/types/Notification.yaml +++ b/airbyte-config/models/src/main/resources/types/Notification.yaml @@ -2,21 +2,32 @@ "$schema": http://json-schema.org/draft-07/schema# "$id": https://github.com/airbytehq/airbyte/blob/master/airbyte-config/models/src/main/resources/types/Notification.yaml title: Notification -description: Notification Settings +description: notification configuration type: object required: + - workspaceId + - name + - webhookUrl - notificationType -additionalProperties: true +additionalProperties: false properties: - # Instead of this type field, we would prefer a json schema "oneOf" but unfortunately, - # the jsonschema2pojo does not seem to support it yet: https://github.com/joelittlejohn/jsonschema2pojo/issues/392 + workspaceId: + type: string + format: uuid + notificationId: + type: string + format: uuid + name: + type: string + webhookUrl: + type: string notificationType: "$ref": NotificationType.yaml - sendOnSuccess: + defaultNotification: type: boolean - default: false - sendOnFailure: + description: if set true the webhook will be triggered to all connections + tombstone: + description: + if not set or false, the configuration is active. if true, then this + configuration is permanently off. type: boolean - default: true - slackConfiguration: - "$ref": SlackNotificationConfiguration.yaml diff --git a/airbyte-config/models/src/main/resources/types/NotificationConnection.yaml b/airbyte-config/models/src/main/resources/types/NotificationConnection.yaml new file mode 100644 index 000000000000..184bd6c63df1 --- /dev/null +++ b/airbyte-config/models/src/main/resources/types/NotificationConnection.yaml @@ -0,0 +1,35 @@ +--- +"$schema": http://json-schema.org/draft-07/schema# +"$id": https://github.com/airbytehq/airbyte/blob/master/airbyte-config/models/src/main/resources/types/NotificationConnection.yaml +title: NotificationConnection +description: notification connection link +type: object +required: + - workspaceId + - notificationId + - sendOnSuccess + - sendOnFailure + - tombstone +additionalProperties: false +properties: + notificationConnectionId: + type: string + format: uuid + workspaceId: + type: string + format: uuid + notificationId: + type: string + format: uuid + connectionId: + type: string + format: uuid + sendOnSuccess: + type: boolean + sendOnFailure: + type: boolean + tombstone: + description: + if not set or false, the configuration is active. if true, then this + configuration is permanently off. + type: boolean diff --git a/airbyte-config/models/src/main/resources/types/NotificationLegacy.yaml b/airbyte-config/models/src/main/resources/types/NotificationLegacy.yaml new file mode 100644 index 000000000000..42a725739adc --- /dev/null +++ b/airbyte-config/models/src/main/resources/types/NotificationLegacy.yaml @@ -0,0 +1,22 @@ +--- +"$schema": http://json-schema.org/draft-07/schema# +"$id": https://github.com/airbytehq/airbyte/blob/master/airbyte-config/models/src/main/resources/types/NotificationLegacy.yaml +title: NotificationLegacy +description: Notification Settings +type: object +required: + - notificationType +additionalProperties: true +properties: + # Instead of this type field, we would prefer a json schema "oneOf" but unfortunately, + # the jsonschema2pojo does not seem to support it yet: https://github.com/joelittlejohn/jsonschema2pojo/issues/392 + notificationType: + "$ref": NotificationType.yaml + sendOnSuccess: + type: boolean + default: false + sendOnFailure: + type: boolean + default: true + slackConfiguration: + "$ref": SlackNotificationConfiguration.yaml diff --git a/airbyte-config/models/src/main/resources/types/StandardWorkspace.yaml b/airbyte-config/models/src/main/resources/types/StandardWorkspace.yaml index 44a44070ae6b..8fa130536549 100644 --- a/airbyte-config/models/src/main/resources/types/StandardWorkspace.yaml +++ b/airbyte-config/models/src/main/resources/types/StandardWorkspace.yaml @@ -42,7 +42,7 @@ properties: notifications: type: array items: - "$ref": Notification.yaml + "$ref": NotificationLegacy.yaml firstCompletedSync: type: boolean feedbackDone: diff --git a/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/ConfigRepository.java b/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/ConfigRepository.java index 8714f8483d92..3a631ba08263 100644 --- a/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/ConfigRepository.java +++ b/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/ConfigRepository.java @@ -24,6 +24,8 @@ import io.airbyte.config.ConfigSchema; import io.airbyte.config.DestinationConnection; import io.airbyte.config.DestinationOAuthParameter; +import io.airbyte.config.Notification; +import io.airbyte.config.NotificationConnection; import io.airbyte.config.SourceConnection; import io.airbyte.config.SourceOAuthParameter; import io.airbyte.config.StandardDestinationDefinition; @@ -137,6 +139,28 @@ public void setFeedback(final UUID workflowId) throws JsonValidationException, C persistence.writeConfig(ConfigSchema.STANDARD_WORKSPACE, workspace.getWorkspaceId().toString(), workspace); } + public List listNotifications(final boolean includeTombstone) throws JsonValidationException, IOException { + + final List notifications = new ArrayList<>(); + + for (final Notification notification : persistence.listConfigs(ConfigSchema.NOTIFICATION, Notification.class)) { + if (!MoreBooleans.isTruthy(notification.getTombstone()) || includeTombstone) { + notifications.add(notification); + } + } + + return notifications; + } + + public void writeNotification(final Notification notification) throws JsonValidationException, IOException { + persistence.writeConfig(ConfigSchema.NOTIFICATION, notification.getNotificationId().toString(), notification); + } + + public void writeNotificationConnection(final NotificationConnection notificationConnection) throws JsonValidationException, IOException { + persistence.writeConfig(ConfigSchema.NOTIFICATION_CONNECTION, notificationConnection.getNotificationConnectionId().toString(), + notificationConnection); + } + public StandardSourceDefinition getStandardSourceDefinition(final UUID sourceDefinitionId) throws JsonValidationException, IOException, ConfigNotFoundException { diff --git a/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DatabaseConfigPersistence.java b/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DatabaseConfigPersistence.java index 904996e67fbf..36e5dc7da839 100644 --- a/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DatabaseConfigPersistence.java +++ b/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DatabaseConfigPersistence.java @@ -11,6 +11,8 @@ import static io.airbyte.db.instance.configs.jooq.Tables.ACTOR_OAUTH_PARAMETER; import static io.airbyte.db.instance.configs.jooq.Tables.CONNECTION; import static io.airbyte.db.instance.configs.jooq.Tables.CONNECTION_OPERATION; +import static io.airbyte.db.instance.configs.jooq.Tables.NOTIFICATION_CONFIG; +import static io.airbyte.db.instance.configs.jooq.Tables.NOTIFICATION_CONNECTION; import static io.airbyte.db.instance.configs.jooq.Tables.OPERATION; import static io.airbyte.db.instance.configs.jooq.Tables.STATE; import static io.airbyte.db.instance.configs.jooq.Tables.WORKSPACE; @@ -33,6 +35,8 @@ import io.airbyte.config.ConfigWithMetadata; import io.airbyte.config.DestinationConnection; import io.airbyte.config.DestinationOAuthParameter; +import io.airbyte.config.Notification; +import io.airbyte.config.NotificationConnection; import io.airbyte.config.OperatorDbt; import io.airbyte.config.OperatorNormalization; import io.airbyte.config.SourceConnection; @@ -762,6 +766,48 @@ private void writeStandardWorkspace(final List configs) throw }); } + private void writeNotification(final List configs) throws IOException { + database.transaction(ctx -> { + writeNotification(configs, ctx); + return null; + }); + } + + private void writeNotificationConnection(final List configs) throws IOException { + database.transaction(ctx -> { + writeNotificationConnection(configs, ctx); + return null; + }); + } + + private void writeNotification(final List configs, final DSLContext ctx) { + configs.forEach((Notification) -> { + ctx.insertInto(NOTIFICATION_CONFIG) + .set(NOTIFICATION_CONFIG.ID, Notification.getNotificationId()) + .set(NOTIFICATION_CONFIG.WORKSPACE_ID, Notification.getWorkspaceId()) + .set(NOTIFICATION_CONFIG.NAME, Notification.getName()) + .set(NOTIFICATION_CONFIG.WEBHOOK_URL, Notification.getWebhookUrl()) + .set(NOTIFICATION_CONFIG.DEFAULT_NOTIFICATION, Notification.getDefaultNotification()) + .set(NOTIFICATION_CONFIG.NOTIFICATION_TYPE, Notification.getNotificationType().value()) + .set(NOTIFICATION_CONFIG.TOMBSTONE, Notification.getTombstone()) + .execute(); + }); + } + + private void writeNotificationConnection(final List configs, final DSLContext ctx) { + configs.forEach((NotificationConnection) -> { + ctx.insertInto(NOTIFICATION_CONNECTION) + .set(NOTIFICATION_CONNECTION.NOTIFICATION_CONNECTION_ID, NotificationConnection.getNotificationConnectionId()) + .set(NOTIFICATION_CONNECTION.WORKSPACE_ID, NotificationConnection.getWorkspaceId()) + .set(NOTIFICATION_CONNECTION.NOTIFICATION_ID, NotificationConnection.getNotificationId()) + .set(NOTIFICATION_CONNECTION.CONNECTION_ID, NotificationConnection.getConnectionId()) + .set(NOTIFICATION_CONNECTION.SEND_ON_SUCCESS, NotificationConnection.getSendOnSuccess()) + .set(NOTIFICATION_CONNECTION.SEND_ON_FAILURE, NotificationConnection.getSendOnFailure()) + .set(NOTIFICATION_CONNECTION.TOMBSTONE, NotificationConnection.getTombstone()) + .execute(); + }); + } + private void writeStandardWorkspace(final List configs, final DSLContext ctx) { final OffsetDateTime timestamp = OffsetDateTime.now(); configs.forEach((standardWorkspace) -> { diff --git a/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DbConverter.java b/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DbConverter.java index 506f107a11d6..0ea69cd66949 100644 --- a/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DbConverter.java +++ b/airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/DbConverter.java @@ -10,7 +10,7 @@ import io.airbyte.commons.enums.Enums; import io.airbyte.commons.json.Jsons; import io.airbyte.config.JobSyncConfig.NamespaceDefinitionType; -import io.airbyte.config.Notification; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.ResourceRequirements; import io.airbyte.config.Schedule; import io.airbyte.config.StandardSync; @@ -47,10 +47,10 @@ public static StandardSync buildStandardSync(final Record record, final List notificationList = new ArrayList<>(); + final List notificationList = new ArrayList<>(); final List fetchedNotifications = Jsons.deserialize(record.get(WORKSPACE.NOTIFICATIONS).data(), List.class); for (final Object notification : fetchedNotifications) { - notificationList.add(Jsons.convertValue(notification, Notification.class)); + notificationList.add(Jsons.convertValue(notification, NotificationLegacy.class)); } return new StandardWorkspace() .withWorkspaceId(record.get(WORKSPACE.ID)) diff --git a/airbyte-config/persistence/src/test/java/io/airbyte/config/persistence/MockData.java b/airbyte-config/persistence/src/test/java/io/airbyte/config/persistence/MockData.java index e0e500563ffa..139c4add9fc7 100644 --- a/airbyte-config/persistence/src/test/java/io/airbyte/config/persistence/MockData.java +++ b/airbyte-config/persistence/src/test/java/io/airbyte/config/persistence/MockData.java @@ -12,8 +12,8 @@ import io.airbyte.config.DestinationConnection; import io.airbyte.config.DestinationOAuthParameter; import io.airbyte.config.JobSyncConfig.NamespaceDefinitionType; -import io.airbyte.config.Notification; import io.airbyte.config.Notification.NotificationType; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.OperatorDbt; import io.airbyte.config.OperatorNormalization; import io.airbyte.config.OperatorNormalization.Option; @@ -86,7 +86,7 @@ public class MockData { private static final Instant NOW = Instant.parse("2021-12-15T20:30:40.00Z"); public static List standardWorkspaces() { - final Notification notification = new Notification() + final NotificationLegacy notification = new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSendOnFailure(true) .withSendOnSuccess(true) diff --git a/airbyte-db/lib/src/main/java/io/airbyte/db/instance/configs/migrations/V0_35_50_001__AddNotificationTable.java b/airbyte-db/lib/src/main/java/io/airbyte/db/instance/configs/migrations/V0_35_50_001__AddNotificationTable.java new file mode 100644 index 000000000000..005dabdc78a8 --- /dev/null +++ b/airbyte-db/lib/src/main/java/io/airbyte/db/instance/configs/migrations/V0_35_50_001__AddNotificationTable.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.db.instance.configs.migrations; + +import com.google.common.annotations.VisibleForTesting; +import java.util.UUID; +import org.flywaydb.core.api.migration.BaseJavaMigration; +import org.flywaydb.core.api.migration.Context; +import org.jooq.DSLContext; +import org.jooq.Field; +import org.jooq.impl.DSL; +import org.jooq.impl.SQLDataType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class V0_35_50_001__AddNotificationTable extends BaseJavaMigration { + + private static final Logger LOGGER = LoggerFactory.getLogger(V0_35_50_001__AddNotificationTable.class); + + @Override + public void migrate(final Context context) throws Exception { + final DSLContext ctx = DSL.using(context.getConnection()); + migrate(ctx); + } + + @VisibleForTesting + public static void migrate(final DSLContext ctx) { + createNotificationConfigTable(ctx); + createNotificationConnectionTable(ctx); + } + + public static void createNotificationConfigTable(final DSLContext ctx) { + + final Field id = DSL.field("id", SQLDataType.UUID.nullable(false)); + final Field workspaceId = DSL.field("workspace_id", SQLDataType.UUID.nullable(false)); + final Field name = DSL.field("name", SQLDataType.VARCHAR(256).nullable(false)); + final Field webhookUrl = DSL.field("webhook_url", SQLDataType.VARCHAR(516).nullable(false)); + final Field defaultNotification = DSL.field("default_notification", SQLDataType.BOOLEAN.nullable(false)); + final Field notificationType = DSL.field("notification_type", SQLDataType.VARCHAR(256).nullable(false)); + final Field tombstone = DSL.field("tombstone", SQLDataType.BOOLEAN.nullable(false)); + + ctx.createTableIfNotExists("notification_config") + .columns(id, workspaceId, name, webhookUrl, defaultNotification, notificationType, tombstone) + .execute(); + LOGGER.info("notification config table created"); + } + + public static void createNotificationConnectionTable(final DSLContext ctx) { + + final Field notificationConnectionId = DSL.field("notification_connection_id", SQLDataType.UUID.nullable(false)); + final Field workspaceId = DSL.field("workspace_id", SQLDataType.UUID.nullable(false)); + final Field connectionId = DSL.field("connection_id", SQLDataType.UUID.nullable(true)); + final Field notificationId = DSL.field("notification_id", SQLDataType.UUID.nullable(false)); + final Field sendOnSuccess = DSL.field("send_on_success", SQLDataType.BOOLEAN.nullable(false)); + final Field sendOnFailure = DSL.field("send_on_failure", SQLDataType.BOOLEAN.nullable(false)); + final Field tombstone = DSL.field("tombstone", SQLDataType.BOOLEAN.nullable(false)); + + ctx.createTableIfNotExists("notification_connection") + .columns(notificationConnectionId, workspaceId, connectionId, notificationId, sendOnSuccess, sendOnFailure, tombstone) + .execute(); + LOGGER.info("notification connection table created"); + } + +} diff --git a/airbyte-db/lib/src/main/resources/configs_database/schema_dump.txt b/airbyte-db/lib/src/main/resources/configs_database/schema_dump.txt index fb0f668844f5..439e7b6f6bca 100644 --- a/airbyte-db/lib/src/main/resources/configs_database/schema_dump.txt +++ b/airbyte-db/lib/src/main/resources/configs_database/schema_dump.txt @@ -111,6 +111,24 @@ create table "public"."connection_operation"( "operation_id" ) ); +create table "public"."notification_config"( + "id" uuid not null, + "workspace_id" uuid not null, + "name" varchar(256) not null, + "webhook_url" varchar(516) not null, + "default_notification" bool not null, + "notification_type" varchar(256) not null, + "tombstone" bool not null +); +create table "public"."notification_connection"( + "notification_connection_id" uuid not null, + "workspace_id" uuid not null, + "connection_id" uuid null, + "notification_id" uuid not null, + "send_on_success" bool not null, + "send_on_failure" bool not null, + "tombstone" bool not null +); create table "public"."operation"( "id" uuid not null, "workspace_id" uuid not null, diff --git a/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/SetupForNormalizedTablesTest.java b/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/SetupForNormalizedTablesTest.java index 66198e9032f3..9e2b01b590a6 100644 --- a/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/SetupForNormalizedTablesTest.java +++ b/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/SetupForNormalizedTablesTest.java @@ -15,8 +15,8 @@ import io.airbyte.config.DestinationConnection; import io.airbyte.config.DestinationOAuthParameter; import io.airbyte.config.JobSyncConfig.NamespaceDefinitionType; -import io.airbyte.config.Notification; import io.airbyte.config.Notification.NotificationType; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.OperatorDbt; import io.airbyte.config.OperatorNormalization; import io.airbyte.config.OperatorNormalization.Option; @@ -155,7 +155,7 @@ private static void insertConfigRecord( } public static StandardWorkspace standardWorkspace() { - final Notification notification = new Notification() + final NotificationLegacy notification = new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSendOnFailure(true) .withSendOnSuccess(true) diff --git a/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/V0_32_8_001__AirbyteConfigDatabaseDenormalization_Test.java b/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/V0_32_8_001__AirbyteConfigDatabaseDenormalization_Test.java index d2020d279b19..0d05d932c79b 100644 --- a/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/V0_32_8_001__AirbyteConfigDatabaseDenormalization_Test.java +++ b/airbyte-db/lib/src/test/java/io/airbyte/db/instance/configs/migrations/V0_32_8_001__AirbyteConfigDatabaseDenormalization_Test.java @@ -17,7 +17,7 @@ import io.airbyte.commons.json.Jsons; import io.airbyte.config.DestinationConnection; import io.airbyte.config.DestinationOAuthParameter; -import io.airbyte.config.Notification; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.OperatorDbt; import io.airbyte.config.OperatorNormalization; import io.airbyte.config.ResourceRequirements; @@ -103,10 +103,10 @@ private void assertDataForWorkspace(final DSLContext context) { final Record workspace = workspaces.get(0); - final List notificationList = new ArrayList<>(); + final List notificationList = new ArrayList<>(); final List fetchedNotifications = Jsons.deserialize(workspace.get(notifications).data(), List.class); for (Object notification : fetchedNotifications) { - notificationList.add(Jsons.convertValue(notification, Notification.class)); + notificationList.add(Jsons.convertValue(notification, NotificationLegacy.class)); } final StandardWorkspace workspaceFromNewTable = new StandardWorkspace() .withWorkspaceId(workspace.get(id)) diff --git a/airbyte-notification/src/main/java/io/airbyte/notification/NotificationClient.java b/airbyte-notification/src/main/java/io/airbyte/notification/NotificationClient.java index 7de40e659fea..871507ba9394 100644 --- a/airbyte-notification/src/main/java/io/airbyte/notification/NotificationClient.java +++ b/airbyte-notification/src/main/java/io/airbyte/notification/NotificationClient.java @@ -4,8 +4,8 @@ package io.airbyte.notification; -import io.airbyte.config.Notification; import io.airbyte.config.Notification.NotificationType; +import io.airbyte.config.NotificationLegacy; import java.io.IOException; public abstract class NotificationClient { @@ -13,7 +13,7 @@ public abstract class NotificationClient { protected boolean sendOnSuccess; protected boolean sendOnFailure; - public NotificationClient(final Notification notification) { + public NotificationClient(final NotificationLegacy notification) { this.sendOnSuccess = notification.getSendOnSuccess(); this.sendOnFailure = notification.getSendOnFailure(); } @@ -36,7 +36,7 @@ public abstract boolean notifyJobSuccess( public abstract boolean notifyFailure(String message) throws IOException, InterruptedException; - public static NotificationClient createNotificationClient(final Notification notification) { + public static NotificationClient createNotificationClient(final NotificationLegacy notification) { if (notification.getNotificationType() == NotificationType.SLACK) { return new SlackNotificationClient(notification); } else { diff --git a/airbyte-notification/src/main/java/io/airbyte/notification/SlackNotificationClient.java b/airbyte-notification/src/main/java/io/airbyte/notification/SlackNotificationClient.java index 533781fb033b..acb577234f75 100644 --- a/airbyte-notification/src/main/java/io/airbyte/notification/SlackNotificationClient.java +++ b/airbyte-notification/src/main/java/io/airbyte/notification/SlackNotificationClient.java @@ -8,7 +8,7 @@ import com.google.common.collect.ImmutableMap.Builder; import io.airbyte.commons.json.Jsons; import io.airbyte.commons.resources.MoreResources; -import io.airbyte.config.Notification; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.SlackNotificationConfiguration; import java.io.IOException; import java.net.URI; @@ -38,7 +38,7 @@ public class SlackNotificationClient extends NotificationClient { .build(); private final SlackNotificationConfiguration config; - public SlackNotificationClient(final Notification notification) { + public SlackNotificationClient(final NotificationLegacy notification) { super(notification); this.config = notification.getSlackConfiguration(); } diff --git a/airbyte-notification/src/test/java/io/airbyte/notification/SlackNotificationClientTest.java b/airbyte-notification/src/test/java/io/airbyte/notification/SlackNotificationClientTest.java index c9c580a87aaa..dc499a73e88b 100644 --- a/airbyte-notification/src/test/java/io/airbyte/notification/SlackNotificationClientTest.java +++ b/airbyte-notification/src/test/java/io/airbyte/notification/SlackNotificationClientTest.java @@ -13,8 +13,8 @@ import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import io.airbyte.commons.json.Jsons; -import io.airbyte.config.Notification; import io.airbyte.config.Notification.NotificationType; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.SlackNotificationConfiguration; import java.io.IOException; import java.io.InputStream; @@ -62,7 +62,7 @@ void testBadResponseWrongNotificationMessage() throws IOException, InterruptedEx final String message = UUID.randomUUID().toString(); server.createContext("/test", new ServerHandler("Message mismatched")); final SlackNotificationClient client = - new SlackNotificationClient(new Notification() + new SlackNotificationClient(new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSlackConfiguration(new SlackNotificationConfiguration().withWebhook(WEBHOOK_URL + server.getAddress().getPort() + "/test"))); assertThrows(IOException.class, () -> client.notifyFailure(message)); @@ -71,7 +71,7 @@ void testBadResponseWrongNotificationMessage() throws IOException, InterruptedEx @Test void testBadWebhookUrl() { final SlackNotificationClient client = - new SlackNotificationClient(new Notification() + new SlackNotificationClient(new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSlackConfiguration(new SlackNotificationConfiguration().withWebhook(WEBHOOK_URL + server.getAddress().getPort() + "/bad"))); assertThrows(IOException.class, () -> client.notifyJobFailure("source-test", "destination-test", "job description", "logUrl")); @@ -81,7 +81,7 @@ void testBadWebhookUrl() { void testEmptyWebhookUrl() throws IOException, InterruptedException { final SlackNotificationClient client = new SlackNotificationClient( - new Notification().withNotificationType(NotificationType.SLACK).withSlackConfiguration(new SlackNotificationConfiguration())); + new NotificationLegacy().withNotificationType(NotificationType.SLACK).withSlackConfiguration(new SlackNotificationConfiguration())); assertFalse(client.notifyJobFailure("source-test", "destination-test", "job description", "logUrl")); } @@ -90,7 +90,7 @@ void testNotify() throws IOException, InterruptedException { final String message = UUID.randomUUID().toString(); server.createContext("/test", new ServerHandler(message)); final SlackNotificationClient client = - new SlackNotificationClient(new Notification() + new SlackNotificationClient(new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSlackConfiguration(new SlackNotificationConfiguration().withWebhook(WEBHOOK_URL + server.getAddress().getPort() + "/test"))); assertTrue(client.notifyFailure(message)); @@ -101,7 +101,7 @@ void testNotify() throws IOException, InterruptedException { void testNotifyJobFailure() throws IOException, InterruptedException { server.createContext("/test", new ServerHandler(EXPECTED_FAIL_MESSAGE)); final SlackNotificationClient client = - new SlackNotificationClient(new Notification() + new SlackNotificationClient(new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSlackConfiguration(new SlackNotificationConfiguration().withWebhook(WEBHOOK_URL + server.getAddress().getPort() + "/test"))); assertTrue(client.notifyJobFailure("source-test", "destination-test", "job description", "logUrl")); @@ -111,7 +111,7 @@ void testNotifyJobFailure() throws IOException, InterruptedException { void testNotifyJobSuccess() throws IOException, InterruptedException { server.createContext("/test", new ServerHandler(EXPECTED_SUCCESS_MESSAGE)); final SlackNotificationClient client = - new SlackNotificationClient(new Notification() + new SlackNotificationClient(new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSendOnSuccess(true) .withSlackConfiguration(new SlackNotificationConfiguration().withWebhook(WEBHOOK_URL + server.getAddress().getPort() + "/test"))); diff --git a/airbyte-scheduler/persistence/src/main/java/io/airbyte/scheduler/persistence/JobNotifier.java b/airbyte-scheduler/persistence/src/main/java/io/airbyte/scheduler/persistence/JobNotifier.java index 4733d0f65242..551323ce56f4 100644 --- a/airbyte-scheduler/persistence/src/main/java/io/airbyte/scheduler/persistence/JobNotifier.java +++ b/airbyte-scheduler/persistence/src/main/java/io/airbyte/scheduler/persistence/JobNotifier.java @@ -9,11 +9,8 @@ import com.google.common.collect.ImmutableMap.Builder; import io.airbyte.analytics.TrackingClient; import io.airbyte.commons.map.MoreMaps; -import io.airbyte.config.Notification; +import io.airbyte.config.*; import io.airbyte.config.Notification.NotificationType; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.StandardWorkspace; import io.airbyte.config.persistence.ConfigRepository; import io.airbyte.notification.NotificationClient; import io.airbyte.scheduler.models.Job; @@ -78,7 +75,7 @@ private void notifyJob(final String reason, final String action, final Job job) final ImmutableMap jobMetadata = TrackingMetadata.generateJobAttemptMetadata(job); final ImmutableMap sourceMetadata = TrackingMetadata.generateSourceDefinitionMetadata(sourceDefinition); final ImmutableMap destinationMetadata = TrackingMetadata.generateDestinationDefinitionMetadata(destinationDefinition); - for (final Notification notification : workspace.getNotifications()) { + for (final NotificationLegacy notification : workspace.getNotifications()) { final NotificationClient notificationClient = getNotificationClient(notification); try { final Builder notificationMetadata = ImmutableMap.builder(); @@ -121,7 +118,7 @@ public void successJob(final Job job) { notifyJob(null, SUCCESS_NOTIFICATION, job); } - protected NotificationClient getNotificationClient(final Notification notification) { + protected NotificationClient getNotificationClient(final NotificationLegacy notification) { return NotificationClient.createNotificationClient(notification); } diff --git a/airbyte-scheduler/persistence/src/test/java/io/airbyte/scheduler/persistence/JobNotifierTest.java b/airbyte-scheduler/persistence/src/test/java/io/airbyte/scheduler/persistence/JobNotifierTest.java index 83385d404ffb..5fb9c97c2c69 100644 --- a/airbyte-scheduler/persistence/src/test/java/io/airbyte/scheduler/persistence/JobNotifierTest.java +++ b/airbyte-scheduler/persistence/src/test/java/io/airbyte/scheduler/persistence/JobNotifierTest.java @@ -14,14 +14,9 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import io.airbyte.analytics.TrackingClient; -import io.airbyte.config.JobConfig; +import io.airbyte.config.*; import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.Notification; import io.airbyte.config.Notification.NotificationType; -import io.airbyte.config.SlackNotificationConfiguration; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.StandardWorkspace; import io.airbyte.config.persistence.ConfigNotFoundException; import io.airbyte.config.persistence.ConfigRepository; import io.airbyte.notification.NotificationClient; @@ -127,8 +122,8 @@ private static Job createJob() { NOW.getEpochSecond() + 123456L); } - private static Notification getSlackNotification() { - return new Notification() + private static NotificationLegacy getSlackNotification() { + return new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSlackConfiguration(new SlackNotificationConfiguration() .withWebhook("http://random.webhook.url/hooks.slack.com/")); diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java b/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java index bc757db728e2..39089fc3c900 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java +++ b/airbyte-server/src/main/java/io/airbyte/server/apis/ConfigurationApi.java @@ -42,7 +42,9 @@ import io.airbyte.api.model.JobListRequestBody; import io.airbyte.api.model.JobReadList; import io.airbyte.api.model.LogsRequestBody; -import io.airbyte.api.model.Notification; +import io.airbyte.api.model.NotificationConnectionCreate; +import io.airbyte.api.model.NotificationCreate; +import io.airbyte.api.model.NotificationLegacy; import io.airbyte.api.model.NotificationRead; import io.airbyte.api.model.OAuthConsentRead; import io.airbyte.api.model.OperationCreate; @@ -297,11 +299,24 @@ public void updateWorkspaceFeedback(final WorkspaceGiveFeedback workspaceGiveFee }); } + // NOTIFICATION @Override - public NotificationRead tryNotificationConfig(final Notification notification) { + public NotificationRead tryNotificationConfig(final NotificationLegacy notification) { return execute(() -> workspacesHandler.tryNotification(notification)); } + // NOTIFICATION + @Override + public NotificationRead createNotification(final NotificationCreate notification) { + return execute(() -> workspacesHandler.createNotification(notification)); + } + + // NOTIFICATION + @Override + public NotificationRead createNotificationConnection(final NotificationConnectionCreate notificationConnection) { + return execute(() -> workspacesHandler.createNotificationConnection(notificationConnection)); + } + // SOURCE @Override diff --git a/airbyte-server/src/main/java/io/airbyte/server/converters/NotificationConverter.java b/airbyte-server/src/main/java/io/airbyte/server/converters/NotificationConverter.java index 17292b10cf17..7340b1174fe8 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/converters/NotificationConverter.java +++ b/airbyte-server/src/main/java/io/airbyte/server/converters/NotificationConverter.java @@ -10,12 +10,12 @@ public class NotificationConverter { - public static List toConfigList(final List notifications) { + public static List toConfigList(final List notifications) { return notifications.stream().map(NotificationConverter::toConfig).collect(Collectors.toList()); } - public static io.airbyte.config.Notification toConfig(final io.airbyte.api.model.Notification notification) { - return new io.airbyte.config.Notification() + public static io.airbyte.config.NotificationLegacy toConfig(final io.airbyte.api.model.NotificationLegacy notification) { + return new io.airbyte.config.NotificationLegacy() .withNotificationType(Enums.convertTo(notification.getNotificationType(), io.airbyte.config.Notification.NotificationType.class)) .withSendOnSuccess(notification.getSendOnSuccess()) .withSendOnFailure(notification.getSendOnFailure()) @@ -27,12 +27,12 @@ private static io.airbyte.config.SlackNotificationConfiguration toConfig(final i .withWebhook(notification.getWebhook()); } - public static List toApiList(final List notifications) { + public static List toApiList(final List notifications) { return notifications.stream().map(NotificationConverter::toApi).collect(Collectors.toList()); } - public static io.airbyte.api.model.Notification toApi(final io.airbyte.config.Notification notification) { - return new io.airbyte.api.model.Notification() + public static io.airbyte.api.model.NotificationLegacy toApi(final io.airbyte.config.NotificationLegacy notification) { + return new io.airbyte.api.model.NotificationLegacy() .notificationType(Enums.convertTo(notification.getNotificationType(), io.airbyte.api.model.NotificationType.class)) .sendOnSuccess(notification.getSendOnSuccess()) .sendOnFailure(notification.getSendOnFailure()) diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/WorkspacesHandler.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/WorkspacesHandler.java index d54f02856df0..22d08e949d4c 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/WorkspacesHandler.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/WorkspacesHandler.java @@ -9,7 +9,9 @@ import io.airbyte.analytics.TrackingClientSingleton; import io.airbyte.api.model.ConnectionRead; import io.airbyte.api.model.DestinationRead; -import io.airbyte.api.model.Notification; +import io.airbyte.api.model.NotificationConnectionCreate; +import io.airbyte.api.model.NotificationCreate; +import io.airbyte.api.model.NotificationLegacy; import io.airbyte.api.model.NotificationRead; import io.airbyte.api.model.NotificationRead.StatusEnum; import io.airbyte.api.model.SlugRequestBody; @@ -21,6 +23,10 @@ import io.airbyte.api.model.WorkspaceReadList; import io.airbyte.api.model.WorkspaceUpdate; import io.airbyte.api.model.WorkspaceUpdateName; +import io.airbyte.commons.enums.Enums; +import io.airbyte.config.Notification; +import io.airbyte.config.Notification.NotificationType; +import io.airbyte.config.NotificationConnection; import io.airbyte.config.StandardWorkspace; import io.airbyte.config.persistence.ConfigNotFoundException; import io.airbyte.config.persistence.ConfigRepository; @@ -183,7 +189,72 @@ public WorkspaceRead updateWorkspaceName(final WorkspaceUpdateName workspaceUpda return buildWorkspaceReadFromId(workspaceId); } - public NotificationRead tryNotification(final Notification notification) { + public NotificationRead createNotification(final NotificationCreate notification) throws JsonValidationException, IOException { + final String name = notification.getName(); + final String webhookUrl = notification.getWebhookUrl(); + final UUID workspaceId = notification.getWorkspaceId(); + final Boolean defaultNotification = notification.getDefaultNotification(); + final Boolean tombstone = notification.getTombstone(); + final NotificationType notificationType = + Enums.convertTo(notification.getNotificationType(), io.airbyte.config.Notification.NotificationType.class); + + final Notification newNotification = new Notification() + .withNotificationId(uuidSupplier.get()) + .withWorkspaceId(workspaceId) + .withName(name) + .withWebhookUrl(webhookUrl) + .withDefaultNotification(defaultNotification) + .withNotificationType(notificationType) + .withTombstone(tombstone); + + configRepository.writeNotification(newNotification); + + // if (defaultNotification) { + // final NotificationConnection workspaceNotification = new + // NotificationConnection(); + // configRepository.writeNotificationConnection(workspaceNotification); + // } + + return new NotificationRead().status(StatusEnum.SUCCEEDED); + } + + public NotificationRead createNotificationConnection(final NotificationConnectionCreate notificationConnection) + throws JsonValidationException, IOException { + final UUID workspaceId = notificationConnection.getWorkspaceId(); + final UUID connectionId = notificationConnection.getConnectionId(); + final UUID notificationId = notificationConnection.getNotificationId(); + final Boolean sendOnSuccess = notificationConnection.getSendOnSuccess(); + final Boolean sendOnFailure = notificationConnection.getSendOnFailure(); + final Boolean tombstone = notificationConnection.getTombstone(); + + final NotificationConnection newNotificationConnection = new NotificationConnection() + .withNotificationConnectionId(uuidSupplier.get()) + .withWorkspaceId(workspaceId) + .withConnectionId(connectionId) + .withNotificationId(notificationId) + .withSendOnSuccess(sendOnSuccess) + .withSendOnFailure(sendOnFailure) + .withTombstone(tombstone); + + configRepository.writeNotificationConnection(newNotificationConnection); + + return new NotificationRead().status(StatusEnum.SUCCEEDED); + } + + // public void deleteNotification(final NotificationIdRequestBody notificationIdRequestBody) + // throws JsonValidationException, IOException, ConfigNotFoundException { + // // get existing implementation + // final Notification persistedNotification = + // configRepository.getNotification(notificationIdRequestBody.getNotificationId(), false); + // + // // need to implement a list of all connections with that connection + // // tombstone them too + // + // persistedNotification.withTombstone(true); + // configRepository.writeNotification(persistedNotification); + // } + + public NotificationRead tryNotification(final NotificationLegacy notification) { try { final NotificationClient notificationClient = NotificationClient.createNotificationClient(NotificationConverter.toConfig(notification)); final String messageFormat = "Hello World! This is a test from Airbyte to try %s notification settings for sync %s"; diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/ArchiveHandlerTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/ArchiveHandlerTest.java index 543ce445452f..c2983afe5886 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/handlers/ArchiveHandlerTest.java +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/ArchiveHandlerTest.java @@ -22,8 +22,8 @@ import io.airbyte.commons.version.AirbyteVersion; import io.airbyte.config.ConfigSchema; import io.airbyte.config.DestinationConnection; -import io.airbyte.config.Notification; import io.airbyte.config.Notification.NotificationType; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.SlackNotificationConfiguration; import io.airbyte.config.SourceConnection; import io.airbyte.config.StandardSourceDefinition; @@ -173,7 +173,7 @@ void testFullExportImportRoundTrip() throws Exception { // This source definition is on an old version .withDockerImageTag(sourceS3DefinitionVersion) .withTombstone(false); - final Notification notification = new Notification() + final NotificationLegacy notification = new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSendOnFailure(true) .withSendOnSuccess(true) diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/WorkspacesHandlerTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/WorkspacesHandlerTest.java index e3bb01da0524..8b27790681df 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/handlers/WorkspacesHandlerTest.java +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/WorkspacesHandlerTest.java @@ -19,6 +19,8 @@ import io.airbyte.api.model.ConnectionReadList; import io.airbyte.api.model.DestinationRead; import io.airbyte.api.model.DestinationReadList; +import io.airbyte.api.model.NotificationCreate; +import io.airbyte.api.model.NotificationRead; import io.airbyte.api.model.SlugRequestBody; import io.airbyte.api.model.SourceRead; import io.airbyte.api.model.SourceReadList; @@ -32,6 +34,7 @@ import io.airbyte.commons.json.Jsons; import io.airbyte.config.Notification; import io.airbyte.config.Notification.NotificationType; +import io.airbyte.config.NotificationLegacy; import io.airbyte.config.SlackNotificationConfiguration; import io.airbyte.config.StandardWorkspace; import io.airbyte.config.persistence.ConfigNotFoundException; @@ -59,6 +62,7 @@ class WorkspacesHandlerTest { private Supplier uuidSupplier; private StandardWorkspace workspace; private WorkspacesHandler workspacesHandler; + private Notification notification; @SuppressWarnings("unchecked") @BeforeEach @@ -70,6 +74,7 @@ void setUp() { uuidSupplier = mock(Supplier.class); workspace = generateWorkspace(); workspacesHandler = new WorkspacesHandler(configRepository, connectionsHandler, destinationHandler, sourceHandler, uuidSupplier); + notification = generateNotificationNew(); } private StandardWorkspace generateWorkspace() { @@ -88,20 +93,51 @@ private StandardWorkspace generateWorkspace() { .withNotifications(List.of(generateNotification())); } - private Notification generateNotification() { + private Notification generateNotificationNew() { return new Notification() + .withNotificationId(UUID.randomUUID()) + .withWorkspaceId(UUID.randomUUID()) + .withName("test notification") + .withWebhookUrl("webhook-test") + .withDefaultNotification(false) + .withTombstone(false); + } + + private NotificationLegacy generateNotification() { + return new NotificationLegacy() .withNotificationType(NotificationType.SLACK) .withSlackConfiguration(new SlackNotificationConfiguration() .withWebhook(FAILURE_NOTIFICATION_WEBHOOK)); } - private io.airbyte.api.model.Notification generateApiNotification() { - return new io.airbyte.api.model.Notification() + private io.airbyte.api.model.NotificationLegacy generateApiNotification() { + return new io.airbyte.api.model.NotificationLegacy() .notificationType(io.airbyte.api.model.NotificationType.SLACK) .slackConfiguration(new io.airbyte.api.model.SlackNotificationConfiguration() .webhook(FAILURE_NOTIFICATION_WEBHOOK)); } + @Test + void testCreateNotification() throws JsonValidationException, IOException { + + final UUID uuid = UUID.randomUUID(); + when(uuidSupplier.get()).thenReturn(uuid); + + configRepository.writeNotification(notification); + + final NotificationCreate notificationCreate = new NotificationCreate() + .name("new notification") + .webhookUrl("webhook test") + .defaultNotification(false) + .tombstone(false); + + final NotificationRead actualRead = workspacesHandler.createNotification(notificationCreate); + final NotificationRead expectedRead = new NotificationRead() + .status(NotificationRead.StatusEnum.SUCCEEDED); + + assertEquals(expectedRead, actualRead); + } + @Test void testCreateWorkspace() throws JsonValidationException, IOException { when(configRepository.listStandardWorkspaces(false)).thenReturn(Collections.singletonList(workspace)); @@ -293,7 +329,7 @@ void testGetWorkspaceBySlug() throws JsonValidationException, ConfigNotFoundExce @Test void testUpdateWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - final io.airbyte.api.model.Notification apiNotification = generateApiNotification(); + final io.airbyte.api.model.NotificationLegacy apiNotification = generateApiNotification(); apiNotification.getSlackConfiguration().webhook("updated"); final WorkspaceUpdate workspaceUpdate = new WorkspaceUpdate() .workspaceId(workspace.getWorkspaceId()) @@ -304,7 +340,7 @@ void testUpdateWorkspace() throws JsonValidationException, ConfigNotFoundExcepti .displaySetupWizard(false) .notifications(List.of(apiNotification)); - final Notification expectedNotification = generateNotification(); + final NotificationLegacy expectedNotification = generateNotification(); expectedNotification.getSlackConfiguration().withWebhook("updated"); final StandardWorkspace expectedWorkspace = new StandardWorkspace() .withWorkspaceId(workspace.getWorkspaceId()) @@ -326,7 +362,7 @@ void testUpdateWorkspace() throws JsonValidationException, ConfigNotFoundExcepti final WorkspaceRead actualWorkspaceRead = workspacesHandler.updateWorkspace(workspaceUpdate); - final io.airbyte.api.model.Notification expectedNotificationRead = generateApiNotification(); + final io.airbyte.api.model.NotificationLegacy expectedNotificationRead = generateApiNotification(); expectedNotificationRead.getSlackConfiguration().webhook("updated"); final WorkspaceRead expectedWorkspaceRead = new WorkspaceRead() .workspaceId(workspace.getWorkspaceId()) diff --git a/docs/reference/api/generated-api-html/index.html b/docs/reference/api/generated-api-html/index.html index 72b355632265..57222d8cbc40 100644 --- a/docs/reference/api/generated-api-html/index.html +++ b/docs/reference/api/generated-api-html/index.html @@ -287,6 +287,8 @@

Logs

Notifications

Oauth

@@ -4069,6 +4071,118 @@

422


Notifications

+
+
+ Up +
post /v1/notifications/create
+
Create a new Notification (createNotification)
+
+ + +

Consumes

+ This API call consumes the following media types via the Content-Type request header: +
    +
  • application/json
  • +
+ +

Request body

+
+
NotificationCreate NotificationCreate (required)
+ +
Body Parameter
+ +
+ + + + +

Return type

+ + + + +

Example data

+
Content-Type: application/json
+
{
+  "message" : "message",
+  "status" : "succeeded"
+}
+ +

Produces

+ This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
    +
  • application/json
  • +
+ +

Responses

+

200

+ Successful operation + NotificationRead +

404

+ Object with given id was not found. + NotFoundKnownExceptionInfo +
+
+
+
+ Up +
post /v1/notifications/add_connection
+
Create a link between a connection and a notification (createNotificationConnection)
+
+ + +

Consumes

+ This API call consumes the following media types via the Content-Type request header: +
    +
  • application/json
  • +
+ +

Request body

+
+
NotificationConnectionCreate NotificationConnectionCreate (required)
+ +
Body Parameter
+ +
+ + + + +

Return type

+ + + + +

Example data

+
Content-Type: application/json
+
{
+  "message" : "message",
+  "status" : "succeeded"
+}
+ +

Produces

+ This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
    +
  • application/json
  • +
+ +

Responses

+

200

+ Successful operation + NotificationRead +

404

+ Object with given id was not found. + NotFoundKnownExceptionInfo +
+
Up @@ -4085,7 +4199,7 @@

Consumes

Request body

-

Notification - Up

+

NotificationConnectionCreate - Up

+
+
+
workspaceId
UUID format: uuid
+
notificationId
UUID format: uuid
+
connectionId
UUID format: uuid
+
sendOnSuccess
+
sendOnFailure
+
tombstone
+
+
+
+

NotificationCreate - Up

+
+
+
workspaceId
UUID format: uuid
+
name
+
webhookUrl
+
defaultNotification (optional)
+
notificationType
+
tombstone (optional)
+
+
+
+

NotificationLegacy - Up

notificationType
@@ -9566,7 +9706,7 @@

WorkspaceCreate - name

news (optional)
securityUpdates (optional)
-
notifications (optional)
+
notifications (optional)
displaySetupWizard (optional)
@@ -9598,7 +9738,7 @@

WorkspaceRead - anonymousDataCollection (optional)
news (optional)
securityUpdates (optional)
-
notifications (optional)
+
notifications (optional)
firstCompletedSync (optional)
feedbackDone (optional)
@@ -9621,7 +9761,7 @@

WorkspaceUpdate - anonymousDataCollection
news
securityUpdates
-
notifications (optional)
+
notifications (optional)