ApplicationServiceImpl.java 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package nju.seec.SEECdemo.logic.service.impl;
  2. import nju.seec.SEECdemo.logic.api.k8s.*;
  3. import nju.seec.SEECdemo.logic.api.k8s.model.Deployment;
  4. import nju.seec.SEECdemo.logic.api.k8s.model.DeploymentStatus;
  5. import nju.seec.SEECdemo.logic.api.k8s.model.Ingress;
  6. import nju.seec.SEECdemo.logic.api.k8s.model.Service;
  7. import nju.seec.SEECdemo.logic.api.k8s.exception.K8sApiException;
  8. import nju.seec.SEECdemo.logic.api.k8s.util.SecretTypeEnum;
  9. import nju.seec.SEECdemo.logic.api.k8s.vo.SecretVO;
  10. import nju.seec.SEECdemo.logic.service.ApplicationService;
  11. import nju.seec.SEECdemo.logic.vo.ApplicationStatusVO;
  12. import nju.seec.SEECdemo.logic.vo.ApplicationVO;
  13. import nju.seec.SEECdemo.util.LoggerUtil;
  14. import nju.seec.SEECdemo.web.dto.ApplicationDTO;
  15. import nju.seec.SEECdemo.web.dto.ContainerDTO;
  16. import nju.seec.SEECdemo.web.dto.PortDTO;
  17. import org.slf4j.Logger;
  18. import org.springframework.beans.factory.annotation.Autowired;
  19. import java.util.*;
  20. import java.util.stream.Collectors;
  21. @org.springframework.stereotype.Service
  22. public class ApplicationServiceImpl implements ApplicationService{
  23. private static final Logger logger = LoggerUtil.getLogger(ApplicationServiceImpl.class);
  24. @Autowired
  25. private DeploymentApi deploymentApi;
  26. @Autowired
  27. private ServiceApi serviceApi;
  28. @Autowired
  29. private NamespaceApi namespaceApi;
  30. @Autowired
  31. private SecretApi secretApi;
  32. @Autowired
  33. private IngressApi ingressApi;
  34. @Override
  35. public ApplicationVO create(ApplicationDTO applicationDTO) {
  36. return null;
  37. }
  38. @Override
  39. public void delete(String projectName, String name) {
  40. ingressApi.deleteIfExists(projectName, name);
  41. serviceApi.deleteIfExists(projectName, name);
  42. deploymentApi.deleteIfExist(projectName, name);
  43. }
  44. @Override
  45. public ApplicationVO update(ApplicationDTO applicationDTO) {
  46. return null;
  47. }
  48. @Override
  49. public ApplicationVO getByName(String projectName, String name) {
  50. Deployment deployment = deploymentApi.get(projectName, name);
  51. if (deployment == null){
  52. //抛出异常
  53. }
  54. return null;
  55. }
  56. @Override
  57. public ApplicationVO deploy(ApplicationDTO applicationDTO) {
  58. String projectName = applicationDTO.getProjectName();
  59. if (!namespaceApi.exists(projectName)) {
  60. //抛出项目不存在异常
  61. return null;
  62. }
  63. try {
  64. //删除现有的同名deployment
  65. deploymentApi.deleteIfExist(applicationDTO.getProjectName(), applicationDTO.getName());
  66. Deployment deployment = buildDeployment(applicationDTO);
  67. deploymentApi.createAsync(deployment);
  68. //删除现有的同名Service
  69. serviceApi.deleteIfExists(applicationDTO.getProjectName(), applicationDTO.getName());
  70. Service service = buildService(applicationDTO);
  71. serviceApi.create(service);
  72. //删除现有的同名Ingress
  73. ingressApi.deleteIfExists(applicationDTO.getProjectName(), applicationDTO.getName());
  74. Ingress ingress = buildIngress(applicationDTO);
  75. ingressApi.create(ingress);
  76. //构建返回数据
  77. return buildApplicationVO(applicationDTO, deployment, ingress);
  78. } catch (K8sApiException e) {
  79. //抛出创建失败异常
  80. deploymentApi.deleteIfExist(applicationDTO.getProjectName(), applicationDTO.getName());
  81. serviceApi.deleteIfExists(applicationDTO.getProjectName(), applicationDTO.getName());
  82. ingressApi.deleteIfExists(applicationDTO.getProjectName(), applicationDTO.getName());
  83. }
  84. return null;
  85. }
  86. @Override
  87. public ApplicationStatusVO getStatus(String projectName, String name) {
  88. Deployment deployment = deploymentApi.get(projectName, name);
  89. if (deployment == null) return null;//抛出异常
  90. return buildApplicationStatusVO(deployment);
  91. }
  92. private Deployment buildDeployment(ApplicationDTO applicationDTO) {
  93. Deployment deployment = applicationDTO.toDeployment();
  94. //将registry密钥作为imagePullSecrets注入
  95. List<String> registrySecrets = secretApi
  96. .getSecretListByType(
  97. applicationDTO.getProjectName(),
  98. SecretTypeEnum.REGISTRY)
  99. .stream()
  100. .map(SecretVO::getName)
  101. .collect(Collectors.toList()
  102. );
  103. deployment.setImagePullSecrets(registrySecrets);
  104. //将一般密钥作为环境变量注入
  105. List<SecretVO> genericSecrets = secretApi.getSecretListByType(applicationDTO.getProjectName(), SecretTypeEnum.Generic);
  106. Map<String, String> env = new HashMap<>();
  107. genericSecrets.forEach(secretVO -> env.putAll(secretVO.getData()));
  108. deployment.getContainers().forEach(containerDTO -> containerDTO.setEnv(env));
  109. return deployment;
  110. }
  111. private Service buildService(ApplicationDTO applicationDTO) {
  112. return applicationDTO.toService();
  113. }
  114. //@todo 构建Ingress
  115. //@fixme 潜在bug 如果容器上的IP和Service上的IP并非一一对应,根据容器的IP暴露Service会出现映射错误
  116. private Ingress buildIngress(ApplicationDTO applicationDTO) {
  117. String appName = applicationDTO.getName();
  118. String projectName = applicationDTO.getProjectName();
  119. Ingress ingress = new Ingress();
  120. ingress.setName(appName);
  121. ingress.setNamespace(projectName);
  122. ingress.setHttpHost("deernowl.cn");
  123. //@todo lambda表达式解决
  124. Set<Ingress.IngressDetail> detailDTOS = new HashSet<>();
  125. for (ContainerDTO containerDTO : applicationDTO.getContainers()) {
  126. String containerName = containerDTO.getName();
  127. Set<Ingress.IngressDetail> ingressDetails = containerDTO.getPorts()
  128. .stream()
  129. .filter(PortDTO::isExpose)
  130. .map(portDTO ->{
  131. Ingress.IngressDetail ingressDetail = new Ingress.IngressDetail();
  132. ingressDetail.setServiceName(applicationDTO.getName());
  133. ingressDetail.setPort(portDTO.getPort());
  134. ingressDetail.setPath("/" + appName + "/" + containerName);
  135. return ingressDetail;
  136. })
  137. .collect(Collectors.toSet());
  138. detailDTOS.addAll(ingressDetails);
  139. }
  140. ingress.setHttpRules(detailDTOS);
  141. return ingress;
  142. }
  143. private ApplicationVO buildApplicationVO(ApplicationDTO applicationDTO, Deployment deployment, Ingress ingress) {
  144. ApplicationVO applicationVO = new ApplicationVO();
  145. applicationVO.setName(applicationDTO.getName());
  146. applicationVO.setProjectName(applicationDTO.getProjectName());
  147. if (ingress.getHttpRules() != null) {
  148. applicationVO.setUrl(
  149. ingress.getHttpRules().stream()
  150. .map(rule -> ingress.getHttpHost() + rule).collect(Collectors.toList())
  151. );
  152. }
  153. ApplicationStatusVO applicationStatusVO = buildApplicationStatusVO(deployment);
  154. applicationVO.setStatus(applicationStatusVO);
  155. return applicationVO;
  156. }
  157. private ApplicationStatusVO buildApplicationStatusVO(Deployment deployment) {
  158. ApplicationStatusVO applicationStatusVO = new ApplicationStatusVO();
  159. applicationStatusVO.setReadyReplicas(deployment.getStatus().getReadyReplicas());
  160. applicationStatusVO.setDesiredReplicas(deployment.getReplicas());
  161. return applicationStatusVO;
  162. }
  163. }