Separate AutoCommit settings

This commit is contained in:
Andrii Shvaika 2022-05-31 13:19:16 +03:00
parent 89c04a3460
commit 07b6813465
24 changed files with 468 additions and 209 deletions

View File

@ -29,24 +29,23 @@ import org.springframework.web.context.request.async.DeferredResult;
import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.MailService;
import org.thingsboard.rule.engine.api.SmsService; import org.thingsboard.rule.engine.api.SmsService;
import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.UpdateMessage; import org.thingsboard.server.common.data.UpdateMessage;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.SecuritySettings;
import org.thingsboard.server.common.data.sms.config.TestSmsRequest; import org.thingsboard.server.common.data.sms.config.TestSmsRequest;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings;
import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import org.thingsboard.server.service.security.system.SystemSecurityService; import org.thingsboard.server.service.security.system.SystemSecurityService;
import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService;
import org.thingsboard.server.service.sync.vc.autocommit.TbAutoCommitSettingsService;
import org.thingsboard.server.service.update.UpdateService; import org.thingsboard.server.service.update.UpdateService;
import static org.thingsboard.server.controller.ControllerConstants.*; import static org.thingsboard.server.controller.ControllerConstants.*;
import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID;
@RestController @RestController
@TbCoreComponent @TbCoreComponent
@ -68,6 +67,9 @@ public class AdminController extends BaseController {
@Autowired @Autowired
private EntitiesVersionControlService versionControlService; private EntitiesVersionControlService versionControlService;
@Autowired
private TbAutoCommitSettingsService autoCommitSettingsService;
@Autowired @Autowired
private UpdateService updateService; private UpdateService updateService;
@ -194,10 +196,10 @@ public class AdminController extends BaseController {
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/vcSettings") @GetMapping("/vcSettings")
@ResponseBody @ResponseBody
public EntitiesVersionControlSettings getVersionControlSettings() throws ThingsboardException { public RepositorySettings getVersionControlSettings() throws ThingsboardException {
try { try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
EntitiesVersionControlSettings versionControlSettings = checkNotNull(versionControlService.getVersionControlSettings(getTenantId())); RepositorySettings versionControlSettings = checkNotNull(versionControlService.getVersionControlSettings(getTenantId()));
versionControlSettings.setPassword(null); versionControlSettings.setPassword(null);
versionControlSettings.setPrivateKey(null); versionControlSettings.setPrivateKey(null);
versionControlSettings.setPrivateKeyPassword(null); versionControlSettings.setPrivateKeyPassword(null);
@ -225,9 +227,9 @@ public class AdminController extends BaseController {
notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH) notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@PostMapping("/vcSettings") @PostMapping("/vcSettings")
public DeferredResult<EntitiesVersionControlSettings> saveVersionControlSettings(@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException { public DeferredResult<RepositorySettings> saveVersionControlSettings(@RequestBody RepositorySettings settings) throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
ListenableFuture<EntitiesVersionControlSettings> future = versionControlService.saveVersionControlSettings(getTenantId(), settings); ListenableFuture<RepositorySettings> future = versionControlService.saveVersionControlSettings(getTenantId(), settings);
return wrapFuture(Futures.transform(future, savedSettings -> { return wrapFuture(Futures.transform(future, savedSettings -> {
savedSettings.setPassword(null); savedSettings.setPassword(null);
savedSettings.setPrivateKey(null); savedSettings.setPrivateKey(null);
@ -251,13 +253,65 @@ public class AdminController extends BaseController {
} }
} }
@ApiOperation(value = "Get auto commit settings (getAutoCommitSettings)",
notes = "Get the auto commit settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/vc/autoCommitSettings")
@ResponseBody
public AutoCommitSettings getAutoCommitSettings() throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return checkNotNull(autoCommitSettingsService.get(getTenantId()));
} catch (Exception e) {
throw handleException(e);
}
}
@ApiOperation(value = "Check version control settings exists (versionControlSettingsExists)",
notes = "Check whether the version control settings exists. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/vc/autoCommitSettings/exists")
@ResponseBody
public Boolean autoCommitSettingsExists() throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return autoCommitSettingsService.get(getTenantId()) != null;
} catch (Exception e) {
throw handleException(e);
}
}
@ApiOperation(value = "Creates or Updates the version control settings (saveVersionControlSettings)",
notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@PostMapping("/vc/autoCommitSettings")
public AutoCommitSettings saveAutoCommitSettings(@RequestBody AutoCommitSettings settings) throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
return autoCommitSettingsService.save(getTenantId(), settings);
}
@ApiOperation(value = "Delete version control settings (deleteVersionControlSettings)",
notes = "Deletes the version control settings."
+ TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/vc/autoCommitSettings", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteAutoCommitSettings() throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.DELETE);
autoCommitSettingsService.delete(getTenantId());
} catch (Exception e) {
throw handleException(e);
}
}
@ApiOperation(value = "Check version control access (checkVersionControlAccess)", @ApiOperation(value = "Check version control access (checkVersionControlAccess)",
notes = "Attempts to check version control access. " + TENANT_AUTHORITY_PARAGRAPH) notes = "Attempts to check version control access. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/vcSettings/checkAccess", method = RequestMethod.POST) @RequestMapping(value = "/vcSettings/checkAccess", method = RequestMethod.POST)
public DeferredResult<Void> checkVersionControlAccess( public DeferredResult<Void> checkVersionControlAccess(
@ApiParam(value = "A JSON value representing the Entities Version Control Settings.") @ApiParam(value = "A JSON value representing the Entities Version Control Settings.")
@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException { @RequestBody RepositorySettings settings) throws ThingsboardException {
try { try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
settings = checkNotNull(settings); settings = checkNotNull(settings);

View File

@ -27,7 +27,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.ExportableEntity; import org.thingsboard.server.common.data.ExportableEntity;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
@ -44,7 +43,7 @@ import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.common.data.sync.ie.EntityExportSettings; import org.thingsboard.server.common.data.sync.ie.EntityExportSettings;
import org.thingsboard.server.common.data.sync.ie.EntityImportResult; import org.thingsboard.server.common.data.sync.ie.EntityImportResult;
import org.thingsboard.server.common.data.sync.ie.EntityImportSettings; import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.EntityDataDiff; import org.thingsboard.server.common.data.sync.vc.EntityDataDiff;
import org.thingsboard.server.common.data.sync.vc.EntityVersion; import org.thingsboard.server.common.data.sync.vc.EntityVersion;
import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionCreationResult;
@ -62,19 +61,18 @@ import org.thingsboard.server.common.data.sync.vc.request.load.SingleEntityVersi
import org.thingsboard.server.common.data.sync.vc.request.load.VersionLoadConfig; import org.thingsboard.server.common.data.sync.vc.request.load.VersionLoadConfig;
import org.thingsboard.server.common.data.sync.vc.request.load.VersionLoadRequest; import org.thingsboard.server.common.data.sync.vc.request.load.VersionLoadRequest;
import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.sync.ie.EntitiesExportImportService; import org.thingsboard.server.service.sync.ie.EntitiesExportImportService;
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService; import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
import org.thingsboard.server.service.sync.vc.autocommit.TbAutoCommitSettingsService;
import org.thingsboard.server.service.sync.vc.data.CommitGitRequest; import org.thingsboard.server.service.sync.vc.data.CommitGitRequest;
import org.thingsboard.server.service.sync.vc.repository.TbRepositorySettingsService;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import java.time.Instant; import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -94,7 +92,8 @@ import static com.google.common.util.concurrent.Futures.transformAsync;
@Slf4j @Slf4j
public class DefaultEntitiesVersionControlService implements EntitiesVersionControlService { public class DefaultEntitiesVersionControlService implements EntitiesVersionControlService {
private final TbVersionControlSettingsService vcSettingsService; private final TbRepositorySettingsService repositorySettingsService;
private final TbAutoCommitSettingsService autoCommitSettingsService;
private final GitVersionControlQueueService gitServiceQueue; private final GitVersionControlQueueService gitServiceQueue;
private final EntitiesExportImportService exportImportService; private final EntitiesExportImportService exportImportService;
private final ExportableEntitiesService exportableEntitiesService; private final ExportableEntitiesService exportableEntitiesService;
@ -336,16 +335,16 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
} }
@Override @Override
public EntitiesVersionControlSettings getVersionControlSettings(TenantId tenantId) { public RepositorySettings getVersionControlSettings(TenantId tenantId) {
return vcSettingsService.get(tenantId); return repositorySettingsService.get(tenantId);
} }
@Override @Override
public ListenableFuture<EntitiesVersionControlSettings> saveVersionControlSettings(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings) { public ListenableFuture<RepositorySettings> saveVersionControlSettings(TenantId tenantId, RepositorySettings versionControlSettings) {
var restoredSettings = this.vcSettingsService.restore(tenantId, versionControlSettings); var restoredSettings = this.repositorySettingsService.restore(tenantId, versionControlSettings);
try { try {
var future = gitServiceQueue.initRepository(tenantId, restoredSettings); var future = gitServiceQueue.initRepository(tenantId, restoredSettings);
return Futures.transform(future, f -> vcSettingsService.save(tenantId, restoredSettings), MoreExecutors.directExecutor()); return Futures.transform(future, f -> repositorySettingsService.save(tenantId, restoredSettings), MoreExecutors.directExecutor());
} catch (Exception e) { } catch (Exception e) {
log.debug("{} Failed to init repository: {}", tenantId, versionControlSettings, e); log.debug("{} Failed to init repository: {}", tenantId, versionControlSettings, e);
throw new RuntimeException("Failed to init repository!", e); throw new RuntimeException("Failed to init repository!", e);
@ -354,7 +353,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
@Override @Override
public ListenableFuture<Void> deleteVersionControlSettings(TenantId tenantId) throws Exception { public ListenableFuture<Void> deleteVersionControlSettings(TenantId tenantId) throws Exception {
if (vcSettingsService.delete(tenantId)) { if (repositorySettingsService.delete(tenantId)) {
return gitServiceQueue.clearRepository(tenantId); return gitServiceQueue.clearRepository(tenantId);
} else { } else {
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
@ -362,8 +361,8 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
} }
@Override @Override
public ListenableFuture<Void> checkVersionControlAccess(TenantId tenantId, EntitiesVersionControlSettings settings) throws ThingsboardException { public ListenableFuture<Void> checkVersionControlAccess(TenantId tenantId, RepositorySettings settings) throws ThingsboardException {
settings = this.vcSettingsService.restore(tenantId, settings); settings = this.repositorySettingsService.restore(tenantId, settings);
try { try {
return gitServiceQueue.testRepository(tenantId, settings); return gitServiceQueue.testRepository(tenantId, settings);
} catch (Exception e) { } catch (Exception e) {
@ -374,22 +373,29 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
@Override @Override
public ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityId entityId) throws Exception { public ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityId entityId) throws Exception {
var settings = vcSettingsService.get(user.getTenantId()); var repositorySettings = repositorySettingsService.get(user.getTenantId());
var entityType = entityId.getEntityType(); if (repositorySettings == null) {
if (settings != null && settings.getAutoCommitSettings() != null && settings.getAutoCommitSettings().containsKey(entityType)) { return Futures.immediateFuture(null);
AutoVersionCreateConfig autoCommitConfig = settings.getAutoCommitSettings().get(entityType);
SingleEntityVersionCreateRequest vcr = new SingleEntityVersionCreateRequest();
var autoCommitBranchName = autoCommitConfig.getBranch();
if (StringUtils.isEmpty(autoCommitBranchName)) {
autoCommitBranchName = StringUtils.isNotEmpty(settings.getDefaultBranch()) ? settings.getDefaultBranch() : "auto-commits";
}
vcr.setBranch(autoCommitBranchName);
vcr.setVersionName("auto-commit by " + user.getEmail() + " at " + Instant.ofEpochSecond(System.currentTimeMillis() / 1000));
vcr.setEntityId(entityId);
vcr.setConfig(autoCommitConfig);
return saveEntitiesVersion(user, vcr);
} }
return Futures.immediateFuture(null); var autoCommitSettings = autoCommitSettingsService.get(user.getTenantId());
if (autoCommitSettings == null) {
return Futures.immediateFuture(null);
}
var entityType = entityId.getEntityType();
AutoVersionCreateConfig autoCommitConfig = autoCommitSettings.get(entityType);
if (autoCommitConfig == null) {
return Futures.immediateFuture(null);
}
SingleEntityVersionCreateRequest vcr = new SingleEntityVersionCreateRequest();
var autoCommitBranchName = autoCommitConfig.getBranch();
if (StringUtils.isEmpty(autoCommitBranchName)) {
autoCommitBranchName = StringUtils.isNotEmpty(repositorySettings.getDefaultBranch()) ? repositorySettings.getDefaultBranch() : "auto-commits";
}
vcr.setBranch(autoCommitBranchName);
vcr.setVersionName("auto-commit at " + Instant.ofEpochSecond(System.currentTimeMillis() / 1000));
vcr.setEntityId(entityId);
vcr.setConfig(autoCommitConfig);
return saveEntitiesVersion(user, vcr);
} }
private String getCauseMessage(Exception e) { private String getCauseMessage(Exception e) {

View File

@ -33,7 +33,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.sync.ie.EntityExportData; import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.EntityVersion; import org.thingsboard.server.common.data.sync.vc.EntityVersion;
import org.thingsboard.server.common.data.sync.vc.EntityVersionsDiff; import org.thingsboard.server.common.data.sync.vc.EntityVersionsDiff;
import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionCreationResult;
@ -271,7 +271,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
} }
private <T> void registerAndSend(PendingGitRequest<T> request, private <T> void registerAndSend(PendingGitRequest<T> request,
Function<ToVersionControlServiceMsg.Builder, ToVersionControlServiceMsg> enrichFunction, EntitiesVersionControlSettings settings, TbQueueCallback callback) { Function<ToVersionControlServiceMsg.Builder, ToVersionControlServiceMsg> enrichFunction, RepositorySettings settings, TbQueueCallback callback) {
if (!request.getFuture().isDone()) { if (!request.getFuture().isDone()) {
pendingRequestMap.putIfAbsent(request.getRequestId(), request); pendingRequestMap.putIfAbsent(request.getRequestId(), request);
var requestBody = enrichFunction.apply(newRequestProto(request, settings)); var requestBody = enrichFunction.apply(newRequestProto(request, settings));
@ -307,7 +307,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
} }
@Override @Override
public ListenableFuture<Void> initRepository(TenantId tenantId, EntitiesVersionControlSettings settings) { public ListenableFuture<Void> initRepository(TenantId tenantId, RepositorySettings settings) {
VoidGitRequest request = new VoidGitRequest(tenantId); VoidGitRequest request = new VoidGitRequest(tenantId);
registerAndSend(request, builder -> builder.setInitRepositoryRequest(GenericRepositoryRequestMsg.newBuilder().build()).build() registerAndSend(request, builder -> builder.setInitRepositoryRequest(GenericRepositoryRequestMsg.newBuilder().build()).build()
@ -317,7 +317,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
} }
@Override @Override
public ListenableFuture<Void> testRepository(TenantId tenantId, EntitiesVersionControlSettings settings) { public ListenableFuture<Void> testRepository(TenantId tenantId, RepositorySettings settings) {
VoidGitRequest request = new VoidGitRequest(tenantId); VoidGitRequest request = new VoidGitRequest(tenantId);
registerAndSend(request, builder -> builder registerAndSend(request, builder -> builder
@ -457,7 +457,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
return PrepareMsg.newBuilder().setCommitMsg(request.getVersionName()).setBranchName(request.getBranch()).build(); return PrepareMsg.newBuilder().setCommitMsg(request.getVersionName()).setBranchName(request.getBranch()).build();
} }
private ToVersionControlServiceMsg.Builder newRequestProto(PendingGitRequest<?> request, EntitiesVersionControlSettings settings) { private ToVersionControlServiceMsg.Builder newRequestProto(PendingGitRequest<?> request, RepositorySettings settings) {
var tenantId = request.getTenantId(); var tenantId = request.getTenantId();
var requestId = request.getRequestId(); var requestId = request.getRequestId();
var builder = ToVersionControlServiceMsg.newBuilder() var builder = ToVersionControlServiceMsg.newBuilder()
@ -466,7 +466,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) .setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setRequestIdMSB(requestId.getMostSignificantBits()) .setRequestIdMSB(requestId.getMostSignificantBits())
.setRequestIdLSB(requestId.getLeastSignificantBits()); .setRequestIdLSB(requestId.getLeastSignificantBits());
EntitiesVersionControlSettings vcSettings = settings; RepositorySettings vcSettings = settings;
if (vcSettings == null && request.requiresSettings()) { if (vcSettings == null && request.requiresSettings()) {
vcSettings = entitiesVersionControlService.getVersionControlSettings(tenantId); vcSettings = entitiesVersionControlService.getVersionControlSettings(tenantId);
} }

View File

@ -1,102 +0,0 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.service.sync.vc;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.TbTransactionalCache;
import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings;
import org.thingsboard.server.common.data.sync.vc.VersionControlAuthMethod;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.queue.util.TbCoreComponent;
@Service
@TbCoreComponent
@RequiredArgsConstructor
public class DefaultTbVersionControlSettingsService implements TbVersionControlSettingsService {
public static final String SETTINGS_KEY = "entitiesVersionControl";
private final AdminSettingsService adminSettingsService;
private final TbTransactionalCache<TenantId, EntitiesVersionControlSettings> cache;
@Override
public EntitiesVersionControlSettings restore(TenantId tenantId, EntitiesVersionControlSettings settings) {
EntitiesVersionControlSettings storedSettings = get(tenantId);
if (storedSettings != null) {
VersionControlAuthMethod authMethod = settings.getAuthMethod();
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(authMethod) && settings.getPassword() == null) {
settings.setPassword(storedSettings.getPassword());
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(authMethod) && settings.getPrivateKey() == null) {
settings.setPrivateKey(storedSettings.getPrivateKey());
if (settings.getPrivateKeyPassword() == null) {
settings.setPrivateKeyPassword(storedSettings.getPrivateKeyPassword());
}
}
}
return settings;
}
@Override
public EntitiesVersionControlSettings get(TenantId tenantId) {
EntitiesVersionControlSettings settings = cache.getAndPutInTransaction(tenantId, () -> {
AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, SETTINGS_KEY);
if (adminSettings != null) {
try {
return JacksonUtil.convertValue(adminSettings.getJsonValue(), EntitiesVersionControlSettings.class);
} catch (Exception e) {
throw new RuntimeException("Failed to load version control settings!", e);
}
}
return null;
}, true);
if (settings != null) {
settings = new EntitiesVersionControlSettings(settings);
}
return settings;
}
@Override
public EntitiesVersionControlSettings save(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings) {
AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, SETTINGS_KEY);
if (adminSettings == null) {
adminSettings = new AdminSettings();
adminSettings.setKey(SETTINGS_KEY);
adminSettings.setTenantId(tenantId);
}
adminSettings.setJsonValue(JacksonUtil.valueToTree(versionControlSettings));
AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(tenantId, adminSettings);
EntitiesVersionControlSettings savedVersionControlSettings;
try {
savedVersionControlSettings = JacksonUtil.convertValue(savedAdminSettings.getJsonValue(), EntitiesVersionControlSettings.class);
} catch (Exception e) {
throw new RuntimeException("Failed to load version control settings!", e);
}
//API calls to adminSettingsService are not in transaction, so we can simply evict the cache.
cache.evict(tenantId);
return savedVersionControlSettings;
}
@Override
public boolean delete(TenantId tenantId) {
boolean result = adminSettingsService.deleteAdminSettings(tenantId, SETTINGS_KEY);
cache.evict(tenantId);
return result;
}
}

View File

@ -16,7 +16,6 @@
package org.thingsboard.server.service.sync.vc; package org.thingsboard.server.service.sync.vc;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -24,7 +23,7 @@ import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.sync.vc.EntityDataDiff; import org.thingsboard.server.common.data.sync.vc.EntityDataDiff;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.EntityVersion; import org.thingsboard.server.common.data.sync.vc.EntityVersion;
import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionCreationResult;
import org.thingsboard.server.common.data.sync.vc.VersionLoadResult; import org.thingsboard.server.common.data.sync.vc.VersionLoadResult;
@ -54,13 +53,13 @@ public interface EntitiesVersionControlService {
ListenableFuture<List<String>> listBranches(TenantId tenantId) throws Exception; ListenableFuture<List<String>> listBranches(TenantId tenantId) throws Exception;
EntitiesVersionControlSettings getVersionControlSettings(TenantId tenantId); RepositorySettings getVersionControlSettings(TenantId tenantId);
ListenableFuture<EntitiesVersionControlSettings> saveVersionControlSettings(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings); ListenableFuture<RepositorySettings> saveVersionControlSettings(TenantId tenantId, RepositorySettings versionControlSettings);
ListenableFuture<Void> deleteVersionControlSettings(TenantId tenantId) throws Exception; ListenableFuture<Void> deleteVersionControlSettings(TenantId tenantId) throws Exception;
ListenableFuture<Void> checkVersionControlAccess(TenantId tenantId, EntitiesVersionControlSettings settings) throws Exception; ListenableFuture<Void> checkVersionControlAccess(TenantId tenantId, RepositorySettings settings) throws Exception;
ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityId entityId) throws Exception; ListenableFuture<VersionCreationResult> autoCommit(SecurityUser user, EntityId entityId) throws Exception;
} }

View File

@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.sync.ie.EntityExportData; import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.EntityVersion; import org.thingsboard.server.common.data.sync.vc.EntityVersion;
import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionCreationResult;
import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo;
@ -64,9 +64,9 @@ public interface GitVersionControlQueueService {
ListenableFuture<String> getContentsDiff(TenantId tenantId, String rawEntityData1, String rawEntityData2); ListenableFuture<String> getContentsDiff(TenantId tenantId, String rawEntityData1, String rawEntityData2);
ListenableFuture<Void> initRepository(TenantId tenantId, EntitiesVersionControlSettings settings); ListenableFuture<Void> initRepository(TenantId tenantId, RepositorySettings settings);
ListenableFuture<Void> testRepository(TenantId tenantId, EntitiesVersionControlSettings settings); ListenableFuture<Void> testRepository(TenantId tenantId, RepositorySettings settings);
ListenableFuture<Void> clearRepository(TenantId tenantId); ListenableFuture<Void> clearRepository(TenantId tenantId);

View File

@ -0,0 +1,80 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.service.sync.vc;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.TbTransactionalCache;
import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import java.io.Serializable;
public abstract class TbAbstractVersionControlSettingsService<T extends Serializable> {
private final String settingsKey;
private final AdminSettingsService adminSettingsService;
private final TbTransactionalCache<TenantId, T> cache;
private final Class<T> clazz;
public TbAbstractVersionControlSettingsService(AdminSettingsService adminSettingsService, TbTransactionalCache<TenantId, T> cache, Class<T> clazz, String settingsKey) {
this.adminSettingsService = adminSettingsService;
this.cache = cache;
this.clazz = clazz;
this.settingsKey = settingsKey;
}
public T get(TenantId tenantId) {
return cache.getAndPutInTransaction(tenantId, () -> {
AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, settingsKey);
if (adminSettings != null) {
try {
return JacksonUtil.convertValue(adminSettings.getJsonValue(), clazz);
} catch (Exception e) {
throw new RuntimeException("Failed to load " + settingsKey + " settings!", e);
}
}
return null;
}, true);
}
public T save(TenantId tenantId, T settings) {
AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, settingsKey);
if (adminSettings == null) {
adminSettings = new AdminSettings();
adminSettings.setKey(settingsKey);
adminSettings.setTenantId(tenantId);
}
adminSettings.setJsonValue(JacksonUtil.valueToTree(settings));
AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(tenantId, adminSettings);
T savedSettings;
try {
savedSettings = JacksonUtil.convertValue(savedAdminSettings.getJsonValue(), clazz);
} catch (Exception e) {
throw new RuntimeException("Failed to load auto commit settings!", e);
}
//API calls to adminSettingsService are not in transaction, so we can simply evict the cache.
cache.evict(tenantId);
return savedSettings;
}
public boolean delete(TenantId tenantId) {
boolean result = adminSettingsService.deleteAdminSettings(tenantId, settingsKey);
cache.evict(tenantId);
return result;
}
}

View File

@ -13,24 +13,22 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.service.sync.vc; package org.thingsboard.server.service.sync.vc.autocommit;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CaffeineTbTransactionalCache; import org.thingsboard.server.cache.CaffeineTbTransactionalCache;
import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings;
import org.thingsboard.server.gen.transport.TransportProtos;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@Service("VersionControlCache") @Service("AutoCommitSettingsCache")
public class VersionControlSettingsCaffeineCache extends CaffeineTbTransactionalCache<TenantId, EntitiesVersionControlSettings> { public class AutoCommitSettingsCaffeineCache extends CaffeineTbTransactionalCache<TenantId, AutoCommitSettings> {
public VersionControlSettingsCaffeineCache(CacheManager cacheManager) { public AutoCommitSettingsCaffeineCache(CacheManager cacheManager) {
super(cacheManager, CacheConstants.VC_SETTINGS_CACHE); super(cacheManager, CacheConstants.AUTO_COMMIT_SETTINGS_CACHE);
} }
} }

View File

@ -13,29 +13,24 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.service.sync.vc; package org.thingsboard.server.service.sync.vc.autocommit;
import com.google.protobuf.InvalidProtocolBufferException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.CacheSpecsMap;
import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.RedisTbTransactionalCache;
import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.cache.TBRedisCacheConfiguration;
import org.thingsboard.server.cache.TbRedisSerializer; import org.thingsboard.server.cache.TbRedisSerializer;
import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings;
import org.thingsboard.server.gen.transport.TransportProtos;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@Service("VersionControlCache") @Service("AutoCommitSettingsCache")
public class VersionControlSettingsRedisCache extends RedisTbTransactionalCache<TenantId, EntitiesVersionControlSettings> { public class AutoCommitSettingsRedisCache extends RedisTbTransactionalCache<TenantId, AutoCommitSettings> {
public VersionControlSettingsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { public AutoCommitSettingsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.VC_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>()); super(CacheConstants.AUTO_COMMIT_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>());
} }
} }

View File

@ -0,0 +1,36 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.service.sync.vc.autocommit;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.TbTransactionalCache;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.TbAbstractVersionControlSettingsService;
@Service
@TbCoreComponent
public class DefaultTbAutoCommitSettingsService extends TbAbstractVersionControlSettingsService<AutoCommitSettings> implements TbAutoCommitSettingsService {
public static final String SETTINGS_KEY = "autoCommitSettings";
public DefaultTbAutoCommitSettingsService(AdminSettingsService adminSettingsService, TbTransactionalCache<TenantId, AutoCommitSettings> cache) {
super(adminSettingsService, cache, AutoCommitSettings.class, SETTINGS_KEY);
}
}

View File

@ -0,0 +1,30 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.service.sync.vc.autocommit;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings;
import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
public interface TbAutoCommitSettingsService {
AutoCommitSettings get(TenantId tenantId);
AutoCommitSettings save(TenantId tenantId, AutoCommitSettings settings);
boolean delete(TenantId tenantId);
}

View File

@ -0,0 +1,63 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.service.sync.vc.repository;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.TbTransactionalCache;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.VersionControlAuthMethod;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.TbAbstractVersionControlSettingsService;
@Service
@TbCoreComponent
public class DefaultTbRepositorySettingsService extends TbAbstractVersionControlSettingsService<RepositorySettings> implements TbRepositorySettingsService {
public static final String SETTINGS_KEY = "entitiesVersionControl";
public DefaultTbRepositorySettingsService(AdminSettingsService adminSettingsService, TbTransactionalCache<TenantId, RepositorySettings> cache) {
super(adminSettingsService, cache, RepositorySettings.class, SETTINGS_KEY);
}
@Override
public RepositorySettings restore(TenantId tenantId, RepositorySettings settings) {
RepositorySettings storedSettings = get(tenantId);
if (storedSettings != null) {
VersionControlAuthMethod authMethod = settings.getAuthMethod();
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(authMethod) && settings.getPassword() == null) {
settings.setPassword(storedSettings.getPassword());
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(authMethod) && settings.getPrivateKey() == null) {
settings.setPrivateKey(storedSettings.getPrivateKey());
if (settings.getPrivateKeyPassword() == null) {
settings.setPrivateKeyPassword(storedSettings.getPrivateKeyPassword());
}
}
}
return settings;
}
@Override
public RepositorySettings get(TenantId tenantId) {
RepositorySettings settings = super.get(tenantId);
if (settings != null) {
settings = new RepositorySettings(settings);
}
return settings;
}
}

View File

@ -0,0 +1,34 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.service.sync.vc.repository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CaffeineTbTransactionalCache;
import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@Service("RepositorySettingsCache")
public class RepositorySettingsCaffeineCache extends CaffeineTbTransactionalCache<TenantId, RepositorySettings> {
public RepositorySettingsCaffeineCache(CacheManager cacheManager) {
super(cacheManager, CacheConstants.REPOSITORY_SETTINGS_CACHE);
}
}

View File

@ -0,0 +1,36 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.service.sync.vc.repository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.CacheSpecsMap;
import org.thingsboard.server.cache.RedisTbTransactionalCache;
import org.thingsboard.server.cache.TBRedisCacheConfiguration;
import org.thingsboard.server.cache.TbRedisSerializer;
import org.thingsboard.server.common.data.CacheConstants;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis")
@Service("RepositorySettingsCache")
public class RepositorySettingsRedisCache extends RedisTbTransactionalCache<TenantId, RepositorySettings> {
public RepositorySettingsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) {
super(CacheConstants.REPOSITORY_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbRedisSerializer<>());
}
}

View File

@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.thingsboard.server.service.sync.vc; package org.thingsboard.server.service.sync.vc.repository;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
public interface TbVersionControlSettingsService { public interface TbRepositorySettingsService {
EntitiesVersionControlSettings restore(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings); RepositorySettings restore(TenantId tenantId, RepositorySettings versionControlSettings);
EntitiesVersionControlSettings get(TenantId tenantId); RepositorySettings get(TenantId tenantId);
EntitiesVersionControlSettings save(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings); RepositorySettings save(TenantId tenantId, RepositorySettings versionControlSettings);
boolean delete(TenantId tenantId); boolean delete(TenantId tenantId);

View File

@ -433,9 +433,12 @@ cache:
edges: edges:
timeToLiveInMinutes: "${CACHE_SPECS_EDGES_TTL:1440}" timeToLiveInMinutes: "${CACHE_SPECS_EDGES_TTL:1440}"
maxSize: "${CACHE_SPECS_EDGES_MAX_SIZE:10000}" maxSize: "${CACHE_SPECS_EDGES_MAX_SIZE:10000}"
vcSettings: repositorySettings:
timeToLiveInMinutes: "${CACHE_SPECS_VC_SETTINGS_TTL:1440}" timeToLiveInMinutes: "${CACHE_SPECS_REPOSITORY_SETTINGS_TTL:1440}"
maxSize: "${CACHE_SPECS_VC_SETTINGS_MAX_SIZE:10000}" maxSize: "${CACHE_SPECS_REPOSITORY_SETTINGS_MAX_SIZE:10000}"
autoCommitSettings:
timeToLiveInMinutes: "${CACHE_SPECS_AUTO_COMMIT_SETTINGS_TTL:1440}"
maxSize: "${CACHE_SPECS_AUTO_COMMIT_SETTINGS_MAX_SIZE:10000}"
redis: redis:
# standalone or cluster # standalone or cluster

View File

@ -31,5 +31,6 @@ public class CacheConstants {
public static final String TOKEN_OUTDATAGE_TIME_CACHE = "tokensOutdatageTime"; public static final String TOKEN_OUTDATAGE_TIME_CACHE = "tokensOutdatageTime";
public static final String OTA_PACKAGE_CACHE = "otaPackages"; public static final String OTA_PACKAGE_CACHE = "otaPackages";
public static final String OTA_PACKAGE_DATA_CACHE = "otaPackagesData"; public static final String OTA_PACKAGE_DATA_CACHE = "otaPackagesData";
public static final String VC_SETTINGS_CACHE = "vcSettings"; public static final String REPOSITORY_SETTINGS_CACHE = "repositorySettings";
public static final String AUTO_COMMIT_SETTINGS_CACHE = "autoCommitSettings";
} }

View File

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* 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.thingsboard.server.common.data.sync.vc;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.sync.vc.request.create.AutoVersionCreateConfig;
import java.util.HashMap;
public class AutoCommitSettings extends HashMap<EntityType, AutoVersionCreateConfig> {
private static final long serialVersionUID = -5757067601838792059L;
}

View File

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.common.data.sync.vc; package org.thingsboard.server.common.data.sync.vc;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data; import lombok.Data;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.sync.vc.request.create.AutoVersionCreateConfig; import org.thingsboard.server.common.data.sync.vc.request.create.AutoVersionCreateConfig;
@ -24,7 +25,8 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
@Data @Data
public class EntitiesVersionControlSettings implements Serializable { @JsonIgnoreProperties(ignoreUnknown = true) // temporary to make sure no need to wipe db during development.
public class RepositorySettings implements Serializable {
private static final long serialVersionUID = -3211552851889198721L; private static final long serialVersionUID = -3211552851889198721L;
private String repositoryUri; private String repositoryUri;
@ -36,12 +38,10 @@ public class EntitiesVersionControlSettings implements Serializable {
private String privateKeyPassword; private String privateKeyPassword;
private String defaultBranch; private String defaultBranch;
private Map<EntityType, AutoVersionCreateConfig> autoCommitSettings; public RepositorySettings() {
public EntitiesVersionControlSettings() {
} }
public EntitiesVersionControlSettings(EntitiesVersionControlSettings settings) { public RepositorySettings(RepositorySettings settings) {
this.repositoryUri = settings.getRepositoryUri(); this.repositoryUri = settings.getRepositoryUri();
this.authMethod = settings.getAuthMethod(); this.authMethod = settings.getAuthMethod();
this.username = settings.getUsername(); this.username = settings.getUsername();
@ -50,6 +50,5 @@ public class EntitiesVersionControlSettings implements Serializable {
this.privateKey = settings.getPrivateKey(); this.privateKey = settings.getPrivateKey();
this.privateKeyPassword = settings.getPrivateKeyPassword(); this.privateKeyPassword = settings.getPrivateKeyPassword();
this.defaultBranch = settings.getDefaultBranch(); this.defaultBranch = settings.getDefaultBranch();
this.autoCommitSettings = settings.getAutoCommitSettings() != null ? new HashMap<>(settings.getAutoCommitSettings()) : new HashMap<>();
} }
} }

View File

@ -35,7 +35,7 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionCreationResult;
import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo;
import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.ServiceType;
@ -495,8 +495,8 @@ public class DefaultClusterVersionControlService extends TbApplicationEventListe
producer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null); producer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
} }
private EntitiesVersionControlSettings getEntitiesVersionControlSettings(ToVersionControlServiceMsg msg) { private RepositorySettings getEntitiesVersionControlSettings(ToVersionControlServiceMsg msg) {
Optional<EntitiesVersionControlSettings> settingsOpt = encodingService.decode(msg.getVcSettings().toByteArray()); Optional<RepositorySettings> settingsOpt = encodingService.decode(msg.getVcSettings().toByteArray());
if (settingsOpt.isPresent()) { if (settingsOpt.isPresent()) {
return settingsOpt.get(); return settingsOpt.get();
} else { } else {

View File

@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.EntityVersion; import org.thingsboard.server.common.data.sync.vc.EntityVersion;
import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionCreationResult;
import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo;
@ -216,13 +216,13 @@ public class DefaultGitRepositoryService implements GitRepositoryService {
} }
@Override @Override
public void testRepository(TenantId tenantId, EntitiesVersionControlSettings settings) throws Exception { public void testRepository(TenantId tenantId, RepositorySettings settings) throws Exception {
Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString()); Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString());
GitRepository.test(settings, repositoryDirectory.toFile()); GitRepository.test(settings, repositoryDirectory.toFile());
} }
@Override @Override
public void initRepository(TenantId tenantId, EntitiesVersionControlSettings settings) throws Exception { public void initRepository(TenantId tenantId, RepositorySettings settings) throws Exception {
clearRepository(tenantId); clearRepository(tenantId);
log.debug("[{}] Init tenant repository started.", tenantId); log.debug("[{}] Init tenant repository started.", tenantId);
Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString()); Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString());
@ -238,7 +238,7 @@ public class DefaultGitRepositoryService implements GitRepositoryService {
} }
@Override @Override
public EntitiesVersionControlSettings getRepositorySettings(TenantId tenantId) throws Exception { public RepositorySettings getRepositorySettings(TenantId tenantId) throws Exception {
var gitRepository = repositories.get(tenantId); var gitRepository = repositories.get(tenantId);
return gitRepository != null ? gitRepository.getSettings() : null; return gitRepository != null ? gitRepository.getSettings() : null;
} }

View File

@ -58,7 +58,7 @@ import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.VersionControlAuthMethod; import org.thingsboard.server.common.data.sync.vc.VersionControlAuthMethod;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -77,14 +77,14 @@ public class GitRepository {
private final Git git; private final Git git;
@Getter @Getter
private final EntitiesVersionControlSettings settings; private final RepositorySettings settings;
private final CredentialsProvider credentialsProvider; private final CredentialsProvider credentialsProvider;
private final SshdSessionFactory sshSessionFactory; private final SshdSessionFactory sshSessionFactory;
@Getter @Getter
private final String directory; private final String directory;
private GitRepository(Git git, EntitiesVersionControlSettings settings, CredentialsProvider credentialsProvider, SshdSessionFactory sshSessionFactory, String directory) { private GitRepository(Git git, RepositorySettings settings, CredentialsProvider credentialsProvider, SshdSessionFactory sshSessionFactory, String directory) {
this.git = git; this.git = git;
this.settings = settings; this.settings = settings;
this.credentialsProvider = credentialsProvider; this.credentialsProvider = credentialsProvider;
@ -92,7 +92,7 @@ public class GitRepository {
this.directory = directory; this.directory = directory;
} }
public static GitRepository clone(EntitiesVersionControlSettings settings, File directory) throws GitAPIException { public static GitRepository clone(RepositorySettings settings, File directory) throws GitAPIException {
CredentialsProvider credentialsProvider = null; CredentialsProvider credentialsProvider = null;
SshdSessionFactory sshSessionFactory = null; SshdSessionFactory sshSessionFactory = null;
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) { if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
@ -109,7 +109,7 @@ public class GitRepository {
return new GitRepository(git, settings, credentialsProvider, sshSessionFactory, directory.getAbsolutePath()); return new GitRepository(git, settings, credentialsProvider, sshSessionFactory, directory.getAbsolutePath());
} }
public static GitRepository open(File directory, EntitiesVersionControlSettings settings) throws IOException { public static GitRepository open(File directory, RepositorySettings settings) throws IOException {
Git git = Git.open(directory); Git git = Git.open(directory);
CredentialsProvider credentialsProvider = null; CredentialsProvider credentialsProvider = null;
SshdSessionFactory sshSessionFactory = null; SshdSessionFactory sshSessionFactory = null;
@ -121,7 +121,7 @@ public class GitRepository {
return new GitRepository(git, settings, credentialsProvider, sshSessionFactory, directory.getAbsolutePath()); return new GitRepository(git, settings, credentialsProvider, sshSessionFactory, directory.getAbsolutePath());
} }
public static void test(EntitiesVersionControlSettings settings, File directory) throws GitAPIException { public static void test(RepositorySettings settings, File directory) throws GitAPIException {
CredentialsProvider credentialsProvider = null; CredentialsProvider credentialsProvider = null;
SshdSessionFactory sshSessionFactory = null; SshdSessionFactory sshSessionFactory = null;
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) { if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {

View File

@ -19,7 +19,7 @@ import org.eclipse.jgit.api.errors.GitAPIException;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.EntityVersion; import org.thingsboard.server.common.data.sync.vc.EntityVersion;
import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionCreationResult;
import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo;
@ -39,11 +39,11 @@ public interface GitRepositoryService {
List<VersionedEntityInfo> listEntitiesAtVersion(TenantId tenantId, String versionId, String path) throws Exception; List<VersionedEntityInfo> listEntitiesAtVersion(TenantId tenantId, String versionId, String path) throws Exception;
void testRepository(TenantId tenantId, EntitiesVersionControlSettings settings) throws Exception; void testRepository(TenantId tenantId, RepositorySettings settings) throws Exception;
void initRepository(TenantId tenantId, EntitiesVersionControlSettings settings) throws Exception; void initRepository(TenantId tenantId, RepositorySettings settings) throws Exception;
EntitiesVersionControlSettings getRepositorySettings(TenantId tenantId) throws Exception; RepositorySettings getRepositorySettings(TenantId tenantId) throws Exception;
void clearRepository(TenantId tenantId) throws IOException; void clearRepository(TenantId tenantId) throws IOException;

View File

@ -18,7 +18,7 @@ package org.thingsboard.server.service.sync.vc;
import lombok.Data; import lombok.Data;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.EntitiesVersionControlSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToVersionControlServiceMsg;
import java.util.UUID; import java.util.UUID;
@ -29,9 +29,9 @@ public class VersionControlRequestCtx {
private final String nodeId; private final String nodeId;
private final UUID requestId; private final UUID requestId;
private final TenantId tenantId; private final TenantId tenantId;
private final EntitiesVersionControlSettings settings; private final RepositorySettings settings;
public VersionControlRequestCtx(ToVersionControlServiceMsg msg, EntitiesVersionControlSettings settings) { public VersionControlRequestCtx(ToVersionControlServiceMsg msg, RepositorySettings settings) {
this.nodeId = msg.getNodeId(); this.nodeId = msg.getNodeId();
this.requestId = new UUID(msg.getRequestIdMSB(), msg.getRequestIdLSB()); this.requestId = new UUID(msg.getRequestIdMSB(), msg.getRequestIdLSB());
this.tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); this.tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));