Commit c07136fa authored by Rustam Lotsmanenko (EPAM)'s avatar Rustam Lotsmanenko (EPAM)
Browse files

GONRG-863

Changes:
Implement authorization(Entitlements)
Backups have ID
Schedule have ID
Restore by ID
remove old backups
Refactoring
parent 883e308d
......@@ -27,7 +27,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
......
......@@ -6,14 +6,18 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.opengroup.osdu.backup.locator.Asset;
import org.opengroup.osdu.backup.model.BackupImportRequest;
import org.opengroup.osdu.backup.model.BackupRole;
import org.opengroup.osdu.backup.model.BackupSchedule;
import org.opengroup.osdu.backup.model.BackupStamp;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
import org.opengroup.osdu.backup.provider.interfaces.BackupService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.annotation.RequestScope;
......@@ -21,29 +25,43 @@ import org.springframework.web.context.annotation.RequestScope;
@RestController
@RequestScope
@RequiredArgsConstructor
@PreAuthorize("@authorizationFilter.hasPermission('" + BackupRole.BACKUP + "')")
public class BackupApi {
private final BackupService backupService;
//TODO Entitlements & roles
@PostMapping("/submitScheduledTask")
public ResponseEntity<String> submitScheduledTask(@RequestBody SubmitScheduleRequest submitScheduleRequest) {
backupService.submitScheduledTask(submitScheduleRequest);
return new ResponseEntity<String>("Task submitted", HttpStatus.OK);
@PostMapping("/schedule")
public ResponseEntity<BackupSchedule> submitBackupSchedule(
@RequestBody BackupSchedule backupSchedule) {
BackupSchedule savedBackupSchedule = backupService.submitBackupSchedule(backupSchedule);
return new ResponseEntity<BackupSchedule>(savedBackupSchedule, HttpStatus.OK);
}
@PostMapping("/submitImport")
public ResponseEntity<String> submitImport(@RequestBody BackupImportRequest backup) {
backupService.submitImportRequest(backup);
return new ResponseEntity<String>("Import request submitted", HttpStatus.OK);
@PutMapping("/schedule")
public ResponseEntity<BackupSchedule> updateBackupSchedule(
@RequestBody BackupSchedule backupSchedule) {
BackupSchedule savedBackupSchedule = backupService.updateBackupSchedule(backupSchedule);
return new ResponseEntity<BackupSchedule>(savedBackupSchedule, HttpStatus.OK);
}
@GetMapping("/listSchedules")
public ResponseEntity<List<SubmitScheduleRequest>> listSchedules() {
return new ResponseEntity<List<SubmitScheduleRequest>>(backupService.listSchedules(), HttpStatus.OK);
@GetMapping("/schedule")
public ResponseEntity<BackupSchedule> getScheduleById(@RequestParam String id) {
return new ResponseEntity<BackupSchedule>(backupService.getBackupSchedule(id), HttpStatus.OK);
}
@GetMapping("/listBackups")
@PostMapping("/backup_import")
public ResponseEntity<BackupStamp> submitImport(@RequestBody BackupImportRequest backupId) {
BackupStamp stamp = backupService.submitBackupImportRequest(backupId);
return new ResponseEntity<BackupStamp>(stamp, HttpStatus.OK);
}
@GetMapping("/list_schedules")
public ResponseEntity<List<BackupSchedule>> listSchedules() {
return new ResponseEntity<List<BackupSchedule>>(backupService.listSchedules(), HttpStatus.OK);
}
@GetMapping("/list_backups")
public ResponseEntity<EnumMap<Asset, List<BackupStamp>>> listBackups() {
return new ResponseEntity<EnumMap<Asset, List<BackupStamp>>>(backupService.listBackups(), HttpStatus.OK);
}
......
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.opengroup.osdu.backup.config.property;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ConfigurationProperties(prefix = "osdu.entitlements")
@Component
public class EntitlementProperties {
String url;
String appKey;
}
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.opengroup.osdu.backup.di;
import lombok.RequiredArgsConstructor;
import org.opengroup.osdu.backup.config.property.EntitlementProperties;
import org.opengroup.osdu.core.common.entitlements.EntitlementsAPIConfig;
import org.opengroup.osdu.core.common.entitlements.EntitlementsFactory;
import org.opengroup.osdu.core.common.entitlements.IEntitlementsFactory;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.stereotype.Component;
@RequiredArgsConstructor
@Component
public class EntitlementsClientFactory extends AbstractFactoryBean<IEntitlementsFactory> {
final EntitlementProperties entitlementProperties;
@Override
protected IEntitlementsFactory createInstance() {
return new EntitlementsFactory(EntitlementsAPIConfig.builder()
.rootUrl(entitlementProperties.getUrl())
.apiKey(entitlementProperties.getAppKey())
.build());
}
@Override
public Class<?> getObjectType() {
return IEntitlementsFactory.class;
}
}
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.opengroup.osdu.backup.middleware;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.opengroup.osdu.core.common.model.entitlements.AuthorizationResponse;
import org.opengroup.osdu.core.common.model.http.DpsHeaders;
import org.opengroup.osdu.core.common.provider.interfaces.IAuthorizationService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
@Slf4j
@RequiredArgsConstructor
@Component("authorizationFilter")
@RequestScope
public class AuthorizationFilter {
final IAuthorizationService authorizationService;
final DpsHeaders headers;
public boolean hasPermission(String... requiredRoles) {
AuthorizationResponse authResponse = authorizationService.authorizeAny(headers, requiredRoles);
headers.put(DpsHeaders.USER_EMAIL, authResponse.getUser());
return true;
}
}
......@@ -11,6 +11,6 @@ import lombok.NoArgsConstructor;
@Builder
public class BackupImportRequest {
private Long backupStampId;
private String backupStampId;
}
package org.opengroup.osdu.backup.model;
public class BackupRole {
public static final String BACKUP = "backup.service";
}
package org.opengroup.osdu.backup.model;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
......@@ -11,16 +12,12 @@ import org.opengroup.osdu.backup.locator.Asset;
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(of = {"assetType", "namespace", "kind"})
public class SubmitScheduleRequest {
@EqualsAndHashCode(of = {"scheduleId", "assetType", "assetContext"})
public class BackupSchedule {
private Asset assetType;
private String namespace;
private String scheduleId;
private String kind;
private String backupPath;
private Asset assetType;
private int backupPeriod;
......@@ -28,6 +25,6 @@ public class SubmitScheduleRequest {
private int lifetime;
// TODO backups lifetime
private Map<String, String> assetContext;
}
package org.opengroup.osdu.backup.model;
import java.time.LocalDate;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
......@@ -13,17 +14,13 @@ import org.opengroup.osdu.backup.locator.Asset;
@Builder
public class BackupStamp {
private Long id;
private String stampId;
private String backupRepository;
private Asset assetType;
private String namespace;
private String kind;
private String backupPath;
private LocalDate tearDownDate;
private Map<String, String> assetContext;
}
package org.opengroup.osdu.backup.model;
import java.util.EnumMap;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.opengroup.osdu.backup.locator.Asset;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class BackupStampsResponse {
EnumMap<Asset, List<BackupStamp>> backupsMap;
}
package org.opengroup.osdu.backup.provider.interfaces;
import java.util.List;
import org.opengroup.osdu.backup.model.BackupImportRequest;
import org.opengroup.osdu.backup.model.BackupSchedule;
import org.opengroup.osdu.backup.model.BackupStamp;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
public interface AssetBackupManager {
void exportBackup(SubmitScheduleRequest submitScheduleRequest);
void exportBackup(BackupSchedule backupSchedule);
void importBackup(BackupImportRequest backup);
BackupStamp importBackup(String backupId);
void deleteBackups(List<BackupStamp> currentDate);
}
......@@ -4,16 +4,20 @@ import java.util.EnumMap;
import java.util.List;
import org.opengroup.osdu.backup.locator.Asset;
import org.opengroup.osdu.backup.model.BackupImportRequest;
import org.opengroup.osdu.backup.model.BackupSchedule;
import org.opengroup.osdu.backup.model.BackupStamp;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
public interface BackupService {
void submitScheduledTask(SubmitScheduleRequest submitScheduleRequest);
BackupSchedule submitBackupSchedule(BackupSchedule backupSchedule);
void submitImportRequest(BackupImportRequest backup);
BackupSchedule updateBackupSchedule(BackupSchedule backupSchedule);
List<SubmitScheduleRequest> listSchedules();
BackupSchedule getBackupSchedule(String id);
BackupStamp submitBackupImportRequest(BackupImportRequest importRequest);
List<BackupSchedule> listSchedules();
EnumMap<Asset, List<BackupStamp>> listBackups();
}
......@@ -16,5 +16,5 @@ public interface BackupStampRepository {
void deleteBackupStamps(List<BackupStamp> currentDate);
BackupStamp findBackupByStampId(Long backupStampId);
BackupStamp findBackupByStampId(String backupStampId);
}
package org.opengroup.osdu.backup.provider.interfaces;
import java.util.List;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
import org.opengroup.osdu.backup.model.BackupSchedule;
public interface ScheduleRepository {
List<SubmitScheduleRequest> listBackupSchedules();
List<BackupSchedule> listBackupSchedules();
SubmitScheduleRequest submitSchedule(SubmitScheduleRequest submitScheduleRequest);
BackupSchedule submitSchedule(BackupSchedule backupSchedule);
BackupSchedule updateSchedule(BackupSchedule backupSchedule);
}
package org.opengroup.osdu.backup.shedulers;
import lombok.RequiredArgsConstructor;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
import org.opengroup.osdu.backup.model.BackupSchedule;
import org.opengroup.osdu.backup.provider.interfaces.AssetBackupManager;
@RequiredArgsConstructor
......@@ -9,10 +9,10 @@ public class BackupScheduledTask implements Runnable {
private final AssetBackupManager assetBackupManager;
private final SubmitScheduleRequest submitScheduleRequest;
private final BackupSchedule backupSchedule;
@Override
public void run() {
assetBackupManager.exportBackup(submitScheduleRequest);
assetBackupManager.exportBackup(backupSchedule);
}
}
package org.opengroup.osdu.backup.shedulers;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
import org.opengroup.osdu.backup.model.BackupSchedule;
public interface SchedulerService {
void addTaskToScheduler(SubmitScheduleRequest submitScheduleRequest);
void addTaskToScheduler(BackupSchedule backupSchedule);
boolean cancelScheduledTask(SubmitScheduleRequest submitScheduleRequest);
boolean cancelScheduledTask(BackupSchedule backupSchedule);
void taskStatusChanged(SubmitScheduleRequest submitScheduleRequest);
void updateTask(BackupSchedule backupSchedule);
}
......@@ -16,7 +16,7 @@ public class TearDownBackupScheduledTask implements Runnable {
private final AssetRepoFactory assetRepoFactory;
private LocalDate tearDownDate = LocalDate.now();
private final LocalDate tearDownDate = LocalDate.now();
@Override
public void run() {
......
......@@ -7,7 +7,7 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.opengroup.osdu.backup.config.AssetRepoFactory;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
import org.opengroup.osdu.backup.model.BackupSchedule;
import org.opengroup.osdu.backup.shedulers.BackupScheduledTask;
import org.opengroup.osdu.backup.shedulers.SchedulerService;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
......@@ -18,7 +18,7 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor
public class SchedulerServiceImpl implements SchedulerService {
private final Map<SubmitScheduleRequest, ScheduledFuture> taskMap = new HashMap<>();
private final Map<BackupSchedule, ScheduledFuture> taskMap = new HashMap<>();
private final TimeUnit timeUnit = TimeUnit.MINUTES;
......@@ -36,30 +36,28 @@ public class SchedulerServiceImpl implements SchedulerService {
}
@Override
public void addTaskToScheduler(SubmitScheduleRequest submitScheduleRequest) {
PeriodicTrigger periodicTrigger = new PeriodicTrigger(submitScheduleRequest.getBackupPeriod(), timeUnit);
public void addTaskToScheduler(BackupSchedule submitBackupScheduleRequest) {
PeriodicTrigger periodicTrigger = new PeriodicTrigger(submitBackupScheduleRequest.getBackupPeriod(), timeUnit);
periodicTrigger.setFixedRate(true);
BackupScheduledTask backupScheduledTask = new BackupScheduledTask(
repoFactory.getAssetRepository(submitScheduleRequest.getAssetType()), submitScheduleRequest);
repoFactory.getAssetRepository(submitBackupScheduleRequest.getAssetType()), submitBackupScheduleRequest);
ScheduledFuture<?> schedule = poolTaskScheduler.schedule(backupScheduledTask, periodicTrigger);
taskMap.put(submitScheduleRequest, schedule);
taskMap.put(submitBackupScheduleRequest, schedule);
}
@Override
public boolean cancelScheduledTask(SubmitScheduleRequest submitScheduleRequest) {
return taskMap.get(submitScheduleRequest).cancel(false);
public void updateTask(BackupSchedule backupSchedule) {
cancelScheduledTask(backupSchedule);
addTaskToScheduler(backupSchedule);
}
@Override
public void taskStatusChanged(SubmitScheduleRequest submitScheduleRequest) {
if (!submitScheduleRequest.isActive()) {
taskMap.get(submitScheduleRequest).cancel(false);
} else {
addTaskToScheduler(submitScheduleRequest);
}
public boolean cancelScheduledTask(BackupSchedule backupSchedule) {
boolean cancel = taskMap.get(backupSchedule).cancel(false);
taskMap.remove(backupSchedule);
return cancel;
}
}
......@@ -14,7 +14,7 @@ import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.opengroup.osdu.backup.model.SubmitScheduleRequest;
import org.opengroup.osdu.backup.model.BackupSchedule;
import org.opengroup.osdu.backup.provider.interfaces.AssetBackupManager;
import org.springframework.test.util.ReflectionTestUtils;
......@@ -27,18 +27,18 @@ public class SchedulerServiceImplTest {
@InjectMocks
private SchedulerServiceImpl schedulerService;
private SubmitScheduleRequest submitScheduleRequest;
private SubmitScheduleRequest submitScheduleRequest1;
private SubmitScheduleRequest submitScheduleRequest2;
private BackupSchedule backupSchedule;
private BackupSchedule backupSchedule1;
private BackupSchedule backupSchedule2;
@Before
public void setUp() throws Exception {
submitScheduleRequest = SubmitScheduleRequest.builder().namespace("test").kind("kind").backupPeriod(2).active(true)
.build();
submitScheduleRequest1 = SubmitScheduleRequest.builder().namespace("test1").kind("kind1").backupPeriod(2).active(true)
.build();
submitScheduleRequest2 = SubmitScheduleRequest.builder().namespace("test2").kind("kind2").backupPeriod(2).active(true)
.build();
// submitScheduleRequest = SubmitScheduleRequest.builder().namespace("test").kind("kind").backupPeriod(2).active(true)
// .build();
// submitScheduleRequest1 = SubmitScheduleRequest.builder().namespace("test1").kind("kind1").backupPeriod(2).active(true)
// .build();
// submitScheduleRequest2 = SubmitScheduleRequest.builder().namespace("test2").kind("kind2").backupPeriod(2).active(true)
// .build();
ReflectionTestUtils.setField(schedulerService, "timeUnit", TimeUnit.SECONDS);
schedulerService.initThreadPool();
......@@ -46,32 +46,32 @@ public class SchedulerServiceImplTest {
@Test
public void addTaskToScheduler() throws InterruptedException {
schedulerService.addTaskToScheduler(submitScheduleRequest);
schedulerService.addTaskToScheduler(submitScheduleRequest1);
schedulerService.addTaskToScheduler(submitScheduleRequest2);
schedulerService.addTaskToScheduler(backupSchedule);
schedulerService.addTaskToScheduler(backupSchedule1);
schedulerService.addTaskToScheduler(backupSchedule2);
sleep(1000);
verify(assetBackupManager, times(3)).exportBackup(any());
schedulerService.cancelScheduledTask(submitScheduleRequest);
schedulerService.cancelScheduledTask(submitScheduleRequest1);
schedulerService.cancelScheduledTask(submitScheduleRequest2);
schedulerService.cancelScheduledTask(backupSchedule);
schedulerService.cancelScheduledTask(backupSchedule1);
schedulerService.cancelScheduledTask(backupSchedule2);
verifyNoMoreInteractions(assetBackupManager);
}
@Test
public void removeTaskFromScheduler() throws InterruptedException {
schedulerService.addTaskToScheduler(submitScheduleRequest);
schedulerService.addTaskToScheduler(backupSchedule);