package cn.seecoder.paas.service.impl; import cn.seecoder.paas.data.dao.ApplicationDAO; import cn.seecoder.paas.data.dao.ConfigDAO; import cn.seecoder.paas.data.dao.EnvironmentDAO; import cn.seecoder.paas.data.entity.Application; import cn.seecoder.paas.data.entity.Config; import cn.seecoder.paas.data.entity.Environment; import cn.seecoder.paas.service.ApplicationService; import cn.seecoder.paas.service.EnvironmentService; import cn.seecoder.paas.service.facade.k8s.PersistentVolumeClaimApi; import cn.seecoder.paas.service.facade.k8s.model.K8sObjectRequest; import cn.seecoder.paas.service.facade.k8s.model.PersistentVolumeClaim; import cn.seecoder.paas.service.model.converter.ApplicationConverter; import cn.seecoder.paas.service.model.converter.ConfigConverter; import cn.seecoder.paas.service.model.vo.AppVolumeVO; import cn.seecoder.paas.service.model.vo.ApplicationVO; import cn.seecoder.paas.service.model.vo.ConfigVO; import cn.seecoder.paas.util.ApplicationProperties; import cn.seecoder.paas.util.ServiceException; import cn.seecoder.paas.util.enums.ConfigBelongsToType; import cn.seecoder.paas.util.enums.ResourceLabel; import io.kubernetes.client.custom.Quantity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import javax.transaction.Transactional; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @Service public class ApplicationServiceImpl implements ApplicationService { private final ApplicationDAO applicationDAO; private final ConfigDAO configDAO; private final EnvironmentService environmentService; private final EnvironmentDAO environmentDAO; private final PersistentVolumeClaimApi persistentVolumeClaimApi; private final ApplicationProperties applicationProperties; @Autowired public ApplicationServiceImpl(ApplicationDAO applicationDAO, ConfigDAO configDAO, EnvironmentService environmentService, EnvironmentDAO environmentDAO, PersistentVolumeClaimApi persistentVolumeClaimApi, ApplicationProperties applicationProperties) { this.applicationDAO = applicationDAO; this.configDAO = configDAO; this.environmentService = environmentService; this.environmentDAO = environmentDAO; this.persistentVolumeClaimApi = persistentVolumeClaimApi; this.applicationProperties = applicationProperties; } @Override @Transactional public ApplicationVO createOrUpdate(ApplicationVO vo) throws ServiceException { ApplicationVO result = ApplicationConverter.convertToVO(applicationDAO.save(ApplicationConverter.convertToEntity(vo))); Config config = configDAO.findByConfigBelongsAndAndEntityId(ConfigBelongsToType.APPLICATION, result.getId()); if (config == null) { ConfigVO configVO = ConfigVO.getEmptyConfigVO(ConfigBelongsToType.APPLICATION, result.getId()); ConfigConverter.convertToVO(configDAO.save(ConfigConverter.convertToEntity(configVO))); } return result; } @Override @Transactional public void delete(Integer id) throws ServiceException { applicationDAO.deleteById(id); configDAO.deleteByConfigBelongsAndAndEntityId(ConfigBelongsToType.APPLICATION, id); List environments = environmentDAO.findAllByAppId(id); for (Environment environment : environments) { environmentService.delete(environment.getId()); } String labelKey = ResourceLabel.RESOURCE.getCode(); String labelValue = ResourceLabel.RESOURCE.getGenerator().gen("application", String.valueOf(id)); List pvcs = persistentVolumeClaimApi.getByCondition( K8sObjectRequest.builder() .namespace(applicationProperties.getDeploymentNamespace()) .labels(Collections.singletonMap(labelKey, labelValue)) .build()); if (!CollectionUtils.isEmpty(pvcs)) { for (PersistentVolumeClaim pvc : pvcs) { persistentVolumeClaimApi.delete(pvc); } } } @Override public List getAll() { return applicationDAO.findAll().stream().map(ApplicationConverter::convertToVO).collect(Collectors.toList()); } @Override public ApplicationVO getDetailById(Integer id) throws ServiceException { Application application = applicationDAO.findById(id).orElse(null); if (application == null) { return null; } ApplicationVO vo = ApplicationConverter.convertToVO(application); Config config = configDAO.findByConfigBelongsAndAndEntityId(ConfigBelongsToType.APPLICATION, id); if (config != null) { vo.setConfig(ConfigConverter.convertToVO(config)); } else { vo.setConfig(ConfigVO.getEmptyConfigVO(ConfigBelongsToType.APPLICATION, id)); } String labelKey = ResourceLabel.RESOURCE.getCode(); String labelValue = ResourceLabel.RESOURCE.getGenerator().gen("application", String.valueOf(application.getId())); List pvcs = persistentVolumeClaimApi.getByCondition( K8sObjectRequest.builder() .namespace(applicationProperties.getDeploymentNamespace()) .labels(Collections.singletonMap(labelKey, labelValue)) .build()); vo.setPvcs(pvcs.stream().map(pvc -> { return new AppVolumeVO(pvc.getName(), application.getId(), pvc.getQuantity().toSuffixedString()); }).collect(Collectors.toList())); return vo; } @Override public void createAppVolume(AppVolumeVO appVolumeVO) throws ServiceException { Application application = applicationDAO.findById(appVolumeVO.getAppId()).orElse(null); if (application == null) { throw ServiceException.INVALID_DATA; } PersistentVolumeClaim pvc = getPVCByAppVolume(appVolumeVO); persistentVolumeClaimApi.create(pvc); } @Override public void updateAppVolume(AppVolumeVO appVolumeVO) throws ServiceException { Application application = applicationDAO.findById(appVolumeVO.getAppId()).orElse(null); if (application == null) { throw ServiceException.INVALID_DATA; } String labelKey = ResourceLabel.RESOURCE.getCode(); String labelValue = ResourceLabel.RESOURCE.getGenerator().gen("application", String.valueOf(appVolumeVO.getAppId())); List pvcs = persistentVolumeClaimApi.getByCondition( K8sObjectRequest.builder() .name("a" + appVolumeVO.getAppId() + "-" + appVolumeVO.getName()) .namespace(applicationProperties.getDeploymentNamespace()) .labels(Collections.singletonMap(labelKey, labelValue)) .build()); if (CollectionUtils.isEmpty(pvcs)) { throw ServiceException.BAD_REQUEST; } PersistentVolumeClaim pvc = getPVCByAppVolume(appVolumeVO); persistentVolumeClaimApi.update(pvc); } private PersistentVolumeClaim getPVCByAppVolume(AppVolumeVO appVolumeVO) { String labelKey = ResourceLabel.RESOURCE.getCode(); String labelValue = ResourceLabel.RESOURCE.getGenerator().gen("application", String.valueOf(appVolumeVO.getAppId())); PersistentVolumeClaim pvc = PersistentVolumeClaim.builder() .storageClassName(applicationProperties.getPvcStorageClassName()) .accessModes(Collections.singletonList("ReadWriteMany")) .volumeMode("Filesystem") .quantity(Quantity.fromString(appVolumeVO.getQuantity())) .build(); pvc.setName("a" + appVolumeVO.getAppId() + "-" + appVolumeVO.getName()); pvc.setNamespace(applicationProperties.getDeploymentNamespace()); pvc.setLabel(labelKey, labelValue); return pvc; } @Override public void deleteAppVolume(AppVolumeVO appVolumeVO) throws ServiceException { Application application = applicationDAO.findById(appVolumeVO.getAppId()).orElse(null); if (application == null) { throw ServiceException.INVALID_DATA; } PersistentVolumeClaim pvc = new PersistentVolumeClaim(); pvc.setNamespace(applicationProperties.getDeploymentNamespace()); pvc.setName(appVolumeVO.getName()); persistentVolumeClaimApi.delete(pvc); } }