Skip to content

Commit

Permalink
fix: clone api doesn't take update configurations (#13592)
Browse files Browse the repository at this point in the history
* fix: clone api doesn't take update configurations

* fix: you will be able to create clone in different workspace

* fix: added description to source/destination body
  • Loading branch information
harshithmullapudi authored Jul 4, 2022
1 parent 5c9a6a5 commit a140c3e
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 44 deletions.
38 changes: 36 additions & 2 deletions airbyte-api/src/main/openapi/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/SourceIdRequestBody"
$ref: "#/components/schemas/SourceCloneRequestBody"
required: true
responses:
"200":
Expand Down Expand Up @@ -1253,7 +1253,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/DestinationIdRequestBody"
$ref: "#/components/schemas/DestinationCloneRequestBody"
required: true
responses:
"200":
Expand Down Expand Up @@ -2715,6 +2715,23 @@ components:
properties:
sourceId:
$ref: "#/components/schemas/SourceId"
SourceCloneRequestBody:
description: The values required to configure the source. The schema for this should have an id of the existing source along with the configuration you want to change in case.
type: object
required:
- sourceCloneId
properties:
sourceCloneId:
$ref: "#/components/schemas/SourceId"
sourceConfiguration:
$ref: "#/components/schemas/SourceCloneConfiguration"
SourceCloneConfiguration:
type: object
properties:
connectionConfiguration:
$ref: "#/components/schemas/SourceConfiguration"
name:
type: string
SourceConfiguration:
description: The values required to configure the source. The schema for this must match the schema return by source_definition_specifications/get for the source.
example: { user: "charles" }
Expand Down Expand Up @@ -3043,6 +3060,23 @@ components:
$ref: "#/components/schemas/DestinationConfiguration"
name:
type: string
DestinationCloneRequestBody:
description: The values required to configure the destination. The schema for this should have an id of the existing destination along with the configuration you want to change in case.
type: object
required:
- destinationCloneId
properties:
destinationCloneId:
$ref: "#/components/schemas/DestinationId"
destinationConfiguration:
$ref: "#/components/schemas/DestinationCloneConfiguration"
DestinationCloneConfiguration:
type: object
properties:
connectionConfiguration:
$ref: "#/components/schemas/DestinationConfiguration"
name:
type: string
DestinationRead:
type: object
required:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.airbyte.api.model.generated.DbMigrationExecutionRead;
import io.airbyte.api.model.generated.DbMigrationReadList;
import io.airbyte.api.model.generated.DbMigrationRequestBody;
import io.airbyte.api.model.generated.DestinationCloneRequestBody;
import io.airbyte.api.model.generated.DestinationCoreConfig;
import io.airbyte.api.model.generated.DestinationCreate;
import io.airbyte.api.model.generated.DestinationDefinitionCreate;
Expand Down Expand Up @@ -64,6 +65,7 @@
import io.airbyte.api.model.generated.SetInstancewideDestinationOauthParamsRequestBody;
import io.airbyte.api.model.generated.SetInstancewideSourceOauthParamsRequestBody;
import io.airbyte.api.model.generated.SlugRequestBody;
import io.airbyte.api.model.generated.SourceCloneRequestBody;
import io.airbyte.api.model.generated.SourceCoreConfig;
import io.airbyte.api.model.generated.SourceCreate;
import io.airbyte.api.model.generated.SourceDefinitionCreate;
Expand Down Expand Up @@ -469,8 +471,8 @@ public void deleteSource(final SourceIdRequestBody sourceIdRequestBody) {
}

