package alien4cloud.deployment;
import alien4cloud.dao.IGenericSearchDAO;
import alien4cloud.dao.model.GetMultipleDataResult;
import alien4cloud.exception.NotFoundException;
import alien4cloud.model.deployment.Deployment;
import alien4cloud.model.deployment.DeploymentTopology;
import alien4cloud.paas.model.PaaSTopologyDeploymentContext;
import alien4cloud.utils.MapUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.inject.Inject;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Manage deployment operations on a cloud.
*/
@Service
@Slf4j
public class DeploymentService {
@Resource(name = "alien-es-dao")
private IGenericSearchDAO alienDao;
@Resource(name = "alien-monitor-es-dao")
private IGenericSearchDAO alienMonitorDao;
@Inject
private DeploymentRuntimeStateService deploymentRuntimeStateService;
@Inject
private DeploymentContextService deploymentContextService;
@Inject
private DeploymentTopologyService deploymentTopologyService;
/**
* Get all deployments for a given orchestrator an application
*
* @param orchestratorId Id of the cloud for which to get deployments (can be null to get deployments for all clouds).
* @param sourceId Id of the application for which to get deployments (can be null to get deployments for all applications).
* @return A {@link GetMultipleDataResult} that contains deployments.
*/
public List<Deployment> getDeployments(String orchestratorId, String sourceId) {
QueryBuilder query = QueryBuilders.boolQuery();
if (orchestratorId != null) {
query = QueryBuilders.boolQuery().must(QueryBuilders.termsQuery("orchestratorId", orchestratorId));
}
if (sourceId != null) {
query = QueryBuilders.boolQuery().must(query).must(QueryBuilders.termsQuery("sourceId", sourceId));
}
if (orchestratorId == null && sourceId == null) {
query = QueryBuilders.matchAllQuery();
}
return alienDao.customFindAll(Deployment.class, query);
}
/**
* Get a deployment given its id
*
* @param id id of the deployment
* @return deployment with given id
*/
public Deployment get(String id) {
return alienDao.findById(Deployment.class, id);
}
/**
* Get a deployment given its id
*
* @param id id of the deployment
* @return deployment with given id
*/
public Deployment getOrfail(String id) {
Deployment deployment = alienDao.findById(Deployment.class, id);
if (deployment == null) {
throw new NotFoundException("Deployment <" + id + "> doesn't exist.");
}
return deployment;
}
/**
* Get an active Deployment for a given environment or throw a NotFoundException if no active deployment can be found for this environment.
*
* @param environmentId Id of the application environment.
* @return The active deployment for this environment
*/
public Deployment getActiveDeploymentOrFail(String environmentId) {
Deployment deployment = getActiveDeployment(environmentId);
if (deployment == null) {
throw new NotFoundException("Deployment for environment <" + environmentId + "> doesn't exist.");
}
return deployment;
}
/**
* Get a deployment for a given environment/
*
* @param applicationEnvironmentId id of the environment
* @return active deployment if exist or the last, null if the application environment has not been deployed
*/
public Deployment getDeployment(String applicationEnvironmentId) {
Map<String, String[]> activeDeploymentFilters = MapUtil.newHashMap(new String[] { "environmentId" },
new String[][] { new String[] { applicationEnvironmentId } });
GetMultipleDataResult<Deployment> dataResult = alienDao.search(Deployment.class, null, activeDeploymentFilters, null, null, 0, Integer.MAX_VALUE,
"endDate", true);
if (dataResult.getData() != null && dataResult.getData().length > 0) {
if (dataResult.getData()[dataResult.getData().length - 1].getEndDate() == null) {
return dataResult.getData()[dataResult.getData().length - 1];
} else {
return dataResult.getData()[0];
}
}
return null;
}
/**
* Get an active deployment for a given environment
*
* @param applicationEnvironmentId id of the environment
* @return active deployment or null if not exist
*/
public Deployment getActiveDeployment(String applicationEnvironmentId) {
Map<String, String[]> activeDeploymentFilters = MapUtil.newHashMap(new String[] { "environmentId", "endDate" },
new String[][] { new String[] { applicationEnvironmentId }, new String[] { null } });
GetMultipleDataResult<Deployment> dataResult = alienDao.search(Deployment.class, null, activeDeploymentFilters, 1);
if (dataResult.getData() != null && dataResult.getData().length > 0) {
return dataResult.getData()[0];
}
return null;
}
/**
* Get an active Deployment for a given cloud and topology or throw a NotFoundException if no active deployment can be found.
*
* @param topologyId id of the topology that has been deployed
* @param orchestratorId id of the target orchestrator.
* @return a deployment
* @throws alien4cloud.exception.NotFoundException if not any deployment exists
*/
public Deployment getActiveDeploymentOrFail(String topologyId, String orchestratorId) {
Deployment deployment = getActiveDeployment(orchestratorId, topologyId);
if (deployment == null) {
throw new NotFoundException("Deployment for cloud <" + orchestratorId + "> and topology <" + topologyId + "> doesn't exist.");
}
return deployment;
}
/**
* Get a topology for a given cloud / topology
*
* @param orchestratorId targeted orchestrator id
* @param topologyId id of the topology to deploy
* @return a deployment
*/
public Deployment getActiveDeployment(String orchestratorId, String topologyId) {
Deployment deployment = null;
Map<String, String[]> activeDeploymentFilters = MapUtil.newHashMap(new String[] { "orchestratorId", "topologyId", "endDate" },
new String[][] { new String[] { orchestratorId }, new String[] { topologyId }, new String[] { null } });
GetMultipleDataResult<Deployment> dataResult = alienDao.search(Deployment.class, null, activeDeploymentFilters, 1);
if (dataResult.getData() != null && dataResult.getData().length > 0) {
deployment = dataResult.getData()[0];
}
return deployment;
}
/**
* Check if there is an active deployment on a given orchestrator with the given orchestrator deployment id.
*
* @param orchestratorId The if of the orchestrator for which to check if there is a deployment with the given orchestratorDeploymentId.
* @param orchestratorDeploymentId Unique if of the deployment for a given orchestrator
* @return True if there is an active deployment for theses ids, false if not.
*/
public boolean isActiveDeployment(String orchestratorId, String orchestratorDeploymentId) {
Map<String, String[]> activeDeploymentFilters = MapUtil.newHashMap(new String[] { "orchestratorId", "orchestratorDeploymentId", "endDate" },
new String[][] { new String[] { orchestratorId }, new String[] { orchestratorDeploymentId }, new String[] { null } });
GetMultipleDataResult<Deployment> dataResult = alienDao.find(Deployment.class, activeDeploymentFilters, 1);
if (dataResult.getData() != null && dataResult.getData().length > 0) {
return true;
}
return false;
}
public Map<String, PaaSTopologyDeploymentContext> getCloudActiveDeploymentContexts(String orchestratorId) {
Deployment[] deployments = getOrchestratorActiveDeployments(orchestratorId);
Map<String, PaaSTopologyDeploymentContext> activeDeploymentContexts = Maps.newHashMap();
for (Deployment deployment : deployments) {
DeploymentTopology topology = deploymentRuntimeStateService.getRuntimeTopology(deployment.getId());
activeDeploymentContexts.put(deployment.getOrchestratorDeploymentId(),
deploymentContextService.buildTopologyDeploymentContext(deployment, deploymentTopologyService.getLocations(topology), topology));
}
return activeDeploymentContexts;
}
private Deployment[] getOrchestratorActiveDeployments(String orchestratorId) {
Map<String, String[]> activeDeploymentFilters = MapUtil.newHashMap(new String[] { "orchestratorId", "endDate" },
new String[][] { new String[] { orchestratorId }, new String[] { null } });
GetMultipleDataResult<Deployment> dataResult = alienDao.search(Deployment.class, null, activeDeploymentFilters, Integer.MAX_VALUE);
return dataResult.getData();
}
public Map<String, Set<String>> getAllOrchestratorIdsAndOrchestratorDeploymentId(String applicationEnvironmentId) {
Map<String, Set<String>> result = new HashMap<>();
Map<String, String[]> activeDeploymentFilters = MapUtil.newHashMap(new String[] { "environmentId" },
new String[][] { new String[] { applicationEnvironmentId } });
GetMultipleDataResult<Deployment> dataResult = alienDao.search(Deployment.class, null, activeDeploymentFilters, Integer.MAX_VALUE);
if (dataResult.getData() != null && dataResult.getData().length > 0) {
for (Deployment deployment : dataResult.getData()) {
if (!result.containsKey(deployment.getOrchestratorId())) {
result.put(deployment.getOrchestratorId(), new HashSet<String>());
}
result.get(deployment.getOrchestratorId()).add(deployment.getOrchestratorDeploymentId());
}
}
return result;
}
/**
* Switch a deployment to undeployed.
*
* @param deployment the deployment to switch.
*/
public void markUndeployed(Deployment deployment) {
if (deployment.getEndDate() == null) {
deployment.setEndDate(new Date());
alienDao.save(deployment);
// Switch the deployed field of the Deployment topology to false
DeploymentTopology deploymentTopology = alienMonitorDao.findById(DeploymentTopology.class, deployment.getId());
deploymentTopology.setDeployed(false);
alienMonitorDao.save(deploymentTopology);
} else {
log.info("Deployment <" + deployment.getId() + "> is already marked as undeployed.");
}
}
/**
* Check if a CSAR is currently deployed through dependencies in a topology.
*
* @return True if the archive is used in a deployment, false if not.
*/
public boolean isArchiveDeployed(String archiveName, String archiveVersion) {
FilterBuilder filter = FilterBuilders.boolFilter().must(FilterBuilders.termFilter("isDeployed", true))
.must(FilterBuilders.nestedFilter("dependencies", FilterBuilders.boolFilter().must(FilterBuilders.termFilter("dependencies.name", archiveName))
.must(FilterBuilders.termFilter("dependencies.version", archiveVersion))));
// Look if there is 1 matching element.
GetMultipleDataResult<DeploymentTopology> result = alienMonitorDao.search(DeploymentTopology.class, null, null, filter, null, 0, 1);
return result.getData() != null && result.getData().length > 0;
}
}