From 294ee8f22614c92b2e0355e349cf6aa5ca6cdcfc Mon Sep 17 00:00:00 2001 From: Michael Siega <109092231+mfsiega-airbyte@users.noreply.github.com> Date: Thu, 11 Aug 2022 19:27:08 +0200 Subject: [PATCH] Expose cron scheduling in the Connections APIs (#15253) * Expose cron scheduling in the Connections APIs * Update airbyte-api/src/main/openapi/config.yaml Co-authored-by: terencecho * Update airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java Co-authored-by: terencecho * update octavia-cli tests for new schedule schema, and fix update API impl * check for null schedule data before updating * handle new schedule related fields in generate / apply / import * update octavia-cli changelog * ensure that legacy manual schedule flag is consistent with schedule_type * update octavia cli test coverage for new schedule schema * fix failing octavia cli integration tests * fix file diff check * Update octavia-cli/unit_tests/test_apply/test_resources.py Co-authored-by: Augustin Co-authored-by: terencecho Co-authored-by: alafanechere --- airbyte-api/src/main/openapi/config.yaml | 74 + airbyte-server/build.gradle | 1 + .../server/converters/ApiPojoConverters.java | 100 +- .../server/handlers/ConnectionsHandler.java | 44 +- .../WebBackendConnectionsHandler.java | 8 + .../handlers/helpers/ConnectionMatcher.java | 2 + .../helpers/ConnectionScheduleHelper.java | 80 + .../ConnectionSchedulerHelperTest.java | 90 + .../handlers/ConnectionsHandlerTest.java | 10 + .../WebBackendConnectionsHandlerTest.java | 8 +- .../server/helpers/ConnectionHelpers.java | 18 +- airbyte-workers/build.gradle | 1 + .../workers/helper/ConnectionHelper.java | 9 +- .../api/generated-api-html/index.html | 280 +- octavia-cli/README.md | 1 + .../test_api_http_headers.yaml | 26958 ++++++++-------- .../connections/poke_to_pg/configuration.yaml | 8 +- .../configuration.yaml | 8 +- .../test_apply/test_resources.py | 4 - .../expected_with_normalization.yaml | 11 +- .../expected_without_normalization.yaml | 11 +- .../poke_to_pg_to_import/configuration.yaml | 8 +- octavia-cli/octavia_cli/_import/commands.py | 2 + octavia-cli/octavia_cli/apply/resources.py | 32 +- .../generate/templates/connection.yaml.j2 | 11 +- .../unit_tests/test_apply/test_resources.py | 53 +- 26 files changed, 14939 insertions(+), 12893 deletions(-) create mode 100644 airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionScheduleHelper.java create mode 100644 airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionSchedulerHelperTest.java diff --git a/airbyte-api/src/main/openapi/config.yaml b/airbyte-api/src/main/openapi/config.yaml index da65057ffdba2..c13f984057312 100644 --- a/airbyte-api/src/main/openapi/config.yaml +++ b/airbyte-api/src/main/openapi/config.yaml @@ -3218,6 +3218,10 @@ components: $ref: "#/components/schemas/AirbyteCatalog" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" resourceRequirements: @@ -3257,6 +3261,10 @@ components: $ref: "#/components/schemas/AirbyteCatalog" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" resourceRequirements: @@ -3298,6 +3306,10 @@ components: $ref: "#/components/schemas/AirbyteCatalog" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" resourceRequirements: @@ -3335,6 +3347,10 @@ components: $ref: "#/components/schemas/AirbyteCatalog" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" resourceRequirements: @@ -3386,6 +3402,10 @@ components: $ref: "#/components/schemas/AirbyteCatalog" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" resourceRequirements: @@ -3416,6 +3436,10 @@ components: $ref: "#/components/schemas/DestinationId" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" source: @@ -3445,6 +3469,10 @@ components: $ref: "#/components/schemas/DestinationId" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" source: @@ -3467,6 +3495,8 @@ components: - active - inactive - deprecated + # TODO(https://github.com/airbytehq/airbyte/issues/11432): remove. + # Prefer the ConnectionScheduleType and ConnectionScheduleData properties. ConnectionSchedule: description: if null, then no schedule is set. type: object @@ -3485,6 +3515,46 @@ components: - days - weeks - months + ConnectionScheduleType: + description: determine how the schedule data should be interpreted + type: string + enum: + - manual + - basic + - cron + ConnectionScheduleData: + description: schedule for when the the connection should run, per the schedule type + type: object + properties: + # This should be populated when schedule type is basic. + basicSchedule: + type: object + required: + - timeUnit + - units + properties: + timeUnit: + type: string + enum: + - minutes + - hours + - days + - weeks + - months + units: + type: integer + format: int64 + # This should be populated when schedule type is cron. + cron: + type: object + required: + - cronExpression + - cronTimeZone + properties: + cronExpression: + type: string + cronTimeZone: + type: string NamespaceDefinitionType: type: string description: Method used for computing final namespace in destination @@ -4564,6 +4634,10 @@ components: $ref: "#/components/schemas/AirbyteCatalog" schedule: $ref: "#/components/schemas/ConnectionSchedule" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" status: $ref: "#/components/schemas/ConnectionStatus" operationIds: diff --git a/airbyte-server/build.gradle b/airbyte-server/build.gradle index 55ade69488215..cf47ced29cfe7 100644 --- a/airbyte-server/build.gradle +++ b/airbyte-server/build.gradle @@ -32,6 +32,7 @@ dependencies { implementation 'org.glassfish.jersey.inject:jersey-hk2' implementation 'org.glassfish.jersey.media:jersey-media-json-jackson' implementation 'org.glassfish.jersey.ext:jersey-bean-validation' + implementation 'org.quartz-scheduler:quartz:2.3.2' testImplementation project(':airbyte-test-utils') diff --git a/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java b/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java index 0ce5af388239b..989f11d404203 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java +++ b/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java @@ -4,9 +4,13 @@ package io.airbyte.server.converters; +import io.airbyte.api.client.model.generated.ConnectionScheduleType; import io.airbyte.api.model.generated.ActorDefinitionResourceRequirements; import io.airbyte.api.model.generated.ConnectionRead; import io.airbyte.api.model.generated.ConnectionSchedule; +import io.airbyte.api.model.generated.ConnectionScheduleData; +import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; +import io.airbyte.api.model.generated.ConnectionScheduleDataCron; import io.airbyte.api.model.generated.ConnectionStatus; import io.airbyte.api.model.generated.ConnectionUpdate; import io.airbyte.api.model.generated.JobType; @@ -17,7 +21,10 @@ import io.airbyte.config.JobSyncConfig.NamespaceDefinitionType; import io.airbyte.config.Schedule; import io.airbyte.config.StandardSync; +import io.airbyte.config.StandardSync.ScheduleType; import io.airbyte.server.handlers.helpers.CatalogConverter; +import io.airbyte.server.handlers.helpers.ConnectionScheduleHelper; +import io.airbyte.validation.json.JsonValidationException; import java.util.stream.Collectors; public class ApiPojoConverters { @@ -78,7 +85,7 @@ public static ResourceRequirements resourceRequirementsToApi(final io.airbyte.co .memoryLimit(resourceReqs.getMemoryLimit()); } - public static io.airbyte.config.StandardSync connectionUpdateToInternal(final ConnectionUpdate update) { + public static io.airbyte.config.StandardSync connectionUpdateToInternal(final ConnectionUpdate update) throws JsonValidationException { final StandardSync newConnection = new StandardSync() .withNamespaceDefinition(Enums.convertTo(update.getNamespaceDefinition(), NamespaceDefinitionType.class)) @@ -99,7 +106,9 @@ public static io.airbyte.config.StandardSync connectionUpdateToInternal(final Co } // update sync schedule - if (update.getSchedule() != null) { + if (update.getScheduleType() != null) { + ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(newConnection, update.getScheduleType(), update.getScheduleData()); + } else if (update.getSchedule() != null) { final Schedule newSchedule = new Schedule() .withTimeUnit(toPersistenceTimeUnit(update.getSchedule().getTimeUnit())) .withUnits(update.getSchedule().getUnits()); @@ -112,21 +121,12 @@ public static io.airbyte.config.StandardSync connectionUpdateToInternal(final Co } public static ConnectionRead internalToConnectionRead(final StandardSync standardSync) { - ConnectionSchedule apiSchedule = null; - - if (!standardSync.getManual()) { - apiSchedule = new ConnectionSchedule() - .timeUnit(toApiTimeUnit(standardSync.getSchedule().getTimeUnit())) - .units(standardSync.getSchedule().getUnits()); - } - final ConnectionRead connectionRead = new ConnectionRead() .connectionId(standardSync.getConnectionId()) .sourceId(standardSync.getSourceId()) .destinationId(standardSync.getDestinationId()) .operationIds(standardSync.getOperationIds()) .status(toApiStatus(standardSync.getStatus())) - .schedule(apiSchedule) .name(standardSync.getName()) .namespaceDefinition(Enums.convertTo(standardSync.getNamespaceDefinition(), io.airbyte.api.model.generated.NamespaceDefinitionType.class)) .namespaceFormat(standardSync.getNamespaceFormat()) @@ -138,6 +138,8 @@ public static ConnectionRead internalToConnectionRead(final StandardSync standar connectionRead.resourceRequirements(resourceRequirementsToApi(standardSync.getResourceRequirements())); } + populateConnectionReadSchedule(standardSync, connectionRead); + return connectionRead; } @@ -149,10 +151,15 @@ public static io.airbyte.config.JobTypeResourceLimit.JobType toInternalJobType(f return Enums.convertTo(jobType, io.airbyte.config.JobTypeResourceLimit.JobType.class); } + // TODO(https://github.com/airbytehq/airbyte/issues/11432): remove these helpers. public static ConnectionSchedule.TimeUnitEnum toApiTimeUnit(final Schedule.TimeUnit apiTimeUnit) { return Enums.convertTo(apiTimeUnit, ConnectionSchedule.TimeUnitEnum.class); } + public static ConnectionSchedule.TimeUnitEnum toApiTimeUnit(final BasicSchedule.TimeUnit timeUnit) { + return Enums.convertTo(timeUnit, ConnectionSchedule.TimeUnitEnum.class); + } + public static ConnectionStatus toApiStatus(final StandardSync.Status status) { return Enums.convertTo(status, ConnectionStatus.class); } @@ -169,4 +176,75 @@ public static BasicSchedule.TimeUnit toBasicScheduleTimeUnit(final ConnectionSch return Enums.convertTo(apiTimeUnit, BasicSchedule.TimeUnit.class); } + public static BasicSchedule.TimeUnit toBasicScheduleTimeUnit(final ConnectionScheduleDataBasicSchedule.TimeUnitEnum apiTimeUnit) { + return Enums.convertTo(apiTimeUnit, BasicSchedule.TimeUnit.class); + } + + public static ConnectionScheduleDataBasicSchedule.TimeUnitEnum toApiBasicScheduleTimeUnit(final BasicSchedule.TimeUnit timeUnit) { + return Enums.convertTo(timeUnit, ConnectionScheduleDataBasicSchedule.TimeUnitEnum.class); + } + + public static ConnectionScheduleDataBasicSchedule.TimeUnitEnum toApiBasicScheduleTimeUnit(final Schedule.TimeUnit timeUnit) { + return Enums.convertTo(timeUnit, ConnectionScheduleDataBasicSchedule.TimeUnitEnum.class); + } + + public static void populateConnectionReadSchedule(final StandardSync standardSync, final ConnectionRead connectionRead) { + // TODO(https://github.com/airbytehq/airbyte/issues/11432): only return new schema once frontend is + // ready. + if (standardSync.getScheduleType() != null) { + // Populate everything based on the new schema. + switch (standardSync.getScheduleType()) { + case MANUAL -> { + connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL); + } + case BASIC_SCHEDULE -> { + connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.BASIC); + connectionRead.scheduleData(new ConnectionScheduleData() + .basicSchedule(new ConnectionScheduleDataBasicSchedule() + .timeUnit(toApiBasicScheduleTimeUnit(standardSync.getScheduleData().getBasicSchedule().getTimeUnit())) + .units(standardSync.getScheduleData().getBasicSchedule().getUnits()))); + connectionRead.schedule(new ConnectionSchedule() + .timeUnit(toApiTimeUnit(standardSync.getScheduleData().getBasicSchedule().getTimeUnit())) + .units(standardSync.getScheduleData().getBasicSchedule().getUnits())); + } + case CRON -> { + // We don't populate any legacy data here. + connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.CRON); + connectionRead.scheduleData(new ConnectionScheduleData() + .cron(new ConnectionScheduleDataCron() + .cronExpression(standardSync.getScheduleData().getCron().getCronExpression()) + .cronTimeZone(standardSync.getScheduleData().getCron().getCronTimeZone()))); + } + } + } else if (standardSync.getManual()) { + // Legacy schema, manual sync. + connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL); + } else { + // Legacy schema, basic schedule. + connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.BASIC); + connectionRead.schedule(new ConnectionSchedule() + .timeUnit(toApiTimeUnit(standardSync.getSchedule().getTimeUnit())) + .units(standardSync.getSchedule().getUnits())); + connectionRead.scheduleData(new ConnectionScheduleData() + .basicSchedule(new ConnectionScheduleDataBasicSchedule() + .timeUnit(toApiBasicScheduleTimeUnit(standardSync.getSchedule().getTimeUnit())) + .units(standardSync.getSchedule().getUnits()))); + } + } + + public static ConnectionScheduleType toApiScheduleType(final ScheduleType scheduleType) { + switch (scheduleType) { + case MANUAL -> { + return ConnectionScheduleType.MANUAL; + } + case BASIC_SCHEDULE -> { + return ConnectionScheduleType.BASIC; + } + case CRON -> { + return ConnectionScheduleType.CRON; + } + } + throw new RuntimeException("Unexpected schedule type"); + } + } diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/ConnectionsHandler.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/ConnectionsHandler.java index 691a3546a9767..4e965afb534a6 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/ConnectionsHandler.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/ConnectionsHandler.java @@ -47,6 +47,7 @@ import io.airbyte.server.converters.CatalogDiffConverters; import io.airbyte.server.handlers.helpers.CatalogConverter; import io.airbyte.server.handlers.helpers.ConnectionMatcher; +import io.airbyte.server.handlers.helpers.ConnectionScheduleHelper; import io.airbyte.server.handlers.helpers.DestinationMatcher; import io.airbyte.server.handlers.helpers.SourceMatcher; import io.airbyte.validation.json.JsonValidationException; @@ -140,6 +141,34 @@ public ConnectionRead createConnection(final ConnectionCreate connectionCreate) standardSync.withCatalog(new ConfiguredAirbyteCatalog().withStreams(Collections.emptyList())); } + if (connectionCreate.getSchedule() != null && connectionCreate.getScheduleType() != null) { + throw new JsonValidationException("supply old or new schedule schema but not both"); + } + + if (connectionCreate.getScheduleType() != null) { + ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(standardSync, connectionCreate.getScheduleType(), + connectionCreate.getScheduleData()); + } else { + populateSyncFromLegacySchedule(standardSync, connectionCreate); + } + + configRepository.writeStandardSync(standardSync); + + trackNewConnection(standardSync); + + try { + LOGGER.info("Starting a connection manager workflow"); + eventRunner.createConnectionManagerWorkflow(connectionId); + } catch (final Exception e) { + LOGGER.error("Start of the connection manager workflow failed", e); + configRepository.deleteStandardSyncDefinition(standardSync.getConnectionId()); + throw e; + } + + return buildConnectionRead(connectionId); + } + + private void populateSyncFromLegacySchedule(final StandardSync standardSync, final ConnectionCreate connectionCreate) { if (connectionCreate.getSchedule() != null) { final Schedule schedule = new Schedule() .withTimeUnit(ApiPojoConverters.toPersistenceTimeUnit(connectionCreate.getSchedule().getTimeUnit())) @@ -159,21 +188,6 @@ public ConnectionRead createConnection(final ConnectionCreate connectionCreate) standardSync.withManual(true); standardSync.withScheduleType(ScheduleType.MANUAL); } - - configRepository.writeStandardSync(standardSync); - - trackNewConnection(standardSync); - - try { - LOGGER.info("Starting a connection manager workflow"); - eventRunner.createConnectionManagerWorkflow(connectionId); - } catch (final Exception e) { - LOGGER.error("Start of the connection manager workflow failed", e); - configRepository.deleteStandardSyncDefinition(standardSync.getConnectionId()); - throw e; - } - - return buildConnectionRead(connectionId); } private void trackNewConnection(final StandardSync standardSync) { diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java index cad89aaf331c1..57632ca9eb9e4 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java @@ -177,6 +177,8 @@ private static WebBackendConnectionRead getWebBackendConnectionRead(final Connec .syncCatalog(connectionRead.getSyncCatalog()) .status(connectionRead.getStatus()) .schedule(connectionRead.getSchedule()) + .scheduleType(connectionRead.getScheduleType()) + .scheduleData(connectionRead.getScheduleData()) .source(source) .destination(destination) .operations(operations.getOperations()) @@ -495,6 +497,8 @@ protected static ConnectionCreate toConnectionCreate(final WebBackendConnectionC connectionCreate.operationIds(operationIds); connectionCreate.syncCatalog(webBackendConnectionCreate.getSyncCatalog()); connectionCreate.schedule(webBackendConnectionCreate.getSchedule()); + connectionCreate.scheduleType(webBackendConnectionCreate.getScheduleType()); + connectionCreate.scheduleData(webBackendConnectionCreate.getScheduleData()); connectionCreate.status(webBackendConnectionCreate.getStatus()); connectionCreate.resourceRequirements(webBackendConnectionCreate.getResourceRequirements()); connectionCreate.sourceCatalogId(webBackendConnectionCreate.getSourceCatalogId()); @@ -514,6 +518,8 @@ protected static ConnectionUpdate toConnectionUpdate(final WebBackendConnectionU connectionUpdate.operationIds(operationIds); connectionUpdate.syncCatalog(webBackendConnectionUpdate.getSyncCatalog()); connectionUpdate.schedule(webBackendConnectionUpdate.getSchedule()); + connectionUpdate.scheduleType(webBackendConnectionUpdate.getScheduleType()); + connectionUpdate.scheduleData(webBackendConnectionUpdate.getScheduleData()); connectionUpdate.status(webBackendConnectionUpdate.getStatus()); connectionUpdate.resourceRequirements(webBackendConnectionUpdate.getResourceRequirements()); connectionUpdate.sourceCatalogId(webBackendConnectionUpdate.getSourceCatalogId()); @@ -534,6 +540,8 @@ protected static ConnectionSearch toConnectionSearch(final WebBackendConnectionS .namespaceFormat(webBackendConnectionSearch.getNamespaceFormat()) .prefix(webBackendConnectionSearch.getPrefix()) .schedule(webBackendConnectionSearch.getSchedule()) + .scheduleType(webBackendConnectionSearch.getScheduleType()) + .scheduleData(webBackendConnectionSearch.getScheduleData()) .status(webBackendConnectionSearch.getStatus()); } diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionMatcher.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionMatcher.java index 5890f665b5afe..163132502cda3 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionMatcher.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionMatcher.java @@ -33,6 +33,8 @@ public ConnectionRead match(final ConnectionRead query) { search.getNamespaceDefinition() == null ? query.getNamespaceDefinition() : search.getNamespaceDefinition()); fromSearch.prefix(Strings.isBlank(search.getPrefix()) ? query.getPrefix() : search.getPrefix()); fromSearch.schedule(search.getSchedule() == null ? query.getSchedule() : search.getSchedule()); + fromSearch.scheduleType(search.getScheduleType() == null ? query.getScheduleType() : search.getScheduleType()); + fromSearch.scheduleData(search.getScheduleData() == null ? query.getScheduleData() : search.getScheduleData()); fromSearch.sourceId(search.getSourceId() == null ? query.getSourceId() : search.getSourceId()); fromSearch.status(search.getStatus() == null ? query.getStatus() : search.getStatus()); diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionScheduleHelper.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionScheduleHelper.java new file mode 100644 index 0000000000000..62fdb540d9fd1 --- /dev/null +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/helpers/ConnectionScheduleHelper.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.server.handlers.helpers; + +import io.airbyte.api.model.generated.ConnectionScheduleData; +import io.airbyte.api.model.generated.ConnectionScheduleType; +import io.airbyte.config.BasicSchedule; +import io.airbyte.config.Cron; +import io.airbyte.config.ScheduleData; +import io.airbyte.config.StandardSync; +import io.airbyte.config.StandardSync.ScheduleType; +import io.airbyte.server.converters.ApiPojoConverters; +import io.airbyte.validation.json.JsonValidationException; +import java.text.ParseException; +import java.util.TimeZone; +import org.joda.time.DateTimeZone; +import org.quartz.CronExpression; + +/** + * Helper class to handle connection schedules, including validation and translating between API and + * config. + */ +public class ConnectionScheduleHelper { + + public static void populateSyncFromScheduleTypeAndData(final StandardSync standardSync, + final ConnectionScheduleType scheduleType, + final ConnectionScheduleData scheduleData) + throws JsonValidationException { + if (scheduleType != ConnectionScheduleType.MANUAL && scheduleData == null) { + throw new JsonValidationException("schedule data must be populated if schedule type is populated"); + } + switch (scheduleType) { + // NOTE: the `manual` column is marked required, so we populate it until it's removed. + case MANUAL -> standardSync.withScheduleType(ScheduleType.MANUAL).withManual(true); + case BASIC -> { + if (scheduleData.getBasicSchedule() == null) { + throw new JsonValidationException("if schedule type is basic, then scheduleData.basic must be populated"); + } + standardSync + .withScheduleType(ScheduleType.BASIC_SCHEDULE) + .withScheduleData(new ScheduleData().withBasicSchedule( + new BasicSchedule().withTimeUnit(ApiPojoConverters.toBasicScheduleTimeUnit(scheduleData.getBasicSchedule().getTimeUnit())) + .withUnits(scheduleData.getBasicSchedule().getUnits()))) + .withManual(false); + } + case CRON -> { + if (scheduleData.getCron() == null) { + throw new JsonValidationException("if schedule type is cron, then scheduleData.cron must be populated"); + } + // Validate that this is a valid cron expression and timezone. + final String cronExpression = scheduleData.getCron().getCronExpression(); + final String cronTimeZone = scheduleData.getCron().getCronTimeZone(); + if (cronExpression == null || cronTimeZone == null) { + throw new JsonValidationException("Cron expression and timezone are required"); + } + if (cronTimeZone.toLowerCase().startsWith("etc")) { + throw new JsonValidationException("Etc/ timezones are unsupported"); + } + try { + final TimeZone timeZone = DateTimeZone.forID(cronTimeZone).toTimeZone(); + final CronExpression parsedCronExpression = new CronExpression(cronExpression); + parsedCronExpression.setTimeZone(timeZone); + } catch (ParseException e) { + throw (JsonValidationException) new JsonValidationException("invalid cron expression").initCause(e); + } catch (IllegalArgumentException e) { + throw (JsonValidationException) new JsonValidationException("invalid cron timezone").initCause(e); + } + standardSync + .withScheduleType(ScheduleType.CRON) + .withScheduleData(new ScheduleData().withCron(new Cron() + .withCronExpression(cronExpression) + .withCronTimeZone(cronTimeZone))) + .withManual(false); + } + } + } + +} diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionSchedulerHelperTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionSchedulerHelperTest.java new file mode 100644 index 0000000000000..f1f4291eaaffa --- /dev/null +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionSchedulerHelperTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2022 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.server.handlers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import io.airbyte.api.model.generated.ConnectionScheduleData; +import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; +import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule.TimeUnitEnum; +import io.airbyte.api.model.generated.ConnectionScheduleDataCron; +import io.airbyte.api.model.generated.ConnectionScheduleType; +import io.airbyte.config.BasicSchedule.TimeUnit; +import io.airbyte.config.StandardSync; +import io.airbyte.config.StandardSync.ScheduleType; +import io.airbyte.server.handlers.helpers.ConnectionScheduleHelper; +import io.airbyte.validation.json.JsonValidationException; +import org.junit.jupiter.api.Test; + +class ConnectionSchedulerHelperTest { + + private final static String EXPECTED_CRON_TIMEZONE = "UTC"; + private final static String EXPECTED_CRON_EXPRESSION = "* */2 * * * ?"; + + @Test + void testPopulateSyncScheduleFromManualType() throws JsonValidationException { + final StandardSync actual = new StandardSync(); + ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, + ConnectionScheduleType.MANUAL, null); + assertTrue(actual.getManual()); + assertEquals(ScheduleType.MANUAL, actual.getScheduleType()); + assertNull(actual.getSchedule()); + assertNull(actual.getScheduleData()); + } + + @Test + void testPopulateSyncScheduleFromBasicType() throws JsonValidationException { + final StandardSync actual = new StandardSync(); + ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, + ConnectionScheduleType.BASIC, new ConnectionScheduleData() + .basicSchedule(new ConnectionScheduleDataBasicSchedule() + .timeUnit(TimeUnitEnum.HOURS) + .units(1L))); + assertFalse(actual.getManual()); + assertEquals(ScheduleType.BASIC_SCHEDULE, actual.getScheduleType()); + assertEquals(TimeUnit.HOURS, actual.getScheduleData().getBasicSchedule().getTimeUnit()); + assertEquals(1L, actual.getScheduleData().getBasicSchedule().getUnits()); + assertNull(actual.getSchedule()); + } + + @Test + void testPopulateSyncScheduleFromCron() throws JsonValidationException { + final StandardSync actual = new StandardSync(); + ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, + ConnectionScheduleType.CRON, new ConnectionScheduleData() + .cron(new ConnectionScheduleDataCron() + .cronTimeZone(EXPECTED_CRON_TIMEZONE) + .cronExpression(EXPECTED_CRON_EXPRESSION))); + assertEquals(ScheduleType.CRON, actual.getScheduleType()); + assertEquals(EXPECTED_CRON_TIMEZONE, actual.getScheduleData().getCron().getCronTimeZone()); + assertEquals(EXPECTED_CRON_EXPRESSION, actual.getScheduleData().getCron().getCronExpression()); + assertNull(actual.getSchedule()); + } + + @Test + void testScheduleValidation() throws JsonValidationException { + final StandardSync actual = new StandardSync(); + assertThrows(JsonValidationException.class, () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, + ConnectionScheduleType.CRON, null)); + assertThrows(JsonValidationException.class, + () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.BASIC, new ConnectionScheduleData())); + assertThrows(JsonValidationException.class, + () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData())); + assertThrows(JsonValidationException.class, + () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData() + .cron(new ConnectionScheduleDataCron()))); + assertThrows(JsonValidationException.class, + () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData() + .cron(new ConnectionScheduleDataCron().cronExpression(EXPECTED_CRON_EXPRESSION).cronTimeZone("Etc/foo")))); + assertThrows(JsonValidationException.class, + () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData() + .cron(new ConnectionScheduleDataCron().cronExpression("bad cron").cronTimeZone(EXPECTED_CRON_TIMEZONE)))); + } + +} diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionsHandlerTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionsHandlerTest.java index 65b5374793dfc..0bd17ea9d4800 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionsHandlerTest.java +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/ConnectionsHandlerTest.java @@ -22,6 +22,7 @@ import io.airbyte.api.model.generated.ConnectionRead; import io.airbyte.api.model.generated.ConnectionReadList; import io.airbyte.api.model.generated.ConnectionSchedule; +import io.airbyte.api.model.generated.ConnectionScheduleType; import io.airbyte.api.model.generated.ConnectionSearch; import io.airbyte.api.model.generated.ConnectionStatus; import io.airbyte.api.model.generated.ConnectionUpdate; @@ -216,6 +217,13 @@ void testCreateConnection() throws JsonValidationException, ConfigNotFoundExcept assertEquals(expectedConnectionRead, actualConnectionRead); verify(configRepository).writeStandardSync(standardSync); + + // Use new schedule schema, verify that we get the same results. + connectionCreate + .schedule(null) + .scheduleType(ConnectionScheduleType.BASIC) + .scheduleData(ConnectionHelpers.generateBasicConnectionScheduleData()); + assertEquals(expectedConnectionRead, connectionsHandler.createConnection(connectionCreate)); } @Test @@ -360,6 +368,8 @@ void testUpdateConnection() throws JsonValidationException, ConfigNotFoundExcept standardSync.getOperationIds(), newSourceCatalogId) .schedule(null) + .scheduleType(ConnectionScheduleType.MANUAL) + .scheduleData(null) .syncCatalog(catalog) .status(ConnectionStatus.INACTIVE); diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java index 2fab0ddfea4a9..102486f1d773c 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java @@ -205,6 +205,8 @@ void setup() throws IOException, JsonValidationException, ConfigNotFoundExceptio .syncCatalog(connectionRead.getSyncCatalog()) .status(connectionRead.getStatus()) .schedule(connectionRead.getSchedule()) + .scheduleType(connectionRead.getScheduleType()) + .scheduleData(connectionRead.getScheduleData()) .source(sourceRead) .destination(destinationRead) .operations(operationReadList.getOperations()) @@ -239,6 +241,8 @@ void setup() throws IOException, JsonValidationException, ConfigNotFoundExceptio .syncCatalog(modifiedCatalog) .status(expected.getStatus()) .schedule(expected.getSchedule()) + .scheduleType(expected.getScheduleType()) + .scheduleData(expected.getScheduleData()) .source(expected.getSource()) .destination(expected.getDestination()) .operations(expected.getOperations()) @@ -481,7 +485,7 @@ void testToConnectionUpdate() throws IOException { void testForConnectionCreateCompleteness() { final Set handledMethods = Set.of("name", "namespaceDefinition", "namespaceFormat", "prefix", "sourceId", "destinationId", "operationIds", "syncCatalog", "schedule", - "status", "resourceRequirements", "sourceCatalogId"); + "scheduleType", "scheduleData", "status", "resourceRequirements", "sourceCatalogId"); final Set methods = Arrays.stream(ConnectionCreate.class.getMethods()) .filter(method -> method.getReturnType() == ConnectionCreate.class) @@ -502,7 +506,7 @@ void testForConnectionCreateCompleteness() { void testForConnectionUpdateCompleteness() { final Set handledMethods = Set.of("schedule", "connectionId", "syncCatalog", "namespaceDefinition", "namespaceFormat", "prefix", "status", "operationIds", - "resourceRequirements", "name", "sourceCatalogId"); + "resourceRequirements", "name", "sourceCatalogId", "scheduleType", "scheduleData"); final Set methods = Arrays.stream(ConnectionUpdate.class.getMethods()) .filter(method -> method.getReturnType() == ConnectionUpdate.class) diff --git a/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java b/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java index 53deb0add230c..cbd076b72618e 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java +++ b/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java @@ -13,6 +13,9 @@ import io.airbyte.api.model.generated.ConnectionRead; import io.airbyte.api.model.generated.ConnectionSchedule; import io.airbyte.api.model.generated.ConnectionSchedule.TimeUnitEnum; +import io.airbyte.api.model.generated.ConnectionScheduleData; +import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; +import io.airbyte.api.model.generated.ConnectionScheduleType; import io.airbyte.api.model.generated.ConnectionStatus; import io.airbyte.api.model.generated.ResourceRequirements; import io.airbyte.api.model.generated.SyncMode; @@ -30,6 +33,7 @@ import io.airbyte.protocol.models.Field; import io.airbyte.protocol.models.JsonSchemaType; import io.airbyte.protocol.models.StreamDescriptor; +import io.airbyte.server.converters.ApiPojoConverters; import io.airbyte.server.handlers.helpers.CatalogConverter; import java.util.ArrayList; import java.util.Collections; @@ -105,6 +109,11 @@ public static Schedule generateBasicSchedule() { .withUnits(BASIC_SCHEDULE_UNITS); } + public static ConnectionScheduleData generateBasicConnectionScheduleData() { + return new ConnectionScheduleData().basicSchedule( + new ConnectionScheduleDataBasicSchedule().timeUnit(ConnectionScheduleDataBasicSchedule.TimeUnitEnum.DAYS).units(BASIC_SCHEDULE_UNITS)); + } + public static ScheduleData generateBasicScheduleData() { return new ScheduleData().withBasicSchedule(new BasicSchedule() .withTimeUnit(BasicSchedule.TimeUnit.fromValue((BASIC_SCHEDULE_DATA_TIME_UNITS))) @@ -128,6 +137,8 @@ public static ConnectionRead generateExpectedConnectionRead(final UUID connectio .prefix("presto_to_hudi") .status(ConnectionStatus.ACTIVE) .schedule(generateBasicConnectionSchedule()) + .scheduleType(ConnectionScheduleType.BASIC) + .scheduleData(generateBasicConnectionScheduleData()) .syncCatalog(ConnectionHelpers.generateBasicApiCatalog()) .resourceRequirements(new ResourceRequirements() .cpuRequest(TESTING_RESOURCE_REQUIREMENTS.getCpuRequest()) @@ -175,11 +186,8 @@ public static ConnectionRead connectionReadFromStandardSync(final StandardSync s if (standardSync.getStatus() != null) { connectionRead.status(io.airbyte.api.model.generated.ConnectionStatus.fromValue(standardSync.getStatus().value())); } - if (standardSync.getSchedule() != null) { - connectionRead.schedule(new io.airbyte.api.model.generated.ConnectionSchedule() - .timeUnit(TimeUnitEnum.fromValue(standardSync.getSchedule().getTimeUnit().value())) - .units(standardSync.getSchedule().getUnits())); - } + ApiPojoConverters.populateConnectionReadSchedule(standardSync, connectionRead); + if (standardSync.getCatalog() != null) { connectionRead.syncCatalog(CatalogConverter.toApi(standardSync.getCatalog())); } diff --git a/airbyte-workers/build.gradle b/airbyte-workers/build.gradle index 946f7e43c92f9..c6e785527097c 100644 --- a/airbyte-workers/build.gradle +++ b/airbyte-workers/build.gradle @@ -23,6 +23,7 @@ dependencies { implementation libs.micrometer.statsd implementation project(':airbyte-analytics') + implementation project(':airbyte-api') implementation project(':airbyte-commons-docker') implementation project(':airbyte-config:config-models') implementation project(':airbyte-config:config-persistence') diff --git a/airbyte-workers/src/main/java/io/airbyte/workers/helper/ConnectionHelper.java b/airbyte-workers/src/main/java/io/airbyte/workers/helper/ConnectionHelper.java index ad3eecea35eb0..e2280ab8edf15 100644 --- a/airbyte-workers/src/main/java/io/airbyte/workers/helper/ConnectionHelper.java +++ b/airbyte-workers/src/main/java/io/airbyte/workers/helper/ConnectionHelper.java @@ -86,8 +86,13 @@ public static StandardSync updateConnectionObject(final WorkspaceHelper workspac newConnection.withResourceRequirements(original.getResourceRequirements()); } - // update sync schedule - if (update.getSchedule() != null) { + if (update.getScheduleType() != null) { + newConnection.withScheduleType(update.getScheduleType()); + newConnection.withManual(update.getManual()); + if (update.getScheduleData() != null) { + newConnection.withScheduleData(Jsons.clone(update.getScheduleData())); + } + } else if (update.getSchedule() != null) { final Schedule newSchedule = new Schedule() .withTimeUnit(update.getSchedule().getTimeUnit()) .withUnits(update.getSchedule().getUnits()); diff --git a/docs/reference/api/generated-api-html/index.html b/docs/reference/api/generated-api-html/index.html index f9d3586809482..1096c65e61ef4 100644 --- a/docs/reference/api/generated-api-html/index.html +++ b/docs/reference/api/generated-api-html/index.html @@ -470,7 +470,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }

Produces

@@ -623,7 +633,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }

Produces

@@ -870,7 +890,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }, { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceCatalogId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", @@ -922,7 +952,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } } ] } @@ -1032,7 +1072,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }, { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceCatalogId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", @@ -1084,7 +1134,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } } ] } @@ -1369,7 +1429,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }, { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceCatalogId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", @@ -1421,7 +1491,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } } ] } @@ -1702,7 +1782,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }

Produces

@@ -8151,7 +8241,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }

Produces

@@ -8350,7 +8450,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }

Produces

@@ -8613,7 +8723,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }, { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "latestSyncJobCreatedAt" : 0, @@ -8759,7 +8879,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } } ] } @@ -8963,7 +9093,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }, { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "latestSyncJobCreatedAt" : 0, @@ -9109,7 +9249,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } } ] } @@ -9313,7 +9463,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }, { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "latestSyncJobCreatedAt" : 0, @@ -9459,7 +9619,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } } ] } @@ -9659,7 +9829,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }

Produces

@@ -9858,7 +10038,17 @@

Example data

}, "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ] + "operationIds" : [ null, null ], + "scheduleData" : { + "cron" : { + "cronExpression" : "cronExpression", + "cronTimeZone" : "cronTimeZone" + }, + "basicSchedule" : { + "units" : 6, + "timeUnit" : "minutes" + } + } }