@Override
public SourceRead cloneSource(final SourceIdRequestBody sourceIdRequestBody) {
return execute(() -> sourceHandler.cloneSource(sourceIdRequestBody));
public SourceRead cloneSource(final SourceCloneRequestBody sourceCloneRequestBody) {
return execute(() -> sourceHandler.cloneSource(sourceCloneRequestBody));
}

@Override
Expand Down Expand Up @@ -629,8 +631,8 @@ public DestinationRead getDestination(final DestinationIdRequestBody destination
}

@Override
public DestinationRead cloneDestination(final DestinationIdRequestBody destinationIdRequestBody) {
return execute(() -> destinationHandler.cloneDestination(destinationIdRequestBody));
public DestinationRead cloneDestination(final DestinationCloneRequestBody destinationCloneRequestBody) {
return execute(() -> destinationHandler.cloneDestination(destinationCloneRequestBody));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import io.airbyte.api.model.generated.ConnectionRead;
import io.airbyte.api.model.generated.DestinationCloneConfiguration;
import io.airbyte.api.model.generated.DestinationCloneRequestBody;
import io.airbyte.api.model.generated.DestinationCreate;
import io.airbyte.api.model.generated.DestinationDefinitionIdRequestBody;
import io.airbyte.api.model.generated.DestinationIdRequestBody;
Expand Down Expand Up @@ -168,26 +170,32 @@ public DestinationRead getDestination(final DestinationIdRequestBody destination
return buildDestinationRead(destinationIdRequestBody.getDestinationId());
}

public DestinationRead cloneDestination(final DestinationIdRequestBody destinationIdRequestBody)
public DestinationRead cloneDestination(final DestinationCloneRequestBody destinationCloneRequestBody)
throws JsonValidationException, IOException, ConfigNotFoundException {
// read destination configuration from db
final DestinationRead destinationToClone = buildDestinationReadWithSecrets(destinationIdRequestBody.getDestinationId());
final ConnectorSpecification spec = getSpec(destinationToClone.getDestinationDefinitionId());
final DestinationRead destinationToClone = buildDestinationReadWithSecrets(destinationCloneRequestBody.getDestinationCloneId());
final DestinationCloneConfiguration destinationCloneConfiguration = destinationCloneRequestBody.getDestinationConfiguration();

// persist
final UUID destinationId = uuidGenerator.get();
final String copyText = " (Copy)";
final String destinationName = destinationToClone.getName() + copyText;
persistDestinationConnection(
destinationName,
destinationToClone.getDestinationDefinitionId(),
destinationToClone.getWorkspaceId(),
destinationId,
destinationToClone.getConnectionConfiguration(),
false);

// read configuration from db
return buildDestinationRead(destinationId, spec);
final DestinationCreate destinationCreate = new DestinationCreate()
.name(destinationName)
.destinationDefinitionId(destinationToClone.getDestinationDefinitionId())
.connectionConfiguration(destinationToClone.getConnectionConfiguration())
.workspaceId(destinationToClone.getWorkspaceId());

if (destinationCloneConfiguration != null) {
if (destinationCloneConfiguration.getName() != null) {
destinationCreate.name(destinationCloneConfiguration.getName());
}

if (destinationCloneConfiguration.getConnectionConfiguration() != null) {
destinationCreate.connectionConfiguration(destinationCloneConfiguration.getConnectionConfiguration());
}
}

return createDestination(destinationCreate);
}

public DestinationReadList listDestinationsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import io.airbyte.api.model.generated.ConnectionRead;
import io.airbyte.api.model.generated.SourceCloneConfiguration;
import io.airbyte.api.model.generated.SourceCloneRequestBody;
import io.airbyte.api.model.generated.SourceCreate;
import io.airbyte.api.model.generated.SourceDefinitionIdRequestBody;
import io.airbyte.api.model.generated.SourceIdRequestBody;
Expand Down Expand Up @@ -130,28 +132,32 @@ public SourceRead getSource(final SourceIdRequestBody sourceIdRequestBody)
return buildSourceRead(sourceIdRequestBody.getSourceId());
}

public SourceRead cloneSource(final SourceIdRequestBody sourceIdRequestBody)
public SourceRead cloneSource(final SourceCloneRequestBody sourceCloneRequestBody)
throws JsonValidationException, IOException, ConfigNotFoundException {
// read source configuration from db
final SourceRead sourceToClone = buildSourceReadWithSecrets(sourceIdRequestBody.getSourceId());
final SourceRead sourceToClone = buildSourceReadWithSecrets(sourceCloneRequestBody.getSourceCloneId());
final SourceCloneConfiguration sourceCloneConfiguration = sourceCloneRequestBody.getSourceConfiguration();

// persist
final UUID sourceId = uuidGenerator.get();
final StandardSourceDefinition sourceDef = configRepository.getSourceDefinitionFromSource(sourceIdRequestBody.getSourceId());
final ConnectorSpecification spec = sourceDef.getSpec();
final String copyText = " (Copy)";
final String sourceName = sourceToClone.getName() + copyText;
persistSourceConnection(
sourceName,
sourceToClone.getSourceDefinitionId(),
sourceToClone.getWorkspaceId(),
sourceId,
false,
sourceToClone.getConnectionConfiguration(),
spec);

// read configuration from db
return buildSourceRead(sourceId, spec);
final SourceCreate sourceCreate = new SourceCreate()
.name(sourceName)
.sourceDefinitionId(sourceToClone.getSourceDefinitionId())
.connectionConfiguration(sourceToClone.getConnectionConfiguration())
.workspaceId(sourceToClone.getWorkspaceId());

if (sourceCloneConfiguration != null) {
if (sourceCloneConfiguration.getName() != null) {
sourceCreate.name(sourceCloneConfiguration.getName());
}

if (sourceCloneConfiguration.getConnectionConfiguration() != null) {
sourceCreate.connectionConfiguration(sourceCloneConfiguration.getConnectionConfiguration());
}
}

return createSource(sourceCreate);
}

public SourceReadList listSourcesForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import io.airbyte.api.model.generated.DestinationCloneConfiguration;
import io.airbyte.api.model.generated.DestinationCloneRequestBody;
import io.airbyte.api.model.generated.DestinationCreate;
import io.airbyte.api.model.generated.DestinationDefinitionIdRequestBody;
import io.airbyte.api.model.generated.DestinationDefinitionSpecificationRead;
Expand Down Expand Up @@ -269,7 +271,7 @@ void testSearchDestinations() throws JsonValidationException, ConfigNotFoundExce
}

@Test
void testCloneDestination() throws JsonValidationException, ConfigNotFoundException, IOException {
void testCloneDestinationWithConfiguration() throws JsonValidationException, ConfigNotFoundException, IOException {
final DestinationConnection clonedConnection = DestinationHelpers.generateDestination(standardDestinationDefinition.getDestinationDefinitionId());
final DestinationRead expectedDestinationRead = new DestinationRead()
.name(clonedConnection.getName())
Expand All @@ -286,7 +288,9 @@ void testCloneDestination() throws JsonValidationException, ConfigNotFoundExcept
.connectionConfiguration(destinationConnection.getConfiguration())
.destinationName(standardDestinationDefinition.getName());

final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody().destinationId(destinationRead.getDestinationId());
final DestinationCloneConfiguration destinationCloneConfiguration = new DestinationCloneConfiguration().name("Copy Name");
final DestinationCloneRequestBody destinationCloneRequestBody = new DestinationCloneRequestBody()
.destinationCloneId(destinationRead.getDestinationId()).destinationConfiguration(destinationCloneConfiguration);

when(uuidGenerator.get()).thenReturn(clonedConnection.getDestinationId());
when(secretsRepositoryReader.getDestinationConnectionWithSecrets(destinationConnection.getDestinationId())).thenReturn(destinationConnection);
Expand All @@ -300,7 +304,45 @@ void testCloneDestination() throws JsonValidationException, ConfigNotFoundExcept
destinationDefinitionSpecificationRead.getConnectionSpecification()))
.thenReturn(destinationConnection.getConfiguration());

final DestinationRead actualDestinationRead = destinationHandler.cloneDestination(destinationIdRequestBody);
final DestinationRead actualDestinationRead = destinationHandler.cloneDestination(destinationCloneRequestBody);

assertEquals(expectedDestinationRead, actualDestinationRead);
}

