Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@
import org.apache.dolphinscheduler.api.validator.ITransformer;
import org.apache.dolphinscheduler.dao.entity.WorkflowDefinition;
import org.apache.dolphinscheduler.dao.repository.WorkflowDefinitionDao;
import org.apache.dolphinscheduler.plugin.task.api.enums.Direct;
import org.apache.dolphinscheduler.plugin.task.api.model.Property;
import org.apache.dolphinscheduler.plugin.task.api.utils.PropertyUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.druid.util.StringUtils;

@Slf4j
@Component
public class TriggerWorkflowRequestTransformer implements ITransformer<WorkflowTriggerRequest, TriggerWorkflowDTO> {
Expand All @@ -39,6 +47,11 @@ public class TriggerWorkflowRequestTransformer implements ITransformer<WorkflowT

@Override
public TriggerWorkflowDTO transform(WorkflowTriggerRequest workflowTriggerRequest) {
List<Property> startParamList =
PropertyUtils.startParamsTransformPropertyList(workflowTriggerRequest.getStartParamList());

validateStartParamList(startParamList);

TriggerWorkflowDTO triggerWorkflowDTO = TriggerWorkflowDTO.builder()
.loginUser(workflowTriggerRequest.getLoginUser())
.startNodes(WorkflowUtils.parseStartNodeList(workflowTriggerRequest.getStartNodes()))
Expand All @@ -51,8 +64,7 @@ public TriggerWorkflowDTO transform(WorkflowTriggerRequest workflowTriggerReques
.workerGroup(workflowTriggerRequest.getWorkerGroup())
.tenantCode(workflowTriggerRequest.getTenantCode())
.environmentCode(workflowTriggerRequest.getEnvironmentCode())
.startParamList(
PropertyUtils.startParamsTransformPropertyList(workflowTriggerRequest.getStartParamList()))
.startParamList(startParamList)
.dryRun(workflowTriggerRequest.getDryRun())
.build();

Expand All @@ -64,4 +76,30 @@ public TriggerWorkflowDTO transform(WorkflowTriggerRequest workflowTriggerReques
triggerWorkflowDTO.setWorkflowDefinition(workflowDefinition);
return triggerWorkflowDTO;
}

private void validateStartParamList(List<Property> startParamList) {
if (startParamList == null || startParamList.isEmpty()) {
return;
}
Comment on lines +81 to +83
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (startParamList == null || startParamList.isEmpty()) {
return;
}
if (CollectionUtils.isEmpty(startParamList)) {
return;
}


Set<String> keys = new HashSet<>();
for (Property param : startParamList) {
// null key
if (StringUtils.isEmpty(param.getProp())) {
throw new ServiceException("Parameter key cannot be empty");
}

String key = param.getProp().trim();
// duplicate keys
if (keys.contains(key)) {
throw new ServiceException("Duplicate parameter key: " + key);
}
keys.add(key);

// IN-type params require a non-empty value
if (Direct.IN.equals(param.getDirect()) && StringUtils.isEmpty(param.getValue())) {
throw new ServiceException("IN parameter value cannot be empty for key: " + key);
}
Comment on lines +87 to +102
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// null key
if (StringUtils.isEmpty(param.getProp())) {
throw new ServiceException("Parameter key cannot be empty");
}
String key = param.getProp().trim();
// duplicate keys
if (keys.contains(key)) {
throw new ServiceException("Duplicate parameter key: " + key);
}
keys.add(key);
// IN-type params require a non-empty value
if (Direct.IN.equals(param.getDirect()) && StringUtils.isEmpty(param.getValue())) {
throw new ServiceException("IN parameter value cannot be empty for key: " + key);
}
if (StringUtils.isEmpty(param.getProp())) {
throw new ServiceException("Parameter key cannot be empty");
}
String key = param.getProp().trim();
if (keys.contains(key)) {
throw new ServiceException("Duplicate parameter key: " + key);
}
if (Direct.IN.equals(param.getDirect()) && StringUtils.isEmpty(param.getValue())) {
throw new ServiceException("IN parameter value cannot be empty for key: " + key);
}
keys.add(key);

}
}
}
5 changes: 3 additions & 2 deletions dolphinscheduler-ui/src/locales/en_US/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,9 @@ export default {
update_directly: 'Whether to update the workflow definition',
dag_name_empty: 'DAG graph name cannot be empty',
positive_integer: 'Please enter a positive integer greater than 0',
prop_empty: 'prop is empty',
prop_repeat: 'prop is repeat',
prop_key_repeat: 'prop key is repeat',
prop_key_empty: 'prop key is empty',
prop_value_empty: 'prop value is empty',
node_not_created: 'Failed to save node not created',
copy_name: 'Copy Name',
view_variables: 'View Variables',
Expand Down
5 changes: 3 additions & 2 deletions dolphinscheduler-ui/src/locales/zh_CN/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,9 @@ export default {
update_directly: '是否更新工作流定义',
dag_name_empty: 'DAG图名称不能为空',
positive_integer: '请输入大于 0 的正整数',
prop_empty: '自定义参数prop不能为空',
prop_repeat: 'prop中有重复',
prop_key_repeat: '自定义参数prop中key有重复',
prop_key_empty: '自定义参数prop中key不能为空',
prop_value_empty: '自定义参数prop中value不能为空',
node_not_created: '未创建节点保存失败',
copy_name: '复制名称',
view_variables: '查看变量',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,23 +98,29 @@ export default defineComponent({
},
globalParams: {
validator() {
const props = new Set()
const globalParams = formValue.value.globalParams || []

const keys = formValue.value.globalParams.map((item) => item.key)
const keysSet = new Set(keys)
if (keysSet.size !== keys.length) {
return new Error(t('project.dag.prop_repeat'))
if (!globalParams || globalParams.length === 0) return true

const keys = globalParams.map((item) => item.key)
const uniqueKeys = new Set(keys)
if (uniqueKeys.size !== keys.length) {
return new Error(t('project.dag.prop_key_repeat'))
}

for (const param of formValue.value.globalParams) {
const prop = param.value
const direct = param.direct
if (direct === 'IN' && !prop) {
return new Error(t('project.dag.prop_empty'))
for (const param of globalParams) {
if (!param.key || param.key.trim() === '') {
return new Error(t('project.dag.prop_key_empty'))
}

props.add(prop)
if (
param.direct === 'IN' &&
(!param.value || param.value.trim() === '')
) {
return new Error(t('project.dag.prop_value_empty'))
}
}
return true
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,13 @@ export default defineComponent({
}
)

const formModel = computed(() => ({
// UI configuration state from form management hook
...startState.startForm,
// Business data injected from modal operations hook
startParamsList: variables.startParamsList
Comment on lines +294 to +297
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// UI configuration state from form management hook
...startState.startForm,
// Business data injected from modal operations hook
startParamsList: variables.startParamsList
...startState.startForm,
startParamsList: variables.startParamsList

}))

return {
t,
showTaskDependType,
Expand All @@ -302,6 +309,7 @@ export default defineComponent({
removeStartParams,
addStartParams,
updateParamsList,
formModel,
...toRefs(variables),
...toRefs(startState),
...toRefs(props),
Expand All @@ -319,7 +327,7 @@ export default defineComponent({
onConfirm={this.handleStart}
confirmLoading={this.saving}
>
<NForm ref='startFormRef' model={this.startForm} rules={this.rules}>
<NForm ref='startFormRef' model={this.formModel} rules={this.rules}>
<NFormItem
label={t('project.workflow.workflow_name')}
path='workflow_name'
Expand Down Expand Up @@ -577,13 +585,13 @@ export default defineComponent({
)}
<NFormItem
label={t('project.workflow.startup_parameter')}
path='startup_parameter'
path='startParamsList'
>
<NDynamicInput
v-model:value={this.startParamsList}
onCreate={() => {
return {
key: '',
prop: '',
direct: 'IN',
type: 'VARCHAR',
value: ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,34 @@ export const useForm = () => {
return new Error(t('project.workflow.warning_group_tip'))
}
}
},
startParamsList: {
trigger: ['input', 'blur'],
validator: (rule: any, value: Array<any>) => {
const params = value || []

if (!params || params.length === 0) return true

const keys = params.map((item) => item.prop)
const uniqueKeys = new Set(keys)
if (uniqueKeys.size !== keys.length) {
return new Error(t('project.dag.prop_key_repeat'))
}

for (const param of params) {
if (!param.prop || param.prop.trim() === '') {
return new Error(t('project.dag.prop_key_empty'))
}

if (
param.direct === 'IN' &&
(!param.value || param.value.trim() === '')
) {
return new Error(t('project.dag.prop_value_empty'))
}
}
return true
}
}
}
})
Expand Down
Loading