Skip to content

Commit 4c8722d

Browse files
authored
Merge pull request #261 from entando/ENG-5468
ENG-5468 ENG-5469 ENG-5470: Fix DB restore function
2 parents e9a9eba + 4154308 commit 4c8722d

File tree

12 files changed

+148
-96
lines changed

12 files changed

+148
-96
lines changed

cds-plugin/src/main/java/org/entando/entando/plugins/jpcds/aps/system/storage/CdsStorageManager.java

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,18 @@ public void saveFile(String subPath, boolean isProtectedResource, InputStream is
8181

8282
private void create(String subPath, boolean isProtectedResource, Optional<InputStream> fileInputStream) {
8383
try {
84-
Optional<TenantConfig> config = getTenantConfig();
84+
Optional<TenantConfig> config = this.getTenantConfig();
8585
if(StringUtils.isBlank(subPath)){
8686
throw new EntRuntimeException(ERROR_VALIDATING_PATH_MSG);
8787
}
8888
this.validateAndReturnResourcePath(config, subPath, false, isProtectedResource);
8989
URI apiUrl = CdsUrlUtils.buildCdsInternalApiUrl(config, configuration, "/upload/");
90-
CdsCreateResponseDto response = caller.executePostCall(apiUrl,
90+
CdsCreateResponseDto response = this.caller.executePostCall(apiUrl,
9191
subPath,
9292
isProtectedResource,
9393
fileInputStream,
9494
config,
9595
false);
96-
9796
if (!response.isStatusOk()) {
9897
throw new EntRuntimeException("Invalid status - Response " + response.isStatusOk());
9998
}
@@ -112,8 +111,8 @@ public void deleteDirectory(String subPath, boolean isProtectedResource) throws
112111
@Override
113112
public boolean deleteFile(String subPath, boolean isProtectedResource) {
114113
try {
115-
Optional<TenantConfig> config = getTenantConfig();
116-
if(StringUtils.isBlank(subPath)){
114+
Optional<TenantConfig> config = this.getTenantConfig();
115+
if (StringUtils.isBlank(subPath)){
117116
throw new EntRuntimeException(ERROR_VALIDATING_PATH_MSG);
118117
}
119118
this.validateAndReturnResourcePath(config, subPath, true, isProtectedResource);
@@ -123,7 +122,7 @@ public boolean deleteFile(String subPath, boolean isProtectedResource) {
123122
.path(CdsUrlUtils.getSection(isProtectedResource, config, this.configuration, true))
124123
.path(subPath)
125124
.build();
126-
return caller.executeDeleteCall(apiUrl, config, false);
125+
return this.caller.executeDeleteCall(apiUrl, config, false);
127126
} catch (EntRuntimeException ert) {
128127
throw ert;
129128
} catch (Exception e) {
@@ -136,32 +135,31 @@ public InputStream getStream(String subPath, boolean isProtectedResource) throws
136135
final String ERROR_EXTRACTING_FILE = "Error extracting file";
137136
URI url = null;
138137
try {
139-
Optional<TenantConfig> config = getTenantConfig();
140-
if(StringUtils.isBlank(subPath)){
138+
Optional<TenantConfig> config = this.getTenantConfig();
139+
if (StringUtils.isBlank(subPath)) {
141140
throw new EntRuntimeException(ERROR_VALIDATING_PATH_MSG);
142141
}
143-
142+
if (!this.exists(subPath, isProtectedResource)) {
143+
throw new EntResourceNotFoundException(
144+
String.format("File \"%s\", protected \"%s\", Not Found", subPath, isProtectedResource));
145+
}
144146
this.validateAndReturnResourcePath(config, subPath, true, isProtectedResource);
145-
146147
url = (isProtectedResource) ?
147148
CdsUrlUtils.buildCdsInternalApiUrl(config, configuration) :
148149
CdsUrlUtils.buildCdsExternalPublicResourceUrl(config, configuration);
149-
150150
url = EntUrlBuilder.builder()
151151
.url(url)
152152
.path(CdsUrlUtils.getSection(isProtectedResource, config, this.configuration, true))
153153
.path(subPath).build();
154-
155154
Optional<ByteArrayInputStream> is = caller.getFile(url, config, isProtectedResource);
156-
return is.orElseThrow(IOException::new);
157-
158-
} catch (EntRuntimeException ert) {
155+
return is.orElse(new ByteArrayInputStream(new byte[0]));
156+
} catch (EntResourceNotFoundException | EntRuntimeException ert) {
159157
throw ert;
160158
} catch (HttpClientErrorException e) {
161159
if (e.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
162160
log.info("File Not found - uri {}", url);
163161
return null;
164-
}
162+
}
165163
throw new EntResourceNotFoundException(ERROR_EXTRACTING_FILE, e);
166164
} catch (Exception e) {
167165
throw new EntResourceNotFoundException(ERROR_EXTRACTING_FILE, e);
@@ -171,7 +169,7 @@ public InputStream getStream(String subPath, boolean isProtectedResource) throws
171169
@Override
172170
public String getResourceUrl(String subPath, boolean isProtectedResource) {
173171
try {
174-
Optional<TenantConfig> config = getTenantConfig();
172+
Optional<TenantConfig> config = this.getTenantConfig();
175173
return this.validateAndReturnResourcePath(config, subPath, false, isProtectedResource);
176174
} catch (Exception e) {
177175
throw new EntRuntimeException("Error extracting resource url", e);
@@ -187,7 +185,7 @@ public boolean exists(String subPath, boolean isProtectedResource) {
187185

188186
// when frontend wants to retrieve public or protected folder contents it gets request with an empty subpath
189187
private boolean isSubPathPresent(String[] filenames, String subPath){
190-
if(StringUtils.isEmpty(subPath)) {
188+
if (StringUtils.isEmpty(subPath)) {
191189
return filenames.length > 0;
192190
} else {
193191
return Arrays.asList(filenames).contains(subPath);
@@ -250,7 +248,7 @@ private List<BasicFileAttributeView> listAttributes(String subPath, boolean isPr
250248
.path(CdsUrlUtils.getSection(isProtectedResource, config, this.configuration, true))
251249
.path(subPath)
252250
.build();
253-
251+
254252
Optional<CdsFileAttributeViewDto[]> cdsFileList = caller.getFileAttributeView(apiUrl, config);
255253

256254
return remapAndSort(cdsFileList, filter);

cds-plugin/src/test/java/org/entando/entando/plugins/jpcds/aps/system/storage/CdsStorageManagerTest.java

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.entando.entando.aps.system.services.tenants.ITenantManager;
3636
import org.entando.entando.aps.system.services.tenants.TenantConfig;
3737
import org.entando.entando.ent.exception.EntException;
38+
import org.entando.entando.ent.exception.EntResourceNotFoundException;
3839
import org.entando.entando.ent.exception.EntRuntimeException;
3940
import org.junit.jupiter.api.Test;
4041
import org.junit.jupiter.api.extension.ExtendWith;
@@ -238,13 +239,19 @@ void shouldManageErrorWhenCallGetStream() throws Exception {
238239
).isInstanceOf(EntRuntimeException.class).hasMessageStartingWith("Error validating path");
239240

240241
String testFilePath = "/testfolder/test.txt";
242+
243+
Assertions.assertThatThrownBy(
244+
()-> cdsStorageManager.getStream(testFilePath, false)
245+
).isInstanceOf(EntResourceNotFoundException.class).hasMessageStartingWith("File \"" + testFilePath);
246+
241247
URI testFile = URI.create( baseUrl + "/custom-path" + testFilePath);
248+
this.mockExecuteListFolder("http://cds-kube-service:8081/mytenant/api/v1/list/protected/testfolder", "test.txt");
242249
Mockito.when(cdsRemoteCaller.getFile(eq(testFile),
243250
any(),
244251
eq(false))).thenReturn(null);
245252
Assertions.assertThatThrownBy(
246253
()-> cdsStorageManager.getStream(testFilePath,false)
247-
).isInstanceOf(EntException.class).hasMessageStartingWith("Error extracting file");
254+
).isInstanceOf(EntResourceNotFoundException.class).hasMessageStartingWith("Error extracting file");
248255

249256
String testFilePathBadGateway = "/testfolder/test-badgw.txt";
250257
URI testFileBadGateway = URI.create( baseUrl + "/custom-path" + testFilePathBadGateway);
@@ -256,15 +263,9 @@ void shouldManageErrorWhenCallGetStream() throws Exception {
256263
()-> cdsStorageManager.getStream(testFilePathBadGateway,false)
257264
).isInstanceOf(EntException.class).hasMessageStartingWith("Error extracting file");
258265

259-
260266
String testFilePathNotFound = "/testfolder/test-notfound.txt";
261-
URI testFileNotFound = URI.create( baseUrl + "/custom-path" + testFilePathNotFound);
262-
Mockito.when(cdsRemoteCaller.getFile(eq(testFileNotFound),
263-
any(),
264-
eq(false))).thenThrow(new HttpClientErrorException(HttpStatus.NOT_FOUND));
265-
266-
Assertions.assertThat(cdsStorageManager.getStream(testFilePathNotFound,false)).isNull();
267-
267+
Assertions.assertThatThrownBy(() -> cdsStorageManager.getStream(testFilePathNotFound,false))
268+
.isInstanceOf(EntResourceNotFoundException.class).hasMessageStartingWith("Error extracting file");
268269
}
269270

270271
@Test
@@ -276,20 +277,22 @@ void shouldReturnDataWhenCallGetStream() throws Exception {
276277
"cdsPath","/mytenant/api/v1/");
277278
TenantConfig tc = new TenantConfig(configMap);
278279
Mockito.when(tenantManager.getConfig("my-tenant")).thenReturn(Optional.ofNullable(tc));
279-
280+
280281
Mockito.when(cdsRemoteCaller.getFile(eq(URI.create("http://my-server/tenant1/cms-resources/test-folder/test.txt")),
281282
any(),
282283
eq(false))).thenReturn(Optional.ofNullable(new ByteArrayInputStream("text random".getBytes(StandardCharsets.UTF_8))));
283-
284+
285+
this.mockExecuteListFolder("http://cds-kube-service:8081/mytenant/api/v1/list/test-folder", "test.txt");
284286
ApsTenantApplicationUtils.setTenant("my-tenant");
285287
InputStream is = cdsStorageManager.getStream(testFilePath,false);
286288
Assertions.assertThat(new BufferedReader(new InputStreamReader(is))
287289
.lines().collect(Collectors.joining(""))).isEqualTo("text random");
288-
290+
289291
Mockito.when(cdsRemoteCaller.getFile(eq(URI.create("http://cds-kube-service:8081/mytenant/api/v1/protected/test-folder/test.txt")),
290292
any(),
291293
eq(true))).thenReturn(Optional.ofNullable(new ByteArrayInputStream("text random".getBytes(StandardCharsets.UTF_8))));
292-
294+
295+
this.mockExecuteListFolder("http://cds-kube-service:8081/mytenant/api/v1/list/protected/test-folder", "test.txt");
293296
is = cdsStorageManager.getStream(testFilePath,true);
294297
Assertions.assertThat(new BufferedReader(new InputStreamReader(is))
295298
.lines().collect(Collectors.joining(""))).isEqualTo("text random");
@@ -466,24 +469,25 @@ void shouldReadFile() throws Exception {
466469
String testFilePath = "/testfolder/test.txt";
467470

468471
Map<String,String> configMap = Map.of("cdsPublicUrl","http://my-server/tenant1/cms-resources",
469-
"cdsPrivateUrl","http://cds-kube-service:8081/",
472+
"cdsPrivateUrl","http://cdsmaster-kube-service:8081/",
470473
"cdsPath","/mytenant/api/v1/");
471474
TenantConfig tc = new TenantConfig(configMap);
472475
Mockito.when(tenantManager.getConfig("my-tenant")).thenReturn(Optional.ofNullable(tc));
473476

474477
Mockito.when(cdsRemoteCaller.getFile(any(),
475478
any(),
476479
eq(false))).thenReturn(Optional.ofNullable(new ByteArrayInputStream("text random".getBytes(StandardCharsets.UTF_8))));
477-
478-
480+
481+
this.mockExecuteListFolder("http://cdsmaster-kube-service:8081/mytenant/api/v1/list/testfolder", "test.txt");
482+
479483
ApsTenantApplicationUtils.setTenant("my-tenant");
480484
Assertions.assertThat(cdsStorageManager.readFile(testFilePath,false))
481485
.isEqualTo("text random");
482486
}
483487

484488
@Test
485489
void shouldManageExceptionWhenReadFile() throws Exception {
486-
String testFilePath = "/testfolder/test.txt";
490+
String testFilePath = "/testfolder/subfolder/test.txt";
487491

488492
Map<String,String> configMap = Map.of("cdsPublicUrl","http://my-server/tenant1/cms-resources",
489493
"cdsPrivateUrl","http://cds-kube-service:8081/",
@@ -500,7 +504,7 @@ void shouldManageExceptionWhenReadFile() throws Exception {
500504
try (MockedStatic<IOUtils> ioUtils = Mockito.mockStatic(IOUtils.class)) {
501505
ioUtils.when(() -> IOUtils.toString(any(InputStream.class), eq(StandardCharsets.UTF_8)))
502506
.thenThrow(new IOException());
503-
507+
this.mockExecuteListFolder("http://cds-kube-service:8081/mytenant/api/v1/list/testfolder/subfolder", "test.txt");
504508
Assertions.assertThatThrownBy(() -> cdsStorageManager.readFile(testFilePath, false))
505509
.isInstanceOf(EntException.class)
506510
.hasMessageStartingWith("Error extracting text");
@@ -585,5 +589,12 @@ void testListAttributes() throws Throwable {
585589
}
586590
assertTrue(containsCms);
587591
}
592+
593+
private void mockExecuteListFolder(String uri, String filename) {
594+
CdsFileAttributeViewDto file = new CdsFileAttributeViewDto();
595+
file.setName(filename);
596+
Mockito.when(cdsRemoteCaller.getFileAttributeView(eq(URI.create(uri)),
597+
any())).thenReturn(Optional.ofNullable(new CdsFileAttributeViewDto[]{file}));
598+
}
588599

589600
}

engine/src/main/java/org/entando/entando/aps/system/init/DatabaseManager.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.entando.entando.ent.util.EntLogging.EntLogFactory;
7171
import org.entando.entando.ent.util.EntLogging.EntLogger;
7272
import org.springframework.beans.factory.ListableBeanFactory;
73+
import org.springframework.beans.factory.annotation.Autowired;
7374
import org.springframework.core.io.Resource;
7475
import org.springframework.web.context.ServletContextAware;
7576

@@ -96,6 +97,9 @@ public class DatabaseManager extends AbstractInitializerManager
9697
private int lockFallbackMinutes;
9798

9899
private ServletContext servletContext;
100+
101+
@Autowired
102+
private ITenantManager tenantManager;
99103

100104
public void init() {
101105
logger.debug("DatabaseManager ready");
@@ -568,7 +572,7 @@ public boolean dropAndRestoreBackup(String subFolderName) throws EntException {
568572
return false;
569573
}
570574
//TODO future improvement - execute 'lifeline' backup
571-
this.getDatabaseRestorer().dropAndRestoreBackup(subFolderName);
575+
this.getDatabaseRestorer().dropAndRestoreBackup(subFolderName, this.tenantManager);
572576
ApsWebApplicationUtils.executeSystemRefresh(this.getServletContext());
573577
return true;
574578
} catch (Throwable t) {
@@ -586,18 +590,24 @@ private boolean restoreBackup(String subFolderName) throws EntException {
586590
logger.error("backup not available - subfolder '{}'", subFolderName);
587591
return false;
588592
}
589-
this.getDatabaseRestorer().restoreBackup(subFolderName);
593+
this.getDatabaseRestorer().restoreBackup(subFolderName, this.tenantManager);
590594
return true;
591595
} catch (Throwable t) {
592596
logger.error("Error while restoring local backup", t);
593597
throw new EntException("Error while restoring local backup", t);
594598
}
595599
}
596600

597-
private String[] extractBeanNames(Class beanClass) {
601+
private String[] extractBeanNames(Class<?> beanClass) {
598602
ListableBeanFactory factory = (ListableBeanFactory) this.getBeanFactory();
599603
return factory.getBeanNamesForType(beanClass);
600604
}
605+
606+
607+
608+
609+
610+
601611

602612
@Override
603613
public InputStream getTableDump(String tableName, String dataSourceName, String subFolderName) throws EntException {

0 commit comments

Comments
 (0)