@Test
void testCloneDestinationWithoutConfiguration() throws JsonValidationException, ConfigNotFoundException, IOException {
final DestinationConnection clonedConnection = DestinationHelpers.generateDestination(standardDestinationDefinition.getDestinationDefinitionId());
final DestinationRead expectedDestinationRead = new DestinationRead()
.name(clonedConnection.getName())
.destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId())
.workspaceId(clonedConnection.getWorkspaceId())
.destinationId(clonedConnection.getDestinationId())
.connectionConfiguration(clonedConnection.getConfiguration())
.destinationName(standardDestinationDefinition.getName());
final DestinationRead destinationRead = new DestinationRead()
.name(destinationConnection.getName())
.destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId())
.workspaceId(destinationConnection.getWorkspaceId())
.destinationId(destinationConnection.getDestinationId())
.connectionConfiguration(destinationConnection.getConfiguration())
.destinationName(standardDestinationDefinition.getName());

final DestinationCloneRequestBody destinationCloneRequestBody =
new DestinationCloneRequestBody().destinationCloneId(destinationRead.getDestinationId());

when(uuidGenerator.get()).thenReturn(clonedConnection.getDestinationId());
when(secretsRepositoryReader.getDestinationConnectionWithSecrets(destinationConnection.getDestinationId())).thenReturn(destinationConnection);
when(configRepository.getDestinationConnection(clonedConnection.getDestinationId())).thenReturn(clonedConnection);

