package com.sequenceiq.periscope.service;
import static com.sequenceiq.periscope.api.model.ClusterState.RUNNING;
import static org.springframework.util.StringUtils.isEmpty;
import java.util.List;
import java.util.stream.StreamSupport;
import javax.inject.Inject;
import javax.ws.rs.BadRequestException;
import org.springframework.stereotype.Service;
import com.google.common.collect.Lists;
import com.sequenceiq.periscope.api.model.ClusterState;
import com.sequenceiq.periscope.api.model.ScalingConfigurationJson;
import com.sequenceiq.periscope.domain.Ambari;
import com.sequenceiq.periscope.domain.Cluster;
import com.sequenceiq.periscope.domain.PeriscopeUser;
import com.sequenceiq.periscope.domain.SecurityConfig;
import com.sequenceiq.periscope.model.AmbariStack;
import com.sequenceiq.periscope.repository.ClusterRepository;
import com.sequenceiq.periscope.repository.SecurityConfigRepository;
import com.sequenceiq.periscope.repository.UserRepository;
@Service
public class ClusterService {
@Inject
private ClusterRepository clusterRepository;
@Inject
private UserRepository userRepository;
@Inject
private SecurityConfigRepository securityConfigRepository;
@Inject
private AlertService alertService;
public Cluster create(PeriscopeUser user, AmbariStack stack, ClusterState clusterState) {
PeriscopeUser periscopeUser = createUserIfAbsent(user);
validateClusterUniqueness(stack);
Cluster cluster = new Cluster(periscopeUser, stack);
if (clusterState != null) {
cluster.setState(clusterState);
}
cluster = save(cluster);
if (stack.getSecurityConfig() != null) {
SecurityConfig securityConfig = stack.getSecurityConfig();
securityConfig.setCluster(cluster);
securityConfigRepository.save(securityConfig);
}
// alertService.addPeriscopeAlerts(cluster);
return cluster;
}
public Cluster update(long clusterId, AmbariStack stack) {
return update(clusterId, stack, true, null);
}
public Cluster update(long clusterId, AmbariStack stack, boolean withPermissionCheck, ClusterState clusterState) {
Cluster cluster = withPermissionCheck ? findOneById(clusterId) : find(clusterId);
ClusterState newState = clusterState != null ? clusterState : cluster.getState();
cluster.setState(newState);
cluster.update(stack);
SecurityConfig sSecConf = stack.getSecurityConfig();
if (sSecConf != null) {
SecurityConfig updatedConfig = sSecConf;
SecurityConfig securityConfig = securityConfigRepository.findByClusterId(clusterId);
if (securityConfig != null) {
securityConfig.update(updatedConfig);
securityConfigRepository.save(securityConfig);
} else {
SecurityConfig sc = new SecurityConfig(sSecConf.getClientKey(), sSecConf.getClientCert(), sSecConf.getServerCert());
sc.setCluster(cluster);
sc = securityConfigRepository.save(sc);
cluster.setSecurityConfig(sc);
}
}
cluster = save(cluster);
addPrometheusAlertsToConsul(cluster);
return cluster;
}
public List<Cluster> findAllByUser(PeriscopeUser user) {
return clusterRepository.findAllByUser(user.getId());
}
public Cluster findOneById(long clusterId) {
return clusterRepository.findOne(clusterId);
}
public Cluster save(Cluster cluster) {
return clusterRepository.save(cluster);
}
public Cluster find(long clusterId) {
return clusterRepository.find(clusterId);
}
public void removeOne(long clusterId) {
Cluster cluster = findOneById(clusterId);
clusterRepository.delete(cluster);
}
public void removeById(long clusterId) {
Cluster cluster = find(clusterId);
clusterRepository.delete(cluster);
}
public void updateScalingConfiguration(long clusterId, ScalingConfigurationJson scalingConfiguration) {
Cluster cluster = findOneById(clusterId);
cluster.setMinSize(scalingConfiguration.getMinSize());
cluster.setMaxSize(scalingConfiguration.getMaxSize());
cluster.setCoolDown(scalingConfiguration.getCoolDown());
save(cluster);
}
public ScalingConfigurationJson getScalingConfiguration(long clusterId) {
Cluster cluster = findOneById(clusterId);
ScalingConfigurationJson configuration = new ScalingConfigurationJson();
configuration.setCoolDown(cluster.getCoolDown());
configuration.setMaxSize(cluster.getMaxSize());
configuration.setMinSize(cluster.getMinSize());
return configuration;
}
public Cluster setState(long clusterId, ClusterState state) {
Cluster cluster = findOneById(clusterId);
cluster.setState(state);
addPrometheusAlertsToConsul(cluster);
return clusterRepository.save(cluster);
}
public List<Cluster> findAll(ClusterState state) {
return clusterRepository.findAllByState(state);
}
public List<Cluster> findAll() {
return Lists.newArrayList(clusterRepository.findAll());
}
private PeriscopeUser createUserIfAbsent(PeriscopeUser user) {
PeriscopeUser periscopeUser = userRepository.findOne(user.getId());
if (periscopeUser == null) {
periscopeUser = userRepository.save(user);
}
return periscopeUser;
}
private void addPrometheusAlertsToConsul(Cluster cluster) {
if (RUNNING.equals(cluster.getState())) {
alertService.addPrometheusAlertsToConsul(cluster);
}
}
private void validateClusterUniqueness(AmbariStack stack) {
Iterable<Cluster> clusters = clusterRepository.findAll();
boolean clusterForTheSameStackAndAmbari = StreamSupport.stream(clusters.spliterator(), false)
.anyMatch(cluster -> {
boolean equalityOfStackId = cluster.getStackId().equals(stack.getStackId());
Ambari ambari = cluster.getAmbari();
Ambari newAmbari = stack.getAmbari();
boolean ambariObjectsNotNull = ambari != null && newAmbari != null;
boolean ambariHostsNotEmpty = !isEmpty(ambari.getHost()) && !isEmpty(newAmbari.getHost());
boolean equalityOfAmbariHost = ambariObjectsNotNull && ambariHostsNotEmpty && ambari.getHost().equals(newAmbari.getHost());
return equalityOfStackId && equalityOfAmbariHost;
});
if (clusterForTheSameStackAndAmbari) {
throw new BadRequestException("Cluster exists for the same Cloudbreak stack id and Ambari host.");
}
}
}