Skip to content

Commit f118784

Browse files
abzymeatsjtudavidzollo
authored andcommitted
[Improvement-16994][TaskPlugin] support serverless spark template (apache#17411)
1 parent c19a554 commit f118784

File tree

10 files changed

+106
-14
lines changed

10 files changed

+106
-14
lines changed

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,31 @@
1818
# See https://pre-commit.com for more information
1919
# See https://pre-commit.com/hooks.html for more hooks
2020

21-
default_stages: [commit, push]
21+
default_stages: [pre-commit, pre-push]
2222
default_language_version:
2323
# force all python hooks to run python3
2424
python: python3
2525
repos:
2626
# Python API Hooks
2727
- repo: https://github.com/pycqa/isort
28-
rev: 5.10.1
28+
rev: 6.0.1
2929
hooks:
3030
- id: isort
3131
name: isort (python)
3232
- repo: https://github.com/psf/black
33-
rev: 22.3.0
33+
rev: 25.1.0
3434
hooks:
3535
- id: black
3636
- repo: https://github.com/pycqa/flake8
37-
rev: 4.0.1
37+
rev: 7.3.0
3838
hooks:
3939
- id: flake8
4040
additional_dependencies: [
4141
'flake8-docstrings>=1.6',
4242
'flake8-black>=0.2',
4343
]
4444
- repo: https://github.com/pycqa/autoflake
45-
rev: v1.4
45+
rev: v2.3.1
4646
hooks:
4747
- id: autoflake
4848
args: [

dolphinscheduler-task-plugin/dolphinscheduler-task-aliyunserverlessspark/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
<dependency>
6868
<groupId>com.aliyun</groupId>
6969
<artifactId>emr_serverless_spark20230808</artifactId>
70-
<version>1.0.0</version>
70+
<version>2.4.1</version>
7171
</dependency>
7272

7373
<dependency>

dolphinscheduler-task-plugin/dolphinscheduler-task-aliyunserverlessspark/src/main/java/org/apache/dolphinscheduler/plugin/task/aliyunserverlessspark/AliyunServerlessSparkParameters.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public class AliyunServerlessSparkParameters extends AbstractParameters {
4747

4848
private String sparkSubmitParameters;
4949

50+
private String templateId;
51+
5052
@JsonProperty("isProduction")
5153
boolean isProduction;
5254

dolphinscheduler-task-plugin/dolphinscheduler-task-aliyunserverlessspark/src/main/java/org/apache/dolphinscheduler/plugin/task/aliyunserverlessspark/AliyunServerlessSparkTask.java

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters;
3131
import org.apache.dolphinscheduler.plugin.task.api.parameters.resource.DataSourceParameters;
3232
import org.apache.dolphinscheduler.plugin.task.api.parameters.resource.ResourceParametersHelper;
33+
import org.apache.dolphinscheduler.plugin.task.api.utils.RetryUtils;
3334
import org.apache.dolphinscheduler.spi.enums.DbType;
3435

3536
import org.apache.commons.lang3.StringUtils;
@@ -39,13 +40,16 @@
3940
import java.util.HashMap;
4041
import java.util.List;
4142
import java.util.Map;
43+
import java.util.stream.Collectors;
4244

4345
import lombok.extern.slf4j.Slf4j;
4446

4547
import com.aliyun.emr_serverless_spark20230808.Client;
4648
import com.aliyun.emr_serverless_spark20230808.models.CancelJobRunRequest;
4749
import com.aliyun.emr_serverless_spark20230808.models.GetJobRunRequest;
4850
import com.aliyun.emr_serverless_spark20230808.models.GetJobRunResponse;
51+
import com.aliyun.emr_serverless_spark20230808.models.GetTemplateRequest;
52+
import com.aliyun.emr_serverless_spark20230808.models.GetTemplateResponse;
4953
import com.aliyun.emr_serverless_spark20230808.models.JobDriver;
5054
import com.aliyun.emr_serverless_spark20230808.models.StartJobRunRequest;
5155
import com.aliyun.emr_serverless_spark20230808.models.StartJobRunResponse;
@@ -64,6 +68,12 @@ public class AliyunServerlessSparkTask extends AbstractRemoteTask {
6468

6569
private AliyunServerlessSparkConnectionParam aliyunServerlessSparkConnectionParam;
6670

71+
private String templateConf;
72+
73+
private String templateDisplayReleaseVersion;
74+
75+
private Boolean templateFusion;
76+
6777
private String jobRunId;
6878

6979
private RunState currentState;
@@ -116,6 +126,26 @@ public void init() {
116126

117127
@Override
118128
public void handle(TaskCallBack taskCallBack) throws TaskException {
129+
try {
130+
GetTemplateResponse getTemplateResponse = aliyunServerlessSparkClient.getTemplate(
131+
aliyunServerlessSparkParameters.getWorkspaceId(),
132+
buildGetTemplateRequest());
133+
134+
if (getTemplateResponse != null) {
135+
templateConf = getTemplateResponse.getBody()
136+
.getData()
137+
.getSparkConf()
138+
.stream()
139+
.map(item -> "--conf " + item.getKey() + "=" + item.getValue())
140+
.collect(Collectors.joining(" "));
141+
142+
templateDisplayReleaseVersion = getTemplateResponse.getBody().getData().getDisplaySparkVersion();
143+
templateFusion = getTemplateResponse.getBody().getData().getFusion();
144+
}
145+
} catch (Exception e) {
146+
throw new AliyunServerlessSparkTaskException("Failed to get serverless spark template!");
147+
}
148+
119149
try {
120150
StartJobRunRequest startJobRunRequest = buildStartJobRunRequest(aliyunServerlessSparkParameters);
121151
RuntimeOptions runtime = new RuntimeOptions();
@@ -128,8 +158,17 @@ public void handle(TaskCallBack taskCallBack) throws TaskException {
128158

129159
while (!RunState.isFinal(currentState)) {
130160
GetJobRunRequest getJobRunRequest = buildGetJobRunRequest();
131-
GetJobRunResponse getJobRunResponse = aliyunServerlessSparkClient
132-
.getJobRun(aliyunServerlessSparkParameters.getWorkspaceId(), jobRunId, getJobRunRequest);
161+
162+
GetJobRunResponse getJobRunResponse = RetryUtils.retryFunction(() -> {
163+
try {
164+
return aliyunServerlessSparkClient
165+
.getJobRun(aliyunServerlessSparkParameters.getWorkspaceId(), jobRunId,
166+
getJobRunRequest);
167+
} catch (Exception e) {
168+
throw new AliyunServerlessSparkTaskException("Failed to get job run!", e);
169+
}
170+
}, new RetryUtils.RetryPolicy(10, 1000L));
171+
133172
currentState = RunState.valueOf(getJobRunResponse.getBody().getJobRun().getState());
134173
log.info("job - {} state - {}", jobRunId, currentState);
135174
Thread.sleep(10 * 1000L);
@@ -199,16 +238,26 @@ protected Client buildAliyunServerlessSparkClient(String accessKeyId, String acc
199238
}
200239

201240
protected StartJobRunRequest buildStartJobRunRequest(AliyunServerlessSparkParameters aliyunServerlessSparkParameters) {
241+
if (templateConf != null) {
242+
aliyunServerlessSparkParameters.setSparkSubmitParameters(
243+
templateConf + " " + aliyunServerlessSparkParameters.getSparkSubmitParameters());
244+
}
245+
202246
StartJobRunRequest startJobRunRequest = new StartJobRunRequest();
203247
startJobRunRequest.setRegionId(regionId);
204248
startJobRunRequest.setResourceQueueId(aliyunServerlessSparkParameters.getResourceQueueId());
205249
startJobRunRequest.setCodeType(aliyunServerlessSparkParameters.getCodeType());
206250
startJobRunRequest.setName(aliyunServerlessSparkParameters.getJobName());
251+
207252
String engineReleaseVersion = aliyunServerlessSparkParameters.getEngineReleaseVersion();
208-
engineReleaseVersion =
209-
StringUtils.isEmpty(engineReleaseVersion) ? AliyunServerlessSparkConstants.DEFAULT_ENGINE
210-
: engineReleaseVersion;
211-
startJobRunRequest.setReleaseVersion(engineReleaseVersion);
253+
254+
if (engineReleaseVersion != null && !engineReleaseVersion.isEmpty()) {
255+
startJobRunRequest.setReleaseVersion(engineReleaseVersion);
256+
} else if (templateDisplayReleaseVersion != null && templateFusion != null) {
257+
startJobRunRequest.setDisplayReleaseVersion(templateDisplayReleaseVersion);
258+
startJobRunRequest.setFusion(templateFusion);
259+
}
260+
212261
Tag envTag = new Tag();
213262
envTag.setKey(AliyunServerlessSparkConstants.ENV_KEY);
214263
String envType = aliyunServerlessSparkParameters.isProduction() ? AliyunServerlessSparkConstants.ENV_PROD
@@ -243,4 +292,14 @@ protected CancelJobRunRequest buildCancelJobRunRequest() {
243292
cancelJobRunRequest.setRegionId(regionId);
244293
return cancelJobRunRequest;
245294
}
295+
296+
protected GetTemplateRequest buildGetTemplateRequest() {
297+
GetTemplateRequest getTemplateRequest = new GetTemplateRequest();
298+
299+
if (aliyunServerlessSparkParameters.getTemplateId() != null) {
300+
getTemplateRequest.setTemplateBizId(aliyunServerlessSparkParameters.getTemplateId());
301+
}
302+
303+
return getTemplateRequest;
304+
}
246305
}

dolphinscheduler-task-plugin/dolphinscheduler-task-aliyunserverlessspark/src/test/java/org/apache/dolphinscheduler/plugin/task/aliyunserverlessspark/AliyunServerlessSparkTaskTest.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.apache.dolphinscheduler.plugin.task.api.parameters.resource.ResourceParametersHelper;
3333
import org.apache.dolphinscheduler.spi.enums.DbType;
3434

35+
import java.util.Collections;
36+
3537
import lombok.extern.slf4j.Slf4j;
3638

3739
import org.junit.jupiter.api.Assertions;
@@ -51,9 +53,12 @@
5153
import com.aliyun.emr_serverless_spark20230808.models.GetJobRunRequest;
5254
import com.aliyun.emr_serverless_spark20230808.models.GetJobRunResponse;
5355
import com.aliyun.emr_serverless_spark20230808.models.GetJobRunResponseBody;
56+
import com.aliyun.emr_serverless_spark20230808.models.GetTemplateResponse;
57+
import com.aliyun.emr_serverless_spark20230808.models.GetTemplateResponseBody;
5458
import com.aliyun.emr_serverless_spark20230808.models.StartJobRunRequest;
5559
import com.aliyun.emr_serverless_spark20230808.models.StartJobRunResponse;
5660
import com.aliyun.emr_serverless_spark20230808.models.StartJobRunResponseBody;
61+
import com.aliyun.emr_serverless_spark20230808.models.Template;
5762

5863
@Slf4j
5964
@ExtendWith(MockitoExtension.class)
@@ -90,6 +95,9 @@ public class AliyunServerlessSparkTaskTest {
9095
@Mock
9196
private CancelJobRunResponse mockCancelJobRunResponse;
9297

98+
@Mock
99+
private GetTemplateResponse mockGetTemplateResponse;
100+
93101
@InjectMocks
94102
@Spy
95103
private AliyunServerlessSparkTask aliyunServerlessSparkTask;
@@ -124,6 +132,8 @@ public class AliyunServerlessSparkTaskTest {
124132

125133
private static final String mockEntryPointArguments = "10";
126134

135+
private static final String mockTemplateId = "TPL-XXXXX";
136+
127137
@BeforeEach
128138
public void before() {
129139
when(mockTaskExecutionContext.getTaskParams()).thenReturn(taskParamsString);
@@ -167,6 +177,12 @@ public void testHandle() {
167177
() -> doReturn(mockGetJobRunResponse).when(mockAliyunServerlessSparkClient).getJobRun(any(), any(),
168178
any()));
169179

180+
mockGetTemplateResponse = new GetTemplateResponse()
181+
.setBody(new GetTemplateResponseBody().setData(new Template().setSparkConf(Collections.emptyList())));
182+
Assertions.assertDoesNotThrow(
183+
() -> doReturn(mockGetTemplateResponse).when(mockAliyunServerlessSparkClient).getTemplate(any(),
184+
any()));
185+
170186
aliyunServerlessSparkTask.init();
171187
aliyunServerlessSparkTask.handle(mockTaskCallBack);
172188
verify(aliyunServerlessSparkTask).setAppIds(mockJobRunId);
@@ -190,6 +206,8 @@ public void testCancelApplication() throws Exception {
190206
public void testBuildStartJobRunRequest() {
191207
AliyunServerlessSparkParameters mockAliyunServerlessSparkParameters =
192208
mock(AliyunServerlessSparkParameters.class);
209+
doReturn(mockWorkspaceId).when(mockAliyunServerlessSparkParameters).getWorkspaceId();
210+
doReturn(mockTemplateId).when(mockAliyunServerlessSparkParameters).getTemplateId();
193211
doReturn(mockResourceQueueId).when(mockAliyunServerlessSparkParameters).getResourceQueueId();
194212
doReturn("JAR").when(mockAliyunServerlessSparkParameters).getCodeType();
195213
doReturn("ds-test").when(mockAliyunServerlessSparkParameters).getJobName();
@@ -198,12 +216,10 @@ public void testBuildStartJobRunRequest() {
198216
doReturn(mockEntryPointArguments).when(mockAliyunServerlessSparkParameters).getEntryPointArguments();
199217

200218
aliyunServerlessSparkTask.buildStartJobRunRequest(mockAliyunServerlessSparkParameters);
201-
202219
verify(mockAliyunServerlessSparkParameters).getResourceQueueId();
203220
verify(mockAliyunServerlessSparkParameters).getCodeType();
204221
verify(mockAliyunServerlessSparkParameters).getJobName();
205222
verify(mockAliyunServerlessSparkParameters).getEngineReleaseVersion();
206223
verify(mockAliyunServerlessSparkParameters).isProduction();
207224
}
208-
209225
}

dolphinscheduler-ui/src/locales/en_US/project.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,8 @@ export default {
922922
entry_point_arguments_tips: 'entry point arguments',
923923
spark_submit_parameters: 'spark submit parameters',
924924
spark_submit_parameters_tips: 'spark submit parameters',
925+
template_id: 'spark template id',
926+
template_id_tips: 'spark template id',
925927
is_production: 'is production',
926928
is_production_tips: 'is production',
927929
json_format_tips: 'Json parameters format is abnormal'

dolphinscheduler-ui/src/locales/zh_CN/project.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,8 @@ export default {
892892
entry_point_arguments_tips: 'entry point arguments',
893893
spark_submit_parameters: 'spark submit parameters',
894894
spark_submit_parameters_tips: 'spark submit parameters',
895+
template_id: 'spark template id',
896+
template_id_tips: 'spark template id',
895897
is_production: 'is production',
896898
is_production_tips: 'is production',
897899
json_format_tips: 'JSON参数格式异常'

dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-aliyun-serverless-spark.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,15 @@ export function useAliyunServerlessSpark(model: {
161161
}
162162
},
163163

164+
{
165+
type: 'input',
166+
field: 'templateId',
167+
name: t('project.node.template_id'),
168+
props: {
169+
placeholder: t('project.node.template_id_tips')
170+
}
171+
},
172+
164173
{
165174
type: 'switch',
166175
field: 'isProduction',

dolphinscheduler-ui/src/views/projects/task/components/node/format-data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ export function formatParams(data: INodeData): {
305305
taskParams.codeType = data.codeType
306306
taskParams.jobName = data.jobName
307307
taskParams.engineReleaseVersion = data.engineReleaseVersion
308+
taskParams.templateId = data.templateId
308309
taskParams.entryPoint = data.entryPoint
309310
taskParams.entryPointArguments = data.entryPointArguments
310311
taskParams.sparkSubmitParameters = data.sparkSubmitParameters

dolphinscheduler-ui/src/views/projects/task/components/node/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ interface ITaskParams {
357357
resourceQueueId?: string
358358
codeType?: string
359359
engineReleaseVersion?: string
360+
templateId?: string
360361
entryPoint?: string
361362
entryPointArguments?: string
362363
sparkSubmitParameters?: string

0 commit comments

Comments
 (0)