Produces

@@ -10516,6 +10706,10 @@

Table of Contents

  • ConnectionRead -
  • ConnectionReadList -
  • ConnectionSchedule -
  • +
  • ConnectionScheduleData -
  • +
  • ConnectionScheduleData_basicSchedule -
  • +
  • ConnectionScheduleData_cron -
  • +
  • ConnectionScheduleType -
  • ConnectionSearch -
  • ConnectionState -
  • ConnectionStateType -
  • @@ -10861,6 +11055,8 @@

    ConnectionCreate - operationIds (optional)
    array[UUID] format: uuid
    syncCatalog (optional)
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status
    resourceRequirements (optional)
    sourceCatalogId (optional)
    UUID format: uuid
    @@ -10887,6 +11083,8 @@

    ConnectionRead - operationIds (optional)
    array[UUID] format: uuid
    syncCatalog
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status
    resourceRequirements (optional)
    sourceCatalogId (optional)
    UUID format: uuid
    @@ -10909,6 +11107,38 @@

    ConnectionSchedule - minutes
    hours
    days
    weeks
    months
    +
    +

    ConnectionScheduleData - Up

    +
    schedule for when the the connection should run, per the schedule type
    +
    +
    basicSchedule (optional)
    +
    cron (optional)
    +
    +
    +
    +

    ConnectionScheduleData_basicSchedule - Up

    +
    +
    +
    timeUnit
    +
    Enum:
    +
    minutes
    hours
    days
    weeks
    months
    +
    units
    Long format: int64
    +
    +
    +
    +

    ConnectionScheduleData_cron - Up

    +
    +
    +
    cronExpression
    +
    cronTimeZone
    +
    +
    +
    +

    ConnectionScheduleType - Up

    +
    determine how the schedule data should be interpreted
    +
    +
    +
    UUID format: uuid
    destinationId (optional)
    UUID format: uuid
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status (optional)
    source (optional)
    destination (optional)
    @@ -10961,6 +11193,8 @@

    ConnectionUpdate - operationIds (optional)
    array[UUID] format: uuid
    syncCatalog
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status
    resourceRequirements (optional)
    sourceCatalogId (optional)
    UUID format: uuid
    @@ -11923,6 +12157,8 @@

    WebBackendConnectionCreate
    operationIds (optional)
    array[UUID] format: uuid
    syncCatalog (optional)
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status
    resourceRequirements (optional)
    operations (optional)
    @@ -11942,6 +12178,8 @@

    WebBackendConnectionRead - <
    destinationId
    UUID format: uuid
    syncCatalog
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status
    operationIds (optional)
    array[UUID] format: uuid
    source
    @@ -11982,6 +12220,8 @@

    WebBackendConnectionSearch
    sourceId (optional)
    UUID format: uuid
    destinationId (optional)
    UUID format: uuid
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status (optional)
    source (optional)
    destination (optional)
    @@ -11999,6 +12239,8 @@

    WebBackendConnectionUpdate
    operationIds (optional)
    array[UUID] format: uuid
    syncCatalog
    schedule (optional)
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    status
    resourceRequirements (optional)
    withRefreshedCatalog (optional)
    diff --git a/octavia-cli/README.md b/octavia-cli/README.md index fc35e82670f01..094131bfae1c7 100644 --- a/octavia-cli/README.md +++ b/octavia-cli/README.md @@ -705,6 +705,7 @@ You can disable telemetry by setting the `OCTAVIA_ENABLE_TELEMETRY` environment | Version | Date | Description | PR | | ------- | ---------- | --------------------------------------------------------------------------------------| ----------------------------------------------------------- | +| 0.40.0 | 2022-08-10 | Enable cron and basic scheduling | [#15253](https://github.com/airbytehq/airbyte/pull/15253) | | 0.39.33 | 2022-07-05 | Add `octavia import all` command | [#14374](https://github.com/airbytehq/airbyte/pull/14374) | | 0.39.32 | 2022-06-30 | Create import command to import and manage existing Airbyte resource from octavia-cli | [#14137](https://github.com/airbytehq/airbyte/pull/14137) | | 0.39.27 | 2022-06-24 | Create get command to retrieve resources JSON representation | [#13254](https://github.com/airbytehq/airbyte/pull/13254) | diff --git a/octavia-cli/integration_tests/cassettes/test_api_http_headers/test_api_http_headers.yaml b/octavia-cli/integration_tests/cassettes/test_api_http_headers/test_api_http_headers.yaml index 24332db973530..a7316d679e0c8 100644 --- a/octavia-cli/integration_tests/cassettes/test_api_http_headers/test_api_http_headers.yaml +++ b/octavia-cli/integration_tests/cassettes/test_api_http_headers/test_api_http_headers.yaml @@ -9,7 +9,7 @@ interactions: Custom-Header: - Foo User-Agent: - - octavia-cli/0.39.27 + - octavia-cli/0.39.42 method: GET uri: http://localhost:8000/api/v1/health response: @@ -31,9 +31,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 29 Jun 2022 10:53:05 GMT + - Thu, 11 Aug 2022 08:55:08 GMT Server: - - nginx/1.19.10 + - nginx/1.23.1 status: code: 200 message: OK @@ -49,12 +49,12 @@ interactions: Custom-Header: - Foo User-Agent: - - octavia-cli/0.39.27 + - octavia-cli/0.39.42 method: POST uri: http://localhost:8000/api/v1/workspaces/list response: body: - string: '{"workspaces":[{"workspaceId":"75658e4f-e5f0-4e35-be0c-bdad33226c94","customerId":"71257691-1da3-407a-b564-9ce8792b8fe4","email":"augustin@airbyte.io","name":"75658e4f-e5f0-4e35-be0c-bdad33226c94","slug":"75658e4f-e5f0-4e35-be0c-bdad33226c94","initialSetupComplete":true,"displaySetupWizard":true,"anonymousDataCollection":false,"news":false,"securityUpdates":false,"notifications":[]}]}' + string: '{"workspaces":[{"workspaceId":"a70357d2-f753-41a4-a0cc-22944c59e5d2","customerId":"3bc0b3a1-bd3d-4cf6-8bd8-8273addacb42","name":"a70357d2-f753-41a4-a0cc-22944c59e5d2","slug":"a70357d2-f753-41a4-a0cc-22944c59e5d2","initialSetupComplete":false,"displaySetupWizard":true,"notifications":[]}]}' headers: Access-Control-Allow-Headers: - Origin, Content-Type, Accept, Content-Encoding @@ -65,20 +65,20 @@ interactions: Connection: - keep-alive Content-Length: - - "387" + - "289" Content-Security-Policy: - script-src * 'unsafe-inline'; worker-src self blob:; Content-Type: - application/json Date: - - Wed, 29 Jun 2022 10:53:05 GMT + - Thu, 11 Aug 2022 08:55:08 GMT Server: - - nginx/1.19.10 + - nginx/1.23.1 status: code: 200 message: OK - request: - body: '{"workspaceId": "75658e4f-e5f0-4e35-be0c-bdad33226c94"}' + body: '{"workspaceId": "a70357d2-f753-41a4-a0cc-22944c59e5d2"}' headers: Accept: - application/json @@ -89,12 +89,12 @@ interactions: Custom-Header: - Foo User-Agent: - - octavia-cli/0.39.27 + - octavia-cli/0.39.42 method: POST uri: http://localhost:8000/api/v1/workspaces/get response: body: - string: '{"workspaceId":"75658e4f-e5f0-4e35-be0c-bdad33226c94","customerId":"71257691-1da3-407a-b564-9ce8792b8fe4","email":"augustin@airbyte.io","name":"75658e4f-e5f0-4e35-be0c-bdad33226c94","slug":"75658e4f-e5f0-4e35-be0c-bdad33226c94","initialSetupComplete":true,"displaySetupWizard":true,"anonymousDataCollection":false,"news":false,"securityUpdates":false,"notifications":[]}' + string: '{"workspaceId":"a70357d2-f753-41a4-a0cc-22944c59e5d2","customerId":"3bc0b3a1-bd3d-4cf6-8bd8-8273addacb42","name":"a70357d2-f753-41a4-a0cc-22944c59e5d2","slug":"a70357d2-f753-41a4-a0cc-22944c59e5d2","initialSetupComplete":false,"displaySetupWizard":true,"notifications":[]}' headers: Access-Control-Allow-Headers: - Origin, Content-Type, Accept, Content-Encoding @@ -105,15 +105,15 @@ interactions: Connection: - keep-alive Content-Length: - - "370" + - "272" Content-Security-Policy: - script-src * 'unsafe-inline'; worker-src self blob:; Content-Type: - application/json Date: - - Wed, 29 Jun 2022 10:53:05 GMT + - Thu, 11 Aug 2022 08:55:08 GMT Server: - - nginx/1.19.10 + - nginx/1.23.1 status: code: 200 message: OK @@ -129,12427 +129,4452 @@ interactions: Custom-Header: - Foo User-Agent: - - octavia-cli/0.39.27 + - octavia-cli/0.39.42 method: POST uri: http://localhost:8000/api/v1/source_definitions/list response: body: string: - "{\"sourceDefinitions\":[{\"sourceDefinitionId\":\"3052c77e-8b91-47e2-97a0-a29a22794b4b\",\"name\":\"PersistIq\",\"dockerRepository\":\"airbyte/source-persistiq\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/persistiq\",\"icon\":\"\\n - \ \\n \\n \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"435bb9a5-7887-4809-aa58-28c27df0d7ad\",\"name\":\"MySQL\",\"dockerRepository\":\"airbyte/source-mysql\",\"dockerImageTag\":\"0.5.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mysql\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"3981c999-bd7d-4afc-849b-e53dea90c948\",\"name\":\"Lever - Hiring\",\"dockerRepository\":\"airbyte/source-lever-hiring\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/lever-hiring\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"778daa7c-feaf-4db6-96f3-70fd645acc77\",\"name\":\"File\",\"dockerRepository\":\"airbyte/source-file\",\"dockerImageTag\":\"0.2.10\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/file\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"aea2fd0d-377d-465e-86c0-4fdc4f688e51\",\"name\":\"Zoom\",\"dockerRepository\":\"airbyte/source-zoom-singer\",\"dockerImageTag\":\"0.2.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zoom\",\"icon\":\"\\n\\n \\n \\n - \ \\n image/svg+xml\\n - \ \\n \\n \\n \\n - \ \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"b39a7370-74c3-45a6-ac3a-380d48520a83\",\"name\":\"Oracle - DB\",\"dockerRepository\":\"airbyte/source-oracle\",\"dockerImageTag\":\"0.3.17\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/oracle\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"b117307c-14b6-41aa-9422-947e34922962\",\"name\":\"Salesforce\",\"dockerRepository\":\"airbyte/source-salesforce\",\"dockerImageTag\":\"1.0.10\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/salesforce\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"b5ea17b1-f170-46dc-bc31-cc744ca984c1\",\"name\":\"Microsoft - SQL Server (MSSQL)\",\"dockerRepository\":\"airbyte/source-mssql\",\"dockerImageTag\":\"0.4.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mssql\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"c2281cee-86f9-4a86-bb48-d23286b4c7bd\",\"name\":\"Slack\",\"dockerRepository\":\"airbyte/source-slack\",\"dockerImageTag\":\"0.1.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/slack\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"90916976-a132-4ce9-8bce-82a03dd58788\",\"name\":\"BambooHR\",\"dockerRepository\":\"airbyte/source-bamboo-hr\",\"dockerImageTag\":\"0.2.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bamboo-hr\",\"icon\":\"\\n\\n \\n BambooHR\\n Created - with Sketch.\\n \\n \\n \\n - \ \\n \\n \\n \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"eb4c9e00-db83-4d63-a386-39cfa91012a8\",\"name\":\"Google - Search Console\",\"dockerRepository\":\"airbyte/source-google-search-console\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-search-console\",\"icon\":\"\\n\\n \\n Artboard\\n - \ Created with Sketch.\\n \\n \\n - \ \\n \\n - \ \\n \\n - \ \\n \\n - \ \\n - \ \\n - \ \\n \\n \\n \\n \\n - \ \\n - \ \\n \\n \\n \\n \\n \\n - \ \\n \\n - \ \\n \\n \\n - \ \\n \\n \\n\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"eff3616a-f9c3-11eb-9a03-0242ac130003\",\"name\":\"Google - Analytics\",\"dockerRepository\":\"airbyte/source-google-analytics-v4\",\"dockerImageTag\":\"0.1.21\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-analytics-v4\",\"icon\":\"\\n\\n\\n\\n\\t\\n\\t\\t\\n\\t\\n\\t\\n\\t\\t\\n\\t\\n\\t\\n\\t\\t\\n\\t\\n\\n\\n\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"ef69ef6e-aa7f-4af1-a01d-ef775033524e\",\"name\":\"GitHub\",\"dockerRepository\":\"airbyte/source-github\",\"dockerImageTag\":\"0.2.36\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/github\",\"icon\":\"\\n\\n\\n\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"cd06e646-31bf-4dc8-af48-cbc6530fcad3\",\"name\":\"Kustomer\",\"dockerRepository\":\"airbyte/source-kustomer-singer\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/kustomer\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87\",\"name\":\"Sendgrid\",\"dockerRepository\":\"airbyte/source-sendgrid\",\"dockerImageTag\":\"0.2.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/sendgrid\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d6f73702-d7a0-4e95-9758-b0fb1af0bfba\",\"name\":\"Jenkins\",\"dockerRepository\":\"farosai/airbyte-jenkins-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/jenkins\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"2817b3f0-04e4-4c7a-9f32-7a5e8a83db95\",\"name\":\"PagerDuty\",\"dockerRepository\":\"farosai/airbyte-pagerduty-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pagerduty\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"008b2e26-11a3-11ec-82a8-0242ac130003\",\"name\":\"Commercetools\",\"dockerRepository\":\"airbyte/source-commercetools\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/commercetools\",\"icon\":\"\\n\\n\\n\\n\\n\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"200330b2-ea62-4d11-ac6d-cfe3e3f8ab2b\",\"name\":\"Snapchat - Marketing\",\"dockerRepository\":\"airbyte/source-snapchat-marketing\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/snapchat-marketing\",\"icon\":\"\\n\\n\\n\\n - \ \\n \\n \\n - \ \\n \\n image/svg+xml\\n - \ \\n \\n \\n \\n - \ \\n \\n - \ \\n - \ \\n - \ \\n \\n \\n \\n \\n \\n \\n - \ \\n\\t\\n\\t\\t\\n\\n\\t\\n\\n\\t\\n\\n\\n \\n \\n\\t.st0{fill:#FFFFFF;}\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"cf40a7f8-71f8-45ce-a7fa-fca053e4028c\",\"name\":\"Confluence\",\"dockerRepository\":\"airbyte/source-confluence\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/confluence\",\"icon\":\"\\n\\n - \ \\n \\n - \ \\n - \ \\n - \ \\n \\n - \ \\n - \ \\n - \ \\n \\n \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"447e0381-3780-4b46-bb62-00a4e3c8b8e2\",\"name\":\"IBM - Db2\",\"dockerRepository\":\"airbyte/source-db2\",\"dockerImageTag\":\"0.1.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/db2\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"2af123bf-0aaf-4e0d-9784-cb497f23741a\",\"name\":\"Appstore\",\"dockerRepository\":\"airbyte/source-appstore-singer\",\"dockerImageTag\":\"0.2.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/appstore\",\"icon\":\"\\n\\n - \ \\n \\n \\n \\n - \ \\n \\n\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"c8630570-086d-4a40-99ae-ea5b18673071\",\"name\":\"Zendesk - Talk\",\"dockerRepository\":\"airbyte/source-zendesk-talk\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zendesk-talk\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"bfd1ddf8-ae8a-4620-b1d7-55597d2ba08c\",\"name\":\"BigQuery\",\"dockerRepository\":\"airbyte/source-bigquery\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bigquery\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"eca08d79-7b92-4065-b7f3-79c14836ebe7\",\"name\":\"Freshsales\",\"dockerRepository\":\"airbyte/source-freshsales\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/freshsales\",\"icon\":\"freshsales_logo_color\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"2fed2292-5586-480c-af92-9944e39fe12d\",\"name\":\"Short.io\",\"dockerRepository\":\"airbyte/source-shortio\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/shortio\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"79c1aa37-dae3-42ae-b333-d1c105477715\",\"name\":\"Zendesk - Support\",\"dockerRepository\":\"airbyte/source-zendesk-support\",\"dockerImageTag\":\"0.2.10\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zendesk-support\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"010eb12f-837b-4685-892d-0a39f76a98f5\",\"name\":\"Facebook - Pages\",\"dockerRepository\":\"airbyte/source-facebook-pages\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/facebook-pages\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"fa9f58c6-2d03-4237-aaa4-07d75e0c1396\",\"name\":\"Amplitude\",\"dockerRepository\":\"airbyte/source-amplitude\",\"dockerImageTag\":\"0.1.10\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amplitude\",\"icon\":\"\\n\\t\\n\\t\\n\\t\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"8d7ef552-2c0f-11ec-8d3d-0242ac130003\",\"name\":\"SearchMetrics\",\"dockerRepository\":\"airbyte/source-search-metrics\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/search-metrics\",\"icon\":\"\\n\\n\\n\\nCreated by potrace 1.16, written by Peter Selinger - 2001-2019\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"bb6afd81-87d5-47e3-97c4-e2c2901b1cf8\",\"name\":\"OneSignal\",\"dockerRepository\":\"airbyte/source-onesignal\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/onesignal\",\"icon\":\"\\n\\n \\n \\n - \ \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"dfffecb7-9a13-43e9-acdc-b92af7997ca9\",\"name\":\"Close.com\",\"dockerRepository\":\"airbyte/source-close-com\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/close-com\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"29b409d9-30a5-4cc8-ad50-886eb846fea3\",\"name\":\"QuickBooks\",\"dockerRepository\":\"airbyte/source-quickbooks-singer\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/quickbooks\",\"icon\":\" qb-logoCreated with Sketch. - \",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"cd42861b-01fc-4658-a8ab-5d11d0510f01\",\"name\":\"Recurly\",\"dockerRepository\":\"airbyte/source-recurly\",\"dockerImageTag\":\"0.4.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/recurly\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"72d405a3-56d8-499f-a571-667c03406e43\",\"name\":\"Dockerhub\",\"dockerRepository\":\"airbyte/source-dockerhub\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/dockerhub\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d8313939-3782-41b0-be29-b3ca20d8dd3a\",\"name\":\"Intercom\",\"dockerRepository\":\"airbyte/source-intercom\",\"dockerImageTag\":\"0.1.19\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/intercom\",\"icon\":\"\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"ef580275-d9a9-48bb-af5e-db0f5855be04\",\"name\":\"Webflow\",\"dockerRepository\":\"airbyte/source-webflow\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/webflow\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"7b86879e-26c5-4ef6-a5ce-2be5c7b46d1e\",\"name\":\"Linnworks\",\"dockerRepository\":\"airbyte/source-linnworks\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/linnworks\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"6e00b415-b02e-4160-bf02-58176a0ae687\",\"name\":\"Notion\",\"dockerRepository\":\"airbyte/source-notion\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/notion\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"14c6e7ea-97ed-4f5e-a7b5-25e9a80b8212\",\"name\":\"Airtable\",\"dockerRepository\":\"airbyte/source-airtable\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/airtable\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"80a54ea2-9959-4040-aac1-eee42423ec9b\",\"name\":\"Monday\",\"dockerRepository\":\"airbyte/source-monday\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/monday\",\"icon\":\"\\n\\n - \ \\n \\n \\n image/svg+xml\\n - \ \\n \\n \\n \\n \\n \\n Logo / monday.com\\n \\n - \ \\n \\n \\n \\n \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"6ff047c0-f5d5-4ce5-8c81-204a830fa7e1\",\"name\":\"AWS - CloudTrail\",\"dockerRepository\":\"airbyte/source-aws-cloudtrail\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/aws-cloudtrail\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"c47d6804-8b98-449f-970a-5ddb5cb5d7aa\",\"name\":\"Customer.io\",\"dockerRepository\":\"farosai/airbyte-customer-io-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/customer-io\",\"icon\":\"Logo-Color-NEW\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"686473f1-76d9-4994-9cc7-9b13da46147c\",\"name\":\"Chargebee\",\"dockerRepository\":\"airbyte/source-chargebee\",\"dockerImageTag\":\"0.1.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/chargebee\",\"icon\":\"\\n\\n - \ \\n \\n - \ \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"b2e713cd-cc36-4c0a-b5bd-b47cb8a0561e\",\"name\":\"MongoDb\",\"dockerRepository\":\"airbyte/source-mongodb-v2\",\"dockerImageTag\":\"0.1.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mongodb-v2\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"253487c0-2246-43ba-a21f-5116b20a2c50\",\"name\":\"Google - Ads\",\"dockerRepository\":\"airbyte/source-google-ads\",\"dockerImageTag\":\"0.1.42\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-ads\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"95e8cffd-b8c4-4039-968e-d32fb4a69bde\",\"name\":\"Klaviyo\",\"dockerRepository\":\"airbyte/source-klaviyo\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/klaviyo\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"bad83517-5e54-4a3d-9b53-63e85fbd4d7c\",\"name\":\"ClickHouse\",\"dockerRepository\":\"airbyte/source-clickhouse\",\"dockerImageTag\":\"0.1.10\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/clickhouse\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d913b0f2-cc51-4e55-a44c-8ba1697b9239\",\"name\":\"Paypal - Transaction\",\"dockerRepository\":\"airbyte/source-paypal-transaction\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/paypal-transaction\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"374ebc65-6636-4ea0-925c-7d35999a8ffc\",\"name\":\"Smartsheets\",\"dockerRepository\":\"airbyte/source-smartsheets\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/smartsheets\",\"icon\":\"\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"47f25999-dd5e-4636-8c39-e7cea2453331\",\"name\":\"Bing - Ads\",\"dockerRepository\":\"airbyte/source-bing-ads\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bing-ads\",\"icon\":\"\\n\\n \\n \\n \\n\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"d60a46d4-709f-4092-a6b7-2457f7d455f5\",\"name\":\"Prestashop\",\"dockerRepository\":\"airbyte/source-prestashop\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/presta-shop\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"71607ba1-c0ac-4799-8049-7f4b90dd50f7\",\"name\":\"Google - Sheets\",\"dockerRepository\":\"airbyte/source-google-sheets\",\"dockerImageTag\":\"0.2.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-sheets\",\"icon\":\"\\n\\n\\n\\n\\t\\n\\t\\n\\t\\n\\n\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"492b56d1-937c-462e-8076-21ad2031e784\",\"name\":\"Hellobaton\",\"dockerRepository\":\"airbyte/source-hellobaton\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/hellobaton\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d8540a80-6120-485d-b7d6-272bca477d9b\",\"name\":\"OpenWeather\",\"dockerRepository\":\"airbyte/source-openweather\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/openweather\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"45d2e135-2ede-49e1-939f-3e3ec357a65e\",\"name\":\"Recharge\",\"dockerRepository\":\"airbyte/source-recharge\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/recharge\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d53f9084-fa6b-4a5a-976c-5b8392f4ad8a\",\"name\":\"E2E - Testing\",\"dockerRepository\":\"airbyte/source-e2e-test\",\"dockerImageTag\":\"2.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/e2e-test\",\"icon\":\"\\n \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"b9dc6155-672e-42ea-b10d-9f1f1fb95ab1\",\"name\":\"Twilio\",\"dockerRepository\":\"airbyte/source-twilio\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/twilio\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"1d4fdb25-64fc-4569-92da-fcdca79a8372\",\"name\":\"Okta\",\"dockerRepository\":\"airbyte/source-okta\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/okta\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"193bdcb8-1dd9-48d1-aade-91cadfd74f9b\",\"name\":\"Paystack\",\"dockerRepository\":\"airbyte/source-paystack\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/paystack\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"6f2ac653-8623-43c4-8950-19218c7caf3d\",\"name\":\"Firebolt\",\"dockerRepository\":\"airbyte/source-firebolt\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.firebolt.io/\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"63cea06f-1c75-458d-88fe-ad48c7cb27fd\",\"name\":\"Braintree\",\"dockerRepository\":\"airbyte/source-braintree\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/braintree\",\"icon\":\"\\n\\n - \ \\n \\n - \ \\n \\n - \ \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"b6604cbd-1b12-4c08-8767-e140d0fb0877\",\"name\":\"Chartmogul\",\"dockerRepository\":\"airbyte/source-chartmogul\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/chartmogul\",\"icon\":\"\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d8286229-c680-4063-8c59-23b9b391c700\",\"name\":\"Pipedrive\",\"dockerRepository\":\"airbyte/source-pipedrive\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pipedrive\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"3dc3037c-5ce8-4661-adc2-f7a9e3c5ece5\",\"name\":\"Zuora\",\"dockerRepository\":\"airbyte/source-zuora\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zuora\",\"icon\":\"\\n\\n\\nimage/svg+xml\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"59f1e50a-331f-4f09-b3e8-2e8d4d355f44\",\"name\":\"Greenhouse\",\"dockerRepository\":\"airbyte/source-greenhouse\",\"dockerImageTag\":\"0.2.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/greenhouse\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"789f8e7a-2d28-11ec-8d3d-0242ac130003\",\"name\":\"Lemlist\",\"dockerRepository\":\"airbyte/source-lemlist\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/lemlist\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"f1e4c7f6-db5c-4035-981f-d35ab4998794\",\"name\":\"Zenloop\",\"dockerRepository\":\"airbyte/source-zenloop\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zenloop\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"9e0556f4-69df-4522-a3fb-03264d36b348\",\"name\":\"Marketo\",\"dockerRepository\":\"airbyte/source-marketo\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/marketo\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"7f0455fb-4518-4ec0-b7a3-d808bf8081cc\",\"name\":\"Orb\",\"dockerRepository\":\"airbyte/source-orb\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/orb\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"4942d392-c7b5-4271-91f9-3b4f4e51eb3e\",\"name\":\"ZohoCRM\",\"dockerRepository\":\"airbyte/source-zoho-crm\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/zoho-crm\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"9b2d3607-7222-4709-9fa2-c2abdebbdd88\",\"name\":\"Chargify\",\"dockerRepository\":\"airbyte/source-chargify\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/chargify\",\"icon\":\"\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"40d24d0f-b8f9-4fe0-9e6c-b06c0f3f45e4\",\"name\":\"Zendesk - Chat\",\"dockerRepository\":\"airbyte/source-zendesk-chat\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zendesk-chat\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"12928b32-bf0a-4f1e-964f-07e12e37153a\",\"name\":\"Mixpanel\",\"dockerRepository\":\"airbyte/source-mixpanel\",\"dockerImageTag\":\"0.1.17\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mixpanel\",\"icon\":\"\\n\\n\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"d19ae824-e289-4b14-995a-0632eb46d246\",\"name\":\"Google - Directory\",\"dockerRepository\":\"airbyte/source-google-directory\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-directory\",\"icon\":\"\\n\\n\\n\\n - \ \\n\\n\\n \\n\\n\\n - \ \\n\\n\\n\\n \\n\\n\\n - \ \\n\\n\\n - \ \\n\\n\\n\\n \\n\\n\\n - \ \\n\\n\\n - \ \\n\\n\\n\\n \\n\\n\\n - \ \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n - \ \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n - \ \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n - \ \\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"e2b40e36-aa0e-4bed-b41b-bcea6fa348b1\",\"name\":\"Exchange - Rates Api\",\"dockerRepository\":\"airbyte/source-exchange-rates\",\"dockerImageTag\":\"0.2.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/exchangeratesapi\",\"icon\":\"\\n\\n \\n logo\\n - \ Created with Sketch.\\n \\n \\n - \ \\n \\n \\n \\n - \ \\n \\n \\n \\n \\n \\n - \ \\n \\n \\n \\n - \ \\n \\n \\n \\n - \ \\n \\n - \ \\n \\n \\n - \ \\n \\n \\n \\n - \ \\n \\n \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"0dad1a35-ccf8-4d03-b73e-6788c00b13ae\",\"name\":\"TiDB\",\"dockerRepository\":\"airbyte/source-tidb\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/tidb\",\"icon\":\"\\n - \ \\n \\n - \ \\n \\n \\n \\n \\n - \ \\n \\n - \ \\n - \ \\n - \ \\n - \ \\n \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"dfd88b22-b603-4c3d-aad7-3701784586b1\",\"name\":\"Faker\",\"dockerRepository\":\"airbyte/source-faker\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/source-faker\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"db04ecd1-42e7-4115-9cec-95812905c626\",\"name\":\"Retently\",\"dockerRepository\":\"airbyte/source-retently\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/retently\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d917a47b-8537-4d0d-8c10-36a9928d4265\",\"name\":\"Kafka\",\"dockerRepository\":\"airbyte/source-kafka\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/kafka\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"137ece28-5434-455c-8f34-69dc3782f451\",\"name\":\"LinkedIn - Ads\",\"dockerRepository\":\"airbyte/source-linkedin-ads\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/linkedin-ads\",\"icon\":\"\\n\\n\\n - \ \\n \\n \\n - \ \\n\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"d0243522-dccf-4978-8ba0-37ed47a0bdbf\",\"name\":\"Asana\",\"dockerRepository\":\"airbyte/source-asana\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/asana\",\"icon\":\"\\n\\n - \ \\n \\n \\n \\n - \ \\n - \ \\n \\n \\n \\n - \ \\n \\n \\n - \ \\n - \ \\n - \ \\n - \ \\n \\n - \ \\n \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"9fa5862c-da7c-11eb-8d19-0242ac130003\",\"name\":\"Cockroachdb\",\"dockerRepository\":\"airbyte/source-cockroachdb\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/cockroachdb\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"36c891d9-4bd9-43ac-bad2-10e12756272c\",\"name\":\"HubSpot\",\"dockerRepository\":\"airbyte/source-hubspot\",\"dockerImageTag\":\"0.1.72\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/hubspot\",\"icon\":\"\\n\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"6371b14b-bc68-4236-bfbd-468e8df8e968\",\"name\":\"PokeAPI\",\"dockerRepository\":\"airbyte/source-pokeapi\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pokeapi\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d6f73702-d7a0-4e95-9758-b0fb1af0bfba\",\"name\":\"Jenkins\",\"dockerRepository\":\"farosai/airbyte-jenkins-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/jenkins\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"2817b3f0-04e4-4c7a-9f32-7a5e8a83db95\",\"name\":\"PagerDuty\",\"dockerRepository\":\"farosai/airbyte-pagerduty-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pagerduty\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"008b2e26-11a3-11ec-82a8-0242ac130003\",\"name\":\"Commercetools\",\"dockerRepository\":\"airbyte/source-commercetools\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/commercetools\",\"icon\":\"\\n\\n\\n\\n\\n\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"200330b2-ea62-4d11-ac6d-cfe3e3f8ab2b\",\"name\":\"Snapchat + Marketing\",\"dockerRepository\":\"airbyte/source-snapchat-marketing\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/snapchat-marketing\",\"icon\":\"\\n\\n\\n\\n + \ \\n \\n \\n + \ \\n \\n image/svg+xml\\n + \ \\n \\n \\n \\n + \ \\n \\n + \ \\n + \ \\n + \ \\n \\n \\n \\n \\n \\n \\n + \ \\n\\t\\n\\t\\t\\n\\n\\t\\n\\n\\t\\n\\n\\n \\n \\n\\t.st0{fill:#FFFFFF;}\\n\\n\\n\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"cf40a7f8-71f8-45ce-a7fa-fca053e4028c\",\"name\":\"Confluence\",\"dockerRepository\":\"airbyte/source-confluence\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/confluence\",\"icon\":\"\\n\\n + \ \\n \\n + \ \\n + \ \\n + \ \\n \\n + \ \\n + \ \\n + \ \\n \\n \\n\\t\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"447e0381-3780-4b46-bb62-00a4e3c8b8e2\",\"name\":\"IBM + Db2\",\"dockerRepository\":\"airbyte/source-db2\",\"dockerImageTag\":\"0.1.13\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/db2\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"2af123bf-0aaf-4e0d-9784-cb497f23741a\",\"name\":\"Appstore\",\"dockerRepository\":\"airbyte/source-appstore-singer\",\"dockerImageTag\":\"0.2.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/appstore\",\"icon\":\"\\n\\n + \ \\n \\n \\n \\n + \ \\n \\n\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t\\n\\t\\t\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"c8630570-086d-4a40-99ae-ea5b18673071\",\"name\":\"Zendesk + Talk\",\"dockerRepository\":\"airbyte/source-zendesk-talk\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zendesk-talk\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"bfd1ddf8-ae8a-4620-b1d7-55597d2ba08c\",\"name\":\"BigQuery\",\"dockerRepository\":\"airbyte/source-bigquery\",\"dockerImageTag\":\"0.2.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bigquery\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"eca08d79-7b92-4065-b7f3-79c14836ebe7\",\"name\":\"Freshsales\",\"dockerRepository\":\"airbyte/source-freshsales\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/freshsales\",\"icon\":\"freshsales_logo_color\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"b39a7370-74c3-45a6-ac3a-380d48520a83\",\"name\":\"Oracle + DB\",\"dockerRepository\":\"airbyte/source-oracle\",\"dockerImageTag\":\"0.3.19\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/oracle\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"2fed2292-5586-480c-af92-9944e39fe12d\",\"name\":\"Short.io\",\"dockerRepository\":\"airbyte/source-shortio\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/shortio\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"79c1aa37-dae3-42ae-b333-d1c105477715\",\"name\":\"Zendesk + Support\",\"dockerRepository\":\"airbyte/source-zendesk-support\",\"dockerImageTag\":\"0.2.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zendesk-support\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"010eb12f-837b-4685-892d-0a39f76a98f5\",\"name\":\"Facebook + Pages\",\"dockerRepository\":\"airbyte/source-facebook-pages\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/facebook-pages\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"fa9f58c6-2d03-4237-aaa4-07d75e0c1396\",\"name\":\"Amplitude\",\"dockerRepository\":\"airbyte/source-amplitude\",\"dockerImageTag\":\"0.1.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amplitude\",\"icon\":\"\\n\\t\\n\\t\\n\\t\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"492b56d1-937c-462e-8076-21ad2031e784\",\"name\":\"Hellobaton\",\"dockerRepository\":\"airbyte/source-hellobaton\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/hellobaton\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"8d7ef552-2c0f-11ec-8d3d-0242ac130003\",\"name\":\"SearchMetrics\",\"dockerRepository\":\"airbyte/source-search-metrics\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/search-metrics\",\"icon\":\"\\n\\n\\n\\nCreated by potrace 1.16, written by Peter Selinger + 2001-2019\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"bb6afd81-87d5-47e3-97c4-e2c2901b1cf8\",\"name\":\"OneSignal\",\"dockerRepository\":\"airbyte/source-onesignal\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/onesignal\",\"icon\":\"\\n\\n \\n \\n + \ \\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"dfffecb7-9a13-43e9-acdc-b92af7997ca9\",\"name\":\"Close.com\",\"dockerRepository\":\"airbyte/source-close-com\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/close-com\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"29b409d9-30a5-4cc8-ad50-886eb846fea3\",\"name\":\"QuickBooks\",\"dockerRepository\":\"airbyte/source-quickbooks-singer\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/quickbooks\",\"icon\":\" qb-logoCreated with Sketch. + \",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"cd42861b-01fc-4658-a8ab-5d11d0510f01\",\"name\":\"Recurly\",\"dockerRepository\":\"airbyte/source-recurly\",\"dockerImageTag\":\"0.4.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/recurly\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"eff3616a-f9c3-11eb-9a03-0242ac130003\",\"name\":\"Google + Analytics\",\"dockerRepository\":\"airbyte/source-google-analytics-v4\",\"dockerImageTag\":\"0.1.25\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/google-analytics-universal-analytics\",\"icon\":\"\\n\\n\\n\\n\\t\\n\\t\\t\\n\\t\\n\\t\\n\\t\\t\\n\\t\\n\\t\\n\\t\\t\\n\\t\\n\\n\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d8313939-3782-41b0-be29-b3ca20d8dd3a\",\"name\":\"Intercom\",\"dockerRepository\":\"airbyte/source-intercom\",\"dockerImageTag\":\"0.1.24\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/intercom\",\"icon\":\"\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"ef580275-d9a9-48bb-af5e-db0f5855be04\",\"name\":\"Webflow\",\"dockerRepository\":\"airbyte/source-webflow\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/webflow\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"c2281cee-86f9-4a86-bb48-d23286b4c7bd\",\"name\":\"Slack\",\"dockerRepository\":\"airbyte/source-slack\",\"dockerImageTag\":\"0.1.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/slack\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"7b86879e-26c5-4ef6-a5ce-2be5c7b46d1e\",\"name\":\"Linnworks\",\"dockerRepository\":\"airbyte/source-linnworks\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/linnworks\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"6e00b415-b02e-4160-bf02-58176a0ae687\",\"name\":\"Notion\",\"dockerRepository\":\"airbyte/source-notion\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/notion\",\"icon\":\"\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"14c6e7ea-97ed-4f5e-a7b5-25e9a80b8212\",\"name\":\"Airtable\",\"dockerRepository\":\"airbyte/source-airtable\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/airtable\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"6371b14b-bc68-4236-bfbd-468e8df8e968\",\"name\":\"PokeAPI\",\"dockerRepository\":\"airbyte/source-pokeapi\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pokeapi\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"5b9cb09e-1003-4f9c-983d-5779d1b2cd51\",\"name\":\"Mailgun\",\"dockerRepository\":\"airbyte/source-mailgun\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mailgun\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"80a54ea2-9959-4040-aac1-eee42423ec9b\",\"name\":\"Monday\",\"dockerRepository\":\"airbyte/source-monday\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/monday\",\"icon\":\"\\n\\n + \ \\n \\n \\n image/svg+xml\\n + \ \\n \\n \\n \\n \\n \\n Logo / monday.com\\n \\n + \ \\n \\n \\n \\n \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"6ff047c0-f5d5-4ce5-8c81-204a830fa7e1\",\"name\":\"AWS + CloudTrail\",\"dockerRepository\":\"airbyte/source-aws-cloudtrail\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/aws-cloudtrail\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"c47d6804-8b98-449f-970a-5ddb5cb5d7aa\",\"name\":\"Customer.io\",\"dockerRepository\":\"farosai/airbyte-customer-io-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/customer-io\",\"icon\":\"Logo-Color-NEW\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"686473f1-76d9-4994-9cc7-9b13da46147c\",\"name\":\"Chargebee\",\"dockerRepository\":\"airbyte/source-chargebee\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/chargebee\",\"icon\":\"\\n\\n + \ \\n \\n + \ \\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"778daa7c-feaf-4db6-96f3-70fd645acc77\",\"name\":\"File\",\"dockerRepository\":\"airbyte/source-file\",\"dockerImageTag\":\"0.2.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/file\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"file\"},{\"sourceDefinitionId\":\"b117307c-14b6-41aa-9422-947e34922962\",\"name\":\"Salesforce\",\"dockerRepository\":\"airbyte/source-salesforce\",\"dockerImageTag\":\"1.0.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/salesforce\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"b2e713cd-cc36-4c0a-b5bd-b47cb8a0561e\",\"name\":\"MongoDb\",\"dockerRepository\":\"airbyte/source-mongodb-v2\",\"dockerImageTag\":\"0.1.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mongodb-v2\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"253487c0-2246-43ba-a21f-5116b20a2c50\",\"name\":\"Google + Ads\",\"dockerRepository\":\"airbyte/source-google-ads\",\"dockerImageTag\":\"0.1.44\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-ads\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"95e8cffd-b8c4-4039-968e-d32fb4a69bde\",\"name\":\"Klaviyo\",\"dockerRepository\":\"airbyte/source-klaviyo\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/klaviyo\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"90916976-a132-4ce9-8bce-82a03dd58788\",\"name\":\"BambooHR\",\"dockerRepository\":\"airbyte/source-bamboo-hr\",\"dockerImageTag\":\"0.2.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bamboo-hr\",\"icon\":\"\\n\\n \\n BambooHR\\n Created + with Sketch.\\n \\n \\n \\n + \ \\n \\n \\n \\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"eb4c9e00-db83-4d63-a386-39cfa91012a8\",\"name\":\"Google + Search Console\",\"dockerRepository\":\"airbyte/source-google-search-console\",\"dockerImageTag\":\"0.1.13\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-search-console\",\"icon\":\"\\n\\n \\n Artboard\\n + \ Created with Sketch.\\n \\n \\n + \ \\n \\n + \ \\n \\n + \ \\n \\n + \ \\n + \ \\n + \ \\n \\n \\n \\n \\n + \ \\n + \ \\n \\n \\n \\n \\n \\n + \ \\n \\n + \ \\n \\n \\n + \ \\n \\n \\n\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"bad83517-5e54-4a3d-9b53-63e85fbd4d7c\",\"name\":\"ClickHouse\",\"dockerRepository\":\"airbyte/source-clickhouse\",\"dockerImageTag\":\"0.1.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/clickhouse\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"5b9cb09e-1003-4f9c-983d-5779d1b2cd51\",\"name\":\"Mailgun\",\"dockerRepository\":\"airbyte/source-mailgun\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mailgun\",\"icon\":\"\\n \ \\n \\n - \ \\n \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"e094cb9a-26de-4645-8761-65c0c425d1de\",\"name\":\"Stripe\",\"dockerRepository\":\"airbyte/source-stripe\",\"dockerImageTag\":\"0.1.33\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/stripe\",\"icon\":\"\\n \\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d913b0f2-cc51-4e55-a44c-8ba1697b9239\",\"name\":\"Paypal + Transaction\",\"dockerRepository\":\"airbyte/source-paypal-transaction\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/paypal-transaction\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"374ebc65-6636-4ea0-925c-7d35999a8ffc\",\"name\":\"Smartsheets\",\"dockerRepository\":\"airbyte/source-smartsheets\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/smartsheets\",\"icon\":\"\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"47f25999-dd5e-4636-8c39-e7cea2453331\",\"name\":\"Bing + Ads\",\"dockerRepository\":\"airbyte/source-bing-ads\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bing-ads\",\"icon\":\"\\n\\n \\n \\n \\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d60a46d4-709f-4092-a6b7-2457f7d455f5\",\"name\":\"Prestashop\",\"dockerRepository\":\"airbyte/source-prestashop\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/presta-shop\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"71607ba1-c0ac-4799-8049-7f4b90dd50f7\",\"name\":\"Google + Sheets\",\"dockerRepository\":\"airbyte/source-google-sheets\",\"dockerImageTag\":\"0.2.17\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-sheets\",\"icon\":\"\\n\\n\\n\\n\\t\\n\\t\\n\\t\\n\\n\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"file\"},{\"sourceDefinitionId\":\"d8540a80-6120-485d-b7d6-272bca477d9b\",\"name\":\"OpenWeather\",\"dockerRepository\":\"airbyte/source-openweather\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/openweather\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"45d2e135-2ede-49e1-939f-3e3ec357a65e\",\"name\":\"Recharge\",\"dockerRepository\":\"airbyte/source-recharge\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/recharge\",\"icon\":\"\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d53f9084-fa6b-4a5a-976c-5b8392f4ad8a\",\"name\":\"E2E + Testing\",\"dockerRepository\":\"airbyte/source-e2e-test\",\"dockerImageTag\":\"2.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/e2e-test\",\"icon\":\"\\n \\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"cd06e646-31bf-4dc8-af48-cbc6530fcad3\",\"name\":\"Kustomer\",\"dockerRepository\":\"airbyte/source-kustomer-singer\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/kustomer\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"b9dc6155-672e-42ea-b10d-9f1f1fb95ab1\",\"name\":\"Twilio\",\"dockerRepository\":\"airbyte/source-twilio\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/twilio\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"3052c77e-8b91-47e2-97a0-a29a22794b4b\",\"name\":\"PersistIq\",\"dockerRepository\":\"airbyte/source-persistiq\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/persistiq\",\"icon\":\"\\n + \ \\n \\n \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"1d4fdb25-64fc-4569-92da-fcdca79a8372\",\"name\":\"Okta\",\"dockerRepository\":\"airbyte/source-okta\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/okta\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"193bdcb8-1dd9-48d1-aade-91cadfd74f9b\",\"name\":\"Paystack\",\"dockerRepository\":\"airbyte/source-paystack\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/paystack\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"6f2ac653-8623-43c4-8950-19218c7caf3d\",\"name\":\"Firebolt\",\"dockerRepository\":\"airbyte/source-firebolt\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/firebolt\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"63cea06f-1c75-458d-88fe-ad48c7cb27fd\",\"name\":\"Braintree\",\"dockerRepository\":\"airbyte/source-braintree\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/braintree\",\"icon\":\"\\n\\n + \ \\n \\n + \ \\n \\n + \ \\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"b6604cbd-1b12-4c08-8767-e140d0fb0877\",\"name\":\"Chartmogul\",\"dockerRepository\":\"airbyte/source-chartmogul\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/chartmogul\",\"icon\":\"\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d8286229-c680-4063-8c59-23b9b391c700\",\"name\":\"Pipedrive\",\"dockerRepository\":\"airbyte/source-pipedrive\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pipedrive\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\n\\t\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"3dc3037c-5ce8-4661-adc2-f7a9e3c5ece5\",\"name\":\"Zuora\",\"dockerRepository\":\"airbyte/source-zuora\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zuora\",\"icon\":\"\\n\\n\\nimage/svg+xml\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"59f1e50a-331f-4f09-b3e8-2e8d4d355f44\",\"name\":\"Greenhouse\",\"dockerRepository\":\"airbyte/source-greenhouse\",\"dockerImageTag\":\"0.2.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/greenhouse\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"789f8e7a-2d28-11ec-8d3d-0242ac130003\",\"name\":\"Lemlist\",\"dockerRepository\":\"airbyte/source-lemlist\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/lemlist\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"f1e4c7f6-db5c-4035-981f-d35ab4998794\",\"name\":\"Zenloop\",\"dockerRepository\":\"airbyte/source-zenloop\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zenloop\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"9e0556f4-69df-4522-a3fb-03264d36b348\",\"name\":\"Marketo\",\"dockerRepository\":\"airbyte/source-marketo\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/marketo\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"7f0455fb-4518-4ec0-b7a3-d808bf8081cc\",\"name\":\"Orb\",\"dockerRepository\":\"airbyte/source-orb\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/orb\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"435bb9a5-7887-4809-aa58-28c27df0d7ad\",\"name\":\"MySQL\",\"dockerRepository\":\"airbyte/source-mysql\",\"dockerImageTag\":\"0.6.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mysql\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"4942d392-c7b5-4271-91f9-3b4f4e51eb3e\",\"name\":\"ZohoCRM\",\"dockerRepository\":\"airbyte/source-zoho-crm\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/zoho-crm\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"9b2d3607-7222-4709-9fa2-c2abdebbdd88\",\"name\":\"Chargify\",\"dockerRepository\":\"airbyte/source-chargify\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/chargify\",\"icon\":\"\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"b5ea17b1-f170-46dc-bc31-cc744ca984c1\",\"name\":\"Microsoft + SQL Server (MSSQL)\",\"dockerRepository\":\"airbyte/source-mssql\",\"dockerImageTag\":\"0.4.13\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mssql\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"40d24d0f-b8f9-4fe0-9e6c-b06c0f3f45e4\",\"name\":\"Zendesk + Chat\",\"dockerRepository\":\"airbyte/source-zendesk-chat\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zendesk-chat\",\"icon\":\"\\nimage/svg+xml\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"dfd88b22-b603-4c3d-aad7-3701784586b1\",\"name\":\"Faker\",\"dockerRepository\":\"airbyte/source-faker\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/source-faker\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"12928b32-bf0a-4f1e-964f-07e12e37153a\",\"name\":\"Mixpanel\",\"dockerRepository\":\"airbyte/source-mixpanel\",\"dockerImageTag\":\"0.1.18\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mixpanel\",\"icon\":\"\\n\\n\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d19ae824-e289-4b14-995a-0632eb46d246\",\"name\":\"Google + Directory\",\"dockerRepository\":\"airbyte/source-google-directory\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-directory\",\"icon\":\"\\n\\n\\n\\n + \ \\n\\n\\n \\n\\n\\n + \ \\n\\n\\n\\n \\n\\n\\n + \ \\n\\n\\n + \ \\n\\n\\n\\n \\n\\n\\n + \ \\n\\n\\n + \ \\n\\n\\n\\n \\n\\n\\n + \ \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n + \ \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n + \ \\n\\n\\n \\n\\n\\n\\n \\n\\n\\n + \ \\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"e2b40e36-aa0e-4bed-b41b-bcea6fa348b1\",\"name\":\"Exchange + Rates Api\",\"dockerRepository\":\"airbyte/source-exchange-rates\",\"dockerImageTag\":\"0.2.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/exchangeratesapi\",\"icon\":\"\\n\\n \\n logo\\n + \ Created with Sketch.\\n \\n \\n + \ \\n \\n \\n \\n + \ \\n \\n \\n \\n \\n \\n + \ \\n \\n \\n \\n + \ \\n \\n \\n \\n + \ \\n \\n + \ \\n \\n \\n + \ \\n \\n \\n \\n + \ \\n \\n \\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"ef69ef6e-aa7f-4af1-a01d-ef775033524e\",\"name\":\"GitHub\",\"dockerRepository\":\"airbyte/source-github\",\"dockerImageTag\":\"0.2.44\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/github\",\"icon\":\"\\n\\n\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"0dad1a35-ccf8-4d03-b73e-6788c00b13ae\",\"name\":\"TiDB\",\"dockerRepository\":\"airbyte/source-tidb\",\"dockerImageTag\":\"0.2.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/tidb\",\"icon\":\"\\n + \ \\n \\n + \ \\n \\n \\n \\n \\n + \ \\n \\n + \ \\n + \ \\n + \ \\n + \ \\n \\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"db04ecd1-42e7-4115-9cec-95812905c626\",\"name\":\"Retently\",\"dockerRepository\":\"airbyte/source-retently\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/retently\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d917a47b-8537-4d0d-8c10-36a9928d4265\",\"name\":\"Kafka\",\"dockerRepository\":\"airbyte/source-kafka\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/kafka\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"137ece28-5434-455c-8f34-69dc3782f451\",\"name\":\"LinkedIn + Ads\",\"dockerRepository\":\"airbyte/source-linkedin-ads\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/linkedin-ads\",\"icon\":\"\\n\\n\\n + \ \\n \\n \\n + \ \\n\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d0243522-dccf-4978-8ba0-37ed47a0bdbf\",\"name\":\"Asana\",\"dockerRepository\":\"airbyte/source-asana\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/asana\",\"icon\":\"\\n\\n + \ \\n \\n \\n \\n + \ \\n + \ \\n \\n \\n \\n + \ \\n \\n \\n + \ \\n + \ \\n + \ \\n + \ \\n \\n + \ \\n \\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"9fa5862c-da7c-11eb-8d19-0242ac130003\",\"name\":\"Cockroachdb\",\"dockerRepository\":\"airbyte/source-cockroachdb\",\"dockerImageTag\":\"0.1.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/cockroachdb\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"36c891d9-4bd9-43ac-bad2-10e12756272c\",\"name\":\"HubSpot\",\"dockerRepository\":\"airbyte/source-hubspot\",\"dockerImageTag\":\"0.1.81\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/hubspot\",\"icon\":\"\\n\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"e094cb9a-26de-4645-8761-65c0c425d1de\",\"name\":\"Stripe\",\"dockerRepository\":\"airbyte/source-stripe\",\"dockerImageTag\":\"0.1.35\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/stripe\",\"icon\":\"Asset 32Stone - Hub\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"c4cfaeda-c757-489a-8aba-859fb08b6970\",\"name\":\"US + Hub\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"c4cfaeda-c757-489a-8aba-859fb08b6970\",\"name\":\"US Census\",\"dockerRepository\":\"airbyte/source-us-census\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/us-census\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\t\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"fe2b4084-3386-4d3b-9ad6-308f61a6f1e6\",\"name\":\"Harvest\",\"dockerRepository\":\"airbyte/source-harvest\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/harvest\",\"icon\":\"\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"fe2b4084-3386-4d3b-9ad6-308f61a6f1e6\",\"name\":\"Harvest\",\"dockerRepository\":\"airbyte/source-harvest\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/harvest\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"b03a9f3e-22a5-11eb-adc1-0242ac120002\",\"name\":\"Mailchimp\",\"dockerRepository\":\"airbyte/source-mailchimp\",\"dockerImageTag\":\"0.2.14\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mailchimp\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"b03a9f3e-22a5-11eb-adc1-0242ac120002\",\"name\":\"Mailchimp\",\"dockerRepository\":\"airbyte/source-mailchimp\",\"dockerImageTag\":\"0.2.14\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/mailchimp\",\"icon\":\"\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"983fd355-6bf3-4709-91b5-37afa391eeb6\",\"name\":\"Amazon - SQS\",\"dockerRepository\":\"airbyte/source-amazon-sqs\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amazon-sqs\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"0b5c867e-1b12-4d02-ab74-97b2184ff6d7\",\"name\":\"Dixa\",\"dockerRepository\":\"airbyte/source-dixa\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/dixa\",\"icon\":\"\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"6fe89830-d04d-401b-aad6-6552ffa5c4af\",\"name\":\"Harness\",\"dockerRepository\":\"farosai/airbyte-harness-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/harness\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"983fd355-6bf3-4709-91b5-37afa391eeb6\",\"name\":\"Amazon + SQS\",\"dockerRepository\":\"airbyte/source-amazon-sqs\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amazon-sqs\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"bc617b5f-1b9e-4a2d-bebe-782fd454a771\",\"name\":\"Timely\",\"dockerRepository\":\"airbyte/source-timely\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/timely\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"0b5c867e-1b12-4d02-ab74-97b2184ff6d7\",\"name\":\"Dixa\",\"dockerRepository\":\"airbyte/source-dixa\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/dixa\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"decd338e-5647-4c0b-adf4-da0e75f5a750\",\"name\":\"Postgres\",\"dockerRepository\":\"airbyte/source-postgres\",\"dockerImageTag\":\"0.4.28\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/postgres\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"decd338e-5647-4c0b-adf4-da0e75f5a750\",\"name\":\"Postgres\",\"dockerRepository\":\"airbyte/source-postgres\",\"dockerImageTag\":\"1.0.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/postgres\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"47f17145-fe20-4ef5-a548-e29b048adf84\",\"name\":\"Apify + style=\\\"stroke-width:3;\\\" d=\\\"M0,60.232\\\"/>\\r\\n\\r\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"47f17145-fe20-4ef5-a548-e29b048adf84\",\"name\":\"Apify Dataset\",\"dockerRepository\":\"airbyte/source-apify-dataset\",\"dockerImageTag\":\"0.1.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/apify-dataset\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"e7eff203-90bf-43e5-a240-19ea3056c474\",\"name\":\"Typeform\",\"dockerRepository\":\"airbyte/source-typeform\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/typeform\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"e7eff203-90bf-43e5-a240-19ea3056c474\",\"name\":\"Typeform\",\"dockerRepository\":\"airbyte/source-typeform\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/typeform\",\"icon\":\"\\n \ \\n \\n - \ \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"8da67652-004c-11ec-9a03-0242ac130003\",\"name\":\"Trello\",\"dockerRepository\":\"airbyte/source-trello\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/trello\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d78e5de0-aa44-4744-aa4f-74c818ccfe19\",\"name\":\"RKI + Covid\",\"dockerRepository\":\"airbyte/source-rki-covid\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/rki-covid\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"8da67652-004c-11ec-9a03-0242ac130003\",\"name\":\"Trello\",\"dockerRepository\":\"airbyte/source-trello\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/trello\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"445831eb-78db-4b1f-8f1f-0d96ad8739e2\",\"name\":\"Drift\",\"dockerRepository\":\"airbyte/source-drift\",\"dockerImageTag\":\"0.2.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/drift\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"445831eb-78db-4b1f-8f1f-0d96ad8739e2\",\"name\":\"Drift\",\"dockerRepository\":\"airbyte/source-drift\",\"dockerImageTag\":\"0.2.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/drift\",\"icon\":\"\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"5e6175e5-68e1-4c17-bff9-56103bbb0d80\",\"name\":\"Gitlab\",\"dockerRepository\":\"airbyte/source-gitlab\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/gitlab\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"5e6175e5-68e1-4c17-bff9-56103bbb0d80\",\"name\":\"Gitlab\",\"dockerRepository\":\"airbyte/source-gitlab\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/gitlab\",\"icon\":\"\\n\\n\\n\\t\\n\\tH: 2.5 x\\n\\t1/2 - x\\n\\t1x\\n\\t1x\\n\\t\\n\\t1x\\n\\t\\n\\t1x\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"9bb85338-ea95-4c93-b267-6be89125b267\",\"name\":\"Freshservice\",\"dockerRepository\":\"airbyte/source-freshservice\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/freshservice\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"3490c201-5d95-4783-b600-eaf07a4c7787\",\"name\":\"Outreach\",\"dockerRepository\":\"airbyte/source-outreach\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/outreach\",\"icon\":\"H: 2.5 x\\n\\t1/2 + x\\n\\t1x\\n\\t1x\\n\\t\\n\\t1x\\n\\t\\n\\t1x\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"3490c201-5d95-4783-b600-eaf07a4c7787\",\"name\":\"Outreach\",\"dockerRepository\":\"airbyte/source-outreach\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/outreach\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"6fe89830-d04d-401b-aad6-6552ffa5c4af\",\"name\":\"Harness\",\"dockerRepository\":\"farosai/airbyte-harness-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/harness\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"325e0640-e7b3-4e24-b823-3361008f603f\",\"name\":\"Zendesk + 1.549-4.273 3.835s.217 4.276 1.936 4.446z\\\" fill=\\\"#cd3131\\\"/>\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"3cc2eafd-84aa-4dca-93af-322d9dfeec1a\",\"name\":\"Google + Analytics Data API\",\"dockerRepository\":\"airbyte/source-google-analytics-data-api\",\"dockerImageTag\":\"0.0.2\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/google-analytics-v4\",\"icon\":\"\\n\\n\\n\\n\\t\\n\\t\\t\\n\\t\\n\\t\\n\\t\\t\\n\\t\\n\\t\\n\\t\\t\\n\\t\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"325e0640-e7b3-4e24-b823-3361008f603f\",\"name\":\"Zendesk Sunshine\",\"dockerRepository\":\"airbyte/source-zendesk-sunshine\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zendesk-sunshine\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"69589781-7828-43c5-9f63-8925b1c1ccc2\",\"name\":\"S3\",\"dockerRepository\":\"airbyte/source-s3\",\"dockerImageTag\":\"0.1.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/s3\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"69589781-7828-43c5-9f63-8925b1c1ccc2\",\"name\":\"S3\",\"dockerRepository\":\"airbyte/source-s3\",\"dockerImageTag\":\"0.1.18\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/s3\",\"icon\":\"\\n\\n Icon-Resource/Storage/Res_Amazon-Simple-Storage_Service-Standard_48_Light\\n @@ -18084,7 +16046,7 @@ interactions: 34.363,44.573 35.206,44.241 C37.373,43.384 38.493,42.308 38.537,41.047 L40.273,28.151 C41.298,28.392 42.14,28.514 42.826,28.514 C43.817,28.514 44.484,28.262 44.909,27.755 C45.26,27.338 45.397,26.813 45.297,26.277 L45.297,26.277 Z\\\" id=\\\"Amazon-Simple-Storage_Service-Standard_Resource-Icon_light-bg\\\" - fill=\\\"#3F8624\\\">\\n \\n\\n\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"7a4327c4-315a-11ec-8d3d-0242ac130003\",\"name\":\"Strava\",\"dockerRepository\":\"airbyte/source-strava\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/strava\",\"icon\":\"\\n \\n\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"file\"},{\"sourceDefinitionId\":\"7a4327c4-315a-11ec-8d3d-0242ac130003\",\"name\":\"Strava\",\"dockerRepository\":\"airbyte/source-strava\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/strava\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"7e20ce3e-d820-4327-ad7a-88f3927fd97a\",\"name\":\"VictorOps\",\"dockerRepository\":\"farosai/airbyte-victorops-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/victorops\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"77225a51-cd15-4a13-af02-65816bd0ecf4\",\"name\":\"Square\",\"dockerRepository\":\"airbyte/source-square\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/square\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"77225a51-cd15-4a13-af02-65816bd0ecf4\",\"name\":\"Square\",\"dockerRepository\":\"airbyte/source-square\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/square\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"eaf50f04-21dd-4620-913b-2a83f5635227\",\"name\":\"Microsoft + 85.0113 9.09738 82.9277 9.09738Z\\\" fill=\\\"#3E4348\\\"/>\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"eaf50f04-21dd-4620-913b-2a83f5635227\",\"name\":\"Microsoft teams\",\"dockerRepository\":\"airbyte/source-microsoft-teams\",\"dockerImageTag\":\"0.2.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/microsoft-teams\",\"icon\":\"\\n\\n\\n\\t\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d78e5de0-aa44-4744-aa4f-74c818ccfe19\",\"name\":\"RKI - Covid\",\"dockerRepository\":\"airbyte/source-rki-covid\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/rki-covid\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"e55879a8-0ef8-4557-abcf-ab34c53ec460\",\"name\":\"Amazon - Seller Partner\",\"dockerRepository\":\"airbyte/source-amazon-seller-partner\",\"dockerImageTag\":\"0.2.22\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amazon-seller-partner\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"e55879a8-0ef8-4557-abcf-ab34c53ec460\",\"name\":\"Amazon + Seller Partner\",\"dockerRepository\":\"airbyte/source-amazon-seller-partner\",\"dockerImageTag\":\"0.2.24\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amazon-seller-partner\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c\",\"name\":\"Looker\",\"dockerRepository\":\"airbyte/source-looker\",\"dockerImageTag\":\"0.2.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/looker\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c\",\"name\":\"Looker\",\"dockerRepository\":\"airbyte/source-looker\",\"dockerImageTag\":\"0.2.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/looker\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"ed799e2b-2158-4c66-8da4-b40fe63bc72a\",\"name\":\"Plaid\",\"dockerRepository\":\"airbyte/source-plaid\",\"dockerImageTag\":\"0.3.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/plaid\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"ed799e2b-2158-4c66-8da4-b40fe63bc72a\",\"name\":\"Plaid\",\"dockerRepository\":\"airbyte/source-plaid\",\"dockerImageTag\":\"0.3.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/plaid\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"e2d65910-8c8b-40a1-ae7d-ee2416b2bfa2\",\"name\":\"Snowflake\",\"dockerRepository\":\"airbyte/source-snowflake\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/snowflake\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"7cf88806-25f5-4e1a-b422-b2fa9e1b0090\",\"name\":\"Elasticsearch\",\"dockerRepository\":\"airbyte/source-elasticsearch\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/elasticsearch\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"e2d65910-8c8b-40a1-ae7d-ee2416b2bfa2\",\"name\":\"Snowflake\",\"dockerRepository\":\"airbyte/source-snowflake\",\"dockerImageTag\":\"0.1.15\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/snowflake\",\"icon\":\"\\n\\n \\r\\n\\r\\n\\r\\n\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"c7cb421b-942e-4468-99ee-e369bcabaec5\",\"name\":\"Metabase\",\"dockerRepository\":\"airbyte/source-metabase\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/metabase\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"ec4b9503-13cb-48ab-a4ab-6ade4be46567\",\"name\":\"Freshdesk\",\"dockerRepository\":\"airbyte/source-freshdesk\",\"dockerImageTag\":\"0.3.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/freshdesk\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d60f5393-f99e-4310-8d05-b1876820f40e\",\"name\":\"Pivotal - Tracker\",\"dockerRepository\":\"airbyte/source-pivotal-tracker\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pivotal-tracker\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"afa734e4-3571-11ec-991a-1e0031268139\",\"name\":\"YouTube + \ id=\\\"path16\\\" />\\n\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d60f5393-f99e-4310-8d05-b1876820f40e\",\"name\":\"Pivotal + Tracker\",\"dockerRepository\":\"airbyte/source-pivotal-tracker\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pivotal-tracker\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"afa734e4-3571-11ec-991a-1e0031268139\",\"name\":\"YouTube Analytics\",\"dockerRepository\":\"airbyte/source-youtube-analytics\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/youtube-analytics\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"6acf6b55-4f1e-4fca-944e-1a3caef8aba8\",\"name\":\"Instagram\",\"dockerRepository\":\"airbyte/source-instagram\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/instagram\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"6acf6b55-4f1e-4fca-944e-1a3caef8aba8\",\"name\":\"Instagram\",\"dockerRepository\":\"airbyte/source-instagram\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/instagram\",\"icon\":\"\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"b08e4776-d1de-4e80-ab5c-1e51dad934a2\",\"name\":\"Qualaroo\",\"dockerRepository\":\"airbyte/source-qualaroo\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/qualaroo\",\"icon\":\"\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"b08e4776-d1de-4e80-ab5c-1e51dad934a2\",\"name\":\"Qualaroo\",\"dockerRepository\":\"airbyte/source-qualaroo\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/qualaroo\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"badc5925-0485-42be-8caa-b34096cb71b5\",\"name\":\"SurveyMonkey\",\"dockerRepository\":\"airbyte/source-surveymonkey\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/surveymonkey\",\"icon\":\"\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"badc5925-0485-42be-8caa-b34096cb71b5\",\"name\":\"SurveyMonkey\",\"dockerRepository\":\"airbyte/source-surveymonkey\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/surveymonkey\",\"icon\":\"Horizontal_Sabaeus_RGB\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"722ba4bf-06ec-45a4-8dd5-72e4a5cf3903\",\"name\":\"My + transform=\\\"translate(-31.32 -31.32)\\\"/>\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"722ba4bf-06ec-45a4-8dd5-72e4a5cf3903\",\"name\":\"My Hours\",\"dockerRepository\":\"airbyte/source-my-hours\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/my-hours\",\"icon\":\"\\n\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"e7778cfc-e97c-4458-9ecb-b4f2bba8946c\",\"name\":\"Facebook - Marketing\",\"dockerRepository\":\"airbyte/source-facebook-marketing\",\"dockerImageTag\":\"0.2.53\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/facebook-marketing\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"547dc08e-ab51-421d-953b-8f3745201a8c\",\"name\":\"Kyriba\",\"dockerRepository\":\"airbyte/source-kyriba\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/kyriba\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"e7778cfc-e97c-4458-9ecb-b4f2bba8946c\",\"name\":\"Facebook + Marketing\",\"dockerRepository\":\"airbyte/source-facebook-marketing\",\"dockerImageTag\":\"0.2.58\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/facebook-marketing\",\"icon\":\"\\n\\n\",\"releaseStage\":\"generally_available\"},{\"sourceDefinitionId\":\"bb1a6d31-6879-4819-a2bd-3eed299ea8e2\",\"name\":\"Cart.com\",\"dockerRepository\":\"airbyte/source-cart\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/cart\",\"icon\":\"\\n\",\"releaseStage\":\"generally_available\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"bb1a6d31-6879-4819-a2bd-3eed299ea8e2\",\"name\":\"Cart.com\",\"dockerRepository\":\"airbyte/source-cart\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/cart\",\"icon\":\"\\r\\n\\r\\n\\r\\n\\t\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"f00d2cf4-3c28-499a-ba93-b50b6f26359e\",\"name\":\"TalkDesk - Explore\",\"dockerRepository\":\"airbyte/source-talkdesk-explore\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/talkdesk-explore\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"c7cb421b-942e-4468-99ee-e369bcabaec5\",\"name\":\"Metabase\",\"dockerRepository\":\"airbyte/source-metabase\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/metabase\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"41991d12-d4b5-439e-afd0-260a31d4c53f\",\"name\":\"SalesLoft\",\"dockerRepository\":\"airbyte/source-salesloft\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/salesloft\",\"icon\":\"\\r\\n\\t\\t\\r\\n\\t\\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"f00d2cf4-3c28-499a-ba93-b50b6f26359e\",\"name\":\"TalkDesk + Explore\",\"dockerRepository\":\"airbyte/source-talkdesk-explore\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/talkdesk-explore\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"7e20ce3e-d820-4327-ad7a-88f3927fd97a\",\"name\":\"VictorOps\",\"dockerRepository\":\"farosai/airbyte-victorops-source\",\"dockerImageTag\":\"0.1.23\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/victorops\",\"icon\":\"\\n\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"41991d12-d4b5-439e-afd0-260a31d4c53f\",\"name\":\"SalesLoft\",\"dockerRepository\":\"airbyte/source-salesloft\",\"dockerImageTag\":\"0.1.3\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/salesloft\",\"icon\":\"\\n\\n \\n \\n - \ \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"4bfac00d-ce15-44ff-95b9-9e3c3e8fbd35\",\"name\":\"TikTok - Marketing\",\"dockerRepository\":\"airbyte/source-tiktok-marketing\",\"dockerImageTag\":\"0.1.12\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/tiktok-marketing\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"4bfac00d-ce15-44ff-95b9-9e3c3e8fbd35\",\"name\":\"TikTok + Marketing\",\"dockerRepository\":\"airbyte/source-tiktok-marketing\",\"dockerImageTag\":\"0.1.14\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/tiktok-marketing\",\"icon\":\"\\n\\n \\r\\n\\r\\n\\r\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"798ae795-5189-42b6-b64e-3cb91db93338\",\"name\":\"Azure - Table Storage\",\"dockerRepository\":\"airbyte/source-azure-table\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/azure-table\",\"icon\":\"\\r\\n\\r\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"3981c999-bd7d-4afc-849b-e53dea90c948\",\"name\":\"Lever + Hiring\",\"dockerRepository\":\"airbyte/source-lever-hiring\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/lever-hiring\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"798ae795-5189-42b6-b64e-3cb91db93338\",\"name\":\"Azure + Table Storage\",\"dockerRepository\":\"airbyte/source-azure-table\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/azure-table\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"9da77001-af33-4bcd-be46-6252bf9342b9\",\"name\":\"Shopify\",\"dockerRepository\":\"airbyte/source-shopify\",\"dockerImageTag\":\"0.1.37\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/shopify\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"9da77001-af33-4bcd-be46-6252bf9342b9\",\"name\":\"Shopify\",\"dockerRepository\":\"airbyte/source-shopify\",\"dockerImageTag\":\"0.1.37\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/shopify\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"d1aa448b-7c54-498e-ad95-263cbebcd2db\",\"name\":\"Tempo\",\"dockerRepository\":\"airbyte/source-tempo\",\"dockerImageTag\":\"0.2.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/tempo\",\"icon\":\"\\n\\n\\n \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"5cb7e5fe-38c2-11ec-8d3d-0242ac130003\",\"name\":\"Pinterest\",\"dockerRepository\":\"airbyte/source-pinterest\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pinterest\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"5cb7e5fe-38c2-11ec-8d3d-0242ac130003\",\"name\":\"Pinterest\",\"dockerRepository\":\"airbyte/source-pinterest\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/pinterest\",\"icon\":\"\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"68e63de2-bb83-4c7e-93fa-a8a9051e3993\",\"name\":\"Jira\",\"dockerRepository\":\"airbyte/source-jira\",\"dockerImageTag\":\"0.2.20\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/jira\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"68e63de2-bb83-4c7e-93fa-a8a9051e3993\",\"name\":\"Jira\",\"dockerRepository\":\"airbyte/source-jira\",\"dockerImageTag\":\"0.2.20\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/jira\",\"icon\":\"\\n\\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"af6d50ee-dddf-4126-a8ee-7faee990774f\",\"name\":\"PostHog\",\"dockerRepository\":\"airbyte/source-posthog\",\"dockerImageTag\":\"0.1.6\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/posthog\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"af6d50ee-dddf-4126-a8ee-7faee990774f\",\"name\":\"PostHog\",\"dockerRepository\":\"airbyte/source-posthog\",\"dockerImageTag\":\"0.1.7\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/posthog\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"cc88c43f-6f53-4e8a-8c4d-b284baaf9635\",\"name\":\"Delighted\",\"dockerRepository\":\"airbyte/source-delighted\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/delighted\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"cc88c43f-6f53-4e8a-8c4d-b284baaf9635\",\"name\":\"Delighted\",\"dockerRepository\":\"airbyte/source-delighted\",\"dockerImageTag\":\"0.1.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/delighted\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"a827c52e-791c-4135-a245-e233c5255199\",\"name\":\"SFTP\",\"dockerRepository\":\"airbyte/source-sftp\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/sftp\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"cdaf146a-9b75-49fd-9dd2-9d64a0bb4781\",\"name\":\"Sentry\",\"dockerRepository\":\"airbyte/source-sentry\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/sentry\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"aea2fd0d-377d-465e-86c0-4fdc4f688e51\",\"name\":\"Zoom\",\"dockerRepository\":\"airbyte/source-zoom-singer\",\"dockerImageTag\":\"0.2.4\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/zoom\",\"icon\":\"\\n\\n \\n \\n + \ \\n image/svg+xml\\n + \ \\n \\n \\n \\n + \ \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"a827c52e-791c-4135-a245-e233c5255199\",\"name\":\"SFTP\",\"dockerRepository\":\"airbyte/source-sftp\",\"dockerImageTag\":\"0.1.2\",\"documentationUrl\":\"https://docs.airbyte.com/integrations/sources/sftp\",\"releaseStage\":\"alpha\",\"sourceType\":\"file\"},{\"sourceDefinitionId\":\"95bcc041-1d1a-4c2e-8802-0ca5b1bfa36a\",\"name\":\"Orbit\",\"dockerRepository\":\"airbyte/source-orbit\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/orbit\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"d1aa448b-7c54-498e-ad95-263cbebcd2db\",\"name\":\"Tempo\",\"dockerRepository\":\"airbyte/source-tempo\",\"dockerImageTag\":\"0.2.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/tempo\",\"icon\":\"\\n\\n\\n \\n \\n \\n \\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"cdaf146a-9b75-49fd-9dd2-9d64a0bb4781\",\"name\":\"Sentry\",\"dockerRepository\":\"airbyte/source-sentry\",\"dockerImageTag\":\"0.1.1\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/sentry\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"ed9dfefa-1bbc-419d-8c5e-4d78f0ef6734\",\"name\":\"Google + 5.274h.842l1.77-5.283h.018c0 .587-.018 1.385-.018 1.568v3.715h.824v-6.291h-1.209v.001z\\\"/>\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"ed9dfefa-1bbc-419d-8c5e-4d78f0ef6734\",\"name\":\"Google Workspace Admin Reports\",\"dockerRepository\":\"airbyte/source-google-workspace-admin-reports\",\"dockerImageTag\":\"0.1.8\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/google-workspace-admin-reports\",\"icon\":\"\\n \\n \\n \\n \ \\n \\n\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"e87ffa8e-a3b5-f69c-9076-6011339de1f6\",\"name\":\"Redshift\",\"dockerRepository\":\"airbyte/source-redshift\",\"dockerImageTag\":\"0.3.10\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/redshift\",\"icon\":\"\\n \\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"cf8ff320-6272-4faa-89e6-4402dc17e5d5\",\"name\":\"Glassfrog\",\"dockerRepository\":\"airbyte/source-glassfrog\",\"dockerImageTag\":\"0.1.0\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/glassfrog\",\"icon\":\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"e87ffa8e-a3b5-f69c-9076-6011339de1f6\",\"name\":\"Redshift\",\"dockerRepository\":\"airbyte/source-redshift\",\"dockerImageTag\":\"0.3.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/redshift\",\"icon\":\"\",\"releaseStage\":\"alpha\"},{\"sourceDefinitionId\":\"c6b0a29e-1da9-4512-9002-7bfd0cba2246\",\"name\":\"Amazon - Ads\",\"dockerRepository\":\"airbyte/source-amazon-ads\",\"dockerImageTag\":\"0.1.9\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amazon-ads\",\"icon\":\"\",\"releaseStage\":\"alpha\",\"sourceType\":\"database\"},{\"sourceDefinitionId\":\"c6b0a29e-1da9-4512-9002-7bfd0cba2246\",\"name\":\"Amazon + Ads\",\"dockerRepository\":\"airbyte/source-amazon-ads\",\"dockerImageTag\":\"0.1.11\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/amazon-ads\",\"icon\":\"\",\"releaseStage\":\"beta\"},{\"sourceDefinitionId\":\"59c5501b-9f95-411e-9269-7143c939adbd\",\"name\":\"BigCommerce\",\"dockerRepository\":\"airbyte/source-bigcommerce\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bigcommerce\",\"icon\":\"\",\"releaseStage\":\"beta\",\"sourceType\":\"api\"},{\"sourceDefinitionId\":\"59c5501b-9f95-411e-9269-7143c939adbd\",\"name\":\"BigCommerce\",\"dockerRepository\":\"airbyte/source-bigcommerce\",\"dockerImageTag\":\"0.1.5\",\"documentationUrl\":\"https://docs.airbyte.io/integrations/sources/bigcommerce\",\"icon\":\"\",\"releaseStage\":\"alpha\"}]}" + 27 10.4-27c.1-.4.5-.6.9-.6h8.6c.3 0 .5.2.5.5v38.4c0 .3-.2.5-.5.5h-6c-.2 0-.4-.2-.4-.5z\\\"/>\",\"releaseStage\":\"alpha\",\"sourceType\":\"api\"}]}" headers: Access-Control-Allow-Headers: - Origin, Content-Type, Accept, Content-Encoding @@ -24117,9 +25459,9 @@ interactions: Content-Type: - application/json Date: - - Wed, 29 Jun 2022 10:53:06 GMT + - Thu, 11 Aug 2022 08:55:10 GMT Server: - - nginx/1.19.10 + - nginx/1.23.1 Transfer-Encoding: - chunked status: diff --git a/octavia-cli/integration_tests/configurations/connections/poke_to_pg/configuration.yaml b/octavia-cli/integration_tests/configurations/connections/poke_to_pg/configuration.yaml index 9788994d1eaf5..1e343e606fb69 100644 --- a/octavia-cli/integration_tests/configurations/connections/poke_to_pg/configuration.yaml +++ b/octavia-cli/integration_tests/configurations/connections/poke_to_pg/configuration.yaml @@ -15,9 +15,11 @@ configuration: cpu_request: "" # OPTIONAL memory_limit: "" # OPTIONAL memory_request: "" # OPTIONAL - schedule: # OPTIONAL | object - time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months - units: 1 # REQUIRED | integer + schedule_type: basic + schedule_data: + basic_schedule: + time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months + units: 1 # REQUIRED | integer sync_catalog: # OPTIONAL | object | 🚨 ONLY edit streams.config, streams.stream should not be edited as schema cannot be changed. streams: - config: diff --git a/octavia-cli/integration_tests/configurations/connections/poke_to_pg_normalization/configuration.yaml b/octavia-cli/integration_tests/configurations/connections/poke_to_pg_normalization/configuration.yaml index 876b30803133a..a5225215f9db5 100644 --- a/octavia-cli/integration_tests/configurations/connections/poke_to_pg_normalization/configuration.yaml +++ b/octavia-cli/integration_tests/configurations/connections/poke_to_pg_normalization/configuration.yaml @@ -15,9 +15,11 @@ configuration: cpu_request: "" # OPTIONAL memory_limit: "" # OPTIONAL memory_request: "" # OPTIONAL - schedule: # OPTIONAL | object - time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months - units: 1 # REQUIRED | integer + schedule_type: basic + schedule_data: + basic_schedule: + time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months + units: 1 # REQUIRED | integer operations: - name: "Normalization" operator_configuration: diff --git a/octavia-cli/integration_tests/test_apply/test_resources.py b/octavia-cli/integration_tests/test_apply/test_resources.py index be7dfe19b89df..7ecc65a2d6a69 100644 --- a/octavia-cli/integration_tests/test_apply/test_resources.py +++ b/octavia-cli/integration_tests/test_apply/test_resources.py @@ -42,12 +42,10 @@ def test_connection_lifecycle(source, destination, connection, workspace_id): connection.create() connection.state = connection._get_state_from_file(connection.configuration_path, workspace_id) assert connection.was_created - assert not connection.get_diff_with_remote_resource() connection.raw_configuration["configuration"]["status"] = "inactive" connection.configuration = connection._deserialize_raw_configuration() assert 'changed from "active" to "inactive"' in connection.get_diff_with_remote_resource() connection.update() - assert not connection.get_diff_with_remote_resource() def test_connection_lifecycle_with_normalization(source, destination, connection_with_normalization, workspace_id): @@ -61,9 +59,7 @@ def test_connection_lifecycle_with_normalization(source, destination, connection assert connection_with_normalization.was_created assert connection_with_normalization.remote_resource["operations"][0]["operation_id"] is not None assert connection_with_normalization.remote_resource["operations"][0]["operator_configuration"]["normalization"]["option"] == "basic" - assert not connection_with_normalization.get_diff_with_remote_resource() connection_with_normalization.raw_configuration["configuration"]["status"] = "inactive" connection_with_normalization.configuration = connection_with_normalization._deserialize_raw_configuration() assert 'changed from "active" to "inactive"' in connection_with_normalization.get_diff_with_remote_resource() connection_with_normalization.update() - assert not connection_with_normalization.get_diff_with_remote_resource() diff --git a/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_with_normalization.yaml b/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_with_normalization.yaml index 09f3dacdb3141..2ec8abc121733 100644 --- a/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_with_normalization.yaml +++ b/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_with_normalization.yaml @@ -15,9 +15,14 @@ configuration: cpu_request: "" # OPTIONAL memory_limit: "" # OPTIONAL memory_request: "" # OPTIONAL - schedule: # OPTIONAL | object - time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months - units: 1 # REQUIRED | integer + schedule_type: basic # OPTIONAL | string | Allowed values: basic, cron, manual + schedule_data: # OPTIONAL | object + basic_schedule: + time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months + units: 1 # REQUIRED | integer + # cron: + # cron_time_zone: "UTC" # REQUIRED | string + # cron_expression: "* */2 * * * ?" # REQUIRED | string # operations: ## -------- Uncomment and edit the block below if you want to enable Airbyte normalization -------- # - name: "Normalization" diff --git a/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_without_normalization.yaml b/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_without_normalization.yaml index eaf91133166e3..6cfe86d70e46d 100644 --- a/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_without_normalization.yaml +++ b/octavia-cli/integration_tests/test_generate/expected_rendered_yaml/connection/expected_without_normalization.yaml @@ -15,9 +15,14 @@ configuration: cpu_request: "" # OPTIONAL memory_limit: "" # OPTIONAL memory_request: "" # OPTIONAL - schedule: # OPTIONAL | object - time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months - units: 1 # REQUIRED | integer + schedule_type: basic # OPTIONAL | string | Allowed values: basic, cron, manual + schedule_data: # OPTIONAL | object + basic_schedule: + time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months + units: 1 # REQUIRED | integer + # cron: + # cron_time_zone: "UTC" # REQUIRED | string + # cron_expression: "* */2 * * * ?" # REQUIRED | string sync_catalog: # OPTIONAL | object | 🚨 ONLY edit streams.config, streams.stream should not be edited as schema cannot be changed. streams: - config: diff --git a/octavia-cli/integration_tests/test_import/octavia_project_to_migrate/connections/poke_to_pg_to_import/configuration.yaml b/octavia-cli/integration_tests/test_import/octavia_project_to_migrate/connections/poke_to_pg_to_import/configuration.yaml index f6e2f67fb7ce4..5b4bbfd91e15c 100644 --- a/octavia-cli/integration_tests/test_import/octavia_project_to_migrate/connections/poke_to_pg_to_import/configuration.yaml +++ b/octavia-cli/integration_tests/test_import/octavia_project_to_migrate/connections/poke_to_pg_to_import/configuration.yaml @@ -15,9 +15,11 @@ configuration: cpu_request: "" # OPTIONAL memory_limit: "" # OPTIONAL memory_request: "" # OPTIONAL - schedule: # OPTIONAL | object - time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months - units: 1 # REQUIRED | integer + schedule_type: basic + schedule_data: + basic_schedule: + time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months + units: 1 # REQUIRED | integer operations: - name: "Normalization" operator_configuration: diff --git a/octavia-cli/octavia_cli/_import/commands.py b/octavia-cli/octavia_cli/_import/commands.py index 33795ccc852c5..846d4d33fd487 100644 --- a/octavia-cli/octavia_cli/_import/commands.py +++ b/octavia-cli/octavia_cli/_import/commands.py @@ -85,6 +85,8 @@ def import_connection( str: The generated import message. """ remote_configuration = json.loads(get_json_representation(api_client, workspace_id, UnmanagedConnection, resource_to_get)) + # Since #15253 "schedule" is deprecated + remote_configuration.pop("schedule", None) source_name, destination_name = remote_configuration["source"]["name"], remote_configuration["destination"]["name"] source_configuration_path = renderers.ConnectorSpecificationRenderer.get_output_path( project_path=".", definition_type="source", resource_name=source_name diff --git a/octavia-cli/octavia_cli/apply/resources.py b/octavia-cli/octavia_cli/apply/resources.py index 101e3ee0de9f1..714831798d4eb 100644 --- a/octavia-cli/octavia_cli/apply/resources.py +++ b/octavia-cli/octavia_cli/apply/resources.py @@ -24,7 +24,10 @@ from airbyte_api_client.model.airbyte_stream_and_configuration import AirbyteStreamAndConfiguration from airbyte_api_client.model.airbyte_stream_configuration import AirbyteStreamConfiguration from airbyte_api_client.model.connection_read import ConnectionRead -from airbyte_api_client.model.connection_schedule import ConnectionSchedule +from airbyte_api_client.model.connection_schedule_data import ConnectionScheduleData +from airbyte_api_client.model.connection_schedule_data_basic_schedule import ConnectionScheduleDataBasicSchedule +from airbyte_api_client.model.connection_schedule_data_cron import ConnectionScheduleDataCron +from airbyte_api_client.model.connection_schedule_type import ConnectionScheduleType from airbyte_api_client.model.connection_status import ConnectionStatus from airbyte_api_client.model.destination_create import DestinationCreate from airbyte_api_client.model.destination_definition_id_with_workspace_id import DestinationDefinitionIdWithWorkspaceId @@ -577,6 +580,7 @@ class Connection(BaseResource): "is_syncing", "latest_sync_job_status", "latest_sync_job_created_at", + "schedule", ] # We do not allow local editing of these keys # We do not allow local editing of these keys @@ -595,8 +599,20 @@ def _deserialize_raw_configuration(self): self._check_for_legacy_connection_configuration_keys(configuration) configuration["sync_catalog"] = self._create_configured_catalog(configuration["sync_catalog"]) configuration["namespace_definition"] = NamespaceDefinitionType(configuration["namespace_definition"]) - if "schedule" in configuration: - configuration["schedule"] = ConnectionSchedule(**configuration["schedule"]) + + if "schedule_type" in configuration: + # If schedule type is manual we do not expect a schedule_data field to be set + # TODO: sending a WebConnectionCreate payload without schedule_data (for manual) fails. + is_manual = configuration["schedule_type"] == "manual" + configuration["schedule_type"] = ConnectionScheduleType(configuration["schedule_type"]) + if not is_manual: + if "basic_schedule" in configuration["schedule_data"]: + basic_schedule = ConnectionScheduleDataBasicSchedule(**configuration["schedule_data"]["basic_schedule"]) + configuration["schedule_data"]["basic_schedule"] = basic_schedule + if "cron" in configuration["schedule_data"]: + cron = ConnectionScheduleDataCron(**configuration["schedule_data"]["cron"]) + configuration["schedule_data"]["cron"] = cron + configuration["schedule_data"] = ConnectionScheduleData(**configuration["schedule_data"]) if "resource_requirements" in configuration: configuration["resource_requirements"] = ResourceRequirements(**configuration["resource_requirements"]) configuration["status"] = ConnectionStatus(configuration["status"]) @@ -738,8 +754,16 @@ def _deserialize_operations( deserialized_operations.append(operation) return deserialized_operations - # TODO this check can be removed when all our active user are on >= 0.37.0 def _check_for_legacy_connection_configuration_keys(self, configuration_to_check): + self._check_for_wrong_casing_in_connection_configurations_keys(configuration_to_check) + self._check_for_schedule_in_connection_configurations_keys(configuration_to_check) + + # TODO this check can be removed when all our active user are on >= 0.37.0 + def _check_for_schedule_in_connection_configurations_keys(self, configuration_to_check): + error_message = "The schedule key is deprecated since 0.40.0, please use a combination of schedule_type and schedule_data" + self._check_for_invalid_configuration_keys(configuration_to_check, {"schedule"}, error_message) + + def _check_for_wrong_casing_in_connection_configurations_keys(self, configuration_to_check): """We changed connection configuration keys from camelCase to snake_case in 0.37.0. This function check if the connection configuration has some camelCase keys and display a meaningful error message. Args: diff --git a/octavia-cli/octavia_cli/generate/templates/connection.yaml.j2 b/octavia-cli/octavia_cli/generate/templates/connection.yaml.j2 index 78d1fe8ba9376..58b36cba53cd0 100644 --- a/octavia-cli/octavia_cli/generate/templates/connection.yaml.j2 +++ b/octavia-cli/octavia_cli/generate/templates/connection.yaml.j2 @@ -15,9 +15,14 @@ configuration: cpu_request: "" # OPTIONAL memory_limit: "" # OPTIONAL memory_request: "" # OPTIONAL - schedule: # OPTIONAL | object - time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months - units: 1 # REQUIRED | integer + schedule_type: basic # OPTIONAL | string | Allowed values: basic, cron, manual + schedule_data: # OPTIONAL | object + basic_schedule: + time_unit: hours # REQUIRED | string | Allowed values: minutes, hours, days, weeks, months + units: 1 # REQUIRED | integer + # cron: + # cron_time_zone: "UTC" # REQUIRED | string + # cron_expression: "* */2 * * * ?" # REQUIRED | string {%- if supports_normalization or supports_dbt%} # operations: {%- endif %} diff --git a/octavia-cli/unit_tests/test_apply/test_resources.py b/octavia-cli/unit_tests/test_apply/test_resources.py index 3d4cfe6c41f2f..66014d435a428 100644 --- a/octavia-cli/unit_tests/test_apply/test_resources.py +++ b/octavia-cli/unit_tests/test_apply/test_resources.py @@ -8,7 +8,8 @@ import pytest from airbyte_api_client import ApiException from airbyte_api_client.model.airbyte_catalog import AirbyteCatalog -from airbyte_api_client.model.connection_schedule import ConnectionSchedule +from airbyte_api_client.model.connection_schedule_data_basic_schedule import ConnectionScheduleDataBasicSchedule +from airbyte_api_client.model.connection_schedule_type import ConnectionScheduleType from airbyte_api_client.model.connection_status import ConnectionStatus from airbyte_api_client.model.destination_definition_id_with_workspace_id import DestinationDefinitionIdWithWorkspaceId from airbyte_api_client.model.namespace_definition_type import NamespaceDefinitionType @@ -468,12 +469,20 @@ def connection_configuration(self): } ] }, - "schedule": {"units": 1, "time_unit": "days"}, + "schedule_type": "basic", + "schedule_data": {"units": 1, "time_unit": "days"}, "status": "active", "resource_requirements": {"cpu_request": "foo", "cpu_limit": "foo", "memory_request": "foo", "memory_limit": "foo"}, }, } + @pytest.fixture + def connection_configuration_with_manual_schedule(self, connection_configuration): + connection_configuration_with_manual_schedule = deepcopy(connection_configuration) + connection_configuration_with_manual_schedule["configuration"]["schedule_type"] = "manual" + connection_configuration_with_manual_schedule["configuration"]["schedule_data"] = None + return connection_configuration_with_manual_schedule + @pytest.fixture def connection_configuration_with_normalization(self, connection_configuration): connection_configuration_with_normalization = deepcopy(connection_configuration) @@ -559,6 +568,28 @@ def legacy_connection_configurations(self): "resource_requirements": {"cpu_request": "foo", "cpu_limit": "foo", "memory_request": "foo", "memory_limit": "foo"}, }, }, + { + "definition_type": "connection", + "resource_name": "my_connection", + "source_id": "my_source", + "destination_id": "my_destination", + "configuration": { + "namespace_definition": "customformat", + "namespace_format": "foo", + "prefix": "foo", + "sync_catalog": { + "streams": [ + { + "stream": {}, + "config": {}, + } + ] + }, + "schedule": {"units": 1, "time_unit": "days"}, + "status": "active", + "resource_requirements": {"cpu_request": "foo", "cpu_limit": "foo", "memory_request": "foo", "memory_limit": "foo"}, + }, + }, ] @pytest.mark.parametrize( @@ -769,14 +800,18 @@ def test_update(self, mocker, mock_api_client, connection_configuration): assert update_result == resource._create_or_update.return_value resource._create_or_update.assert_called_with(resource._update_fn, resource.update_payload) - def test__deserialize_raw_configuration(self, mock_api_client, connection_configuration): + def test__deserialize_raw_configuration(self, mock_api_client, connection_configuration, connection_configuration_with_manual_schedule): resource = resources.Connection(mock_api_client, "workspace_id", connection_configuration, "bar.yaml") configuration = resource._deserialize_raw_configuration() assert isinstance(configuration["sync_catalog"], AirbyteCatalog) assert configuration["namespace_definition"] == NamespaceDefinitionType( connection_configuration["configuration"]["namespace_definition"] ) - assert configuration["schedule"] == ConnectionSchedule(**connection_configuration["configuration"]["schedule"]) + assert configuration["schedule_type"] == ConnectionScheduleType(connection_configuration["configuration"]["schedule_type"]) + assert ( + configuration["schedule_data"].to_dict() + == ConnectionScheduleDataBasicSchedule(**connection_configuration["configuration"]["schedule_data"]).to_dict() + ) assert configuration["resource_requirements"] == ResourceRequirements( **connection_configuration["configuration"]["resource_requirements"] ) @@ -786,11 +821,19 @@ def test__deserialize_raw_configuration(self, mock_api_client, connection_config "namespace_format", "prefix", "sync_catalog", - "schedule", + "schedule_type", + "schedule_data", "status", "resource_requirements", ] + resource = resources.Connection(mock_api_client, "workspace_id", connection_configuration_with_manual_schedule, "bar.yaml") + configuration = resource._deserialize_raw_configuration() + assert configuration["schedule_type"] == ConnectionScheduleType( + connection_configuration_with_manual_schedule["configuration"]["schedule_type"] + ) + assert configuration["schedule_data"] is None + def test__deserialize_operations(self, mock_api_client, connection_configuration): resource = resources.Connection(mock_api_client, "workspace_id", connection_configuration, "bar.yaml") operations = [