package alien4cloud.orchestrators.services;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;
import alien4cloud.dao.IGenericSearchDAO;
import alien4cloud.dao.model.GetMultipleDataResult;
import alien4cloud.exception.AlreadyExistException;
import alien4cloud.exception.NotFoundException;
import alien4cloud.model.orchestrators.ArtifactSupport;
import alien4cloud.model.orchestrators.Orchestrator;
import alien4cloud.model.orchestrators.OrchestratorConfiguration;
import alien4cloud.model.orchestrators.OrchestratorState;
import alien4cloud.model.orchestrators.locations.Location;
import alien4cloud.model.orchestrators.locations.LocationSupport;
import alien4cloud.orchestrators.locations.services.LocationService;
import alien4cloud.orchestrators.plugin.IOrchestratorPluginFactory;
import alien4cloud.utils.MapUtil;
import lombok.extern.slf4j.Slf4j;
/**
* Manages orchestrators
*/
@Slf4j
@Service
public class OrchestratorService {
public static final String[] ENABLED_STATES = new String[] { OrchestratorState.CONNECTED.toString(),
OrchestratorState.CONNECTING.toString(), OrchestratorState.DISCONNECTED.toString() };
@Resource(name = "alien-es-dao")
private IGenericSearchDAO alienDAO;
@Inject
private OrchestratorFactoriesRegistry orchestratorFactoriesRegistry;
@Inject
private LocationService locationService;
/**
* Creates an orchestrator.
*
* @param name The unique name that defines the orchestrator from user point of view.
* @param pluginId The id of the plugin used to communicate with the orchestrator.
* @param pluginBean The bean in the plugin that is indeed managing communication.
* @return The generated identifier for the orchestrator.
*/
public synchronized String create(String name, String pluginId, String pluginBean) {
Orchestrator orchestrator = new Orchestrator();
// generate an unique id
orchestrator.setId(UUID.randomUUID().toString());
orchestrator.setName(name);
orchestrator.setPluginId(pluginId);
orchestrator.setPluginBean(pluginBean);
// by default clouds are disabled as it should be configured before being enabled.
orchestrator.setState(OrchestratorState.DISABLED);
orchestrator.setAuthorizedUsers(new ArrayList<String>());
orchestrator.setAuthorizedGroups(new ArrayList<String>());
// get default configuration for the orchestrator.
IOrchestratorPluginFactory orchestratorFactory = getPluginFactory(orchestrator);
OrchestratorConfiguration configuration = new OrchestratorConfiguration(orchestrator.getId(), orchestratorFactory.getDefaultConfiguration());
ensureNameUnicityAndSave(orchestrator);
alienDAO.save(configuration);
return orchestrator.getId();
}
/**
* Save the orchestrator but ensure that the name is unique before saving it.
*
* @param orchestrator The orchestrator to save.
*/
private synchronized void ensureNameUnicityAndSave(Orchestrator orchestrator) {
ensureNameUnicityAndSave(orchestrator, null);
}
/**
* Save the orchestrator but ensure that the name is unique before saving it.
*
* @param orchestrator The orchestrator to save.
*/
public synchronized void ensureNameUnicityAndSave(Orchestrator orchestrator, String oldName) {
if (StringUtils.isBlank(oldName) || !Objects.equals(orchestrator.getName(), oldName)) {
// check that the orchestrator doesn't already exists
if (alienDAO.count(Orchestrator.class, QueryBuilders.termQuery("name", orchestrator.getName())) > 0) {
throw new AlreadyExistException("a cloud with the given name already exists.");
}
}
alienDAO.save(orchestrator);
}
/**
* Delete an existing orchestrator.
*
* @param id The id of the orchestrator to delete.
*/
public void delete(String id) {
// delete all locations for the orchestrator
Location[] locations = locationService.getOrchestratorLocations(id);
if (locations != null) {
for (Location location : locations) {
locationService.delete(id, location.getId());
}
}
// delete the orchestrator configuration
alienDAO.delete(OrchestratorConfiguration.class, id);
alienDAO.delete(Orchestrator.class, id);
}
/**
* Get the orchestrator matching the given id
*
* @param id If of the orchestrator that we want to get.
* @return An instance of the orchestrator.
*/
public Orchestrator get(String id) {
return alienDAO.findById(Orchestrator.class, id);
}
/**
* Get the orchestrator matching the given id or throw a NotFoundException
*
* @param id If of the orchestrator that we want to get.
* @return An instance of the orchestrator.
*/
public Orchestrator getOrFail(String id) {
Orchestrator orchestrator = alienDAO.findById(Orchestrator.class, id);
if (orchestrator == null) {
throw new NotFoundException("Orchestrator [" + id + "] doesn't exists.");
}
return orchestrator;
}
/**
* Get multiple orchestrators.
*
* @param query The query to apply to filter orchestrators.
* @param from The start index of the query.
* @param size The maximum number of elements to return.
* @param authorizationFilter authorization filter
* @return A {@link GetMultipleDataResult} that contains Orchestrator objects.
*/
public GetMultipleDataResult<Orchestrator> search(String query, OrchestratorState status, int from, int size, FilterBuilder authorizationFilter) {
Map<String, String[]> filters = null;
if (status != null) {
filters = MapUtil.newHashMap(new String[] { "status" }, new String[][] { new String[] { status.toString() } });
}
return alienDAO.search(Orchestrator.class, query, filters, authorizationFilter, null, from, size);
}
/**
* Get the location support information for a given orchestrator.
*
* @param orchestratorId The id of the orchestrator for which to get location support information.
* @return location support information.
*/
public LocationSupport getLocationSupport(String orchestratorId) {
Orchestrator orchestrator = getOrFail(orchestratorId);
IOrchestratorPluginFactory orchestratorFactory = getPluginFactory(orchestrator);
return orchestratorFactory.getLocationSupport();
}
/**
* Get the artifact support information for a given orchestrator.
*
* @param orchestratorId The id of the orchestrator for which to get location support information.
* @return artifact support information.
*/
public ArtifactSupport getArtifactSupport(String orchestratorId) {
Orchestrator orchestrator = getOrFail(orchestratorId);
IOrchestratorPluginFactory orchestratorFactory = getPluginFactory(orchestrator);
return orchestratorFactory.getArtifactSupport();
}
/**
* Get the orchestrator plugin factory for the given orchestrator.
*
* @param orchestrator The orchestrator for which to get the orchestrator plugin factory.
* @return An instance of the orchestrator plugin factory for the given orchestrator.
*/
public IOrchestratorPluginFactory getPluginFactory(Orchestrator orchestrator) {
return orchestratorFactoriesRegistry.getPluginBean(orchestrator.getPluginId(), orchestrator.getPluginBean());
}
public List<Orchestrator> getAllEnabledOrchestrators() {
return alienDAO.customFindAll(Orchestrator.class, QueryBuilders.termsQuery("state", ENABLED_STATES));
}
public List<Orchestrator> getAll() {
return alienDAO.customFindAll(Orchestrator.class, null);
}
}