/**
* Copyright (C) 2015 Orange
* 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 com.francetelecom.clara.cloud.core.service;
import com.francetelecom.clara.cloud.commons.ValidatorUtil;
import com.francetelecom.clara.cloud.core.service.exception.ApplicationNotFoundException;
import com.francetelecom.clara.cloud.core.service.exception.ApplicationReleaseNotFoundException;
import com.francetelecom.clara.cloud.core.service.exception.DuplicateApplicationReleaseException;
import com.francetelecom.clara.cloud.core.service.exception.PaasUserNotFoundException;
import com.francetelecom.clara.cloud.coremodel.*;
import com.francetelecom.clara.cloud.model.TechnicalDeploymentTemplate;
import com.francetelecom.clara.cloud.model.TechnicalDeploymentTemplateRepository;
import com.francetelecom.clara.cloud.paas.projection.ProjectionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.net.URL;
import java.util.List;
/**
* Business implementation for ApplicationRelease management
* <p/>
* All methods are defined as transactional. If no transaction is in progress
* during method call, then it will start a new transaction.
*
* @author Clara
*/
public class ManageApplicationReleaseImpl implements ManageApplicationRelease {
private static final Logger log = LoggerFactory.getLogger(ManageApplicationReleaseImpl.class);
@Autowired
private SecurityUtils securityUtils;
@Autowired(required = true)
private ApplicationReleaseRepository applicationReleaseRepository;
@Autowired(required = true)
private PaasUserRepository paasUserRepository;
@Autowired(required = true)
private ApplicationRepository applicationRepository;
@Autowired(required = true)
private EnvironmentRepository environmentRepository;
@Autowired(required = true)
private ProjectionService projectionService;
@Autowired(required = true)
private TechnicalDeploymentTemplateRepository technicalDeploymentTemplateRepository;
@Override
public List<ApplicationRelease> findApplicationReleases(int firstIndex, int count) {
if (securityUtils.currentUserIsAdmin()) {
return applicationReleaseRepository.findAll();
} else {
return applicationReleaseRepository.findAllPublicOrPrivateByMember(securityUtils.currentUser().getValue());
}
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public List<ApplicationRelease> findMyApplicationReleases() {
return (List<ApplicationRelease>) applicationReleaseRepository.findAllByApplicationMember(securityUtils.currentUser().getValue());
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public List<ApplicationRelease> findApplicationReleasesByAppUID(String applicationUid) throws ApplicationNotFoundException {
Application application = applicationRepository.findByUid(applicationUid);
if (application == null) {
String message = "Application[" + applicationUid + "] does not exist";
log.info(message);
throw new ApplicationNotFoundException(message);
}
if (securityUtils.currentUserIsAdmin()) {
return applicationReleaseRepository.findApplicationReleasesByAppUID(applicationUid);
} else {
return applicationReleaseRepository.findPublicOrPrivateByMemberAndByAppUID(securityUtils.currentUser().getValue(), applicationUid);
}
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackForClassName = {"BusinessException"})
public String createApplicationRelease(String applicationUID, String ssoId, String version) throws PaasUserNotFoundException, ApplicationNotFoundException,
DuplicateApplicationReleaseException {
return createApplicationRelease(applicationUID, ssoId, version, null, null, null);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackForClassName = {"BusinessException"})
public String createApplicationRelease(String applicationUID, String ssoId, String version, String description, URL versionControlUrl, String middlewareProfile)
throws PaasUserNotFoundException, ApplicationNotFoundException, DuplicateApplicationReleaseException {
PaasUser paasUser = paasUserRepository.findBySsoId(new SSOId(ssoId));
if (paasUser == null) {
String message = "PaasUser[" + ssoId + "] does not exist";
log.info(message);
throw new PaasUserNotFoundException(message);
}
Application application = applicationRepository.findByUid(applicationUID);
if (application == null) {
String message = "Application[" + applicationUID + "] does not exist";
log.info(message);
throw new ApplicationNotFoundException(message);
}
ApplicationRelease applicationRelease = new ApplicationRelease(application, version);
if (middlewareProfile != null) {
applicationRelease.setMiddlewareProfileVersion(middlewareProfile);
}
if (description != null) {
applicationRelease.setDescription(description);
}
if (versionControlUrl != null) {
applicationRelease.setVersionControlUrl(versionControlUrl);
}
// cannot create if not authorized
assertHasWritePermissionFor(applicationRelease);
// if application version is not unique per application then throw
// exception
if (!isReleaseVersionUniqueForApplication(applicationUID, version)) {
String message = "A release [" + version + "] already exists for the application [" + application.getLabel() + "]";
log.info(message);
throw new DuplicateApplicationReleaseException(message);
}
// Validate model
ValidatorUtil.validate(applicationRelease);
applicationReleaseRepository.save(applicationRelease);
return applicationRelease.getUID();
}
private boolean releaseHasNoActiveEnvironment(String releaseUID) {
return environmentRepository.countActiveByApplicationReleaseUid(releaseUID) == 0;
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackForClassName = {"BusinessException"})
public void deleteApplicationRelease(String releaseUID) throws ApplicationReleaseNotFoundException {
ApplicationRelease applicationRelease = applicationReleaseRepository.findByUID(releaseUID);
// we should find application release
if (applicationRelease == null) {
String message = "ApplicationRelease[" + releaseUID + "] does not exist";
log.info(message);
throw new ApplicationReleaseNotFoundException(message);
}
// cannot remove if not authorized
assertHasWritePermissionFor(applicationRelease);
// we can remove release if it has no active environment
if (releaseHasNoActiveEnvironment(releaseUID)) {
applicationRelease.markAsRemoved();
} else {
String message = "Cannot delete release with UID[" + releaseUID + "] because it has active environments.";
log.info(message);
throw new IllegalStateException(message);
}
}
private void assertHasWritePermissionFor(ApplicationRelease applicationRelease) {
securityUtils.assertHasWritePermissionFor(applicationRelease);
}
private boolean hasWritePermissionFor(ApplicationRelease applicationRelease) {
return securityUtils.hasWritePermissionFor(applicationRelease.getApplication());
}
private void assertHasReadPermissionFor(ApplicationRelease applicationRelease) {
securityUtils.assertHasReadPermissionFor(applicationRelease);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public void purgeOldRemovedReleases() {
log.info("*** purge old releases");
// find removed releases
List<ApplicationRelease> toPurgeReleases = applicationReleaseRepository.findRemovedReleasesWithoutEnvironment();
if (toPurgeReleases != null) {
for (ApplicationRelease release : toPurgeReleases) {
deleteTechnicalDeploymentTemplates(release.getUID());
applicationReleaseRepository.delete(release);
}
}
}
private void deleteTechnicalDeploymentTemplates(String releaseId) {
List<TechnicalDeploymentTemplate> templates = technicalDeploymentTemplateRepository.findAllByReleaseId(releaseId);
if (templates != null) {
technicalDeploymentTemplateRepository.delete(templates);
}
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public void deleteAndPurgeApplicationRelease(String uid) throws ApplicationReleaseNotFoundException {
deleteApplicationRelease(uid);
ApplicationRelease applicationRelease = applicationReleaseRepository.findByUID(uid);
deleteTechnicalDeploymentTemplates(applicationRelease.getUID());
applicationReleaseRepository.delete(applicationRelease);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackForClassName = {"BusinessException"})
public boolean canBeDeleted(String releaseUID) throws ApplicationReleaseNotFoundException {
ApplicationRelease applicationRelease = applicationReleaseRepository.findByUID(releaseUID);
if (applicationRelease == null) {
String message = "ApplicationRelease[" + releaseUID + "] does not exist";
log.info(message);
throw new ApplicationReleaseNotFoundException(message);
}
return environmentRepository.countActiveByApplicationReleaseUid(releaseUID) == 0 && hasWritePermissionFor(applicationRelease);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public ApplicationRelease findApplicationReleaseByUID(String uid) throws ApplicationReleaseNotFoundException {
log.debug("/******* recherche de l application release - UID[" + uid + "] **********/");
ApplicationRelease applicationRelease = applicationReleaseRepository.findByUID(uid);
if (applicationRelease == null) {
String message = "ApplicationRelease[" + uid + "] does not exist";
log.info(message);
throw new ApplicationReleaseNotFoundException(message);
}
assertHasReadPermissionFor(applicationRelease);
applicationRelease.getApplication().setEditable(hasWritePermissionFor(applicationRelease));
return applicationRelease;
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public ApplicationRelease updateApplicationRelease(ApplicationRelease applicationRelease) throws ApplicationReleaseNotFoundException {
ApplicationRelease existing = applicationReleaseRepository.findByUID(applicationRelease.getUID());
if (existing == null) {
String message = "ApplicationRelease with uid[" + applicationRelease.getUID() + "] does not exist.";
log.info(message);
throw new ApplicationReleaseNotFoundException(message);
}
// cannot remove if not authorized
assertHasWritePermissionFor(applicationRelease);
return applicationReleaseRepository.save(applicationRelease);
}
@Override
public long countApplicationReleases() {
if (securityUtils.currentUserIsAdmin()) {
return applicationReleaseRepository.countApplicationReleases();
} else {
return applicationReleaseRepository.countPublicOrPrivateByMember(securityUtils.currentUser().getValue());
}
}
@Override
public long countMyApplicationReleases() {
return applicationReleaseRepository.countByApplicationMember(securityUtils.currentUser().getValue());
}
@Override
public long countApplicationReleasesByAppUID(String applicationUID) throws ApplicationNotFoundException {
Application application = applicationRepository.findByUid(applicationUID);
if (application == null) {
String message = "Application[" + applicationUID + "] does not exist";
log.info(message);
throw new ApplicationNotFoundException(message);
}
if (securityUtils.currentUserIsAdmin()) {
return applicationReleaseRepository.countApplicationReleasesByApplicationUID(applicationUID);
} else {
return applicationReleaseRepository.countPublicOrPrivateByMemberAndByAppUID(securityUtils.currentUser().getValue(), applicationUID);
}
}
@Override
public ApplicationRelease findApplicationReleaseByApplicationAndReleaseVersion(String applicationUID, String releaseVersion) throws ApplicationReleaseNotFoundException {
ApplicationRelease release = applicationReleaseRepository.findByApplicationUIDAndReleaseVersion(applicationUID, releaseVersion);
if (release == null) {
throw new ApplicationReleaseNotFoundException("ApplicationRelease from application " + applicationUID + " and with version " + releaseVersion + " has not been found");
}
assertHasReadPermissionFor(release);
return release;
}
@Override
public boolean isReleaseVersionUniqueForApplication(String applicationUID, String version) {
return applicationReleaseRepository.findByApplicationUIDAndReleaseVersion(applicationUID, version) == null;
}
public void setEnvironmentRepository(EnvironmentRepository repository) {
this.environmentRepository = repository;
}
@Override
public List<MiddlewareProfile> findAllMiddlewareProfil() {
return projectionService.findAllMiddlewareProfil();
}
public void setApplicationRepository(ApplicationRepository repository) {
this.applicationRepository = repository;
}
public void setPaasUserRepository(PaasUserRepository repository) {
this.paasUserRepository = repository;
}
public void setApplicationReleaseRepository(ApplicationReleaseRepository repository) {
this.applicationReleaseRepository = repository;
}
public void setProjectionService(ProjectionService projectionService) {
this.projectionService = projectionService;
}
public void setTechnicalDeploymentTemplateRepository(TechnicalDeploymentTemplateRepository technicalDeploymentTemplateRepository) {
this.technicalDeploymentTemplateRepository = technicalDeploymentTemplateRepository;
}
}