diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java index 667016f5b8a8..c79cba095000 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java @@ -105,6 +105,10 @@ public void testStartWorkflowInstance() { projectCode = (long) ((LinkedHashMap) ((List) queryAllProjectListResponse .getBody().getData()).get(0)).get("code"); + HttpResponse assignWorkerGroupsResponse = + projectPage.assignWorkerGroups(loginUser, projectCode, new String[]{"default"}); + Assertions.assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + // upload test workflow definition json ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("workflow-json/test.json").getFile()); diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/SchedulerAPITest.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/SchedulerAPITest.java index 2919b0a66f08..a44a416f7b4e 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/SchedulerAPITest.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/SchedulerAPITest.java @@ -98,6 +98,11 @@ public void testCreateSchedule() { projectCode = (long) ((LinkedHashMap) ((List) queryAllProjectListResponse .getBody().getData()).get(0)).get("code"); + + String[] workerGroups = {"default"}; + HttpResponse assignWorkerGroupsResponse = projectPage.assignWorkerGroups(loginUser, projectCode, workerGroups); + Assertions.assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("workflow-json/test.json").getFile()); workflowDefinitionPage.createWorkflowDefinition(loginUser, projectCode, file, workflowDefinitionName); diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowDefinitionAPITest.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowDefinitionAPITest.java index b58e268e6ca0..a05782c946d1 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowDefinitionAPITest.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowDefinitionAPITest.java @@ -94,6 +94,11 @@ public void testCreateWorkflowDefinition() { projectCode = (long) ((LinkedHashMap) ((List) queryAllProjectListResponse .getBody().getData()).get(0)).get("code"); + + HttpResponse assignWorkerGroupsResponse = + projectPage.assignWorkerGroups(loginUser, projectCode, new String[]{"default"}); + Assertions.assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("workflow-json/test.json").getFile()); HttpResponse createWorkflowDefinitionResponse = workflowDefinitionPage diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowInstanceAPITest.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowInstanceAPITest.java index a13019df8f19..45ec0e6314aa 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowInstanceAPITest.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/WorkflowInstanceAPITest.java @@ -116,6 +116,10 @@ public void testQueryWorkflowInstancesByWorkflowInstanceId() { projectCode = (long) ((LinkedHashMap) ((List) queryAllProjectListResponse .getBody().getData()).get(0)).get("code"); + HttpResponse assignWorkerGroupsResponse = + projectPage.assignWorkerGroups(loginUser, projectCode, new String[]{"default"}); + assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + // upload test workflow definition json ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("workflow-json/test.json").getFile()); diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/DependentTaskAPITest.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/DependentTaskAPITest.java index 9d15e4c92bc4..bd4f45e6754d 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/DependentTaskAPITest.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/DependentTaskAPITest.java @@ -122,6 +122,10 @@ public void testCreateUpstreamWorkflow() throws Exception { Assertions.assertNotEquals(0, projectCode, "project should be found by name"); log.info("project code: {}", projectCode); + HttpResponse assignWorkerGroupsResponse = + projectPage.assignWorkerGroups(loginUser, projectCode, new String[]{"default"}); + Assertions.assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + // create upstream workflow definition (shell task: echo hello) ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("workflow-json/test.json").getFile()); diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/EmrServerlessTaskAPITest.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/EmrServerlessTaskAPITest.java index 655f4026d856..187bc32a2af5 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/EmrServerlessTaskAPITest.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/EmrServerlessTaskAPITest.java @@ -106,6 +106,10 @@ public void testEmrServerlessSuccessWorkflowInstance() throws Exception { projectCode = (long) ((LinkedHashMap) ((List) queryAllProjectListResponse .getBody().getData()).get(0)).get("code"); + HttpResponse assignWorkerGroupsResponse = + projectPage.assignWorkerGroups(loginUser, projectCode, new String[]{"default"}); + Assertions.assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + // upload test workflow definition json ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/GrpcTaskAPITest.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/GrpcTaskAPITest.java index df7ceb2fa178..5b3c6dbae7ee 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/GrpcTaskAPITest.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/tasks/GrpcTaskAPITest.java @@ -103,6 +103,10 @@ public void testGrpcFailedWorkflowInstance() { projectCode = (long) ((LinkedHashMap) ((List) queryAllProjectListResponse .getBody().getData()).get(0)).get("code"); + HttpResponse assignWorkerGroupsResponse = + projectPage.assignWorkerGroups(loginUser, projectCode, new String[]{"default"}); + Assertions.assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + // upload test workflow definition json ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("workflow-json/task-grpc/grpcFailedWorkflow.json").getFile()); @@ -153,6 +157,10 @@ public void testGrpcSuccessWorkflowInstance() { projectCode = (long) ((LinkedHashMap) ((List) queryAllProjectListResponse .getBody().getData()).get(0)).get("code"); + HttpResponse assignWorkerGroupsResponse = + projectPage.assignWorkerGroups(loginUser, projectCode, new String[]{"default"}); + Assertions.assertTrue(assignWorkerGroupsResponse.getBody().getSuccess()); + // upload test workflow definition json ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource("workflow-json/task-grpc/grpcSuccessWorkflow.json").getFile()); diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/pages/project/ProjectPage.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/pages/project/ProjectPage.java index 3a9aaa079db5..3778a7bc2448 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/pages/project/ProjectPage.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/pages/project/ProjectPage.java @@ -177,4 +177,17 @@ public HttpResponse deleteProject(User loginUser, Long code) { String url = String.format("/projects/%d", code); return requestClient.delete(url, headers, params); } + + public HttpResponse assignWorkerGroups(User loginUser, long projectCode, String[] workerGroups) { + Map params = new HashMap<>(); + params.put("loginUser", loginUser); + params.put("workerGroups", workerGroups); + Map headers = new HashMap<>(); + headers.put(Constants.SESSION_ID_KEY, sessionId); + + RequestClient requestClient = new RequestClient(); + String url = String.format("/projects/%d/worker-group", projectCode); + return requestClient.post(url, headers, params); + } + } diff --git a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/utils/RequestClient.java b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/utils/RequestClient.java index 37faa358ea9f..ee8fd0988cfd 100644 --- a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/utils/RequestClient.java +++ b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/utils/RequestClient.java @@ -21,20 +21,12 @@ import org.apache.dolphinscheduler.api.test.entity.HttpResponse; import org.apache.dolphinscheduler.api.test.entity.HttpResponseBody; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicHeader; - -import java.io.File; -import java.nio.file.Files; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -import java.util.Objects; +import java.util.SortedMap; +import java.util.TreeMap; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -95,20 +87,62 @@ public HttpResponse get(String url, Map headers, Map params) { - StringBuilder sb = new StringBuilder(Constants.QUESTION_MARK); - if (!params.isEmpty()) { - for (Map.Entry item : params.entrySet()) { - Object value = item.getValue(); - if (Objects.nonNull(value)) { - sb.append(Constants.AND_MARK); - sb.append(item.getKey()); - sb.append(Constants.EQUAL_MARK); - sb.append(value); + return getParams(params, true); + } + + public static String getParams(Map params, boolean includeQuestionMark) { + if (params == null || params.isEmpty()) { + return ""; + } + + if (!(params instanceof SortedMap)) { + params = new TreeMap<>(params); + } + + StringBuilder sb = new StringBuilder(params.size() * 16); + boolean isFirst = true; + + for (Map.Entry entry : params.entrySet()) { + Object value = entry.getValue(); + if (value == null) { + continue; + } + + String key = entry.getKey(); + + if (value.getClass().isArray()) { + int length = java.lang.reflect.Array.getLength(value); + for (int i = 0; i < length; i++) { + Object item = java.lang.reflect.Array.get(value, i); + if (item != null) { + appendParam(sb, isFirst, key, item.toString(), includeQuestionMark); + isFirst = false; + } } + } else { + appendParam(sb, isFirst, key, value.toString(), includeQuestionMark); + isFirst = false; + } + } + + return sb.toString(); + } + + private static void appendParam(StringBuilder sb, boolean isFirst, String key, String value, + boolean includeQuestionMark) { + if (isFirst) { + if (includeQuestionMark) { + sb.append(Constants.QUESTION_MARK); } - return sb.toString(); } else { - return ""; + sb.append(Constants.AND_MARK); + } + try { + sb.append(URLEncoder.encode(key, StandardCharsets.UTF_8.name())) + .append(Constants.EQUAL_MARK) + .append(URLEncoder.encode(value, StandardCharsets.UTF_8.name())); + } catch (Exception e) { + sb.append(key).append(Constants.EQUAL_MARK).append(value); } } @@ -121,7 +155,8 @@ public HttpResponse post(String url, Map headers, Map headers, Map headers, Map headers, Map params, - File file) { - try { - Headers headersBuilder = Headers.of(headers); - MultipartEntityBuilder builder = MultipartEntityBuilder.create(); - builder.addTextBody("json", getParams(params), ContentType.MULTIPART_FORM_DATA); - builder.addBinaryBody( - "file", - Files.newInputStream(file.toPath()), - ContentType.APPLICATION_OCTET_STREAM, - file.getName()); - HttpEntity multipart = builder.build(); - String requestUrl = String.format("%s%s", Constants.DOLPHINSCHEDULER_API_URL, url); - log.info("POST request to {}, Headers: {}, Params: {}", requestUrl, headersBuilder, params); - HttpPost httpPost = new HttpPost(requestUrl); - for (Map.Entry header : headers.entrySet()) { - httpPost.setHeader(new BasicHeader(header.getKey(), header.getValue())); - } - httpPost.setEntity(multipart); - CloseableHttpClient client = HttpClients.createDefault(); - return client.execute(httpPost); - } catch (Exception e) { - log.error("error", e); - } - return null; - } - @SneakyThrows public HttpResponse delete(String url, Map headers, Map params) { if (headers == null) { diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/ProjectPreferencesDTO.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/ProjectPreferencesDTO.java new file mode 100644 index 000000000000..c6f7f6cdd73d --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/ProjectPreferencesDTO.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.dto; + +import lombok.Data; + +@Data +public class ProjectPreferencesDTO { + + private String taskPriority; + + private String workerGroup; + + private Long environmentCode; + + private Integer failRetryTimes; + + private Integer failRetryInterval; + + private Integer cpuQuota; + + private Integer memoryMax; + + private Boolean timeoutFlag; + + private String[] timeoutNotifyStrategy; + + private Integer timeout; + + private String warningType; + + private String tenantCode; + + private Integer warningGroupId; +} 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 b47a9b108921..a69e38073fff 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 @@ -583,6 +583,9 @@ public enum Status { USED_WORKER_GROUP_EXISTS(1402004, "You can not reassign worker groups to the project, cause these worker groups {0} are already used.", "Worker组{0}被项目中任务或定时引用,无法重新分配"), + WORKER_GROUP_NOT_ASSIGNED_TO_PROJECT(1402005, + "Worker group [{0}] is not assigned to the project.", + "Worker组[{0}]未分配给项目"), CREATE_WORKFLOW_LINEAGE_ERROR(1403001, "create workflow lineage error", "创建工作流血缘错误"), UPDATE_WORKFLOW_LINEAGE_ERROR(1403002, "update workflow lineage error", "更新工作流血缘错误"), DELETE_WORKFLOW_LINEAGE_ERROR(1403003, "delete workflow lineage error", "删除工作流血缘错误"), diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationService.java index 19f18d9a3bc3..fc04aec005db 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationService.java @@ -22,6 +22,7 @@ import org.apache.dolphinscheduler.dao.entity.User; import java.util.List; +import java.util.Set; public interface ProjectWorkerGroupRelationService { @@ -43,4 +44,22 @@ public interface ProjectWorkerGroupRelationService { */ List queryAssignedWorkerGroupsByProject(User loginUser, Long projectCode); + /** + * check if worker group is assigned to project + * + * @param projectCode project code + * @param workerGroup worker group name + * @return true if worker group is assigned to project + */ + boolean isWorkerGroupAssignedToProject(Long projectCode, String workerGroup); + + /** + * get all assigned worker group names for a project + * This includes both directly assigned worker groups and worker groups used by tasks/schedules + * + * @param projectCode project code + * @return set of all assigned worker group names + */ + Set getAllAssignedWorkerGroupNames(Long projectCode); + } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectPreferenceServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectPreferenceServiceImpl.java index 299af216c2e4..164df5ade502 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectPreferenceServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectPreferenceServiceImpl.java @@ -19,17 +19,24 @@ import static org.apache.dolphinscheduler.api.constants.ApiFuncIdentificationConstant.PROJECT; +import org.apache.dolphinscheduler.api.dto.ProjectPreferencesDTO; import org.apache.dolphinscheduler.api.enums.Status; +import org.apache.dolphinscheduler.api.exceptions.ServiceException; import org.apache.dolphinscheduler.api.service.ProjectPreferenceService; import org.apache.dolphinscheduler.api.service.ProjectService; import org.apache.dolphinscheduler.api.utils.Result; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidationContext; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidator; import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils; +import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.dao.entity.Project; import org.apache.dolphinscheduler.dao.entity.ProjectPreference; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.dao.mapper.ProjectPreferenceMapper; import org.apache.dolphinscheduler.dao.repository.ProjectDao; +import org.apache.commons.lang3.StringUtils; + import java.util.Date; import java.util.Objects; @@ -55,6 +62,9 @@ public class ProjectPreferenceServiceImpl extends BaseServiceImpl @Autowired private ProjectDao projectDao; + @Autowired + private WorkerGroupValidator workerGroupValidator; + @Override public Result updateProjectPreference(User loginUser, long projectCode, String preferences) { Result result = new Result(); @@ -67,6 +77,27 @@ public Result updateProjectPreference(User loginUser, long projectCode, String p .selectOne(new QueryWrapper().lambda().eq(ProjectPreference::getProjectCode, projectCode)); + if (StringUtils.isNotEmpty(preferences)) { + try { + ProjectPreferencesDTO preferencesDTO = JSONUtils.parseObject(preferences, ProjectPreferencesDTO.class); + if (preferencesDTO != null && StringUtils.isNotEmpty(preferencesDTO.getWorkerGroup())) { + WorkerGroupValidationContext workerGroupContext = WorkerGroupValidationContext.builder() + .workerGroup(preferencesDTO.getWorkerGroup()) + .projectCode(projectCode) + .build(); + try { + workerGroupValidator.validate(workerGroupContext); + } catch (ServiceException e) { + putMsg(result, Status.WORKER_GROUP_NOT_ASSIGNED_TO_PROJECT, preferencesDTO.getWorkerGroup()); + return result; + } + } + } catch (Exception e) { + log.warn("Failed to parse preferences JSON: {}", preferences, e); + throw new ServiceException(Status.UPDATE_PROJECT_PREFERENCE_ERROR); + } + } + Date now = new Date(); if (Objects.isNull(projectPreference)) { projectPreference = new ProjectPreference(); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectWorkerGroupRelationServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectWorkerGroupRelationServiceImpl.java index a43a1efd5709..d66295e59234 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectWorkerGroupRelationServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProjectWorkerGroupRelationServiceImpl.java @@ -208,6 +208,22 @@ public List queryAssignedWorkerGroupsByProject(User loginUse }).distinct().collect(Collectors.toList()); } + @Override + public Set getAllAssignedWorkerGroupNames(Long projectCode) { + Project project = projectDao.queryByCode(projectCode); + Set assignedWorkerGroups = new TreeSet<>(); + + if (project != null) { + assignedWorkerGroups.addAll(getAllUsedWorkerGroups(project)); + } + + Set directlyAssignedGroups = + projectWorkerGroupDao.queryAssignedWorkerGroupNamesByProjectCode(projectCode); + assignedWorkerGroups.addAll(directlyAssignedGroups); + + return assignedWorkerGroups; + } + private Set getAllUsedWorkerGroups(Project project) { Set usedWorkerGroups = new TreeSet<>(); // query all worker groups that tasks depend on @@ -226,4 +242,12 @@ private Set getAllUsedWorkerGroups(Project project) { return usedWorkerGroups; } + @Override + public boolean isWorkerGroupAssignedToProject(Long projectCode, String workerGroup) { + if (StringUtils.isEmpty(workerGroup)) { + return false; + } + return getAllAssignedWorkerGroupNames(projectCode).contains(workerGroup); + } + } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java index 12df89e9fccf..68f1ce73c79e 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java @@ -29,6 +29,8 @@ import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.validator.TenantExistValidator; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidationContext; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidator; import org.apache.dolphinscheduler.api.vo.ScheduleVO; import org.apache.dolphinscheduler.common.constants.Constants; import org.apache.dolphinscheduler.common.enums.FailureStrategy; @@ -97,6 +99,9 @@ public class SchedulerServiceImpl extends BaseServiceImpl implements SchedulerSe @Autowired private TenantExistValidator tenantExistValidator; + @Autowired + private WorkerGroupValidator workerGroupValidator; + /** * save schedule * @@ -182,6 +187,12 @@ public Schedule insertSchedule(User loginUser, scheduleObj.setUserName(loginUser.getUserName()); scheduleObj.setReleaseState(ReleaseState.OFFLINE); scheduleObj.setWorkflowInstancePriority(workflowInstancePriority); + + WorkerGroupValidationContext workerGroupContext = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(projectCode) + .build(); + workerGroupValidator.validate(workerGroupContext); scheduleObj.setWorkerGroup(workerGroup); scheduleObj.setEnvironmentCode(environmentCode); scheduleDao.insert(scheduleObj); @@ -570,6 +581,11 @@ private Schedule updateSchedule(Schedule schedule, WorkflowDefinition workflowDe schedule.setFailureStrategy(failureStrategy); } + WorkerGroupValidationContext workerGroupContext = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(workflowDefinition.getProjectCode()) + .build(); + workerGroupValidator.validate(workerGroupContext); schedule.setWorkerGroup(workerGroup); schedule.setEnvironmentCode(environmentCode); schedule.setUpdateTime(now); diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java index fecf8ec40641..b798e3ed12b4 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java @@ -51,6 +51,7 @@ import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.validator.GlobalParamsValidator; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidator; import org.apache.dolphinscheduler.common.constants.Constants; import org.apache.dolphinscheduler.common.enums.ReleaseState; import org.apache.dolphinscheduler.common.enums.UserType; @@ -209,6 +210,9 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl implements Wo @Autowired private GlobalParamsValidator globalParamsValidator; + @Autowired + private WorkerGroupValidator workerGroupValidator; + /** * create workflow definition * @@ -256,6 +260,10 @@ public WorkflowDefinition createWorkflowDefinition(User loginUser, globalParamsValidator.validate(globalParams); List taskDefinitionLogs = generateTaskDefinitionList(taskDefinitionJson); + + // Validate worker groups in task definitions + validateTaskWorkerGroups(projectCode, taskDefinitionLogs); + List taskRelationList = generateTaskRelationList(taskRelationJson, taskDefinitionLogs); long workflowDefinitionCode = CodeGenerateUtils.genCode(); @@ -381,6 +389,21 @@ private List generateTaskDefinitionList(String taskDefinition } } + /** + * Validate worker groups in task definitions + */ + private void validateTaskWorkerGroups(long projectCode, List taskDefinitionLogs) { + if (CollectionUtils.isEmpty(taskDefinitionLogs)) { + return; + } + + List workerGroups = taskDefinitionLogs.stream() + .map(TaskDefinitionLog::getWorkerGroup) + .collect(Collectors.toList()); + + workerGroupValidator.validate(workerGroups, projectCode); + } + private List generateTaskRelationList(String taskRelationJson, List taskDefinitionLogs) { try { @@ -626,6 +649,10 @@ public WorkflowDefinition updateWorkflowDefinition(User loginUser, globalParamsValidator.validate(globalParams); List taskDefinitionLogs = generateTaskDefinitionList(taskDefinitionJson); + + // Validate worker groups in task definitions + validateTaskWorkerGroups(projectCode, taskDefinitionLogs); + List taskRelationList = generateTaskRelationList(taskRelationJson, taskDefinitionLogs); WorkflowDefinition workflowDefinition = workflowDefinitionDao.queryByCode(code).orElse(null); @@ -1636,7 +1663,6 @@ public void switchWorkflowDefinitionVersion(User loginUser, long projectCode, lo * * @param srcProjectCode srcProjectCode * @param targetProjectCode targetProjectCode - * @param result result * @param failedWorkflowList failedWorkflowList * @param isCopy isCopy */ diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidationContext.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidationContext.java new file mode 100644 index 000000000000..0831019d950c --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidationContext.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.validator; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkerGroupValidationContext { + + private String workerGroup; + + private long projectCode; + +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidator.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidator.java new file mode 100644 index 000000000000..452b32ea2bda --- /dev/null +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidator.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.validator; + +import org.apache.dolphinscheduler.api.enums.Status; +import org.apache.dolphinscheduler.api.exceptions.ServiceException; +import org.apache.dolphinscheduler.api.service.ProjectWorkerGroupRelationService; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * Validator for workerGroup validation + * Checks if the workerGroup is assigned to the project + */ +@Slf4j +@Component +public class WorkerGroupValidator implements IValidator { + + @Autowired + private ProjectWorkerGroupRelationService projectWorkerGroupRelationService; + + @Override + public void validate(final WorkerGroupValidationContext context) { + String workerGroup = context.getWorkerGroup(); + long projectCode = context.getProjectCode(); + + if (StringUtils.isEmpty(workerGroup)) { + log.warn("Worker group is empty or null for project {}", projectCode); + throw new ServiceException(Status.WORKER_GROUP_NOT_ASSIGNED_TO_PROJECT, workerGroup); + } + + Set assignedWorkerGroupNames = + projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(projectCode); + + if (assignedWorkerGroupNames == null || !assignedWorkerGroupNames.contains(workerGroup)) { + log.warn("Worker group {} is not assigned to project {}", workerGroup, projectCode); + throw new ServiceException(Status.WORKER_GROUP_NOT_ASSIGNED_TO_PROJECT, workerGroup); + } + } + + /** + * Validate a list of workerGroups are assigned to the project + * This method queries the assigned workerGroups once and then checks all workerGroups against it + * + * @param workerGroups the list of workerGroups to validate + * @param projectCode the project code + */ + public void validate(final List workerGroups, final long projectCode) { + if (CollectionUtils.isEmpty(workerGroups)) { + return; + } + + List distinctWorkerGroups = workerGroups.stream() + .distinct() + .collect(Collectors.toList()); + + Set assignedWorkerGroupNames = projectWorkerGroupRelationService + .getAllAssignedWorkerGroupNames(projectCode); + + if (assignedWorkerGroupNames == null) { + assignedWorkerGroupNames = new java.util.HashSet<>(); + } + + Set finalAssignedWorkerGroupNames = assignedWorkerGroupNames; + List unassignedWorkerGroups = distinctWorkerGroups.stream() + .filter(wg -> StringUtils.isEmpty(wg) || !finalAssignedWorkerGroupNames.contains(wg)) + .collect(Collectors.toList()); + + if (!unassignedWorkerGroups.isEmpty()) { + log.warn("Worker groups {} are not assigned to project {}", unassignedWorkerGroups, projectCode); + throw new ServiceException(Status.WORKER_GROUP_NOT_ASSIGNED_TO_PROJECT, + String.join(",", unassignedWorkerGroups)); + } + } +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/workflow/TriggerWorkflowDTOValidator.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/workflow/TriggerWorkflowDTOValidator.java index 4837beec2a49..cbd523c941fe 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/workflow/TriggerWorkflowDTOValidator.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/workflow/TriggerWorkflowDTOValidator.java @@ -20,6 +20,8 @@ import org.apache.dolphinscheduler.api.validator.IValidator; import org.apache.dolphinscheduler.api.validator.StartParamListValidator; import org.apache.dolphinscheduler.api.validator.TenantExistValidator; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidationContext; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidator; import org.apache.dolphinscheduler.common.enums.CommandType; import org.apache.dolphinscheduler.common.enums.ReleaseState; @@ -35,10 +37,14 @@ public class TriggerWorkflowDTOValidator implements IValidator projectPreferenceService.updateProjectPreference(loginUser, projectCode, "value")); + // no permission + Mockito.doThrow(new ServiceException(Status.USER_NO_WRITE_PROJECT_PERM)) + .when(projectService).checkHasProjectWritePermissionThrowException(Mockito.any(), Mockito.any()); + Assertions.assertThrows(ServiceException.class, + () -> projectPreferenceService.updateProjectPreference(loginUser, projectCode, VALID_PREFERENCES)); + // when preference exists in project Mockito.when(projectPreferenceMapper.selectOne(Mockito.any())).thenReturn(null); Mockito.when(projectDao.queryByCode(projectCode)).thenReturn(getProject(projectCode)); @@ -77,12 +88,12 @@ public void testUpdateProjectPreference() { Mockito.when(projectPreferenceMapper.insert(Mockito.any())).thenReturn(1); - Result result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, "value"); + Result result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, VALID_PREFERENCES); Assertions.assertEquals(Status.SUCCESS.getCode(), result.getCode()); // database operatation fail Mockito.when(projectPreferenceMapper.insert(Mockito.any())).thenReturn(-1); - result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, "value"); + result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, VALID_PREFERENCES); Assertions.assertEquals(Status.CREATE_PROJECT_PREFERENCE_ERROR.getCode(), result.getCode()); // when preference exists in project @@ -90,12 +101,12 @@ public void testUpdateProjectPreference() { // success Mockito.when(projectPreferenceMapper.updateById(Mockito.any())).thenReturn(1); - result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, "value"); + result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, VALID_PREFERENCES); Assertions.assertEquals(Status.SUCCESS.getCode(), result.getCode()); // database operation fail Mockito.when(projectPreferenceMapper.updateById(Mockito.any())).thenReturn(-1); - result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, "value"); + result = projectPreferenceService.updateProjectPreference(loginUser, projectCode, VALID_PREFERENCES); Assertions.assertEquals(Status.UPDATE_PROJECT_PREFERENCE_ERROR.getCode(), result.getCode()); } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationServiceTest.java index 0bb91d22a328..7c8fbaf6d5ec 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProjectWorkerGroupRelationServiceTest.java @@ -259,4 +259,101 @@ private TaskDefinition getTaskDefinitionWithDiffWorkerGroup() { taskDefinition.setWorkerGroup("new"); return taskDefinition; } + + @Test + public void testIsWorkerGroupAssignedToProject() { + Mockito.when(projectDao.queryByCode(projectCode)).thenReturn(getProject()); + Mockito.when(projectWorkerGroupDao.queryAssignedWorkerGroupNamesByProjectCode(projectCode)) + .thenReturn(Sets.newHashSet("g_suyc")); + Mockito.when(taskDefinitionDao.queryAllTaskDefinitionWorkerGroups(projectCode)) + .thenReturn(new ArrayList<>()); + Mockito.when(scheduleDao.querySchedulerListByProjectName(Mockito.any())) + .thenReturn(Lists.newArrayList()); + + Assertions.assertTrue(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "g_suyc")); + + Assertions.assertFalse(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "")); + + Assertions + .assertFalse(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "default")); + + Assertions.assertFalse(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, null)); + + Assertions.assertFalse( + projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "unassigned_group")); + } + + @Test + public void testIsWorkerGroupAssignedToProjectWithDefaultAssigned() { + Mockito.when(projectDao.queryByCode(projectCode)).thenReturn(getProject()); + Mockito.when(projectWorkerGroupDao.queryAssignedWorkerGroupNamesByProjectCode(projectCode)) + .thenReturn(Sets.newHashSet("g_suyc", "default")); + Mockito.when(taskDefinitionDao.queryAllTaskDefinitionWorkerGroups(projectCode)) + .thenReturn(new ArrayList<>()); + Mockito.when(scheduleDao.querySchedulerListByProjectName(Mockito.any())) + .thenReturn(Lists.newArrayList()); + + Assertions.assertTrue(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "g_suyc")); + + Assertions.assertTrue(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "default")); + + Assertions.assertFalse(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "")); + + Assertions.assertFalse(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, null)); + + Assertions.assertFalse( + projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "unassigned_group")); + } + + @Test + public void testIsWorkerGroupAssignedToProjectWithUsedWorkerGroups() { + Mockito.when(projectDao.queryByCode(projectCode)).thenReturn(getProject()); + Mockito.when(projectWorkerGroupDao.queryAssignedWorkerGroupNamesByProjectCode(projectCode)) + .thenReturn(Sets.newHashSet("g_suyc")); + Mockito.when(taskDefinitionDao.queryAllTaskDefinitionWorkerGroups(projectCode)) + .thenReturn(Lists.newArrayList("group-from-task")); + + org.apache.dolphinscheduler.dao.entity.Schedule schedule = + new org.apache.dolphinscheduler.dao.entity.Schedule(); + schedule.setWorkerGroup("group-from-schedule"); + Mockito.when(scheduleDao.querySchedulerListByProjectName(Mockito.any())) + .thenReturn(Lists.newArrayList(schedule)); + + Assertions.assertTrue(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "g_suyc")); + + Assertions.assertTrue( + projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "group-from-task")); + + Assertions.assertTrue( + projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "group-from-schedule")); + + Assertions + .assertFalse(projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "default")); + + Assertions.assertFalse( + projectWorkerGroupRelationService.isWorkerGroupAssignedToProject(projectCode, "unassigned_group")); + } + + @Test + public void testGetAllAssignedWorkerGroupNamesWithUsedWorkerGroups() { + Mockito.when(projectDao.queryByCode(projectCode)).thenReturn(getProject()); + Mockito.when(projectWorkerGroupDao.queryAssignedWorkerGroupNamesByProjectCode(projectCode)) + .thenReturn(Sets.newHashSet("g_suyc")); + Mockito.when(taskDefinitionDao.queryAllTaskDefinitionWorkerGroups(projectCode)) + .thenReturn(Lists.newArrayList("group-from-task")); + + org.apache.dolphinscheduler.dao.entity.Schedule schedule = + new org.apache.dolphinscheduler.dao.entity.Schedule(); + schedule.setWorkerGroup("group-from-schedule"); + Mockito.when(scheduleDao.querySchedulerListByProjectName(Mockito.any())) + .thenReturn(Lists.newArrayList(schedule)); + + java.util.Set assignedGroups = + projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(projectCode); + + Assertions.assertEquals(3, assignedGroups.size()); + Assertions.assertTrue(assignedGroups.contains("g_suyc")); + Assertions.assertTrue(assignedGroups.contains("group-from-task")); + Assertions.assertTrue(assignedGroups.contains("group-from-schedule")); + } } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/WorkflowDefinitionServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/WorkflowDefinitionServiceTest.java index 3ea6da8fb3a9..212dab0dd61f 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/WorkflowDefinitionServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/WorkflowDefinitionServiceTest.java @@ -41,12 +41,12 @@ import org.apache.dolphinscheduler.api.service.impl.WorkflowDefinitionServiceImpl; import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.validator.GlobalParamsValidator; +import org.apache.dolphinscheduler.api.validator.WorkerGroupValidator; import org.apache.dolphinscheduler.common.constants.Constants; import org.apache.dolphinscheduler.common.enums.FailureStrategy; import org.apache.dolphinscheduler.common.enums.Priority; import org.apache.dolphinscheduler.common.enums.ReleaseState; import org.apache.dolphinscheduler.common.enums.UserType; -import org.apache.dolphinscheduler.common.enums.WarningType; import org.apache.dolphinscheduler.common.enums.WorkflowExecutionTypeEnum; import org.apache.dolphinscheduler.common.graph.DAG; import org.apache.dolphinscheduler.common.utils.DateUtils; @@ -197,6 +197,9 @@ public class WorkflowDefinitionServiceTest extends BaseServiceTestTool { @Mock private GlobalParamsValidator globalParamsValidator; + @Mock + private WorkerGroupValidator workerGroupValidator; + @Mock private UserDao userDao; @@ -836,6 +839,7 @@ public void testCreateWorkflowDefinitionShouldSyncVersionToResponse() { eq(Boolean.TRUE))).thenReturn(1); when(processService.saveTaskRelation(eq(user), eq(projectCode), anyLong(), eq(1), anyList(), anyList(), eq(Boolean.TRUE))).thenReturn(Constants.EXIT_CODE_SUCCESS); + doNothing().when(workerGroupValidator).validate(anyList(), anyLong()); WorkflowDefinition workflowDefinition = workflowDefinitionService.createWorkflowDefinition( user, projectCode, name, description, "[]", "[]", timeout, @@ -862,6 +866,7 @@ public void testUpdateWorkflowDefinitionShouldSyncVersionToResponse() { .thenReturn(Collections.emptyList()); when(processService.saveTaskRelation(eq(user), eq(projectCode), eq(processDefinitionCode), eq(2), anyList(), anyList(), eq(Boolean.TRUE))).thenReturn(Constants.EXIT_CODE_SUCCESS); + doNothing().when(workerGroupValidator).validate(anyList(), anyLong()); WorkflowDefinition resultDefinition = workflowDefinitionService.updateWorkflowDefinition( user, projectCode, name, processDefinitionCode, description, "[]", "[]", timeout, @@ -990,7 +995,7 @@ private Schedule getSchedule() { schedule.setUserId(1); schedule.setReleaseState(ReleaseState.OFFLINE); schedule.setWorkflowInstancePriority(Priority.MEDIUM); - schedule.setWarningType(WarningType.NONE); + schedule.setWarningType(null); schedule.setWarningGroupId(1); schedule.setWorkerGroup(WorkerGroupUtils.getDefaultWorkerGroup()); return schedule; diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidatorTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidatorTest.java new file mode 100644 index 000000000000..c1e0c9571e0a --- /dev/null +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/validator/WorkerGroupValidatorTest.java @@ -0,0 +1,364 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.dolphinscheduler.api.validator; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.when; + +import org.apache.dolphinscheduler.api.exceptions.ServiceException; +import org.apache.dolphinscheduler.api.service.ProjectWorkerGroupRelationService; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class WorkerGroupValidatorTest { + + @Mock + private ProjectWorkerGroupRelationService projectWorkerGroupRelationService; + + @InjectMocks + private WorkerGroupValidator workerGroupValidator; + + private static final long PROJECT_CODE = 1L; + + @Test + void testValidate_nullWorkerGroup() { + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(null) + .projectCode(PROJECT_CODE) + .build(); + + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testValidate_emptyWorkerGroup() { + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup("") + .projectCode(PROJECT_CODE) + .build(); + + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testValidate_blankWorkerGroup() { + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(" ") + .projectCode(PROJECT_CODE) + .build(); + + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testValidate_validWorkerGroup() { + String validWorkerGroup = "g_suyc"; + Set assignedGroups = new HashSet<>(Collections.singletonList(validWorkerGroup)); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(validWorkerGroup) + .projectCode(PROJECT_CODE) + .build(); + + assertThatCode(() -> workerGroupValidator.validate(context)) + .doesNotThrowAnyException(); + } + + @Test + void testValidate_invalidWorkerGroup() { + String invalidWorkerGroup = "invalid-group"; + Set assignedGroups = new HashSet<>(Collections.singletonList("g_suyc")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(invalidWorkerGroup) + .projectCode(PROJECT_CODE) + .build(); + + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class) + .hasMessageContaining(invalidWorkerGroup); + } + + @Test + void testValidate_defaultNotAssigned() { + String workerGroup = "default"; + Set assignedGroups = new HashSet<>(Collections.singletonList("g_suyc")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(PROJECT_CODE) + .build(); + + // "default" should fail when not explicitly assigned + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class) + .hasMessageContaining("default"); + } + + @Test + void testValidate_defaultAssigned() { + String workerGroup = "default"; + Set assignedGroups = new HashSet<>(Arrays.asList("g_suyc", "default")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(PROJECT_CODE) + .build(); + + // "default" should pass when explicitly assigned + assertThatCode(() -> workerGroupValidator.validate(context)) + .doesNotThrowAnyException(); + } + + @Test + void testValidate_differentProjectCode() { + long anotherProjectCode = 2L; + String workerGroup = "g_suyc"; + + Set assignedGroups1 = new HashSet<>(Collections.singletonList(workerGroup)); + Set assignedGroups2 = new HashSet<>(Collections.singletonList("other-group")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups1); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(anotherProjectCode)) + .thenReturn(assignedGroups2); + + // Should pass for PROJECT_CODE + WorkerGroupValidationContext validContext = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(PROJECT_CODE) + .build(); + assertThatCode(() -> workerGroupValidator.validate(validContext)) + .doesNotThrowAnyException(); + + // Should fail for anotherProjectCode + WorkerGroupValidationContext invalidContext = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(anotherProjectCode) + .build(); + assertThatThrownBy(() -> workerGroupValidator.validate(invalidContext)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testValidate_caseSensitive() { + String workerGroup = "G_SUYC"; + Set assignedGroups = new HashSet<>(Collections.singletonList("g_suyc")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(PROJECT_CODE) + .build(); + + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testValidate_assignedWorkerGroupsNull() { + String workerGroup = "g_suyc"; + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(null); + + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(PROJECT_CODE) + .build(); + + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testValidate_assignedWorkerGroupsEmpty() { + String workerGroup = "g_suyc"; + Set assignedGroups = new HashSet<>(); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + WorkerGroupValidationContext context = WorkerGroupValidationContext.builder() + .workerGroup(workerGroup) + .projectCode(PROJECT_CODE) + .build(); + + assertThatThrownBy(() -> workerGroupValidator.validate(context)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testBatchValidate_nullList() { + assertThatCode(() -> workerGroupValidator.validate((List) null, PROJECT_CODE)) + .doesNotThrowAnyException(); + } + + @Test + void testBatchValidate_emptyList() { + assertThatCode(() -> workerGroupValidator.validate(Collections.emptyList(), PROJECT_CODE)) + .doesNotThrowAnyException(); + } + + @Test + void testBatchValidate_listWithOnlyEmptyStrings() { + List workerGroups = Arrays.asList("", " ", null); + // Empty/null values should cause validation failure + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testBatchValidate_allValidWorkerGroups() { + List workerGroups = Arrays.asList("g_suyc", "group-a", "group-b"); + Set assignedGroups = new HashSet<>(Arrays.asList("g_suyc", "group-a", "group-b")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + assertThatCode(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .doesNotThrowAnyException(); + } + + @Test + void testBatchValidate_someInvalidWorkerGroups() { + List workerGroups = Arrays.asList("g_suyc", "invalid-group"); + Set assignedGroups = new HashSet<>(Collections.singletonList("g_suyc")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class) + .hasMessageContaining("invalid-group"); + } + + @Test + void testBatchValidate_allInvalidWorkerGroups() { + List workerGroups = Arrays.asList("invalid-1", "invalid-2"); + Set assignedGroups = new HashSet<>(); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class) + .hasMessageContaining("invalid-1") + .hasMessageContaining("invalid-2"); + } + + @Test + void testBatchValidate_withDuplicates() { + List workerGroups = Arrays.asList("g_suyc", "g_suyc", "group-a"); + Set assignedGroups = new HashSet<>(Arrays.asList("g_suyc", "group-a")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + // Should not throw because duplicates are filtered out + assertThatCode(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .doesNotThrowAnyException(); + } + + @Test + void testBatchValidate_withEmptyStrings() { + List workerGroups = Arrays.asList("g_suyc", "", "group-a"); + Set assignedGroups = new HashSet<>(Arrays.asList("g_suyc", "group-a")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + // Should throw because empty strings are now invalid + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testBatchValidate_defaultNotAssigned() { + List workerGroups = Arrays.asList("g_suyc", "default"); + Set assignedGroups = new HashSet<>(Collections.singletonList("g_suyc")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + // "default" should fail when not explicitly assigned + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class) + .hasMessageContaining("default"); + } + + @Test + void testBatchValidate_defaultAssigned() { + List workerGroups = Arrays.asList("g_suyc", "default"); + Set assignedGroups = new HashSet<>(Arrays.asList("g_suyc", "default")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + // "default" should pass when explicitly assigned + assertThatCode(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .doesNotThrowAnyException(); + } + + @Test + void testBatchValidate_assignedWorkerGroupsNull() { + List workerGroups = Arrays.asList("g_suyc", "group-a"); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(null); + + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testBatchValidate_assignedWorkerGroupsEmpty() { + List workerGroups = Arrays.asList("g_suyc", "group-a"); + Set assignedGroups = new HashSet<>(); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class); + } + + @Test + void testBatchValidate_mixedNullAndValidValues() { + List workerGroups = Arrays.asList("g_suyc", null, "group-a"); + Set assignedGroups = new HashSet<>(Arrays.asList("g_suyc", "group-a")); + when(projectWorkerGroupRelationService.getAllAssignedWorkerGroupNames(PROJECT_CODE)) + .thenReturn(assignedGroups); + + // Should fail because null is invalid even though other groups are valid + assertThatThrownBy(() -> workerGroupValidator.validate(workerGroups, PROJECT_CODE)) + .isInstanceOf(ServiceException.class); + } +} diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowE2ETest.java index 7ad0ff08e6e7..6e09d9b3d457 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowE2ETest.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowE2ETest.java @@ -34,6 +34,7 @@ import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage; import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; import org.apache.dolphinscheduler.e2e.pages.security.UserPage; +import org.apache.dolphinscheduler.e2e.pages.security.WorkerGroupPage; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -78,9 +79,18 @@ public static void setup() { WebDriverWaitFactory.createWebDriverWait(userPage.driver()).until(ExpectedConditions.visibilityOfElementLocated( new By.ByClassName("name"))); - userPage.update(user, user, email, phone, tenant) + WorkerGroupPage workerGroupPage = userPage.update(user, user, email, phone, tenant) + .goToNav(SecurityPage.class) + .goToTab(WorkerGroupPage.class); + + if (workerGroupPage.workerGroupList().stream() + .noneMatch(it -> it.getText().contains("default"))) { + workerGroupPage.create("default"); + } + + workerGroupPage .goToNav(ProjectPage.class) - .create(project); + .createProjectUntilSuccess(project); } @AfterAll @@ -118,6 +128,7 @@ void testCreateWorkflow() { .script("echo ${today}\necho ${global_param}\n") .name("test-1") .addParam("today", "${system.datetime}") + .setWorkerGroup("default") .submit() .submit() diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowHttpTaskE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowHttpTaskE2ETest.java index 0408b384b94c..e99f50439a9f 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowHttpTaskE2ETest.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowHttpTaskE2ETest.java @@ -32,6 +32,7 @@ import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage; import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; import org.apache.dolphinscheduler.e2e.pages.security.UserPage; +import org.apache.dolphinscheduler.e2e.pages.security.WorkerGroupPage; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -78,9 +79,18 @@ public static void setup() { WebDriverWaitFactory.createWebDriverWait(userPage.driver()).until(ExpectedConditions.visibilityOfElementLocated( new By.ByClassName("name"))); - userPage.update(user, user, email, phone, tenant) + WorkerGroupPage workerGroupPage = userPage.update(user, user, email, phone, tenant) + .goToNav(SecurityPage.class) + .goToTab(WorkerGroupPage.class); + + if (workerGroupPage.workerGroupList().stream() + .noneMatch(it -> it.getText().contains("default"))) { + workerGroupPage.create("default"); + } + + workerGroupPage .goToNav(ProjectPage.class) - .create(project); + .createProjectUntilSuccess(project); } @AfterAll @@ -117,6 +127,7 @@ void testCreateWorkflow() { .url(mockServerUrl) .name("test-1") .addParam("today", "${system.datetime}") + .setWorkerGroup("default") .submit() .submit() diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowJavaTaskE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowJavaTaskE2ETest.java index 8d7a662ad2a5..30b848b045c9 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowJavaTaskE2ETest.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowJavaTaskE2ETest.java @@ -36,6 +36,7 @@ import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage; import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; import org.apache.dolphinscheduler.e2e.pages.security.UserPage; +import org.apache.dolphinscheduler.e2e.pages.security.WorkerGroupPage; import java.io.File; import java.io.FileOutputStream; @@ -206,9 +207,18 @@ public static void setup() { WebDriverWaitFactory.createWebDriverWait(userPage.driver()) .until(ExpectedConditions.visibilityOfElementLocated(new By.ByClassName("name"))); - userPage.update(user, user, email, phone, tenant) + WorkerGroupPage workerGroupPage = userPage.update(user, user, email, phone, tenant) + .goToNav(SecurityPage.class) + .goToTab(WorkerGroupPage.class); + + if (workerGroupPage.workerGroupList().stream() + .noneMatch(it -> it.getText().contains("default"))) { + workerGroupPage.create("default"); + } + + workerGroupPage .goToNav(ProjectPage.class) - .create(project); + .createProjectUntilSuccess(project); ProjectPage projectPage = new ProjectPage(browser); Awaitility.await().untilAsserted(() -> assertThat(projectPage.projectList()) @@ -264,6 +274,7 @@ void testCreateFatJarWorkflow() { .selectJavaResource("fat.jar") .name("test-1") .selectEnv(environmentName) + .setWorkerGroup("default") .submit() .submit() .name(workflow) @@ -343,6 +354,7 @@ void testCreateNormalJarWorkflow() { .selectJavaResource("normal2.jar") .name("test-2") .selectEnv(environmentName) + .setWorkerGroup("default") .submit() .submit() .name(workflow2) diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowSwitchE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowSwitchE2ETest.java index f95338836bd6..6f434f566fc6 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowSwitchE2ETest.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowSwitchE2ETest.java @@ -34,6 +34,7 @@ import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.SwitchTaskForm; import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage; import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; +import org.apache.dolphinscheduler.e2e.pages.security.WorkerGroupPage; import java.util.List; @@ -60,13 +61,22 @@ class WorkflowSwitchE2ETest { @BeforeAll public static void setup() { - new LoginPage(browser) + WorkerGroupPage workerGroupPage = new LoginPage(browser) .login("admin", "dolphinscheduler123") .goToNav(SecurityPage.class) .goToTab(TenantPage.class) .create(tenant) + .goToNav(SecurityPage.class) + .goToTab(WorkerGroupPage.class); + + if (workerGroupPage.workerGroupList().stream() + .noneMatch(it -> it.getText().contains("default"))) { + workerGroupPage.create("default"); + } + + workerGroupPage .goToNav(ProjectPage.class) - .create(project); + .createProjectUntilSuccess(project); } @AfterAll @@ -99,6 +109,7 @@ void testCreateSwitchWorkflow() { workflowForm.addTask(TaskType.SHELL) .script("echo ${today}\necho ${global_param}\n") .name("pre-task") + .setWorkerGroup("default") .submit(); SwitchTaskForm switchTaskForm = workflowForm.addTask(TaskType.SWITCH); @@ -110,12 +121,14 @@ void testCreateSwitchWorkflow() { .script("echo ${key}") .preTask("switch") .name(ifBranchName) + .setWorkerGroup("default") .submit(); workflowForm.addTask(TaskType.SHELL) .script("echo ${key}") .preTask("switch") .name(elseBranchName) + .setWorkerGroup("default") .submit(); // format dag diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/PythonTaskE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/PythonTaskE2ETest.java index cb18e5884879..dce4beb02e2c 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/PythonTaskE2ETest.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/PythonTaskE2ETest.java @@ -36,6 +36,7 @@ import org.apache.dolphinscheduler.e2e.pages.security.SecurityPage; import org.apache.dolphinscheduler.e2e.pages.security.TenantPage; import org.apache.dolphinscheduler.e2e.pages.security.UserPage; +import org.apache.dolphinscheduler.e2e.pages.security.WorkerGroupPage; import java.util.Date; @@ -66,15 +67,22 @@ public static void setup() { .goToTab(UserPage.class) .update(adminUser); } - tenantPage + WorkerGroupPage workerGroupPage = tenantPage .goToNav(SecurityPage.class) .goToTab(EnvironmentPage.class) .createEnvironmentUntilSuccess(pythonEnvironment.getEnvironmentName(), pythonEnvironment.getEnvironmentConfig(), pythonEnvironment.getEnvironmentDesc(), - pythonEnvironment.getEnvironmentWorkerGroup()); + pythonEnvironment.getEnvironmentWorkerGroup()) + .goToNav(SecurityPage.class) + .goToTab(WorkerGroupPage.class); + + if (workerGroupPage.workerGroupList().stream() + .noneMatch(it -> it.getText().contains("default"))) { + workerGroupPage.create("default"); + } - tenantPage + workerGroupPage .goToNav(ProjectPage.class) .createProjectUntilSuccess(projectName); } @@ -97,6 +105,7 @@ void testRunPythonTasks_SuccessCase() { .addTask(WorkflowForm.TaskType.PYTHON) .script(pythonScripts) .name(taskName) + .setWorkerGroup("default") .submit() .submit() @@ -139,6 +148,7 @@ void testRunPythonTasks_WorkflowParamsCase() { .addTask(WorkflowForm.TaskType.PYTHON) .script(pythonScripts) .name(taskName) + .setWorkerGroup("default") .submit() .submit() @@ -182,6 +192,7 @@ void testRunPythonTasks_LocalParamsCase() { .script(pythonScripts) .name(taskName) .addParam("name", "tom") + .setWorkerGroup("default") .submit() .submit() @@ -224,6 +235,7 @@ void testRunPythonTasks_GlobalParamsOverrideLocalParamsCase() { .script(pythonScripts) .name(taskName) .addParam("name", "tom") + .setWorkerGroup("default") .submit() .submit() @@ -281,6 +293,7 @@ void testRunPythonTasks_UsingResourceFile() { .name(taskName) .selectResource(testFileName) .addParam("file_name", String.format("%s.sh", testFileName)) + .setWorkerGroup("default") .submit() .submit() @@ -318,6 +331,7 @@ void testRunPythonTasks_FailedCase() { .addTask(WorkflowForm.TaskType.PYTHON) .script(pythonScripts) .name(taskName) + .setWorkerGroup("default") .submit() .submit() diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/ShellTaskE2ETest.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/ShellTaskE2ETest.java index 7a547201c97d..e1b5a2c7ad82 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/ShellTaskE2ETest.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/tasks/ShellTaskE2ETest.java @@ -63,7 +63,16 @@ public static void setup() { .update(adminUser); } - tenantPage + WorkerGroupPage workerGroupPage = tenantPage + .goToNav(SecurityPage.class) + .goToTab(WorkerGroupPage.class); + + if (workerGroupPage.workerGroupList().stream() + .noneMatch(it -> it.getText().contains("default"))) { + workerGroupPage.create("default"); + } + + workerGroupPage .goToNav(ProjectPage.class) .createProjectUntilSuccess(projectName); } @@ -84,6 +93,7 @@ void testRunShellTasks_SuccessCase() { .addTask(WorkflowForm.TaskType.SHELL) .script("echo hello world\n") .name(taskName) + .setWorkerGroup("default") .submit() .submit() @@ -119,6 +129,7 @@ void testRunShellTasks_WorkflowParamsCase() { .addTask(WorkflowForm.TaskType.SHELL) .script("[ \"${name}\" = \"tom\" ] && echo \"success\" || { echo \"failed\"; exit 1; }") .name(taskName) + .setWorkerGroup("default") .submit() .submit() @@ -155,6 +166,7 @@ void testRunShellTasks_LocalParamsCase() { .script("[ \"${name}\" = \"tom\" ] && echo \"success\" || { echo \"failed\"; exit 1; }") .name(taskName) .addParam("name", "tom") + .setWorkerGroup("default") .submit() .submit() @@ -190,6 +202,7 @@ void testRunShellTasks_GlobalParamsOverrideLocalParamsCase() { .script("[ \"${name}\" = \"jerry\" ] && echo \"success\" || { echo \"failed\"; exit 1; }") .name(taskName) .addParam("name", "tom") + .setWorkerGroup("default") .submit() .submit() @@ -232,6 +245,7 @@ void testRunShellTasks_UsingResourceFile() { .script("cat " + testFileName + ".sh") .name(taskName) .selectResource(testFileName) + .setWorkerGroup("default") .submit() .submit() @@ -266,6 +280,7 @@ void testRunShellTasks_FailedCase() { .addTask(WorkflowForm.TaskType.SHELL) .script("echo 'I am failed'\n exit1\n") .name(taskName) + .setWorkerGroup("default") .submit() .submit() diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/ProjectPage.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/ProjectPage.java index 69dbb176d9c6..14c36cf63e3e 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/ProjectPage.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/ProjectPage.java @@ -71,10 +71,10 @@ public ProjectPage create(String project) { public ProjectPage createProjectUntilSuccess(String project) { create(project); - assignWorkerGroup(project, "default"); await().untilAsserted(() -> assertThat(projectList()) .as("project list should contain newly-created project") .anyMatch(it -> it.getText().contains(project))); + assignWorkerGroup(project, "default"); return this; } @@ -169,7 +169,9 @@ public ProjectPage verifyRemovedWorkerGroup(String project, String workerGroup) throw new RuntimeException( "Worker group should have been deleted but still exists: " + workerGroup); }); - assignWorkerGroupForm.buttonCancel().click(); + + await().until(() -> assignWorkerGroupForm.buttonCancel().isEnabled()); + driver.executeScript("arguments[0].click();", assignWorkerGroupForm.buttonCancel()); return this; } diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java index 7c47eb36a1dd..7811648222dd 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowForm.java @@ -26,6 +26,7 @@ import org.apache.dolphinscheduler.e2e.pages.project.workflow.task.SwitchTaskForm; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.util.List; import lombok.Getter; @@ -111,6 +112,8 @@ public WebElement getTask(String taskName) { } public WorkflowSaveDialog submit() { + WebDriverWaitFactory.createWebDriverWait(driver, Duration.ofSeconds(5)) + .until(ExpectedConditions.invisibilityOfElementLocated(By.className("n-modal-mask"))); buttonSave().click(); WebDriverWaitFactory.createWebDriverWait(driver) .until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(.,'Basic Information')]"))); diff --git a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/task/TaskNodeForm.java b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/task/TaskNodeForm.java index bec099385d00..0a4884fcc76f 100644 --- a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/task/TaskNodeForm.java +++ b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/task/TaskNodeForm.java @@ -20,6 +20,7 @@ import org.apache.dolphinscheduler.e2e.core.WebDriverWaitFactory; import org.apache.dolphinscheduler.e2e.pages.project.workflow.WorkflowForm; +import java.time.Duration; import java.util.List; import lombok.Getter; @@ -70,6 +71,12 @@ public abstract class TaskNodeForm { }) private WebElement selectEnv; + @FindBys({ + @FindBy(className = "worker-group-select"), + @FindBy(className = "n-base-selection"), + }) + private WebElement selectWorkerGroup; + @FindBys({ @FindBy(className = "btn-custom-parameters"), @FindBy(tagName = "button"), @@ -142,6 +149,26 @@ public TaskNodeForm selectEnv(String envName) { return this; } + public TaskNodeForm setWorkerGroup(String workerGroupName) { + ((JavascriptExecutor) parent().driver()).executeScript("arguments[0].click();", selectWorkerGroup); + + final By optionsLocator = By.xpath( + "//div[contains(@class, 'n-select-menu')]//div[contains(@class, 'n-base-select-option')]"); + + WebDriverWaitFactory.createWebDriverWait(parent().driver(), Duration.ofSeconds(5)) + .until(ExpectedConditions.visibilityOfElementLocated(optionsLocator)); + + parent().driver() + .findElements(optionsLocator) + .stream() + .filter(it -> workerGroupName.equals(it.getText().trim())) + .findFirst() + .orElseThrow(() -> new RuntimeException("No such worker group: " + workerGroupName)) + .click(); + + return this; + } + public TaskNodeForm preTask(String preTaskName) { ((JavascriptExecutor) parent().driver()).executeScript("arguments[0].click();", selectPreTasks); diff --git a/dolphinscheduler-ui/src/views/projects/preference/use-form.ts b/dolphinscheduler-ui/src/views/projects/preference/use-form.ts index d7a97f509dfa..9776d5a7cb78 100644 --- a/dolphinscheduler-ui/src/views/projects/preference/use-form.ts +++ b/dolphinscheduler-ui/src/views/projects/preference/use-form.ts @@ -59,7 +59,7 @@ export function useForm() { const data = reactive({ model: { taskPriority: 'MEDIUM', - workerGroup: 'default', + workerGroup: null, environmentCode: null, failRetryTimes: 0, failRetryInterval: 1, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-worker-group.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-worker-group.ts index 401684411354..597adb218d85 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-worker-group.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-worker-group.ts @@ -44,6 +44,7 @@ export function useWorkerGroup(projectCode: number): IJsonItem { return { type: 'select', field: 'workerGroup', + class: 'worker-group-select', span: 12, name: t('project.node.worker_group'), props: { diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-aliyun-serverless-spark.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-aliyun-serverless-spark.ts index 6ffeb5ea7c11..f72448e5f0e0 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-aliyun-serverless-spark.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-aliyun-serverless-spark.ts @@ -40,7 +40,7 @@ export function useAliyunServerlessSpark({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, type: 'ALIYUN_SERVERLESS_SPARK', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-chunjun.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-chunjun.ts index 2223e0b3e207..02f8ed6353f1 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-chunjun.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-chunjun.ts @@ -42,7 +42,7 @@ export function useChunjun({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, customConfig: true, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-conditions.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-conditions.ts index 08e325099fd0..70b38461a8c9 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-conditions.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-conditions.ts @@ -40,7 +40,7 @@ export function useConditions({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, timeout: 30, relation: 'AND', dependTaskList: [], diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-data-factory.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-data-factory.ts index 1ea010a4c20e..0d6baed99d46 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-data-factory.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-data-factory.ts @@ -41,7 +41,7 @@ export function useDataFactory({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, timeoutNotifyStrategy: ['WARN'], diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datasync.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datasync.ts index f46ac6bef961..c74f8b348cc1 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datasync.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datasync.ts @@ -40,7 +40,7 @@ export function useDatasync({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, timeoutNotifyStrategy: ['WARN'] diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datax.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datax.ts index 0304f06a7516..92771d0efc68 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datax.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-datax.ts @@ -41,7 +41,7 @@ export function useDataX({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, cpuQuota: -1, memoryMax: -1, delayTime: 0, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dependent.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dependent.ts index b140eea7f3d0..c9a1cb754391 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dependent.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dependent.ts @@ -40,7 +40,7 @@ export function useDependent({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, relation: 'AND', dependTaskList: [], diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dinky.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dinky.ts index 080ea473ada8..d929ba856f02 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dinky.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dinky.ts @@ -40,7 +40,7 @@ export function useDinky({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, timeoutNotifyStrategy: ['WARN'] diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dms.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dms.ts index 28726b37190d..33e0d3bca301 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dms.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dms.ts @@ -40,7 +40,7 @@ export function useDms({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, timeoutNotifyStrategy: ['WARN'], diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dvc.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dvc.ts index eeeb9618c9ef..1ddab634c4a5 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dvc.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dvc.ts @@ -40,7 +40,7 @@ export function useDvc({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, timeoutNotifyStrategy: ['WARN'], diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr-serverless.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr-serverless.ts index 1b3408262718..6423f911c4db 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr-serverless.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr-serverless.ts @@ -41,7 +41,7 @@ export function useEmrServerless({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, applicationId: '', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr.ts index 00fb55aa7a30..841df1f0d7af 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-emr.ts @@ -41,7 +41,7 @@ export function useEmr({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, programType: 'ADD_JOB_FLOW_STEPS', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink-stream.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink-stream.ts index 3b70abff3048..a69ccb4bd223 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink-stream.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink-stream.ts @@ -40,7 +40,7 @@ export function useFlinkStream({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, programType: 'SCALA', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink.ts index 9e956eb0ff18..85308a81c08c 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-flink.ts @@ -40,7 +40,7 @@ export function useFlink({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, programType: 'SCALA', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-grpc.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-grpc.ts index af2b856809d1..50e8c3beb504 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-grpc.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-grpc.ts @@ -40,7 +40,7 @@ export function useGrpc({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, grpcCredentialType: 'INSECURE', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-hive-cli.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-hive-cli.ts index cbe5bd7988a3..a9c5fd58ae74 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-hive-cli.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-hive-cli.ts @@ -40,7 +40,7 @@ export function useHiveCli({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, hiveCliTaskExecutionType: 'SCRIPT' diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-http.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-http.ts index eeb42c51e0c9..73a0c7cf716a 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-http.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-http.ts @@ -40,7 +40,7 @@ export function useHttp({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, httpMethod: 'GET', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-java.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-java.ts index 8671e6e79a75..a948a2458dd0 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-java.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-java.ts @@ -40,7 +40,7 @@ export function useJava({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, isModulePath: false, rawScript: '', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-jupyter.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-jupyter.ts index 21ca400ac51d..04c1f52eff3c 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-jupyter.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-jupyter.ts @@ -40,7 +40,7 @@ export function useJupyter({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, cpuQuota: -1, memoryMax: -1, delayTime: 0, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-k8s.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-k8s.ts index e5ce9dad1ad7..faa059e1e75c 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-k8s.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-k8s.ts @@ -43,7 +43,7 @@ export function useK8s({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, type: 'K8S', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-kubeflow.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-kubeflow.ts index a9c82bea6a3f..4cea28d9abbc 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-kubeflow.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-kubeflow.ts @@ -40,7 +40,7 @@ export function useKubeflow({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, timeoutNotifyStrategy: ['WARN'] diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-linkis.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-linkis.ts index 4d022030327c..cc0487833fe2 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-linkis.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-linkis.ts @@ -41,7 +41,7 @@ export function useLinkis({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, cpuQuota: -1, memoryMax: -1, delayTime: 0, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mlflow.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mlflow.ts index b68c910a0c91..4e3cdc4de7cb 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mlflow.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mlflow.ts @@ -40,7 +40,7 @@ export function useMlflow({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, algorithm: 'svm', mlflowTrackingUri: 'http://127.0.0.1:5000', mlflowTaskType: 'MLflow Projects', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mr.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mr.ts index ade369889586..7fc496275857 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mr.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-mr.ts @@ -40,7 +40,7 @@ export function useMr({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, programType: 'SCALA', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-openmldb.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-openmldb.ts index f878ce8f0c59..11643f4dc6ae 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-openmldb.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-openmldb.ts @@ -42,7 +42,7 @@ export function useOpenmldb({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, zk: '', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-procedure.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-procedure.ts index 2a0def32d55a..ea9d2d3af807 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-procedure.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-procedure.ts @@ -41,7 +41,7 @@ export function useProcedure({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, type: data?.taskParams?.type ? data?.taskParams?.type : 'MYSQL', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-python.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-python.ts index d58a13201076..0593d90366d6 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-python.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-python.ts @@ -41,7 +41,7 @@ export function usePython({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, cpuQuota: -1, memoryMax: -1, delayTime: 0, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-remote-shell.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-remote-shell.ts index 1340ee457276..6bdf75c364e1 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-remote-shell.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-remote-shell.ts @@ -42,7 +42,7 @@ export function useRemoteShell({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, type: 'SSH', rawScript: '' diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sagemaker.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sagemaker.ts index 3e7d6ff5d75b..86a71c1d213d 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sagemaker.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sagemaker.ts @@ -40,7 +40,7 @@ export function userSagemaker({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, type: 'SAGEMAKER', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sea-tunnel.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sea-tunnel.ts index 6df07f71f215..3890949cb1b2 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sea-tunnel.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sea-tunnel.ts @@ -41,7 +41,7 @@ export function useSeaTunnel({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, cpuQuota: -1, memoryMax: -1, delayTime: 0, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-shell.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-shell.ts index a90ab59dd8ef..4f787dc69734 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-shell.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-shell.ts @@ -42,7 +42,7 @@ export function useShell({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, cpuQuota: -1, memoryMax: -1, delayTime: 0, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-spark.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-spark.ts index 883950ae516f..488f54851435 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-spark.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-spark.ts @@ -40,7 +40,7 @@ export function useSpark({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, programType: 'SCALA', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sql.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sql.ts index 371ae737fa7d..160de9231bce 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sql.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sql.ts @@ -41,7 +41,7 @@ export function useSql({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, type: 'MYSQL', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sqoop.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sqoop.ts index 879b06858fc6..3e97d6d86743 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sqoop.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sqoop.ts @@ -40,7 +40,7 @@ export function useSqoop({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, cpuQuota: -1, memoryMax: -1, delayTime: 0, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sub-workflow.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sub-workflow.ts index 540460700cc8..30bf862bba4c 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sub-workflow.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sub-workflow.ts @@ -43,7 +43,7 @@ export function useSubWorkflow({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, timeoutNotifyStrategy: ['WARN'] diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-switch.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-switch.ts index 1e6d3f80cc34..2c0ee5963cd9 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-switch.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-switch.ts @@ -40,7 +40,7 @@ export function useSwitch({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, rawScript: '', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-zeppelin.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-zeppelin.ts index 8c072549a937..e5dc4efb3f16 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-zeppelin.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-zeppelin.ts @@ -40,7 +40,7 @@ export function useZeppelin({ environmentCode: null, failRetryInterval: 1, failRetryTimes: 0, - workerGroup: 'default', + workerGroup: null, delayTime: 0, timeout: 30, type: 'ZEPPELIN', diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/types.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/types.ts index 218f318db0d0..0f7c57917a6f 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/types.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/types.ts @@ -511,7 +511,7 @@ interface INodeData timeout?: number timeoutFlag?: boolean timeoutNotifyStrategy?: string[] - workerGroup?: string + workerGroup?: string | null code?: number name?: string preTasks?: number[] diff --git a/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-form.ts b/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-form.ts index f4955a9d990d..11ab72047f12 100644 --- a/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-form.ts +++ b/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-form.ts @@ -62,7 +62,7 @@ export const useForm = () => { complementDependentMode: 'OFF_MODE', runMode: 'RUN_MODE_SERIAL', workflowInstancePriority: 'MEDIUM', - workerGroup: 'default', + workerGroup: null, tenantCode: 'default', environmentCode: null, startParams: null, @@ -140,7 +140,7 @@ export const useForm = () => { warningType: 'NONE', workflowInstancePriority: 'MEDIUM', warningGroupId: null as null | number, - workerGroup: 'default', + workerGroup: null, tenantCode: 'default', environmentCode: null as null | string },