when(configRepository.getStandardDestinationDefinition(destinationDefinitionSpecificationRead.getDestinationDefinitionId()))
.thenReturn(standardDestinationDefinition);
when(configRepository.getDestinationDefinitionFromDestination(destinationConnection.getDestinationId()))
.thenReturn(standardDestinationDefinition);
when(secretsProcessor.prepareSecretsForOutput(destinationConnection.getConfiguration(),
destinationDefinitionSpecificationRead.getConnectionSpecification()))
.thenReturn(destinationConnection.getConfiguration());

final DestinationRead actualDestinationRead = destinationHandler.cloneDestination(destinationCloneRequestBody);

assertEquals(expectedDestinationRead, actualDestinationRead);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import io.airbyte.api.model.generated.ConnectionIdRequestBody;
import io.airbyte.api.model.generated.ConnectionRead;
import io.airbyte.api.model.generated.ConnectionReadList;
import io.airbyte.api.model.generated.SourceCloneConfiguration;
import io.airbyte.api.model.generated.SourceCloneRequestBody;
import io.airbyte.api.model.generated.SourceCreate;
import io.airbyte.api.model.generated.SourceDefinitionIdRequestBody;
import io.airbyte.api.model.generated.SourceDefinitionSpecificationRead;
Expand Down Expand Up @@ -198,12 +200,12 @@ void testGetSource() throws JsonValidationException, ConfigNotFoundException, IO
}

@Test
void testCloneSource() throws JsonValidationException, ConfigNotFoundException, IOException {
void testCloneSourceWithoutConfigChange() throws JsonValidationException, ConfigNotFoundException, IOException {
final SourceConnection clonedConnection = SourceHelpers.generateSource(standardSourceDefinition.getSourceDefinitionId());
final SourceRead expectedClonedSourceRead = SourceHelpers.getSourceRead(clonedConnection, standardSourceDefinition);
final SourceRead sourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition);

final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody().sourceId(sourceRead.getSourceId());
final SourceCloneRequestBody sourceCloneRequestBody = new SourceCloneRequestBody().sourceCloneId(sourceRead.getSourceId());

when(uuidGenerator.get()).thenReturn(clonedConnection.getSourceId());
when(secretsRepositoryReader.getSourceConnectionWithSecrets(sourceConnection.getSourceId())).thenReturn(sourceConnection);
Expand All @@ -216,7 +218,33 @@ void testCloneSource() throws JsonValidationException, ConfigNotFoundException,
secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification()))
.thenReturn(sourceConnection.getConfiguration());

final SourceRead actualSourceRead = sourceHandler.cloneSource(sourceIdRequestBody);
final SourceRead actualSourceRead = sourceHandler.cloneSource(sourceCloneRequestBody);

assertEquals(expectedClonedSourceRead, actualSourceRead);
}

@Test
void testCloneSourceWithConfigChange() throws JsonValidationException, ConfigNotFoundException, IOException {
final SourceConnection clonedConnection = SourceHelpers.generateSource(standardSourceDefinition.getSourceDefinitionId());
final SourceRead expectedClonedSourceRead = SourceHelpers.getSourceRead(clonedConnection, standardSourceDefinition);
final SourceRead sourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition);

final SourceCloneConfiguration sourceCloneConfiguration = new SourceCloneConfiguration().name("Copy Name");
final SourceCloneRequestBody sourceCloneRequestBody =
new SourceCloneRequestBody().sourceCloneId(sourceRead.getSourceId()).sourceConfiguration(sourceCloneConfiguration);

when(uuidGenerator.get()).thenReturn(clonedConnection.getSourceId());
when(secretsRepositoryReader.getSourceConnectionWithSecrets(sourceConnection.getSourceId())).thenReturn(sourceConnection);
when(configRepository.getSourceConnection(clonedConnection.getSourceId())).thenReturn(clonedConnection);

when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId()))
.thenReturn(standardSourceDefinition);
when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition);
when(
secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification()))
.thenReturn(sourceConnection.getConfiguration());

final SourceRead actualSourceRead = sourceHandler.cloneSource(sourceCloneRequestBody);

assertEquals(expectedClonedSourceRead, actualSourceRead);
}
Expand Down
Loading

0 comments on commit a140c3e

Please sign in to comment.