package com.sequenceiq.cloudbreak.service.template;
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.Stack;
import com.sequenceiq.cloudbreak.domain.Template;
import com.sequenceiq.cloudbreak.repository.StackRepository;
import com.sequenceiq.cloudbreak.repository.TemplateRepository;
import com.sequenceiq.cloudbreak.service.DuplicateKeyValueException;
import com.sequenceiq.cloudbreak.util.NameUtil;
@Service
@Transactional
public class TemplateService {
private static final Logger LOGGER = LoggerFactory.getLogger(TemplateService.class);
private static final String TEMPLATE_NOT_FOUND_MSG = "Template '%s' not found.";
@Inject
private TemplateRepository templateRepository;
@Inject
private StackRepository stackRepository;
public Set<Template> retrievePrivateTemplates(CbUser user) {
return templateRepository.findForUser(user.getUserId());
}
public Set<Template> retrieveAccountTemplates(CbUser user) {
if (user.getRoles().contains(CbUserRole.ADMIN)) {
return templateRepository.findAllInAccount(user.getAccount());
} else {
return templateRepository.findPublicInAccountForUser(user.getUserId(), user.getAccount());
}
}
@PostAuthorize("hasPermission(returnObject,'read')")
public Template get(Long id) {
Template template = templateRepository.findOne(id);
if (template == null) {
throw new NotFoundException(String.format(TEMPLATE_NOT_FOUND_MSG, id));
} else {
return template;
}
}
@Transactional(Transactional.TxType.NEVER)
public Template create(CbUser user, Template template) {
LOGGER.debug("Creating template: [User: '{}', Account: '{}']", user.getUsername(), user.getAccount());
Template savedTemplate;
template.setOwner(user.getUserId());
template.setAccount(user.getAccount());
try {
savedTemplate = templateRepository.save(template);
} catch (Exception ex) {
throw new DuplicateKeyValueException(APIResourceType.TEMPLATE, template.getName(), ex);
}
return savedTemplate;
}
public void delete(Long templateId, CbUser user) {
Template template = templateRepository.findByIdInAccount(templateId, user.getAccount());
if (template == null) {
throw new NotFoundException(String.format(TEMPLATE_NOT_FOUND_MSG, templateId));
}
delete(template, user);
}
public Template getPrivateTemplate(String name, CbUser user) {
Template template = templateRepository.findByNameInUser(name, user.getUserId());
if (template == null) {
throw new NotFoundException(String.format(TEMPLATE_NOT_FOUND_MSG, name));
} else {
return template;
}
}
@PostAuthorize("hasPermission(returnObject,'read')")
public Template getPublicTemplate(String name, CbUser user) {
Template template = templateRepository.findOneByName(name, user.getAccount());
if (template == null) {
throw new NotFoundException(String.format(TEMPLATE_NOT_FOUND_MSG, name));
} else {
return template;
}
}
public void delete(String templateName, CbUser user) {
Template template = templateRepository.findByNameInAccount(templateName, user.getAccount(), user.getUserId());
if (template == null) {
throw new NotFoundException(String.format(TEMPLATE_NOT_FOUND_MSG, templateName));
}
delete(template, user);
}
private void delete(Template template, CbUser user) {
LOGGER.debug("Deleting template. {} - {}", new Object[]{template.getId(), template.getName()});
List<Stack> allStackForTemplate = stackRepository.findAllStackForTemplate(template.getId());
if (allStackForTemplate.isEmpty()) {
if (!user.getUserId().equals(template.getOwner()) && !user.getRoles().contains(CbUserRole.ADMIN)) {
throw new BadRequestException("Templates can be deleted only by account admins or owners.");
}
template.setTopology(null);
if (ResourceStatus.USER_MANAGED.equals(template.getStatus())) {
templateRepository.delete(template);
} else {
template.setName(NameUtil.postfixWithTimestamp(template.getName()));
template.setStatus(ResourceStatus.DEFAULT_DELETED);
templateRepository.save(template);
}
} else {
if (isRunningStackReferToTemplate(allStackForTemplate)) {
throw new BadRequestException(String.format(
"There are stacks associated with template '%s'. Please remove these before deleting the template.", template.getName()));
} else {
template.setName(NameUtil.postfixWithTimestamp(template.getName()));
template.setTopology(null);
template.setDeleted(true);
if (ResourceStatus.DEFAULT.equals(template.getStatus())) {
template.setStatus(ResourceStatus.DEFAULT_DELETED);
}
templateRepository.save(template);
}
}
}
private boolean isRunningStackReferToTemplate(List<Stack> allStackForTemplate) {
boolean result = false;
for (Stack stack : allStackForTemplate) {
if (!stack.isDeleteCompleted()) {
result = true;
break;
}
}
return result;
}
}