fix: Fix importing datasource with same name but different plugin issue (#12512)
Co-authored-by: Anagh Hegde <anagh@appsmith.com>
This commit is contained in:
parent
f201ec7bcd
commit
ffd0595330
|
|
@ -591,9 +591,9 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
/**
|
||||
* This function will take the application reference object to hydrate the application in mongoDB
|
||||
*
|
||||
* @param organizationId organization to which application is going to be stored
|
||||
* @param applicationJson application resource which contains necessary information to save the application
|
||||
* @param applicationId application which needs to be saved with the updated resources
|
||||
* @param organizationId organization to which application is going to be stored
|
||||
* @param applicationJson application resource which contains necessary information to import the application
|
||||
* @param applicationId application which needs to be saved with the updated resources
|
||||
* @return Updated application
|
||||
*/
|
||||
public Mono<Application> importApplicationInOrganization(String organizationId,
|
||||
|
|
@ -689,6 +689,7 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
// Check for duplicate datasources to avoid duplicates in target organization
|
||||
.flatMap(datasource -> {
|
||||
|
||||
final String importedDatasourceName = datasource.getName();
|
||||
// Check if the datasource has gitSyncId and if it's already in DB
|
||||
if (datasource.getGitSyncId() != null
|
||||
&& savedDatasourcesGitIdToDatasourceMap.containsKey(datasource.getGitSyncId())) {
|
||||
|
|
@ -702,7 +703,11 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
datasource.setPluginId(null);
|
||||
AppsmithBeanUtils.copyNestedNonNullProperties(datasource, existingDatasource);
|
||||
existingDatasource.setStructure(null);
|
||||
return datasourceService.update(existingDatasource.getId(), existingDatasource);
|
||||
return datasourceService.update(existingDatasource.getId(), existingDatasource)
|
||||
.map(datasource1 -> {
|
||||
datasourceMap.put(importedDatasourceName, datasource1.getId());
|
||||
return datasource1;
|
||||
});
|
||||
}
|
||||
|
||||
// This is explicitly copied over from the map we created before
|
||||
|
|
@ -719,11 +724,11 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
updateAuthenticationDTO(datasource, decryptedFields);
|
||||
}
|
||||
|
||||
return createUniqueDatasourceIfNotPresent(existingDatasourceFlux, datasource, organizationId, applicationId);
|
||||
})
|
||||
.map(datasource -> {
|
||||
datasourceMap.put(datasource.getName(), datasource.getId());
|
||||
return datasource;
|
||||
return createUniqueDatasourceIfNotPresent(existingDatasourceFlux, datasource, organizationId)
|
||||
.map(datasource1 -> {
|
||||
datasourceMap.put(importedDatasourceName, datasource1.getId());
|
||||
return datasource1;
|
||||
});
|
||||
})
|
||||
.collectList();
|
||||
})
|
||||
|
|
@ -1726,9 +1731,7 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
*/
|
||||
private Mono<Datasource> createUniqueDatasourceIfNotPresent(Flux<Datasource> existingDatasourceFlux,
|
||||
Datasource datasource,
|
||||
String organizationId,
|
||||
String applicationId) {
|
||||
|
||||
String organizationId) {
|
||||
/*
|
||||
1. If same datasource is present return
|
||||
2. If unable to find the datasource create a new datasource with unique name and return
|
||||
|
|
@ -1743,16 +1746,8 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
}
|
||||
|
||||
return existingDatasourceFlux
|
||||
.map(ds -> {
|
||||
final DatasourceConfiguration dsAuthConfig = ds.getDatasourceConfiguration();
|
||||
if (dsAuthConfig != null && dsAuthConfig.getAuthentication() != null) {
|
||||
dsAuthConfig.getAuthentication().setAuthenticationResponse(null);
|
||||
dsAuthConfig.getAuthentication().setAuthenticationType(null);
|
||||
}
|
||||
return ds;
|
||||
})
|
||||
// For git import exclude datasource configuration
|
||||
.filter(ds -> applicationId != null ? ds.getName().equals(datasource.getName()) : ds.softEquals(datasource))
|
||||
.filter(ds -> ds.getName().equals(datasource.getName()) && datasource.getPluginId().equals(ds.getPluginId()))
|
||||
.next() // Get the first matching datasource, we don't need more than one here.
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
if (datasourceConfig != null && datasourceConfig.getAuthentication() != null) {
|
||||
|
|
|
|||
|
|
@ -1702,7 +1702,7 @@ public class GitServiceTest {
|
|||
StepVerifier
|
||||
.create(applicationMono)
|
||||
.expectErrorMatches(throwable -> throwable instanceof AppsmithException
|
||||
&& throwable.getMessage().equals(AppsmithError.GIT_ACTION_FAILED.getMessage("checkout", "origin/branchInLocal already exists in remote")))
|
||||
&& throwable.getMessage().equals(AppsmithError.GIT_ACTION_FAILED.getMessage("checkout", "origin/branchInLocal already exists in local - branchInLocal")))
|
||||
.verify();
|
||||
}
|
||||
|
||||
|
|
@ -2486,7 +2486,7 @@ public class GitServiceTest {
|
|||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void importApplicationFromGit_validRequestWithDuplicateDatasourceOfSameTypeCancelledMidway_Success() throws GitAPIException, IOException {
|
||||
public void importApplicationFromGit_validRequestWithDuplicateDatasourceOfSameTypeCancelledMidway_Success() {
|
||||
Organization organization = new Organization();
|
||||
organization.setName("gitImportOrgCancelledMidway");
|
||||
final String testOrgId = organizationService.create(organization)
|
||||
|
|
@ -2497,6 +2497,7 @@ public class GitServiceTest {
|
|||
GitAuth gitAuth = gitService.generateSSHKey().block();
|
||||
|
||||
ApplicationJson applicationJson = createAppJson(filePath).block();
|
||||
applicationJson.getExportedApplication().setName(null);
|
||||
applicationJson.getDatasourceList().get(0).setName("db-auth-testGitImportRepo");
|
||||
|
||||
String pluginId = pluginRepository.findByPackageName("mongo-plugin").block().getId();
|
||||
|
|
@ -2521,7 +2522,7 @@ public class GitServiceTest {
|
|||
|
||||
// Wait for git clone to complete
|
||||
Mono<Application> gitConnectedAppFromDbMono = Mono.just(testOrgId)
|
||||
.flatMap(application -> {
|
||||
.flatMap(ignore -> {
|
||||
try {
|
||||
// Before fetching the git connected application, sleep for 5 seconds to ensure that the clone
|
||||
// completes
|
||||
|
|
|
|||
|
|
@ -2182,5 +2182,111 @@ public class ImportExportApplicationServiceTests {
|
|||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void importApplication_datasourceWithSameNameAndDifferentPlugin_importedWithValidActionsAndSuffixedDatasource() {
|
||||
|
||||
ApplicationJson applicationJson = createAppJson("test_assets/ImportExportServiceTest/valid-application.json").block();
|
||||
|
||||
Organization testOrganization = new Organization();
|
||||
testOrganization.setName("Duplicate datasource with different plugin org");
|
||||
testOrganization = organizationService.create(testOrganization).block();
|
||||
|
||||
Datasource testDatasource = new Datasource();
|
||||
// Chose any plugin except for mongo, as json static file has mongo plugin for datasource
|
||||
Plugin postgreSQLPlugin = pluginRepository.findByName("PostgreSQL").block();
|
||||
testDatasource.setPluginId(postgreSQLPlugin.getId());
|
||||
testDatasource.setOrganizationId(testOrganization.getId());
|
||||
final String datasourceName = applicationJson.getDatasourceList().get(0).getName();
|
||||
testDatasource.setName(datasourceName);
|
||||
datasourceService.create(testDatasource).block();
|
||||
|
||||
final Mono<Application> resultMono = importExportApplicationService.importApplicationInOrganization(testOrganization.getId(), applicationJson);
|
||||
|
||||
StepVerifier
|
||||
.create(resultMono
|
||||
.flatMap(application -> Mono.zip(
|
||||
Mono.just(application),
|
||||
datasourceService.findAllByOrganizationId(application.getOrganizationId(), MANAGE_DATASOURCES).collectList(),
|
||||
newActionService.findAllByApplicationIdAndViewMode(application.getId(), false, READ_ACTIONS, null).collectList()
|
||||
)))
|
||||
.assertNext(tuple -> {
|
||||
final Application application = tuple.getT1();
|
||||
final List<Datasource> datasourceList = tuple.getT2();
|
||||
final List<NewAction> actionList = tuple.getT3();
|
||||
|
||||
assertThat(application.getName()).isEqualTo("valid_application");
|
||||
|
||||
List<String> datasourceNameList = new ArrayList<>();
|
||||
assertThat(datasourceList).isNotEmpty();
|
||||
datasourceList.forEach(datasource -> {
|
||||
assertThat(datasource.getOrganizationId()).isEqualTo(application.getOrganizationId());
|
||||
datasourceNameList.add(datasource.getName());
|
||||
});
|
||||
// Check if both suffixed and newly imported datasource are present
|
||||
assertThat(datasourceNameList).contains(datasourceName, datasourceName + " #1");
|
||||
|
||||
assertThat(actionList).isNotEmpty();
|
||||
actionList.forEach(newAction -> {
|
||||
ActionDTO actionDTO = newAction.getUnpublishedAction();
|
||||
assertThat(actionDTO.getDatasource()).isNotNull();
|
||||
});
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void importApplication_datasourceWithSameNameAndPlugin_importedWithValidActionsWithoutSuffixedDatasource() {
|
||||
|
||||
ApplicationJson applicationJson = createAppJson("test_assets/ImportExportServiceTest/valid-application.json").block();
|
||||
|
||||
Organization testOrganization = new Organization();
|
||||
testOrganization.setName("Duplicate datasource with same plugin org");
|
||||
testOrganization = organizationService.create(testOrganization).block();
|
||||
|
||||
Datasource testDatasource = new Datasource();
|
||||
// Chose plugin same as mongo, as json static file has mongo plugin for datasource
|
||||
Plugin postgreSQLPlugin = pluginRepository.findByName("MongoDB").block();
|
||||
testDatasource.setPluginId(postgreSQLPlugin.getId());
|
||||
testDatasource.setOrganizationId(testOrganization.getId());
|
||||
final String datasourceName = applicationJson.getDatasourceList().get(0).getName();
|
||||
testDatasource.setName(datasourceName);
|
||||
datasourceService.create(testDatasource).block();
|
||||
|
||||
final Mono<Application> resultMono = importExportApplicationService.importApplicationInOrganization(testOrganization.getId(), applicationJson);
|
||||
|
||||
StepVerifier
|
||||
.create(resultMono
|
||||
.flatMap(application -> Mono.zip(
|
||||
Mono.just(application),
|
||||
datasourceService.findAllByOrganizationId(application.getOrganizationId(), MANAGE_DATASOURCES).collectList(),
|
||||
newActionService.findAllByApplicationIdAndViewMode(application.getId(), false, READ_ACTIONS, null).collectList()
|
||||
)))
|
||||
.assertNext(tuple -> {
|
||||
final Application application = tuple.getT1();
|
||||
final List<Datasource> datasourceList = tuple.getT2();
|
||||
final List<NewAction> actionList = tuple.getT3();
|
||||
|
||||
assertThat(application.getName()).isEqualTo("valid_application");
|
||||
|
||||
List<String> datasourceNameList = new ArrayList<>();
|
||||
assertThat(datasourceList).isNotEmpty();
|
||||
datasourceList.forEach(datasource -> {
|
||||
assertThat(datasource.getOrganizationId()).isEqualTo(application.getOrganizationId());
|
||||
datasourceNameList.add(datasource.getName());
|
||||
});
|
||||
// Check that there are no datasources are created with suffix names as datasource's are of same plugin
|
||||
assertThat(datasourceNameList).contains(datasourceName);
|
||||
|
||||
assertThat(actionList).isNotEmpty();
|
||||
actionList.forEach(newAction -> {
|
||||
ActionDTO actionDTO = newAction.getUnpublishedAction();
|
||||
assertThat(actionDTO.getDatasource()).isNotNull();
|
||||
});
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user