package nju.seec.SEECdemo.logic.service.impl; import io.kubernetes.client.models.V1LimitRange; import nju.seec.SEECdemo.data.entity.ResourceConfig; import nju.seec.SEECdemo.logic.api.k8s.LimitRangeApi; import nju.seec.SEECdemo.logic.api.k8s.NamespaceApi; import nju.seec.SEECdemo.logic.api.k8s.ResourceQuotaApi; import nju.seec.SEECdemo.logic.api.k8s.SecretApi; import nju.seec.SEECdemo.logic.api.k8s.model.Namespace; import nju.seec.SEECdemo.logic.api.k8s.model.ResourceQuota; import nju.seec.SEECdemo.logic.service.DBService; import nju.seec.SEECdemo.logic.service.ProjectService; import nju.seec.SEECdemo.logic.vo.DBDetailVO; import nju.seec.SEECdemo.logic.vo.ProjectVO; import nju.seec.SEECdemo.logic.vo.projecttemplate.ProjectTemplate; import nju.seec.SEECdemo.util.ApplicationProperties; import nju.seec.SEECdemo.util.DateUtil; import nju.seec.SEECdemo.util.LoggerUtil; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.util.HashMap; import java.util.Map; import static nju.seec.SEECdemo.util.Constants.*; @Service public class ProjectServiceImpl implements ProjectService{ private static final Logger logger = LoggerUtil.getLogger(ProjectService.class); @Autowired private NamespaceApi namespaceApi; @Autowired private ResourceQuotaApi resourceQuotaApi; @Autowired private ProjectTemplate seecIITemplate; @Autowired private SecretApi secretApi; @Autowired private DBService dbService; @Autowired private ApplicationProperties applicationProperties; @Autowired private LimitRangeApi limitRangeApi; @Override public ProjectVO createSeecIIProject(String projectName, String description, LocalDate startsAt, LocalDate endsAt) { if (namespaceApi.exists(projectName)) { LoggerUtil.error(logger, "项目已经存在, projectName={}", projectName); return null; } try { //创建部署空间 String type = seecIITemplate.getName(); Namespace namespace = buildNamespace(projectName, type, description, startsAt, endsAt); namespaceApi.create(namespace); } catch (Exception e) { LoggerUtil.error(logger, e, "创建项目失败,projectName={}, projectType={}", projectName, seecIITemplate.getName()); return null; } try { //为部署空间配置私有仓库密钥 ApplicationProperties.Registry registry = applicationProperties.getRegistry(); secretApi.createPrivateRegistrySecret(projectName, registry.getHost(), registry.getUsername(), registry.getPassword()); //创建项目资源限额 ResourceQuota resourceQuota = buildResourceQuota(projectName, seecIITemplate.getDefaultResourceConfig()); resourceQuotaApi.create(resourceQuota); //创建项目资源默认配额 V1LimitRange v1LimitRange = buildLimitRange(projectName, seecIITemplate.getDefaultResourceConfig()); limitRangeApi.createLimitRange(projectName, v1LimitRange); //创建项目同名数据库 DBDetailVO dbDetailVO = dbService.createSchemaAndUserForProject(projectName); Map data = new HashMap<>(); data.put("DB_URL", dbDetailVO.getUrl().getBytes()); data.put("DB_SCHEMA", dbDetailVO.getSchema().getBytes()); data.put("DB_USERNAME", dbDetailVO.getUsername().getBytes()); data.put("DB_PASSWORD", dbDetailVO.getPassword().getBytes()); secretApi.createGenericSecret(projectName, projectName + "-" + DB_SECRET_NAME, data); //封装返回数据 ProjectVO projectVO = new ProjectVO(); projectVO.setName(projectName); projectVO.setDescription(description); projectVO.setStartsAt(DateUtil.fromDateToString(startsAt)); projectVO.setEndsAt(DateUtil.fromDateToString(endsAt)); projectVO.getExtra().put(ProjectVO.DB, dbDetailVO); return projectVO; } catch (Exception e) { LoggerUtil.error(logger, e, "配置项目失败,projectName={}, projectType={}", projectName, seecIITemplate.getName()); namespaceApi.delete(projectName); } return null; } @Override public boolean deleteProject(long projectId) { return false; } @Override public boolean deleteProjectForce(long projectId) { return false; } /** * 根据项目信息构建Namespace * @param projectName Namespace的名称 * @param type 项目的类型,存在Namespace的标签中 * @param description 项目的描述,可以存在Namespace的标签或者注释中 * @param startsAt 项目开始时间,存在Namespace的标签中 * @param endsAt 项目的结束时间,存在Namespace的标签中 * @return */ private Namespace buildNamespace(String projectName, String type, String description, LocalDate startsAt, LocalDate endsAt){ Namespace namespace = new Namespace(); namespace.setName(projectName); namespace.addToLabel(TYPE_LABEL, type); namespace.addToLabel(DESCRIPTION_LABEL, description); namespace.addToLabel(STARTS_AT_LABEL, DateUtil.fromDateToString(startsAt, DateUtil.BASE_DATE_FORMAT)); namespace.addToLabel(ENDS_AT_LABEL, DateUtil.fromDateToString(endsAt, DateUtil.BASE_DATE_FORMAT)); return namespace; } private ResourceQuota buildResourceQuota(String projectName, ResourceConfig resourceConfig) { ResourceQuota resourceQuota = new ResourceQuota(); resourceQuota.setNamespace(projectName); resourceQuota.setName(projectName); resourceQuota.setMaxMemoryTotalRequest(resourceConfig.getMaxMemory()); resourceQuota.setMaxMemoryTotalLimit(resourceConfig.getMaxMemory()); resourceQuota.setMaxCpuTotalRequest(resourceConfig.getMaxCPU()); resourceQuota.setMaxCpuTotalLimit(resourceConfig.getMaxCPU()); return resourceQuota; } private V1LimitRange buildLimitRange(String projectName, ResourceConfig resourceConfig) { //配置应用的默认配额 Map defaultValue = new HashMap<>(); defaultValue.put("cpu", 50); defaultValue.put("memory", 500); V1LimitRange v1LimitRange = limitRangeApi.toLimitRange(projectName, projectName, defaultValue, defaultValue, null, null); return v1LimitRange; } }