/**
* 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.environment.impl;
import com.francetelecom.clara.cloud.commons.BusinessException;
import com.francetelecom.clara.cloud.commons.NotFoundException;
import com.francetelecom.clara.cloud.commons.TechnicalException;
import com.francetelecom.clara.cloud.commons.ValidatorUtil;
import com.francetelecom.clara.cloud.core.service.SecurityUtils;
import com.francetelecom.clara.cloud.core.service.exception.ApplicationReleaseNotFoundException;
import com.francetelecom.clara.cloud.core.service.exception.PaasUserNotFoundException;
import com.francetelecom.clara.cloud.coremodel.*;
import com.francetelecom.clara.cloud.deployment.technical.service.ManageTechnicalDeploymentTemplate;
import com.francetelecom.clara.cloud.deployment.technical.service.TechnicalDeploymentCloner;
import com.francetelecom.clara.cloud.model.DeploymentProfileEnum;
import com.francetelecom.clara.cloud.model.TechnicalDeployment;
import com.francetelecom.clara.cloud.model.TechnicalDeploymentInstance;
import com.francetelecom.clara.cloud.model.TechnicalDeploymentTemplate;
import com.francetelecom.clara.cloud.paas.projection.ProjectionService;
import com.francetelecom.clara.cloud.paas.projection.UnsupportedProjectionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* Utils to manages environment. We need this class to solve transaction lifecycle
*/
@Service
public class ManageEnvironmentImplUtils {
@Autowired
private SecurityUtils securityUtils;
@Autowired
private EnvironmentRepository environmentRepository;
@Autowired
private PaasUserRepository paasUserRepository;
@Autowired
private ProjectionService projectionService;
@Autowired
private ManageTechnicalDeploymentTemplate manageTechnicalDeploymentTemplate;
@Autowired
private ConfigRoleRepository configRoleRepository;
@Autowired
private ApplicationReleaseRepository applicationReleaseRepository;
@Autowired
private TechnicalDeploymentCloner tdCloner;
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = BusinessException.class)
public String createTDI(String releaseUID, DeploymentProfileEnum profile, String ownerSsoId, String label, List<String> configRolesUIDs) throws PaasUserNotFoundException,
ApplicationReleaseNotFoundException, UnsupportedProjectionException {
// Fetch an AppRelease from DB which is up-to-date and may be browsed
// for fetching lazy associations
ApplicationRelease applicationRelease = applicationReleaseRepository.findByUID(releaseUID);
if (applicationRelease == null) {
throw new ApplicationReleaseNotFoundException("ApplicationRelease#" + releaseUID);
}
// Fetch a PaasUser from DB which is up-to-date and may be browsed for
// fetching lazy associations
PaasUser owner = paasUserRepository.findBySsoId(new SSOId(ownerSsoId));
if (owner == null) {
throw new PaasUserNotFoundException("PaasUser#" + ownerSsoId);
}
assertHasWritePermissionFor(applicationRelease);
// Force projection and locking of AppRelease
if (applicationRelease.isEditing()) {
// TODO: add consistency validation step and reject the request
applicationRelease.validate();
}
if (applicationRelease.isValidated()) {
generateDeploymentTemplates(applicationRelease,profileToUseForProjection());
applicationRelease.lock();
}
TechnicalDeploymentTemplate tdt = null;
try {
tdt = manageTechnicalDeploymentTemplate.findTechnicalDeploymentTemplate(profile, applicationRelease.getUID());
} catch (NotFoundException e) {
//should not occur since tdt has just been created
throw new TechnicalException(e);
}
// Instantiate the TDI and point it to the TDT.
// FIXME: envName -> replace by
TechnicalDeployment tdClone = tdCloner.deepCopy(tdt.getTechnicalDeployment());
TechnicalDeploymentInstance tdi = new TechnicalDeploymentInstance(tdt, tdClone);
overrideTemplateWhenConfigRolesSpecified(configRolesUIDs, applicationRelease, tdi);
// FIXME: ensure max size of 150 chars on environment name
Environment environment = new Environment(profile, label, applicationRelease, owner,tdi);
ValidatorUtil.validate(environment);
environmentRepository.save(environment);
return environment.getUID();
}
protected void overrideTemplateWhenConfigRolesSpecified(List<String> configRolesUIDs, ApplicationRelease applicationRelease, TechnicalDeploymentInstance tdi) {
List<ConfigRole> configRoles = null;
if (configRolesUIDs != null) {
configRoles = configRoleRepository.findByUidIn(configRolesUIDs);
}
if (configRoles != null && ! configRoles.isEmpty()) {
projectionService.updateDeploymentTemplateInstance(tdi, applicationRelease, configRoles);
}
}
private void assertHasWritePermissionFor(ApplicationRelease release) {
securityUtils.assertHasWritePermissionFor(release);
}
/**
* For now, we limit projection to DEV and PROD.
*
* @return
*/
public static List<DeploymentProfileEnum> profileToUseForProjection() {
List<DeploymentProfileEnum> profiles = new ArrayList<DeploymentProfileEnum>();
profiles.add(DeploymentProfileEnum.DEVELOPMENT);
profiles.add(DeploymentProfileEnum.PRODUCTION);
return profiles;
}
private void generateDeploymentTemplates(ApplicationRelease applicationRelease,List<DeploymentProfileEnum> profiles) throws UnsupportedProjectionException {
//FIXME � d�placer ds projectionService.generateNewDeploymentTemplate
assert applicationRelease.isValidated();
for (DeploymentProfileEnum profile : profiles) {
// FIXME: propagate the Tenant to the projection, or alternatively
// the SubTenantCatalog to use.
TechnicalDeploymentTemplate tdt = projectionService.generateNewDeploymentTemplate(applicationRelease, profile);
manageTechnicalDeploymentTemplate.createTechnicalDeploymentTemplate(tdt);
}
}
public void setEnvironmentRepository(EnvironmentRepository repository) {
this.environmentRepository = repository;
}
public void setPaasUserRepository(PaasUserRepository repository) {
this.paasUserRepository = repository;
}
public void setProjectionService(ProjectionService projectionService) {
this.projectionService = projectionService;
}
public void setConfigRoleRepository(ConfigRoleRepository configRoleRepository) {
this.configRoleRepository = configRoleRepository;
}
public void setApplicationReleaseRepository(ApplicationReleaseRepository repository) {
this.applicationReleaseRepository = repository;
}
public void setTdCloner(TechnicalDeploymentCloner tdCloner) {
this.tdCloner = tdCloner;
}
public void setManageTechnicalDeploymentTemplate(ManageTechnicalDeploymentTemplate manageTechnicalDeploymentTemplate) {
this.manageTechnicalDeploymentTemplate = manageTechnicalDeploymentTemplate;
}
}