diff --git a/docs/docs/en/guide/security.md b/docs/docs/en/guide/security.md index d4449c49a1..92302183c4 100644 --- a/docs/docs/en/guide/security.md +++ b/docs/docs/en/guide/security.md @@ -162,7 +162,7 @@ worker.groups=default,test > Add or update k8s cluster -- First enter the configuration of the k8s cluster connection into the table `t_ds_k8s` in the database, which will be configured later by the web page. +- First enter the configuration of the k8s cluster connection into the table `t_ds_k8s` in the database for batch job and will removed later, the creation of the namespace now selects the cluster by drop-down options. > Add or update namespace diff --git a/docs/docs/zh/guide/security.md b/docs/docs/zh/guide/security.md index ee8973773f..80417b39dc 100644 --- a/docs/docs/zh/guide/security.md +++ b/docs/docs/zh/guide/security.md @@ -165,7 +165,7 @@ worker.groups=default,test > 创建/更新 k8s集群 -- 先把k8s集群连接的配置录入 database 的表 `t_ds_k8s`,后续会通过页面配置. +- 先把k8s集群连接的配置录入 database 的表 `t_ds_k8s`给批次使用后续移除,namespace的创建现在通过下拉选择集群. > 创建/更新 namespace diff --git a/docs/img/new_ui/dev/security/create-namespace.png b/docs/img/new_ui/dev/security/create-namespace.png index aac7cdf79a..c7a7632629 100644 Binary files a/docs/img/new_ui/dev/security/create-namespace.png and b/docs/img/new_ui/dev/security/create-namespace.png differ diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java index ac2e29534d..7f331774bc 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java @@ -20,7 +20,7 @@ package org.apache.dolphinscheduler.api.controller; import static org.apache.dolphinscheduler.api.enums.Status.CREATE_K8S_NAMESPACE_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.DELETE_K8S_NAMESPACE_BY_ID_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.QUERY_AUTHORIZED_NAMESPACE_ERROR; -import static org.apache.dolphinscheduler.api.enums.Status.QUERY_CAN_USE_K8S_CLUSTER_ERROR; +import static org.apache.dolphinscheduler.api.enums.Status.QUERY_CAN_USE_K8S_NAMESPACE_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.QUERY_K8S_NAMESPACE_LIST_PAGING_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.QUERY_UNAUTHORIZED_NAMESPACE_ERROR; import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_K8S_NAMESPACE_ERROR; @@ -78,18 +78,18 @@ public class K8sNamespaceController extends BaseController { */ @ApiOperation(value = "queryNamespaceListPaging", notes = "QUERY_NAMESPACE_LIST_PAGING_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "searchVal", value = "SEARCH_VAL", dataType = "String"), - @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "10"), - @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "1") + @ApiImplicitParam(name = "searchVal", value = "SEARCH_VAL", dataType = "String"), + @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "10"), + @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "1") }) @GetMapping() @ResponseStatus(HttpStatus.OK) @ApiException(QUERY_K8S_NAMESPACE_LIST_PAGING_ERROR) @AccessLogAnnotation(ignoreRequestArgs = "loginUser") - public Result queryProjectListPaging(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, - @RequestParam(value = "searchVal", required = false) String searchVal, - @RequestParam("pageSize") Integer pageSize, - @RequestParam("pageNo") Integer pageNo + public Result queryNamespaceListPaging(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, + @RequestParam(value = "searchVal", required = false) String searchVal, + @RequestParam("pageSize") Integer pageSize, + @RequestParam("pageNo") Integer pageNo ) { Result result = checkPageParams(pageNo, pageSize); @@ -107,17 +107,17 @@ public class K8sNamespaceController extends BaseController { * * @param loginUser * @param namespace k8s namespace - * @param k8s k8s name + * @param clusterCode clusterCode * @param limitsCpu max cpu * @param limitsMemory max memory * @return */ @ApiOperation(value = "createK8sNamespace", notes = "CREATE_NAMESPACE_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "namespace", value = "NAMESPACE", required = true, dataType = "String"), - @ApiImplicitParam(name = "k8s", value = "K8S", required = true, dataType = "String"), - @ApiImplicitParam(name = "limits_cpu", value = "LIMITS_CPU", required = false, dataType = "Double"), - @ApiImplicitParam(name = "limits_memory", value = "LIMITS_MEMORY", required = false, dataType = "Integer") + @ApiImplicitParam(name = "namespace", value = "NAMESPACE", required = true, dataType = "String"), + @ApiImplicitParam(name = "clusterCode", value = "CLUSTER_CODE", required = true, dataType = "Long"), + @ApiImplicitParam(name = "limits_cpu", value = "LIMITS_CPU", required = false, dataType = "Double"), + @ApiImplicitParam(name = "limits_memory", value = "LIMITS_MEMORY", required = false, dataType = "Integer") }) @PostMapping() @ResponseStatus(HttpStatus.CREATED) @@ -125,11 +125,11 @@ public class K8sNamespaceController extends BaseController { @AccessLogAnnotation(ignoreRequestArgs = "loginUser") public Result createNamespace(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam(value = "namespace") String namespace, - @RequestParam(value = "k8s") String k8s, + @RequestParam(value = "clusterCode") Long clusterCode, @RequestParam(value = "limitsCpu", required = false) Double limitsCpu, @RequestParam(value = "limitsMemory", required = false) Integer limitsMemory ) { - Map result = k8sNamespaceService.createK8sNamespace(loginUser, namespace, k8s, limitsCpu, limitsMemory); + Map result = k8sNamespaceService.createK8sNamespace(loginUser, namespace, clusterCode, limitsCpu, limitsMemory); return returnDataList(result); } @@ -137,17 +137,17 @@ public class K8sNamespaceController extends BaseController { * update namespace,namespace and k8s not allowed update, because may create on k8s,can delete and create new instead * * @param loginUser - * @param userName owner + * @param userName owner * @param limitsCpu max cpu * @param limitsMemory max memory * @return */ @ApiOperation(value = "updateK8sNamespace", notes = "UPDATE_NAMESPACE_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "id", value = "K8S_NAMESPACE_ID", required = true, dataType = "Int", example = "100"), - @ApiImplicitParam(name = "userName", value = "OWNER", required = false, dataType = "String"), - @ApiImplicitParam(name = "limitsCpu", value = "LIMITS_CPU", required = false, dataType = "Double"), - @ApiImplicitParam(name = "limitsMemory", value = "LIMITS_MEMORY", required = false, dataType = "Integer")}) + @ApiImplicitParam(name = "id", value = "K8S_NAMESPACE_ID", required = true, dataType = "Int", example = "100"), + @ApiImplicitParam(name = "userName", value = "OWNER", required = false, dataType = "String"), + @ApiImplicitParam(name = "limitsCpu", value = "LIMITS_CPU", required = false, dataType = "Double"), + @ApiImplicitParam(name = "limitsMemory", value = "LIMITS_MEMORY", required = false, dataType = "Integer")}) @PutMapping(value = "/{id}") @ResponseStatus(HttpStatus.CREATED) @ApiException(UPDATE_K8S_NAMESPACE_ERROR) @@ -165,15 +165,15 @@ public class K8sNamespaceController extends BaseController { /** * verify namespace and k8s,one k8s namespace is unique * - * @param loginUser login user - * @param namespace namespace - * @param k8s k8s + * @param loginUser login user + * @param namespace namespace + * @param clusterCode cluster code * @return true if the k8s and namespace not exists, otherwise return false */ @ApiOperation(value = "verifyNamespaceK8s", notes = "VERIFY_NAMESPACE_K8S_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "namespace", value = "NAMESPACE", required = true, dataType = "String"), - @ApiImplicitParam(name = "k8s", value = "K8S", required = true, dataType = "String") + @ApiImplicitParam(name = "namespace", value = "NAMESPACE", required = true, dataType = "String"), + @ApiImplicitParam(name = "clusterCode", value = "CLUSTER_CODE", required = true, dataType = "Long"), }) @PostMapping(value = "/verify") @ResponseStatus(HttpStatus.OK) @@ -181,10 +181,10 @@ public class K8sNamespaceController extends BaseController { @AccessLogAnnotation(ignoreRequestArgs = "loginUser") public Result verifyNamespace(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam(value = "namespace") String namespace, - @RequestParam(value = "k8s") String k8s + @RequestParam(value = "clusterCode") Long clusterCode ) { - return k8sNamespaceService.verifyNamespaceK8s(namespace, k8s); + return k8sNamespaceService.verifyNamespaceK8s(namespace, clusterCode); } @@ -197,7 +197,7 @@ public class K8sNamespaceController extends BaseController { */ @ApiOperation(value = "delNamespaceById", notes = "DELETE_NAMESPACE_BY_ID_NOTES") @ApiImplicitParams({ - @ApiImplicitParam(name = "id", value = "NAMESPACE_ID", required = true, dataType = "Int", example = "100") + @ApiImplicitParam(name = "id", value = "NAMESPACE_ID", required = true, dataType = "Int", example = "100") }) @PostMapping(value = "/delete") @ResponseStatus(HttpStatus.OK) @@ -213,7 +213,7 @@ public class K8sNamespaceController extends BaseController { * query unauthorized namespace * * @param loginUser login user - * @param userId user id + * @param userId user id * @return the namespaces which user have not permission to see */ @ApiOperation(value = "queryUnauthorizedNamespace", notes = "QUERY_UNAUTHORIZED_NAMESPACE_NOTES") @@ -234,7 +234,7 @@ public class K8sNamespaceController extends BaseController { * query unauthorized namespace * * @param loginUser login user - * @param userId user id + * @param userId user id * @return namespaces which the user have permission to see */ @ApiOperation(value = "queryAuthorizedNamespace", notes = "QUERY_AUTHORIZED_NAMESPACE_NOTES") @@ -260,10 +260,10 @@ public class K8sNamespaceController extends BaseController { @ApiOperation(value = "queryAvailableNamespaceList", notes = "QUERY_AVAILABLE_NAMESPACE_LIST_NOTES") @GetMapping(value = "/available-list") @ResponseStatus(HttpStatus.OK) - @ApiException(QUERY_CAN_USE_K8S_CLUSTER_ERROR) + @ApiException(QUERY_CAN_USE_K8S_NAMESPACE_ERROR) @AccessLogAnnotation(ignoreRequestArgs = "loginUser") public Result queryAvailableNamespaceList(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) User loginUser) { List result = k8sNamespaceService.queryNamespaceAvailable(loginUser); return success(result); } -} +} \ No newline at end of file diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java index a04d994440..7918f5502c 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java @@ -423,6 +423,7 @@ public enum Status { RESOURCE_FULL_NAME_TOO_LONG_ERROR(1300015, "resource's fullname is too long error", "资源文件名过长"), TENANT_FULL_NAME_TOO_LONG_ERROR(1300016, "tenant's fullname is too long error", "租户名过长"), USER_PASSWORD_LENGTH_ERROR(1300017, "user's password length error", "用户密码长度错误"), + QUERY_CAN_USE_K8S_NAMESPACE_ERROR(1300018, "login user query can used namespace list error", "查询可用命名空间错误"), NO_CURRENT_OPERATING_PERMISSION(1400001, "The current user does not have this permission.", "当前用户无此权限"), FUNCTION_DISABLED(1400002, "The current feature is disabled.", "当前功能已被禁用"), diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sClientService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sClientService.java index b8f07c5ae5..dcfc6e734a 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sClientService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sClientService.java @@ -18,6 +18,7 @@ package org.apache.dolphinscheduler.api.k8s; import org.apache.dolphinscheduler.dao.entity.K8sNamespace; +import org.apache.dolphinscheduler.remote.exceptions.RemotingException; import java.util.Optional; @@ -41,15 +42,15 @@ public class K8sClientService { @Autowired private K8sManager k8sManager; - public ResourceQuota upsertNamespaceAndResourceToK8s(K8sNamespace k8sNamespace, String yamlStr) { - upsertNamespaceToK8s(k8sNamespace.getNamespace(), k8sNamespace.getK8s()); + public ResourceQuota upsertNamespaceAndResourceToK8s(K8sNamespace k8sNamespace, String yamlStr) throws RemotingException { + upsertNamespaceToK8s(k8sNamespace.getNamespace(), k8sNamespace.getClusterCode()); return upsertNamespacedResourceToK8s(k8sNamespace, yamlStr); } - public Optional deleteNamespaceToK8s(String name, String k8s) { - Optional result = getNamespaceFromK8s(name, k8s); + public Optional deleteNamespaceToK8s(String name, Long clusterCode) throws RemotingException { + Optional result = getNamespaceFromK8s(name, clusterCode); if (result.isPresent()) { - KubernetesClient client = k8sManager.getK8sClient(k8s); + KubernetesClient client = k8sManager.getK8sClient(clusterCode); Namespace body = new Namespace(); ObjectMeta meta = new ObjectMeta(); meta.setNamespace(name); @@ -57,12 +58,12 @@ public class K8sClientService { body.setMetadata(meta); client.namespaces().delete(body); } - return getNamespaceFromK8s(name, k8s); + return getNamespaceFromK8s(name, clusterCode); } - private ResourceQuota upsertNamespacedResourceToK8s(K8sNamespace k8sNamespace, String yamlStr) { + private ResourceQuota upsertNamespacedResourceToK8s(K8sNamespace k8sNamespace, String yamlStr) throws RemotingException { - KubernetesClient client = k8sManager.getK8sClient(k8sNamespace.getK8s()); + KubernetesClient client = k8sManager.getK8sClient(k8sNamespace.getClusterCode()); //创建资源 ResourceQuota queryExist = client.resourceQuotas() @@ -86,9 +87,9 @@ public class K8sClientService { .createOrReplace(body); } - private Optional getNamespaceFromK8s(String name, String k8s) { + private Optional getNamespaceFromK8s(String name, Long clusterCode) throws RemotingException { NamespaceList listNamespace = - k8sManager.getK8sClient(k8s).namespaces().list(); + k8sManager.getK8sClient(clusterCode).namespaces().list(); Optional list = listNamespace.getItems().stream() @@ -99,11 +100,11 @@ public class K8sClientService { return list; } - private Namespace upsertNamespaceToK8s(String name, String k8s) { - Optional result = getNamespaceFromK8s(name, k8s); + private Namespace upsertNamespaceToK8s(String name, Long clusterCode) throws RemotingException { + Optional result = getNamespaceFromK8s(name, clusterCode); //if not exist create if (!result.isPresent()) { - KubernetesClient client = k8sManager.getK8sClient(k8s); + KubernetesClient client = k8sManager.getK8sClient(clusterCode); Namespace body = new Namespace(); ObjectMeta meta = new ObjectMeta(); meta.setNamespace(name); @@ -114,4 +115,4 @@ public class K8sClientService { return result.get(); } -} +} \ No newline at end of file diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sManager.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sManager.java index 4c98ddb617..52b7123cd8 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sManager.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/k8s/K8sManager.java @@ -17,29 +17,25 @@ package org.apache.dolphinscheduler.api.k8s; -import org.apache.dolphinscheduler.dao.entity.K8s; -import org.apache.dolphinscheduler.dao.mapper.K8sMapper; +import org.apache.dolphinscheduler.common.utils.ClusterConfUtils; +import org.apache.dolphinscheduler.dao.entity.Cluster; +import org.apache.dolphinscheduler.dao.mapper.ClusterMapper; import org.apache.dolphinscheduler.remote.exceptions.RemotingException; import java.util.Hashtable; -import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; - import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; /** - * A separate class, because then wait for multiple environment feature, currently using db configuration, later unified + * use multiple environment feature */ @Component public class K8sManager { @@ -48,27 +44,76 @@ public class K8sManager { /** * cache k8s client */ - private static Map clientMap = new Hashtable<>(); + private static Map clientMap = new Hashtable<>(); @Autowired - private K8sMapper k8sMapper; + private ClusterMapper clusterMapper; - public KubernetesClient getK8sClient(String k8sName) { - if (null == k8sName) { + /** + * get k8s client for api use + * + * @param clusterCode + * @return + */ + public synchronized KubernetesClient getK8sClient(Long clusterCode) throws RemotingException { + if (null == clusterCode) { return null; } - return clientMap.get(k8sName); + + return getAndUpdateK8sClient(clusterCode, false); + } + + /** + * @param clusterCode + * @return new client if need updated + */ + public synchronized KubernetesClient getAndUpdateK8sClient(Long clusterCode, boolean update) throws RemotingException { + if (null == clusterCode) { + return null; + } + + if (update) { + deleteK8sClientInner(clusterCode); + } + + if (clientMap.containsKey(clusterCode)) { + return clientMap.get(clusterCode); + } else { + createK8sClientInner(clusterCode); + } + return clientMap.get(clusterCode); } - @EventListener - public void buildApiClientAll(ApplicationReadyEvent readyEvent) throws RemotingException { - QueryWrapper nodeWrapper = new QueryWrapper<>(); - List k8sList = k8sMapper.selectList(nodeWrapper); - if (k8sList != null) { - for (K8s k8s : k8sList) { - DefaultKubernetesClient client = getClient(k8s.getK8sConfig()); - clientMap.put(k8s.getK8sName(), client); + private void deleteK8sClientInner(Long clusterCode) { + if (clusterCode == null) { + return; + } + Cluster cluster = clusterMapper.queryByClusterCode(clusterCode); + if (cluster == null) { + return; + } + KubernetesClient client = clientMap.get(clusterCode); + if (client != null) { + client.close(); + } + } + + private void createK8sClientInner(Long clusterCode) throws RemotingException { + Cluster cluster = clusterMapper.queryByClusterCode(clusterCode); + if (cluster == null) { + return; + } + + String k8sConfig = ClusterConfUtils.getK8sConfig(cluster.getConfig()); + if (k8sConfig != null) { + DefaultKubernetesClient client = null; + try { + client = getClient(k8sConfig); + clientMap.put(clusterCode, client); + } catch (RemotingException e) { + logger.error("cluster code ={},fail to get k8s ApiClient: {}", clusterCode, e.getMessage()); + throw new RemotingException("fail to get k8s ApiClient:" + e.getMessage()); } } } @@ -82,4 +127,5 @@ public class K8sManager { throw new RemotingException("fail to get k8s ApiClient:" + e.getMessage()); } } -} + +} \ No newline at end of file diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/K8sNamespaceService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/K8sNamespaceService.java index d56c8ab537..d3f15a4dd6 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/K8sNamespaceService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/K8sNamespaceService.java @@ -28,6 +28,7 @@ import java.util.Map; * k8s namespace service impl */ public interface K8sNamespaceService { + /** * query namespace list paging * @@ -39,19 +40,17 @@ public interface K8sNamespaceService { */ Result queryListPaging(User loginUser, String searchVal, Integer pageNo, Integer pageSize); - /** * create namespace,if not exist on k8s,will create,if exist only register in db * * @param loginUser login user * @param namespace namespace - * @param k8s k8s not null + * @param clusterCode k8s not null * @param limitsCpu limits cpu, can null means not limit * @param limitsMemory limits memory, can null means not limit * @return */ - Map createK8sNamespace(User loginUser, String namespace, String k8s, Double limitsCpu, Integer limitsMemory); - + Map createK8sNamespace(User loginUser, String namespace, Long clusterCode, Double limitsCpu, Integer limitsMemory); /** * update K8s Namespace tag and resource limit @@ -67,11 +66,11 @@ public interface K8sNamespaceService { /** * verify namespace and k8s * - * @param namespace namespace - * @param k8s k8s + * @param namespace namespace + * @param clusterCode cluster code * @return true if the k8s and namespace not exists, otherwise return false */ - Result verifyNamespaceK8s(String namespace, String k8s); + Result verifyNamespaceK8s(String namespace, Long clusterCode); /** * delete namespace by id @@ -107,4 +106,4 @@ public interface K8sNamespaceService { * @return namespace list */ List queryNamespaceAvailable(User loginUser); -} +} \ No newline at end of file diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ClusterServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ClusterServiceImpl.java index e069d0611f..38f1a0ff8a 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ClusterServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ClusterServiceImpl.java @@ -19,15 +19,20 @@ package org.apache.dolphinscheduler.api.service.impl; import org.apache.dolphinscheduler.api.dto.ClusterDto; import org.apache.dolphinscheduler.api.enums.Status; +import org.apache.dolphinscheduler.api.k8s.K8sManager; import org.apache.dolphinscheduler.api.service.ClusterService; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.Constants; +import org.apache.dolphinscheduler.common.utils.ClusterConfUtils; import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils; import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils.CodeGenerateException; import org.apache.dolphinscheduler.dao.entity.Cluster; +import org.apache.dolphinscheduler.dao.entity.K8sNamespace; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.ClusterMapper; +import org.apache.dolphinscheduler.dao.mapper.K8sNamespaceMapper; +import org.apache.dolphinscheduler.remote.exceptions.RemotingException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; @@ -46,6 +51,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -60,6 +66,11 @@ public class ClusterServiceImpl extends BaseServiceImpl implements ClusterServic @Autowired private ClusterMapper clusterMapper; + @Autowired + private K8sManager k8sManager; + + @Autowired + private K8sNamespaceMapper k8sNamespaceMapper; /** * create cluster * @@ -237,6 +248,14 @@ public class ClusterServiceImpl extends BaseServiceImpl implements ClusterServic return result; } + Integer relatedNamespaceNumber = k8sNamespaceMapper + .selectCount(new QueryWrapper().lambda().eq(K8sNamespace::getClusterCode, code)); + + if (relatedNamespaceNumber > 0) { + putMsg(result, Status.DELETE_CLUSTER_RELATED_NAMESPACE_EXISTS); + return result; + } + int delete = clusterMapper.deleteByCode(code); if (delete > 0) { putMsg(result, Status.SUCCESS); @@ -281,6 +300,16 @@ public class ClusterServiceImpl extends BaseServiceImpl implements ClusterServic return result; } + if (!Constants.K8S_LOCAL_TEST_CLUSTER_CODE.equals(clusterExist.getCode()) + && !config.equals(ClusterConfUtils.getK8sConfig(clusterExist.getConfig()))) { + try { + k8sManager.getAndUpdateK8sClient(code, true); + } catch (RemotingException e) { + putMsg(result, Status.K8S_CLIENT_OPS_ERROR, name); + return result; + } + } + //update cluster clusterExist.setConfig(config); clusterExist.setName(name); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/K8SNamespaceServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/K8SNamespaceServiceImpl.java index 91d66b2c00..ed903348e8 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/K8SNamespaceServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/K8SNamespaceServiceImpl.java @@ -22,13 +22,16 @@ import org.apache.dolphinscheduler.api.service.K8sNamespaceService; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.Constants; -import org.apache.dolphinscheduler.common.enums.AuthorizationType; +import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils; +import org.apache.dolphinscheduler.dao.entity.Cluster; import org.apache.dolphinscheduler.dao.entity.K8sNamespace; import org.apache.dolphinscheduler.dao.entity.User; +import org.apache.dolphinscheduler.dao.mapper.ClusterMapper; import org.apache.dolphinscheduler.dao.mapper.K8sNamespaceMapper; +import org.apache.dolphinscheduler.remote.exceptions.RemotingException; import org.apache.dolphinscheduler.api.k8s.K8sClientService; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.Date; @@ -63,11 +66,16 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames + " hard:\n" + " ${limitCpu}\n" + " ${limitMemory}\n"; + @Autowired private K8sNamespaceMapper k8sNamespaceMapper; + @Autowired private K8sClientService k8sClientService; + @Autowired + private ClusterMapper clusterMapper; + /** * query namespace list paging * @@ -80,6 +88,11 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames @Override public Result queryListPaging(User loginUser, String searchVal, Integer pageNo, Integer pageSize) { Result result = new Result(); + if (!isAdmin(loginUser)) { + putMsg(result, Status.USER_NO_OPERATION_PERM); + return result; + } + Page page = new Page<>(pageNo, pageSize); IPage k8sNamespaceList = k8sNamespaceMapper.queryK8sNamespacePaging(page, searchVal); @@ -99,16 +112,15 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames * * @param loginUser login user * @param namespace namespace - * @param k8s k8s not null + * @param clusterCode k8s not null * @param limitsCpu limits cpu, can null means not limit * @param limitsMemory limits memory, can null means not limit * @return */ @Override - public Map createK8sNamespace(User loginUser, String namespace, String k8s, Double limitsCpu, Integer limitsMemory) { + public Map createK8sNamespace(User loginUser, String namespace, Long clusterCode, Double limitsCpu, Integer limitsMemory) { Map result = new HashMap<>(); - if (!canOperatorPermissions(loginUser, null,AuthorizationType.K8S_NAMESPACE,null)) { - putMsg(result, Status.USER_NO_OPERATION_PERM); + if (isNotAdmin(loginUser, result)) { return result; } @@ -117,8 +129,8 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames return result; } - if (StringUtils.isEmpty(k8s)) { - putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.K8S); + if (clusterCode == null) { + putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.CLUSTER); return result; } @@ -132,27 +144,45 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames return result; } - if (checkNamespaceExistInDb(namespace, k8s)) { - putMsg(result, Status.K8S_NAMESPACE_EXIST, namespace, k8s); + if (checkNamespaceExistInDb(namespace, clusterCode)) { + putMsg(result, Status.K8S_NAMESPACE_EXIST, namespace, clusterCode); + return result; + } + + Cluster cluster = clusterMapper.queryByClusterCode(clusterCode); + if (cluster == null) { + putMsg(result, Status.CLUSTER_NOT_EXISTS, namespace, clusterCode); + return result; + } + + long code = 0L; + try { + code = CodeGenerateUtils.getInstance().genCode(); + cluster.setCode(code); + } catch (CodeGenerateUtils.CodeGenerateException e) { + logger.error("Cluster code get error, ", e); + } + if (code == 0L) { + putMsg(result, Status.INTERNAL_SERVER_ERROR_ARGS, "Error generating cluster code"); return result; } K8sNamespace k8sNamespaceObj = new K8sNamespace(); Date now = new Date(); + k8sNamespaceObj.setCode(code); k8sNamespaceObj.setNamespace(namespace); - k8sNamespaceObj.setK8s(k8s); + k8sNamespaceObj.setClusterCode(clusterCode); k8sNamespaceObj.setUserId(loginUser.getId()); k8sNamespaceObj.setLimitsCpu(limitsCpu); k8sNamespaceObj.setLimitsMemory(limitsMemory); - k8sNamespaceObj.setOnlineJobNum(0); k8sNamespaceObj.setPodReplicas(0); k8sNamespaceObj.setPodRequestCpu(0.0); k8sNamespaceObj.setPodRequestMemory(0); k8sNamespaceObj.setCreateTime(now); k8sNamespaceObj.setUpdateTime(now); - if (!Constants.K8S_LOCAL_TEST_CLUSTER.equals(k8sNamespaceObj.getK8s())) { + if (!Constants.K8S_LOCAL_TEST_CLUSTER_CODE.equals(k8sNamespaceObj.getClusterCode())) { try { String yamlStr = genDefaultResourceYaml(k8sNamespaceObj); k8sClientService.upsertNamespaceAndResourceToK8s(k8sNamespaceObj, yamlStr); @@ -181,8 +211,7 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames @Override public Map updateK8sNamespace(User loginUser, int id, String userName, Double limitsCpu, Integer limitsMemory) { Map result = new HashMap<>(); - if (!canOperatorPermissions(loginUser, null,AuthorizationType.K8S_NAMESPACE,null)) { - putMsg(result, Status.USER_NO_OPERATION_PERM); + if (isNotAdmin(loginUser, result)) { return result; } @@ -207,7 +236,7 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames k8sNamespaceObj.setLimitsMemory(limitsMemory); k8sNamespaceObj.setUpdateTime(now); - if (!Constants.K8S_LOCAL_TEST_CLUSTER.equals(k8sNamespaceObj.getK8s())) { + if (!Constants.K8S_LOCAL_TEST_CLUSTER_CODE.equals(k8sNamespaceObj.getClusterCode())) { try { String yamlStr = genDefaultResourceYaml(k8sNamespaceObj); k8sClientService.upsertNamespaceAndResourceToK8s(k8sNamespaceObj, yamlStr); @@ -227,25 +256,25 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames /** * verify namespace and k8s * - * @param namespace namespace - * @param k8s k8s + * @param namespace namespace + * @param clusterCode cluster code * @return true if the k8s and namespace not exists, otherwise return false */ @Override - public Result verifyNamespaceK8s(String namespace, String k8s) { + public Result verifyNamespaceK8s(String namespace, Long clusterCode) { Result result = new Result<>(); if (StringUtils.isEmpty(namespace)) { putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.NAMESPACE); return result; } - if (StringUtils.isEmpty(k8s)) { - putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.K8S); + if (clusterCode == null) { + putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.CLUSTER); return result; } - if (checkNamespaceExistInDb(namespace, k8s)) { - putMsg(result, Status.K8S_NAMESPACE_EXIST, namespace, k8s); + if (checkNamespaceExistInDb(namespace, clusterCode)) { + putMsg(result, Status.K8S_NAMESPACE_EXIST, namespace, clusterCode); return result; } @@ -263,8 +292,7 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames @Override public Map deleteNamespaceById(User loginUser, int id) { Map result = new HashMap<>(); - if (!canOperatorPermissions(loginUser, null,AuthorizationType.K8S_NAMESPACE,null)) { - putMsg(result, Status.USER_NO_OPERATION_PERM); + if (isNotAdmin(loginUser, result)) { return result; } @@ -273,8 +301,13 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames putMsg(result, Status.K8S_NAMESPACE_NOT_EXIST, id); return result; } - if (!Constants.K8S_LOCAL_TEST_CLUSTER.equals(k8sNamespaceObj.getK8s())) { - k8sClientService.deleteNamespaceToK8s(k8sNamespaceObj.getNamespace(), k8sNamespaceObj.getK8s()); + if (!Constants.K8S_LOCAL_TEST_CLUSTER_CODE.equals(k8sNamespaceObj.getClusterCode())) { + try { + k8sClientService.deleteNamespaceToK8s(k8sNamespaceObj.getNamespace(), k8sNamespaceObj.getClusterCode()); + } catch (RemotingException e) { + putMsg(result, Status.K8S_CLIENT_OPS_ERROR, id); + return result; + } } k8sNamespaceMapper.deleteById(id); putMsg(result, Status.SUCCESS); @@ -287,8 +320,8 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames * @param namespace namespace * @return true if the k8s and namespace not exists, otherwise return false */ - private boolean checkNamespaceExistInDb(String namespace, String k8s) { - return k8sNamespaceMapper.existNamespace(namespace, k8s) == Boolean.TRUE; + private boolean checkNamespaceExistInDb(String namespace, Long clusterCode) { + return k8sNamespaceMapper.existNamespace(namespace, clusterCode) == Boolean.TRUE; } /** @@ -338,8 +371,7 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames @Override public Map queryUnauthorizedNamespace(User loginUser, Integer userId) { Map result = new HashMap<>(); - if (loginUser.getId() != userId && !canOperatorPermissions(loginUser, null,AuthorizationType.K8S_NAMESPACE,null)) { - putMsg(result, Status.USER_NO_OPERATION_PERM); + if (loginUser.getId() != userId && isNotAdmin(loginUser, result)) { return result; } // query all namespace list,this auth does not like project @@ -367,8 +399,7 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames public Map queryAuthorizedNamespace(User loginUser, Integer userId) { Map result = new HashMap<>(); - if (loginUser.getId() != userId && !canOperatorPermissions(loginUser, null,AuthorizationType.K8S_NAMESPACE,null)) { - putMsg(result, Status.USER_NO_OPERATION_PERM); + if (loginUser.getId() != userId && isNotAdmin(loginUser, result)) { return result; } @@ -387,7 +418,7 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames */ @Override public List queryNamespaceAvailable(User loginUser) { - if (canOperatorPermissions(loginUser,null,AuthorizationType.K8S_NAMESPACE,null)) { + if (isAdmin(loginUser)) { return k8sNamespaceMapper.selectList(null); } else { return k8sNamespaceMapper.queryNamespaceAvailable(loginUser.getId()); @@ -419,5 +450,4 @@ public class K8SNamespaceServiceImpl extends BaseServiceImpl implements K8sNames } return resultList; } - -} +} \ No newline at end of file diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ClusterControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ClusterControllerTest.java index fd255ce0f3..8ee52f8664 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ClusterControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/ClusterControllerTest.java @@ -42,7 +42,7 @@ import com.google.common.base.Preconditions; public class ClusterControllerTest extends AbstractControllerTest { public static final String clusterName = "Cluster1"; - public static final String config = "this is config content"; + public static final String config = "{\"k8s\":\"apiVersion: v1\"}"; public static final String desc = "this is cluster description"; private static final Logger logger = LoggerFactory.getLogger(ClusterControllerTest.class); private String clusterCode; diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceControllerTest.java index d265ebb118..9631ab6d11 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceControllerTest.java @@ -28,12 +28,8 @@ import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.dao.entity.User; -import java.util.HashMap; -import java.util.Map; - import org.junit.Assert; import org.junit.Test; -import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; @@ -72,7 +68,7 @@ public class K8sNamespaceControllerTest extends AbstractControllerTest { MultiValueMap paramsMap = new LinkedMultiValueMap<>(); paramsMap.add("namespace", NAMESPACE_CREATE_STRING); - paramsMap.add("k8s", "k8s"); + paramsMap.add("clusterCode", "0"); MvcResult mvcResult = mockMvc.perform(post("/k8s-namespace") .header(SESSION_ID, sessionId) @@ -82,7 +78,7 @@ public class K8sNamespaceControllerTest extends AbstractControllerTest { .andReturn(); Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); - Assert.assertEquals(Status.K8S_CLIENT_OPS_ERROR.getCode(), result.getCode().intValue());//because we not have a k8s cluster in test env + Assert.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue());//because we not have a k8s cluster in test env logger.info("create queue return result:{}", mvcResult.getResponse().getContentAsString()); } @@ -108,8 +104,8 @@ public class K8sNamespaceControllerTest extends AbstractControllerTest { public void verifyNamespace() throws Exception { // queue value exist MultiValueMap paramsMap = new LinkedMultiValueMap<>(); - paramsMap.add("namespace", NAMESPACE_CREATE_STRING); - paramsMap.add("k8s", "default"); + paramsMap.add("namespace", "NAMESPACE_CREATE_STRING"); + paramsMap.add("clusterCode", "100"); // success @@ -127,7 +123,7 @@ public class K8sNamespaceControllerTest extends AbstractControllerTest { //error paramsMap.clear(); paramsMap.add("namespace", null); - paramsMap.add("k8s", "default"); + paramsMap.add("clusterCode", "100"); mvcResult = mockMvc.perform(post("/k8s-namespace/verify") .header(SESSION_ID, sessionId) .params(paramsMap)) diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/k8s/K8sManagerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/k8s/K8sManagerTest.java index 0d2033e88d..fb36dd2e35 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/k8s/K8sManagerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/k8s/K8sManagerTest.java @@ -17,8 +17,9 @@ package org.apache.dolphinscheduler.api.k8s; -import org.apache.dolphinscheduler.dao.entity.K8s; -import org.apache.dolphinscheduler.dao.mapper.K8sMapper; +import org.apache.dolphinscheduler.dao.entity.Cluster; +import org.apache.dolphinscheduler.dao.mapper.ClusterMapper; +import org.apache.dolphinscheduler.remote.exceptions.RemotingException; import java.util.ArrayList; import java.util.List; @@ -42,7 +43,7 @@ public class K8sManagerTest { private K8sManager k8sManager; @Mock - private K8sMapper k8sMapper; + private ClusterMapper clusterMapper; @Before public void setUp() throws Exception { @@ -53,26 +54,27 @@ public class K8sManagerTest { } @Test - public void getK8sClient() { - Mockito.when(k8sMapper.selectList(Mockito.any())).thenReturn(getK8sList()); + public void getK8sClient() throws RemotingException { + Mockito.when(clusterMapper.selectList(Mockito.any())).thenReturn(getClusterList()); - KubernetesClient result = k8sManager.getK8sClient("must null"); + KubernetesClient result = k8sManager.getK8sClient(1L); Assert.assertNull(result); result = k8sManager.getK8sClient(null); Assert.assertNull(result); } - private K8s getK8s() { - K8s k8s = new K8s(); - k8s.setId(1); - k8s.setK8sName("default"); - k8s.setK8sConfig("k8s config"); - return k8s; + private Cluster getCluster() { + Cluster cluster = new Cluster(); + cluster.setId(1); + cluster.setCode(1L); + cluster.setName("cluster"); + cluster.setConfig("{\"k8s\":\"k8s config yaml\"}"); + return cluster; } - private List getK8sList() { - List k8sList = new ArrayList<>(); - k8sList.add(getK8s()); - return k8sList; + private List getClusterList() { + List clusterList = new ArrayList<>(); + clusterList.add(getCluster()); + return clusterList; } } \ No newline at end of file diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ClusterServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ClusterServiceTest.java index 7c22c57fc6..ac2e261ce9 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ClusterServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ClusterServiceTest.java @@ -221,6 +221,11 @@ public class ClusterServiceTest { result = clusterService.deleteClusterByCode(loginUser,1L); logger.info(result.toString()); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); + + Mockito.when(k8sNamespaceMapper.selectCount(Mockito.any())).thenReturn(1); + result = clusterService.deleteClusterByCode(loginUser,1L); + logger.info(result.toString()); + Assert.assertEquals(Status.DELETE_CLUSTER_RELATED_NAMESPACE_EXISTS, result.get(Constants.STATUS)); } @Test diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/K8SNamespaceServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/K8SNamespaceServiceTest.java index f2c5b7064c..8732a59658 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/K8SNamespaceServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/K8SNamespaceServiceTest.java @@ -18,15 +18,15 @@ package org.apache.dolphinscheduler.api.service; import org.apache.dolphinscheduler.api.enums.Status; -import org.apache.dolphinscheduler.api.service.impl.BaseServiceImpl; import org.apache.dolphinscheduler.api.service.impl.K8SNamespaceServiceImpl; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.common.Constants; -import org.apache.dolphinscheduler.common.enums.AuthorizationType; import org.apache.dolphinscheduler.common.enums.UserType; +import org.apache.dolphinscheduler.dao.entity.Cluster; import org.apache.dolphinscheduler.dao.entity.K8sNamespace; import org.apache.dolphinscheduler.dao.entity.User; +import org.apache.dolphinscheduler.dao.mapper.ClusterMapper; import org.apache.dolphinscheduler.dao.mapper.K8sNamespaceMapper; import org.apache.dolphinscheduler.dao.mapper.UserMapper; import org.apache.dolphinscheduler.api.k8s.K8sClientService; @@ -37,7 +37,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.dolphinscheduler.api.permission.ResourcePermissionCheckService; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -57,7 +56,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; public class K8SNamespaceServiceTest { private static final Logger logger = LoggerFactory.getLogger(K8SNamespaceServiceTest.class); - private static final Logger baseServiceLogger = LoggerFactory.getLogger(BaseServiceImpl.class); @InjectMocks private K8SNamespaceServiceImpl k8sNamespaceService; @@ -69,18 +67,18 @@ public class K8SNamespaceServiceTest { private K8sClientService k8sClientService; @Mock - private ResourcePermissionCheckService resourcePermissionCheckService; + private UserMapper userMapper; @Mock - private UserMapper userMapper; + private ClusterMapper clusterMapper; private String namespace = "default"; - private String k8s = "default"; + private Long clusterCode = 100L; @Before public void setUp() throws Exception { Mockito.when(k8sClientService.upsertNamespaceAndResourceToK8s(Mockito.any(K8sNamespace.class), Mockito.anyString())).thenReturn(null); - Mockito.when(k8sClientService.deleteNamespaceToK8s(Mockito.anyString(), Mockito.anyString())).thenReturn(null); + Mockito.when(k8sClientService.deleteNamespaceToK8s(Mockito.anyString(), Mockito.anyLong())).thenReturn(null); } @After @@ -101,10 +99,8 @@ public class K8SNamespaceServiceTest { @Test public void createK8sNamespace() { - Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.K8S_NAMESPACE, getLoginUser().getId(), null, baseServiceLogger)).thenReturn(true); - Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.K8S_NAMESPACE, null, 0, baseServiceLogger)).thenReturn(true); // namespace is null - Map result = k8sNamespaceService.createK8sNamespace(getLoginUser(), null, k8s, 10.0, 100); + Map result = k8sNamespaceService.createK8sNamespace(getLoginUser(), null, clusterCode, 10.0, 100); logger.info(result.toString()); Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, result.get(Constants.STATUS)); // k8s is null @@ -112,11 +108,12 @@ public class K8SNamespaceServiceTest { logger.info(result.toString()); Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, result.get(Constants.STATUS)); // correct - result = k8sNamespaceService.createK8sNamespace(getLoginUser(), namespace, k8s, 10.0, 100); + Mockito.when(clusterMapper.queryByClusterCode(Mockito.anyLong())).thenReturn(getCluster()); + result = k8sNamespaceService.createK8sNamespace(getLoginUser(), namespace, clusterCode, 10.0, 100); logger.info(result.toString()); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); //null limit cpu and mem - result = k8sNamespaceService.createK8sNamespace(getLoginUser(), namespace, k8s, null, null); + result = k8sNamespaceService.createK8sNamespace(getLoginUser(), namespace, clusterCode, null, null); logger.info(result.toString()); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } @@ -124,8 +121,7 @@ public class K8SNamespaceServiceTest { @Test public void updateK8sNamespace() { Mockito.when(k8sNamespaceMapper.selectById(1)).thenReturn(getNamespace()); - Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.K8S_NAMESPACE, getLoginUser().getId(), null, baseServiceLogger)).thenReturn(true); - Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.K8S_NAMESPACE, null, 0, baseServiceLogger)).thenReturn(true); + Map result = k8sNamespaceService.updateK8sNamespace(getLoginUser(), 1, null, null, null); logger.info(result.toString()); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); @@ -142,10 +138,10 @@ public class K8SNamespaceServiceTest { @Test public void verifyNamespaceK8s() { - Mockito.when(k8sNamespaceMapper.existNamespace(namespace, k8s)).thenReturn(true); + Mockito.when(k8sNamespaceMapper.existNamespace(namespace, clusterCode)).thenReturn(true); //namespace null - Result result = k8sNamespaceService.verifyNamespaceK8s(null, k8s); + Result result = k8sNamespaceService.verifyNamespaceK8s(null, clusterCode); logger.info(result.toString()); Assert.assertEquals(result.getCode().intValue(), Status.REQUEST_PARAMS_NOT_VALID_ERROR.getCode()); @@ -155,12 +151,12 @@ public class K8SNamespaceServiceTest { Assert.assertEquals(result.getCode().intValue(), Status.REQUEST_PARAMS_NOT_VALID_ERROR.getCode()); //exist - result = k8sNamespaceService.verifyNamespaceK8s(namespace, k8s); + result = k8sNamespaceService.verifyNamespaceK8s(namespace, clusterCode); logger.info(result.toString()); Assert.assertEquals(result.getCode().intValue(), Status.K8S_NAMESPACE_EXIST.getCode()); //not exist - result = k8sNamespaceService.verifyNamespaceK8s(namespace, "other k8s"); + result = k8sNamespaceService.verifyNamespaceK8s(namespace, 9999L); logger.info(result.toString()); Assert.assertEquals(result.getCode().intValue(), Status.SUCCESS.getCode()); } @@ -169,8 +165,7 @@ public class K8SNamespaceServiceTest { public void deleteNamespaceById() { Mockito.when(k8sNamespaceMapper.deleteById(Mockito.any())).thenReturn(1); Mockito.when(k8sNamespaceMapper.selectById(1)).thenReturn(getNamespace()); - Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.K8S_NAMESPACE, getLoginUser().getId(), null, baseServiceLogger)).thenReturn(true); - Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.K8S_NAMESPACE, null, 0, baseServiceLogger)).thenReturn(true); + Map result = k8sNamespaceService.deleteNamespaceById(getLoginUser(), 1); logger.info(result.toString()); Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); @@ -179,8 +174,7 @@ public class K8SNamespaceServiceTest { @Test public void testQueryAuthorizedNamespace() { Mockito.when(k8sNamespaceMapper.queryAuthedNamespaceListByUserId(2)).thenReturn(getNamespaceList()); - Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.K8S_NAMESPACE, getLoginUser().getId(), null, baseServiceLogger)).thenReturn(true); - Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.K8S_NAMESPACE, null, 0, baseServiceLogger)).thenReturn(true); + User loginUser = getLoginUser(); // test admin user @@ -203,8 +197,7 @@ public class K8SNamespaceServiceTest { public void testQueryUnAuthorizedNamespace() { Mockito.when(k8sNamespaceMapper.queryAuthedNamespaceListByUserId(2)).thenReturn(new ArrayList<>()); Mockito.when(k8sNamespaceMapper.selectList(Mockito.any())).thenReturn(getNamespaceList()); - Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.K8S_NAMESPACE, 0, null, baseServiceLogger)).thenReturn(true); - Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.K8S_NAMESPACE, null, 0, baseServiceLogger)).thenReturn(true); + // test admin user User loginUser = new User(); loginUser.setUserType(UserType.ADMIN_USER); @@ -235,7 +228,7 @@ public class K8SNamespaceServiceTest { private K8sNamespace getNamespace() { K8sNamespace k8sNamespace = new K8sNamespace(); k8sNamespace.setId(1); - k8sNamespace.setK8s(k8s); + k8sNamespace.setClusterCode(clusterCode); k8sNamespace.setNamespace(namespace); return k8sNamespace; } @@ -245,4 +238,14 @@ public class K8SNamespaceServiceTest { k8sNamespaceList.add(getNamespace()); return k8sNamespaceList; } + + private Cluster getCluster() { + Cluster cluster = new Cluster(); + cluster.setId(1); + cluster.setCode(1L); + cluster.setName("clusterName"); + cluster.setConfig("{}"); + cluster.setOperator(1); + return cluster; + } } \ No newline at end of file diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java index ea54e362cc..6f253d99a4 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java @@ -804,10 +804,10 @@ public final class Constants { * use for k8s */ public static final String NAMESPACE = "namespace"; - public static final String K8S = "k8s"; + public static final String CLUSTER = "cluster"; public static final String LIMITS_CPU = "limitsCpu"; public static final String LIMITS_MEMORY = "limitsMemory"; - public static final String K8S_LOCAL_TEST_CLUSTER = "ds_null_k8s"; + public static final Long K8S_LOCAL_TEST_CLUSTER_CODE = 0L; /** * schedule timezone diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8sNamespace.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8sNamespace.java index e6864a58bd..fde51dbebe 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8sNamespace.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8sNamespace.java @@ -32,6 +32,11 @@ public class K8sNamespace { @TableId(value = "id", type = IdType.AUTO) private Integer id; + /** + * cluster code + */ + private Long code; + /** * namespace name */ @@ -92,16 +97,16 @@ public class K8sNamespace { private Integer podReplicas = 0; /** - * online job + * cluster code */ - @TableField("online_job_num") - private Integer onlineJobNum = 0; + @TableField("cluster_code") + private Long clusterCode; /** * k8s name */ - @TableField("k8s") - private String k8s; + @TableField(exist = false) + private String clusterName; public Integer getId() { return id; @@ -175,20 +180,20 @@ public class K8sNamespace { this.podReplicas = podReplicas; } - public Integer getOnlineJobNum() { - return onlineJobNum; + public Long getClusterCode() { + return clusterCode; } - public void setOnlineJobNum(Integer onlineJobNum) { - this.onlineJobNum = onlineJobNum; + public void setClusterCode(Long clusterCode) { + this.clusterCode = clusterCode; } - public String getK8s() { - return k8s; + public String getClusterName() { + return clusterName; } - public void setK8s(String k8s) { - this.k8s = k8s; + public void setClusterName(String clusterName) { + this.clusterName = clusterName; } public Double getPodRequestCpu() { @@ -211,14 +216,14 @@ public class K8sNamespace { public String toString() { return "K8sNamespace{" + "id=" + id + + "code=" + code + ", namespace=" + namespace + ", limitsCpu=" + limitsCpu + ", limitsMemory=" + limitsMemory + - ", userId=" + userId + ", podRequestCpu=" + podRequestCpu + ", podRequestMemory=" + podRequestMemory + ", podReplicas=" + podReplicas + - ", k8s=" + k8s + + ", clusterCode=" + clusterCode + ", createTime=" + createTime + ", updateTime=" + updateTime + '}'; @@ -239,13 +244,21 @@ public class K8sNamespace { return true; } - return namespace.equals(k8sNamespace.namespace) && k8s.equals(k8sNamespace.k8s); + return namespace.equals(k8sNamespace.namespace) && clusterName.equals(k8sNamespace.clusterName); } @Override public int hashCode() { int result = id; - result = 31 * result + (k8s+namespace).hashCode(); + result = 31 * result + (clusterName + namespace).hashCode(); return result; } -} + + public Long getCode() { + return code; + } + + public void setCode(Long code) { + this.code = code; + } +} \ No newline at end of file diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.java index e8f80ebf3f..f89e7579e4 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.java @@ -43,11 +43,11 @@ public interface K8sNamespaceMapper extends BaseMapper { /** * check the target namespace exist * - * @param namespace namespace - * @param k8s k8s name + * @param namespace namespace + * @param clusterCode clusterCode * @return true if exist else return null */ - Boolean existNamespace(@Param("namespace") String namespace, @Param("k8s") String k8s); + Boolean existNamespace(@Param("namespace") String namespace, @Param("clusterCode") Long clusterCode); /** * query namespace except userId @@ -72,4 +72,12 @@ public interface K8sNamespaceMapper extends BaseMapper { * @return namespace list */ List queryNamespaceAvailable(@Param("userId") Integer userId); -} + + /** + * check the target namespace + * + * @param namespaceCode namespaceCode + * @return true if exist else return null + */ + K8sNamespace queryByNamespaceCode(@Param("clusterCode") Long namespaceCode); +} \ No newline at end of file diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml index ba32fc2b12..4acea799df 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml @@ -20,22 +20,26 @@ - id, namespace, k8s, user_id, limits_memory, limits_cpu, online_job_num, pod_replicas, pod_request_cpu, pod_request_memory, create_time, update_time + id, code, namespace, user_id, limits_memory, limits_cpu, pod_replicas, pod_request_cpu, pod_request_memory, cluster_code, create_time, update_time - ${alias}.id, ${alias}.namespace, ${alias}.k8s, ${alias}.user_id, ${alias}.limits_memory, ${alias}.limits_cpu, ${alias}.online_job_num, ${alias}.pod_replicas, ${alias}.pod_request_cpu, ${alias}.pod_request_memory, ${alias}.create_time, ${alias}.update_time + ${alias}.id, ${alias}.code, ${alias}.namespace, ${alias}.user_id, ${alias}.limits_memory, ${alias}.limits_cpu, ${alias}.pod_replicas, ${alias}.pod_request_cpu, ${alias}.pod_request_memory, ${alias}.cluster_code, ${alias}.create_time, ${alias}.update_time @@ -76,4 +80,10 @@ on b.id = a.namespace_id where b.id is not null - + + \ No newline at end of file diff --git a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql index 134d31644b..18e6efb61c 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql @@ -1907,35 +1907,34 @@ CREATE TABLE t_ds_k8s DROP TABLE IF EXISTS t_ds_k8s_namespace; CREATE TABLE t_ds_k8s_namespace ( id int(11) NOT NULL AUTO_INCREMENT , + code bigint(20) NOT NULL, limits_memory int(11) DEFAULT NULL, namespace varchar(100) DEFAULT NULL, - online_job_num int(11) DEFAULT NULL, user_id int(11) DEFAULT NULL, pod_replicas int(11) DEFAULT NULL, pod_request_cpu decimal(14,3) DEFAULT NULL, pod_request_memory int(11) DEFAULT NULL, limits_cpu decimal(14,3) DEFAULT NULL, - k8s varchar(100) DEFAULT NULL, + cluster_code bigint(20) NOT NULL, create_time datetime DEFAULT NULL , update_time datetime DEFAULT NULL , PRIMARY KEY (id) , - UNIQUE KEY k8s_namespace_unique (namespace,k8s) + UNIQUE KEY k8s_namespace_unique (namespace,cluster_code) ); - -- ---------------------------- -- Records of t_ds_k8s_namespace -- ---------------------------- INSERT INTO `t_ds_k8s_namespace` -(`id`,`limits_memory`,`namespace`,`online_job_num`,`user_id`,`pod_replicas`,`pod_request_cpu`,`pod_request_memory`,`limits_cpu`,`k8s`,`create_time`,`update_time`) -VALUES (1, 1000, 'flink_test', 99, 1, 1, 0.1, 1, NULL, 'ds_null_k8s', '2022-03-03 11:31:24.0', '2022-03-03 11:31:24.0'); +(`id`,`code`,`limits_memory`,`namespace`,`user_id`,`pod_replicas`,`pod_request_cpu`,`pod_request_memory`,`limits_cpu`,`cluster_code`,`create_time`,`update_time`) +VALUES (1, 990001, 1000, 'flink_test', 1, 1, 0.1, 1, 100, 0, '2022-03-03 11:31:24.0', '2022-03-03 11:31:24.0'); INSERT INTO `t_ds_k8s_namespace` -(`id`,`limits_memory`,`namespace`,`online_job_num`,`user_id`,`pod_replicas`,`pod_request_cpu`,`pod_request_memory`,`limits_cpu`,`k8s`,`create_time`,`update_time`) -VALUES (2, 500, 'spark_test', 90, 2,1,10000,1, NULL, 'ds_null_k8s', '2021-03-03 11:31:24.0', '2021-03-03 11:31:24.0'); +(`id`,`code`,`limits_memory`,`namespace`,`user_id`,`pod_replicas`,`pod_request_cpu`,`pod_request_memory`,`limits_cpu`,`cluster_code`,`create_time`,`update_time`) +VALUES (2, 990002, 500, 'spark_test', 2, 1, 10000, 1, 100, 0, '2021-03-03 11:31:24.0', '2021-03-03 11:31:24.0'); INSERT INTO `t_ds_k8s_namespace` -(`id`,`limits_memory`,`namespace`,`online_job_num`,`user_id`,`pod_replicas`,`pod_request_cpu`,`pod_request_memory`,`limits_cpu`,`k8s`,`create_time`,`update_time`) -VALUES (3, 200, 'auth_test', 68, 3,1,100,1, 10000, 'ds_null_k8s', '2020-03-03 11:31:24.0', '2020-03-03 11:31:24.0'); +(`id`,`code`,`limits_memory`,`namespace`,`user_id`,`pod_replicas`,`pod_request_cpu`,`pod_request_memory`,`limits_cpu`,`cluster_code`,`create_time`,`update_time`) +VALUES (3, 990003, 200, 'auth_test', 3, 1, 100, 1, 10000, 0, '2020-03-03 11:31:24.0', '2020-03-03 11:31:24.0'); -- ---------------------------- -- Table structure for t_ds_relation_namespace_user @@ -1990,4 +1989,4 @@ CREATE TABLE t_ds_cluster INSERT INTO `t_ds_cluster` (`id`,`code`,`name`,`config`,`description`,`operator`,`create_time`,`update_time`) -VALUES (100, 100, 'ds_null_k8s', '{"k8s":"ds_null_k8s"}', 'test', 1, '2021-03-03 11:31:24.0', '2021-03-03 11:31:24.0'); +VALUES (100, 0, 'ds_null_k8s', '{"k8s":"ds_null_k8s"}', 'test', 1, '2021-03-03 11:31:24.0', '2021-03-03 11:31:24.0'); diff --git a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql index 62ebe62038..714d32a121 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql @@ -1901,19 +1901,19 @@ CREATE TABLE `t_ds_k8s` ( DROP TABLE IF EXISTS `t_ds_k8s_namespace`; CREATE TABLE `t_ds_k8s_namespace` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `code` bigint(20) NOT NULL DEFAULT '0', `limits_memory` int(11) DEFAULT NULL, `namespace` varchar(100) DEFAULT NULL, - `online_job_num` int(11) DEFAULT NULL, `user_id` int(11) DEFAULT NULL, `pod_replicas` int(11) DEFAULT NULL, `pod_request_cpu` decimal(14,3) DEFAULT NULL, `pod_request_memory` int(11) DEFAULT NULL, `limits_cpu` decimal(14,3) DEFAULT NULL, - `k8s` varchar(100) DEFAULT NULL, + `cluster_code` bigint(20) NOT NULL DEFAULT '0', `create_time` datetime DEFAULT NULL COMMENT 'create time', `update_time` datetime DEFAULT NULL COMMENT 'update time', PRIMARY KEY (`id`), - UNIQUE KEY `k8s_namespace_unique` (`namespace`,`k8s`) + UNIQUE KEY `k8s_namespace_unique` (`namespace`,`cluster_code`) ) ENGINE= INNODB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8; -- ---------------------------- diff --git a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql index 148d04c2cd..27b5e80d89 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql @@ -1900,21 +1900,22 @@ CREATE TABLE t_ds_k8s ( DROP TABLE IF EXISTS t_ds_k8s_namespace; CREATE TABLE t_ds_k8s_namespace ( id serial NOT NULL, + code bigint NOT NULL, limits_memory int DEFAULT NULL , namespace varchar(100) DEFAULT NULL , - online_job_num int DEFAULT '0' , user_id int DEFAULT NULL, pod_replicas int DEFAULT NULL, pod_request_cpu NUMERIC(13,4) NULL, pod_request_memory int DEFAULT NULL, limits_cpu NUMERIC(13,4) NULL, - k8s varchar(100) DEFAULT NULL, + cluster_code bigint NOT NULL, create_time timestamp DEFAULT NULL , update_time timestamp DEFAULT NULL , PRIMARY KEY (id) , - CONSTRAINT k8s_namespace_unique UNIQUE (namespace,k8s) + CONSTRAINT k8s_namespace_unique UNIQUE (namespace,cluster_code) ); + -- -- Table structure for table t_ds_relation_namespace_user -- diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/mysql/dolphinscheduler_ddl.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/mysql/dolphinscheduler_ddl.sql index 081e12f1f8..f46f1c7e5e 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/mysql/dolphinscheduler_ddl.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/mysql/dolphinscheduler_ddl.sql @@ -266,19 +266,19 @@ CREATE TABLE `t_ds_k8s` ( DROP TABLE IF EXISTS `t_ds_k8s_namespace`; CREATE TABLE `t_ds_k8s_namespace` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `code` bigint(20) NOT NULL DEFAULT '0', `limits_memory` int(11) DEFAULT NULL, `namespace` varchar(100) DEFAULT NULL, - `online_job_num` int(11) DEFAULT NULL, `user_id` int(11) DEFAULT NULL, `pod_replicas` int(11) DEFAULT NULL, `pod_request_cpu` decimal(14,3) DEFAULT NULL, `pod_request_memory` int(11) DEFAULT NULL, `limits_cpu` decimal(14,3) DEFAULT NULL, - `k8s` varchar(100) DEFAULT NULL, + `cluster_code` bigint(20) NOT NULL DEFAULT '0', `create_time` datetime DEFAULT NULL COMMENT 'create time', `update_time` datetime DEFAULT NULL COMMENT 'update time', PRIMARY KEY (`id`), - UNIQUE KEY `k8s_namespace_unique` (`namespace`,`k8s`) + UNIQUE KEY `k8s_namespace_unique` (`namespace`,`cluster_code`) ) ENGINE= INNODB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8; -- ---------------------------- diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/postgresql/dolphinscheduler_ddl.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/postgresql/dolphinscheduler_ddl.sql index c00c7deadc..8712a6a1e0 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/postgresql/dolphinscheduler_ddl.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.0.0_schema/postgresql/dolphinscheduler_ddl.sql @@ -242,19 +242,19 @@ EXECUTE 'CREATE TABLE IF NOT EXISTS '|| quote_ident(v_schema) ||'."t_ds_k8s" ( EXECUTE 'CREATE TABLE IF NOT EXISTS '|| quote_ident(v_schema) ||'."t_ds_k8s_namespace" ( id serial NOT NULL, + code bigint NOT NULL, limits_memory int DEFAULT NULL , namespace varchar(100) DEFAULT NULL , - online_job_num int DEFAULT NULL, user_id int DEFAULT NULL, pod_replicas int DEFAULT NULL, pod_request_cpu NUMERIC(13,4) NULL, pod_request_memory int DEFAULT NULL, limits_cpu NUMERIC(13,4) NULL, - k8s varchar(100) DEFAULT NULL, + cluster_code bigint NOT NULL, create_time timestamp DEFAULT NULL , update_time timestamp DEFAULT NULL , PRIMARY KEY (id) , - CONSTRAINT k8s_namespace_unique UNIQUE (namespace,k8s) + CONSTRAINT k8s_namespace_unique UNIQUE (namespace,cluster_code) )'; EXECUTE 'CREATE TABLE IF NOT EXISTS '|| quote_ident(v_schema) ||'."t_ds_relation_namespace_user" ( diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapperTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapperTest.java index 75946f8aee..74b2887c63 100644 --- a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapperTest.java +++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapperTest.java @@ -23,7 +23,6 @@ import org.apache.dolphinscheduler.dao.entity.K8sNamespace; import java.util.Date; import java.util.List; -import org.apache.dolphinscheduler.dao.entity.User; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -46,13 +45,14 @@ public class K8sNamespaceMapperTest extends BaseDaoTest { private K8sNamespace insertOne() { //insertOne K8sNamespace k8sNamespace = new K8sNamespace(); + k8sNamespace.setCode(999L); k8sNamespace.setNamespace("testNamespace"); - k8sNamespace.setK8s("ds_null_k8s"); + k8sNamespace.setClusterCode(100L); + k8sNamespace.setClusterName("ds_null_k8s"); k8sNamespace.setLimitsCpu(100.0); k8sNamespace.setLimitsMemory(100); k8sNamespace.setCreateTime(new Date()); k8sNamespace.setUpdateTime(new Date()); - k8sNamespace.setId(1); k8sNamespaceMapper.insert(k8sNamespace); return k8sNamespace; } diff --git a/dolphinscheduler-ui/src/locales/en_US/security.ts b/dolphinscheduler-ui/src/locales/en_US/security.ts index cde8692d9b..2dbb66fe84 100644 --- a/dolphinscheduler-ui/src/locales/en_US/security.ts +++ b/dolphinscheduler-ui/src/locales/en_US/security.ts @@ -269,8 +269,6 @@ export default { k8s_namespace_tips: 'Please enter k8s namespace', k8s_cluster: 'K8S Cluster', k8s_cluster_tips: 'Please enter k8s cluster', - owner: 'Owner', - owner_tips: 'Please enter owner', limit_cpu: 'Limit CPU', limit_cpu_tips: 'Please enter limit CPU', limit_memory: 'Limit Memory', diff --git a/dolphinscheduler-ui/src/locales/zh_CN/security.ts b/dolphinscheduler-ui/src/locales/zh_CN/security.ts index c06129c25f..9135ba78e4 100644 --- a/dolphinscheduler-ui/src/locales/zh_CN/security.ts +++ b/dolphinscheduler-ui/src/locales/zh_CN/security.ts @@ -269,8 +269,6 @@ export default { k8s_namespace_tips: '请输入k8s命名空间', k8s_cluster: 'K8S集群', k8s_cluster_tips: '请输入k8s集群', - owner: '负责人', - owner_tips: '请输入负责人', limit_cpu: '最大CPU', limit_cpu_tips: '请输入最大CPU', limit_memory: '最大内存', diff --git a/dolphinscheduler-ui/src/service/modules/k8s-namespace/types.ts b/dolphinscheduler-ui/src/service/modules/k8s-namespace/types.ts index a29a1cf51a..7ceae5c86e 100644 --- a/dolphinscheduler-ui/src/service/modules/k8s-namespace/types.ts +++ b/dolphinscheduler-ui/src/service/modules/k8s-namespace/types.ts @@ -23,7 +23,7 @@ interface ListReq { interface K8SReq { namespace: string - k8s: string + clusterCode: string owner?: string tag?: string limitsCpu?: number | string @@ -49,4 +49,4 @@ interface NamespaceListRes { start: number } -export { ListReq, K8SReq, NamespaceItem, NamespaceListRes } +export { ListReq, K8SReq, NamespaceItem, NamespaceListRes } \ No newline at end of file diff --git a/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/k8s-namespace-modal.tsx b/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/k8s-namespace-modal.tsx index 4d7a1e6be2..9992f4353f 100644 --- a/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/k8s-namespace-modal.tsx +++ b/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/k8s-namespace-modal.tsx @@ -22,7 +22,8 @@ import { NFormItem, NInput, NInputGroup, - NInputGroupLabel + NInputGroupLabel, + NSelect } from 'naive-ui' import { useModal } from './use-modal' import { useI18n } from 'vue-i18n' @@ -45,13 +46,13 @@ const K8sNamespaceModal = defineComponent({ }, emits: ['cancelModal', 'confirmModal'], setup(props, ctx) { - const { variables, handleValidate } = useModal(props, ctx) + const { variables, handleValidate, getListData } = useModal(props, ctx) const { t } = useI18n() const cancelModal = () => { if (props.statusRef === 0) { variables.model.namespace = '' - variables.model.k8s = '' + variables.model.clusterCode = '' variables.model.limitsCpu = '' variables.model.limitsMemory = '' variables.model.userId = '' @@ -64,35 +65,42 @@ const K8sNamespaceModal = defineComponent({ } watch( - () => props.statusRef, - () => { - if (props.statusRef === 0) { - variables.model.namespace = '' - variables.model.k8s = '' - variables.model.limitsCpu = '' - variables.model.limitsMemory = '' - variables.model.userId = '' - } else { + () => props.showModalRef, + () => { + props.showModalRef && getListData() + } + ) + + watch( + () => props.statusRef, + () => { + if (props.statusRef === 0) { + variables.model.namespace = '' + variables.model.clusterCode = '' + variables.model.limitsCpu = '' + variables.model.limitsMemory = '' + variables.model.userId = '' + } else { + variables.model.id = props.row.id + variables.model.namespace = props.row.namespace + variables.model.clusterCode = props.row.clusterCode + variables.model.limitsCpu = props.row.limitsCpu + '' + variables.model.limitsMemory = props.row.limitsMemory + '' + variables.model.userId = props.row.userId + } + } + ) + + watch( + () => props.row, + () => { variables.model.id = props.row.id variables.model.namespace = props.row.namespace - variables.model.k8s = props.row.k8s + variables.model.clusterCode = props.row.clusterCode variables.model.limitsCpu = props.row.limitsCpu + '' variables.model.limitsMemory = props.row.limitsMemory + '' variables.model.userId = props.row.userId } - } - ) - - watch( - () => props.row, - () => { - variables.model.id = props.row.id - variables.model.namespace = props.row.namespace - variables.model.k8s = props.row.k8s - variables.model.limitsCpu = props.row.limitsCpu + '' - variables.model.limitsMemory = props.row.limitsMemory + '' - variables.model.userId = props.row.userId - } ) return { t, ...toRefs(variables), cancelModal, confirmModal } @@ -100,89 +108,80 @@ const K8sNamespaceModal = defineComponent({ render() { const { t } = this return ( -
- - {{ - default: () => ( - - - - - - - - - - - CORE - - - - - - GB - - - - - - - ) - }} - -
+
+ + {{ + default: () => ( + + + + + + + + + + + CORE + + + + + + GB + + + + ) + }} + +
) } }) -export default K8sNamespaceModal +export default K8sNamespaceModal \ No newline at end of file diff --git a/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/use-modal.ts b/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/use-modal.ts index 9bebe8ea6d..92248c7175 100644 --- a/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/use-modal.ts +++ b/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/components/use-modal.ts @@ -22,10 +22,12 @@ import { createK8sNamespace, updateK8sNamespace } from '@/service/modules/k8s-namespace' +import { queryAllClusterList } from '@/service/modules/cluster' +import { useAsyncState } from '@vueuse/core' export function useModal( - props: any, - ctx: SetupContext<('cancelModal' | 'confirmModal')[]> + props: any, + ctx: SetupContext<('cancelModal' | 'confirmModal')[]> ) { const { t } = useI18n() @@ -34,10 +36,11 @@ export function useModal( model: { id: ref(-1), namespace: ref(''), - k8s: ref(''), + clusterCode: ref(''), userId: ref(''), limitsCpu: ref(''), - limitsMemory: ref('') + limitsMemory: ref(''), + clusterOptions: [] }, saving: false, rules: { @@ -50,11 +53,11 @@ export function useModal( } } }, - k8s: { + clusterCode: { required: true, trigger: ['input', 'blur'], validator() { - if (variables.model.k8s === '') { + if (variables.model.clusterCode === '') { return new Error(t('security.k8s_namespace.k8s_cluster_tips')) } } @@ -70,19 +73,43 @@ export function useModal( try { statusRef === 0 - ? await submitK8SNamespaceModal() - : await updateK8SNamespaceModal() + ? await submitK8SNamespaceModal() + : await updateK8SNamespaceModal() variables.saving = false } catch (err) { variables.saving = false } } + const getListData = () => { + const { state } = useAsyncState( + queryAllClusterList().then((res: any) => { + variables.model.clusterOptions = res + .filter((item: any) => { + if (item.config) { + const k8s = JSON.parse(item.config).k8s + return !!k8s + } + return false + }) + .map((item: any) => { + return { + label: item.name, + value: item.code + } + }) + }), + {} + ) + + return state + } + const submitK8SNamespaceModal = () => { verifyNamespaceK8s(variables.model).then(() => { createK8sNamespace(variables.model).then(() => { variables.model.namespace = '' - variables.model.k8s = '' + variables.model.clusterCode = '' variables.model.limitsCpu = '' variables.model.limitsMemory = '' variables.model.userId = '' @@ -93,14 +120,15 @@ export function useModal( const updateK8SNamespaceModal = () => { updateK8sNamespace(variables.model, variables.model.id).then( - (ignored: any) => { - ctx.emit('confirmModal', props.showModalRef) - } + (ignored: any) => { + ctx.emit('confirmModal', props.showModalRef) + } ) } return { variables, - handleValidate + handleValidate, + getListData } -} +} \ No newline at end of file diff --git a/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/use-table.ts b/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/use-table.ts index 9a857b27d9..b1ddb82507 100644 --- a/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/use-table.ts +++ b/dolphinscheduler-ui/src/views/security/k8s-namespace-manage/use-table.ts @@ -50,9 +50,9 @@ export function useTable() { getTableData({ pageSize: variables.pageSize, pageNo: - variables.tableData.length === 1 && variables.page > 1 - ? variables.page - 1 - : variables.page, + variables.tableData.length === 1 && variables.page > 1 + ? variables.page - 1 + : variables.page, searchVal: variables.searchVal }) }) @@ -73,14 +73,9 @@ export function useTable() { }, { title: t('security.k8s_namespace.k8s_cluster'), - key: 'k8s', + key: 'clusterName', ...COLUMN_WIDTH_CONFIG['name'] }, - { - title: t('security.k8s_namespace.owner'), - key: 'userId', - ...COLUMN_WIDTH_CONFIG['userName'] - }, { title: t('security.k8s_namespace.limit_cpu'), key: 'limitsCpu', @@ -109,61 +104,61 @@ export function useTable() { return h(NSpace, null, { default: () => [ h( - NTooltip, - {}, - { - trigger: () => - h( - NButton, - { - circle: true, - type: 'info', - size: 'small', - onClick: () => { - handleEdit(row) - } - }, - { - icon: () => - h(NIcon, null, { default: () => h(EditOutlined) }) - } - ), - default: () => t('security.k8s_namespace.edit') - } - ), - h( - NPopconfirm, - { - onPositiveClick: () => { - handleDelete(row) - } - }, - { - trigger: () => - h( - NTooltip, - {}, - { - trigger: () => - h( + NTooltip, + {}, + { + trigger: () => + h( NButton, { circle: true, - type: 'error', - size: 'small' + type: 'info', + size: 'small', + onClick: () => { + handleEdit(row) + } }, { icon: () => - h(NIcon, null, { - default: () => h(DeleteOutlined) - }) + h(NIcon, null, { default: () => h(EditOutlined) }) } - ), - default: () => t('security.k8s_namespace.delete') - } - ), - default: () => t('security.k8s_namespace.delete_confirm') - } + ), + default: () => t('security.k8s_namespace.edit') + } + ), + h( + NPopconfirm, + { + onPositiveClick: () => { + handleDelete(row) + } + }, + { + trigger: () => + h( + NTooltip, + {}, + { + trigger: () => + h( + NButton, + { + circle: true, + type: 'error', + size: 'small' + }, + { + icon: () => + h(NIcon, null, { + default: () => h(DeleteOutlined) + }) + } + ), + default: () => t('security.k8s_namespace.delete') + } + ), + default: () => t('security.k8s_namespace.delete_confirm') + } ) ] }) @@ -193,24 +188,24 @@ export function useTable() { if (variables.loadingRef) return variables.loadingRef = true const { state } = useAsyncState( - queryNamespaceListPaging({ ...params }).then((res: NamespaceListRes) => { - variables.tableData = res.totalList.map((item, unused) => { - item.createTime = format( - parseTime(item.createTime), - 'yyyy-MM-dd HH:mm:ss' - ) - item.updateTime = format( - parseTime(item.updateTime), - 'yyyy-MM-dd HH:mm:ss' - ) - return { - ...item - } - }) as any - variables.totalPage = res.totalPage - variables.loadingRef = false - }), - {} + queryNamespaceListPaging({ ...params }).then((res: NamespaceListRes) => { + variables.tableData = res.totalList.map((item, unused) => { + item.createTime = format( + parseTime(item.createTime), + 'yyyy-MM-dd HH:mm:ss' + ) + item.updateTime = format( + parseTime(item.updateTime), + 'yyyy-MM-dd HH:mm:ss' + ) + return { + ...item + } + }) as any + variables.totalPage = res.totalPage + variables.loadingRef = false + }), + {} ) return state @@ -221,4 +216,4 @@ export function useTable() { getTableData, createColumns } -} +} \ No newline at end of file