package com.sequenceiq.cloudbreak.service.constraint;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.stereotype.Service;
import com.sequenceiq.cloudbreak.common.type.APIResourceType;
import com.sequenceiq.cloudbreak.common.type.CbUserRole;
import com.sequenceiq.cloudbreak.common.type.ResourceStatus;
import com.sequenceiq.cloudbreak.controller.BadRequestException;
import com.sequenceiq.cloudbreak.controller.NotFoundException;
import com.sequenceiq.cloudbreak.domain.CbUser;
import com.sequenceiq.cloudbreak.domain.Cluster;
import com.sequenceiq.cloudbreak.domain.ConstraintTemplate;
import com.sequenceiq.cloudbreak.repository.ClusterRepository;
import com.sequenceiq.cloudbreak.repository.ConstraintTemplateRepository;
import com.sequenceiq.cloudbreak.service.DuplicateKeyValueException;
import com.sequenceiq.cloudbreak.util.NameUtil;
@Service
@Transactional
public class ConstraintTemplateService {
private static final Logger LOGGER = LoggerFactory.getLogger(ConstraintTemplateService.class);
private static final String CONSTRAINT_NOT_FOUND_MSG = "Constraint template '%s' not found.";
@Inject
private ConstraintTemplateRepository constraintTemplateRepository;
@Inject
private ClusterRepository clusterRepository;
public Set<ConstraintTemplate> retrievePrivateConstraintTemplates(CbUser user) {
return constraintTemplateRepository.findForUser(user.getUserId());
}
public Set<ConstraintTemplate> retrieveAccountConstraintTemplates(CbUser user) {
if (user.getRoles().contains(CbUserRole.ADMIN)) {
return constraintTemplateRepository.findAllInAccount(user.getAccount());
} else {
return constraintTemplateRepository.findPublicInAccountForUser(user.getUserId(), user.getAccount());
}
}
@PostAuthorize("hasPermission(returnObject,'read')")
public ConstraintTemplate get(Long id) {
ConstraintTemplate constraintTemplate = constraintTemplateRepository.findOne(id);
if (constraintTemplate == null) {
throw new NotFoundException(String.format(CONSTRAINT_NOT_FOUND_MSG, id));
} else {
return constraintTemplate;
}
}
public ConstraintTemplate create(CbUser user, ConstraintTemplate constraintTemplate) {
LOGGER.debug("Creating constraint template: [User: '{}', Account: '{}']", user.getUsername(), user.getAccount());
constraintTemplate.setOwner(user.getUserId());
constraintTemplate.setAccount(user.getAccount());
try {
return constraintTemplateRepository.save(constraintTemplate);
} catch (Exception e) {
throw new DuplicateKeyValueException(APIResourceType.CONSTRAINT_TEMPLATE, constraintTemplate.getName(), e);
}
}
public void delete(String name, CbUser user) {
ConstraintTemplate constraintTemplate = constraintTemplateRepository.findByNameInAccount(name, user.getAccount(), user.getUserId());
if (constraintTemplate == null) {
throw new NotFoundException(String.format(CONSTRAINT_NOT_FOUND_MSG, name));
}
delete(constraintTemplate, user);
}
public void delete(Long id, CbUser user) {
ConstraintTemplate constraintTemplate = constraintTemplateRepository.findByIdInAccount(id, user.getAccount());
if (constraintTemplate == null) {
throw new NotFoundException(String.format(CONSTRAINT_NOT_FOUND_MSG, id));
}
delete(constraintTemplate, user);
}
@PostAuthorize("hasPermission(returnObject,'read')")
public ConstraintTemplate getPublicTemplate(String name, CbUser user) {
ConstraintTemplate constraintTemplate = constraintTemplateRepository.findOneByName(name, user.getAccount());
if (constraintTemplate == null) {
throw new NotFoundException(String.format(CONSTRAINT_NOT_FOUND_MSG, name));
} else {
return constraintTemplate;
}
}
public ConstraintTemplate getPrivateTemplate(String name, CbUser user) {
ConstraintTemplate constraintTemplate = constraintTemplateRepository.findByNameInUser(name, user.getUserId());
if (constraintTemplate == null) {
throw new NotFoundException(String.format(CONSTRAINT_NOT_FOUND_MSG, name));
} else {
return constraintTemplate;
}
}
private void delete(ConstraintTemplate constraintTemplate, CbUser user) {
LOGGER.debug("Deleting constraint template. {} - {}", new Object[]{constraintTemplate.getId(), constraintTemplate.getName()});
List<Cluster> clusters = clusterRepository.findAllClustersForConstraintTemplate(constraintTemplate.getId());
if (clusters.isEmpty()) {
if (!user.getUserId().equals(constraintTemplate.getOwner()) && !user.getRoles().contains(CbUserRole.ADMIN)) {
throw new BadRequestException("Constraint templates can only be deleted by account admins or owners.");
}
if (ResourceStatus.USER_MANAGED.equals(constraintTemplate.getStatus())) {
constraintTemplateRepository.delete(constraintTemplate);
} else {
constraintTemplate.setName(NameUtil.postfixWithTimestamp(constraintTemplate.getName()));
constraintTemplate.setStatus(ResourceStatus.DEFAULT_DELETED);
constraintTemplateRepository.save(constraintTemplate);
}
} else {
if (isRunningClusterReferToTemplate(clusters)) {
throw new BadRequestException(String.format(
"There are stacks associated with template '%s'. Please remove these before deleting the template.", constraintTemplate.getName()));
} else {
constraintTemplate.setName(NameUtil.postfixWithTimestamp(constraintTemplate.getName()));
constraintTemplate.setDeleted(true);
if (ResourceStatus.DEFAULT.equals(constraintTemplate.getStatus())) {
constraintTemplate.setStatus(ResourceStatus.DEFAULT_DELETED);
}
constraintTemplateRepository.save(constraintTemplate);
}
}
}
private boolean isRunningClusterReferToTemplate(List<Cluster> clusters) {
boolean result = false;
for (Cluster cluster: clusters) {
if (!cluster.isDeleteCompleted()) {
result = true;
break;
}
}
return result;
}
}