Browse Source

[Feature][UI Next] Add http into task. (#8447)

Amy0104 3 years ago
parent
commit
02e47da30b

+ 18 - 1
dolphinscheduler-ui-next/src/locales/modules/en_US.ts

@@ -613,6 +613,7 @@ const project = {
     prop_tips: 'prop(required)',
     prop_repeat: 'prop is repeat',
     value_tips: 'value(optional)',
+    value_required_tips: 'value(required)',
     pre_tasks: 'Pre tasks',
     program_type: 'Program Type',
     spark_version: 'Spark Version',
@@ -653,7 +654,23 @@ const project = {
       'If there are a large number of tasks requiring complement, you can use the custom parallelism to ' +
       'set the complement task thread to a reasonable value to avoid too large impact on the server.',
     task_manager_number: 'TaskManager Number',
-    task_manager_number_tips: 'Please enter TaskManager number'
+    task_manager_number_tips: 'Please enter TaskManager number',
+    http_url: 'Http Url',
+    http_url_tips: 'Please Enter Http Url',
+    http_method: 'Http Method',
+    http_parameters: 'Http Parameters',
+    http_check_condition: 'Http Check Condition',
+    http_condition: 'Http Condition',
+    http_condition_tips: 'Please Enter Http Condition',
+    timeout_settings: 'Timeout Settings',
+    connect_timeout: 'Connect Timeout',
+    ms: 'ms',
+    socket_timeout: 'Socket Timeout',
+    status_code_default: 'Default response code 200',
+    status_code_custom: 'Custom response code',
+    body_contains: 'Content includes',
+    body_not_contains: 'Content does not contain',
+    http_parameters_position: 'Http Parameters Position'
   }
 }
 

+ 18 - 1
dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts

@@ -606,6 +606,7 @@ const project = {
     prop_tips: 'prop(必填)',
     prop_repeat: 'prop中有重复',
     value_tips: 'value(选填)',
+    value_required_tips: 'value(必填)',
     pre_tasks: '前置任务',
     program_type: '程序类型',
     spark_version: 'Spark版本',
@@ -645,7 +646,23 @@ const project = {
     parallelism_complement_tips:
       '如果存在大量任务需要补数时,可以利用自定义并行度将补数的任务线程设置成合理的数值,避免对服务器造成过大的影响',
     task_manager_number: 'TaskManager数量',
-    task_manager_number_tips: '请输入TaskManager数量'
+    task_manager_number_tips: '请输入TaskManager数量',
+    http_url: '请求地址',
+    http_url_tips: '请填写请求地址(必填)',
+    http_method: '请求类型',
+    http_parameters: '请求参数',
+    http_check_condition: '校验条件',
+    http_condition: '校验内容',
+    http_condition_tips: '请填写校验内容',
+    timeout_settings: '超时设置',
+    connect_timeout: '连接超时',
+    ms: '毫秒',
+    socket_timeout: 'Socket超时',
+    status_code_default: '默认响应码200',
+    status_code_custom: '自定义响应码',
+    body_contains: '内容包含',
+    body_not_contains: '内容不包含',
+    http_parameters_position: '参数位置'
   }
 }
 

+ 1 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/index.ts

@@ -34,3 +34,4 @@ export { useShell } from './use-shell'
 export { useSpark } from './use-spark'
 export { useMr } from './use-mr'
 export { useFlink } from './use-flink'
+export { useHttp } from './use-http'

+ 274 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/fields/use-http.ts

@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+import { computed } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { IJsonItem } from '../types'
+
+export function useHttp(model: { [field: string]: any }): IJsonItem[] {
+  const { t } = useI18n()
+  const timeoutSpan = computed(() => (model.timeoutSetting ? 12 : 0))
+
+  const HTTP_CHECK_CONDITIONs = [
+    {
+      label: t('project.node.status_code_default'),
+      value: 'STATUS_CODE_DEFAULT'
+    },
+    {
+      label: t('project.node.status_code_custom'),
+      value: 'STATUS_CODE_CUSTOM'
+    },
+    {
+      label: t('project.node.body_contains'),
+      value: 'BODY_CONTAINS'
+    },
+    {
+      label: t('project.node.body_not_contains'),
+      value: 'BODY_NOT_CONTAINS'
+    }
+  ]
+
+  return [
+    {
+      type: 'input',
+      field: 'url',
+      name: t('project.node.http_url'),
+      props: {
+        placeholder: t('project.node.http_url_tips')
+      },
+      validate: {
+        trigger: ['input', 'blur'],
+        required: true,
+        validator(validate: any, value: string) {
+          if (!value) {
+            return new Error(t('project.node.http_url_tips'))
+          }
+        }
+      }
+    },
+    {
+      type: 'select',
+      field: 'httpMethod',
+      span: 12,
+      name: t('project.node.http_method'),
+      options: HTTP_METHODS
+    },
+    {
+      type: 'custom-parameters',
+      field: 'httpParams',
+      name: t('project.node.http_parameters'),
+      children: [
+        {
+          type: 'input',
+          field: 'prop',
+          span: 6,
+          props: {
+            placeholder: t('project.node.prop_tips'),
+            maxLength: 256
+          },
+          validate: {
+            trigger: ['input', 'blur'],
+            required: true,
+            validator(validate: any, value: string) {
+              if (!value) {
+                return new Error(t('project.node.prop_tips'))
+              }
+
+              const sameItems = model.localParams.filter(
+                (item: { prop: string }) => item.prop === value
+              )
+
+              if (sameItems.length > 1) {
+                return new Error(t('project.node.prop_repeat'))
+              }
+            }
+          }
+        },
+        {
+          type: 'select',
+          field: 'httpParametersType',
+          span: 6,
+          options: POSITIONS,
+          value: 'PARAMETER'
+        },
+        {
+          type: 'input',
+          field: 'value',
+          span: 6,
+          props: {
+            placeholder: t('project.node.value_tips'),
+            maxLength: 256
+          },
+          validate: {
+            trigger: ['input', 'blur'],
+            required: true,
+            validator(validate: any, value: string) {
+              if (!value) {
+                return new Error(t('project.node.value_required_tips'))
+              }
+            }
+          }
+        }
+      ]
+    },
+    {
+      type: 'select',
+      field: 'httpCheckCondition',
+      name: t('project.node.http_check_condition'),
+      options: HTTP_CHECK_CONDITIONs
+    },
+    {
+      type: 'input',
+      field: 'condition',
+      name: t('project.node.http_condition'),
+      props: {
+        type: 'textarea',
+        placeholder: t('project.node.http_condition_tips')
+      }
+    },
+    {
+      type: 'switch',
+      field: 'timeoutSetting',
+      name: t('project.node.timeout_settings')
+    },
+    {
+      type: 'input-number',
+      field: 'connectTimeout',
+      name: t('project.node.connect_timeout'),
+      span: timeoutSpan,
+      props: {
+        max: Math.pow(7, 10) - 1
+      },
+      slots: {
+        suffix: () => t('project.node.ms')
+      },
+      validate: {
+        trigger: ['input', 'blur'],
+        validator(validate: any, value: string) {
+          if (!Number.isInteger(parseInt(value))) {
+            return new Error(
+              t('project.node.connect_timeout') +
+                t('project.node.positive_integer_tips')
+            )
+          }
+        }
+      }
+    },
+    {
+      type: 'input-number',
+      field: 'socketTimeout',
+      name: t('project.node.socket_timeout'),
+      span: timeoutSpan,
+      props: {
+        max: Math.pow(7, 10) - 1
+      },
+      slots: {
+        suffix: () => t('project.node.ms')
+      },
+      validate: {
+        trigger: ['input', 'blur'],
+        validator(validate: any, value: string) {
+          if (!Number.isInteger(parseInt(value))) {
+            return new Error(
+              t('project.node.socket_timeout') +
+                t('project.node.positive_integer_tips')
+            )
+          }
+        }
+      }
+    },
+    {
+      type: 'custom-parameters',
+      field: 'localParams',
+      name: t('project.node.custom_parameters'),
+      children: [
+        {
+          type: 'input',
+          field: 'prop',
+          span: 6,
+          props: {
+            placeholder: t('project.node.prop_tips'),
+            maxLength: 256
+          },
+          validate: {
+            trigger: ['input', 'blur'],
+            required: true,
+            validator(validate: any, value: string) {
+              if (!value) {
+                return new Error(t('project.node.prop_tips'))
+              }
+
+              const sameItems = model.localParams.filter(
+                (item: { prop: string }) => item.prop === value
+              )
+
+              if (sameItems.length > 1) {
+                return new Error(t('project.node.prop_repeat'))
+              }
+            }
+          }
+        },
+        {
+          type: 'input',
+          field: 'value',
+          span: 6,
+          props: {
+            placeholder: t('project.node.value_tips'),
+            maxLength: 256
+          }
+        }
+      ]
+    }
+  ]
+}
+
+const HTTP_METHODS = [
+  {
+    value: 'GET',
+    label: 'GET'
+  },
+  {
+    value: 'POST',
+    label: 'POST'
+  },
+  {
+    value: 'HEAD',
+    label: 'HEAD'
+  },
+  {
+    value: 'PUT',
+    label: 'PUT'
+  },
+  {
+    value: 'DELETE',
+    label: 'DELETE'
+  }
+]
+
+const POSITIONS = [
+  {
+    value: 'PARAMETER',
+    label: 'Parameter'
+  },
+  {
+    value: 'BODY',
+    label: 'Body'
+  },
+  {
+    value: 'HEADERS',
+    label: 'Headers'
+  }
+]

+ 15 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/format-data.ts

@@ -57,6 +57,15 @@ export function formatParams(data: INodeData): {
     taskParams.taskManager = data.taskManager
     taskParams.parallelism = data.parallelism
   }
+  if (data.taskType === 'HTTP') {
+    taskParams.httpMethod = data.httpMethod
+    taskParams.httpCheckCondition = data.httpCheckCondition
+    taskParams.httpParams = data.httpParams
+    taskParams.url = data.url
+    taskParams.condition = data.condition
+    taskParams.connectTimeout = data.connectTimeout
+    taskParams.socketTimeout = data.socketTimeout
+  }
 
   const params = {
     processDefinitionCode: data.processName ? String(data.processName) : '',
@@ -124,6 +133,12 @@ export function formatModel(data: ITaskData) {
       (item: { id: number }) => item.id
     )
   }
+  if (
+    data.taskParams?.connectTimeout !== 60000 ||
+    data.taskParams?.socketTimeout !== 60000
+  ) {
+    params.timeoutSetting = true
+  }
   if (data.taskParams?.mainJar) {
     params.mainJar = data.taskParams?.mainJar.id
   }

+ 89 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/tasks/use-http.ts

@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+import { reactive } from 'vue'
+import * as Fields from '../fields/index'
+import type { IJsonItem, INodeData, ITaskData } from '../types'
+
+export function useHttp({
+  projectCode,
+  from = 0,
+  readonly,
+  data
+}: {
+  projectCode: number
+  from?: number
+  readonly?: boolean
+  data?: ITaskData
+}) {
+  const model = reactive({
+    taskType: 'HTTP',
+    name: '',
+    flag: 'YES',
+    description: '',
+    timeoutFlag: false,
+    localParams: [],
+    environmentCode: null,
+    failRetryInterval: 1,
+    failRetryTimes: 0,
+    workerGroup: 'default',
+    delayTime: 0,
+    timeout: 30,
+    httpMethod: 'GET',
+    httpCheckCondition: 'STATUS_CODE_DEFAULT',
+    httpParams: [],
+    url: '',
+    condition: '',
+    timeoutSetting: false,
+    connectTimeout: 60000,
+    socketTimeout: 60000
+  } as INodeData)
+
+  let extra: IJsonItem[] = []
+  if (from === 1) {
+    extra = [
+      Fields.useTaskType(model, readonly),
+      Fields.useProcessName({
+        model,
+        projectCode,
+        isCreate: !data?.id,
+        from,
+        processName: data?.processName,
+        code: data?.code
+      })
+    ]
+  }
+
+  return {
+    json: [
+      Fields.useName(),
+      ...extra,
+      Fields.useRunFlag(),
+      Fields.useDescription(),
+      Fields.useTaskPriority(),
+      Fields.useWorkerGroup(),
+      Fields.useEnvironmentName(model, !data?.id),
+      ...Fields.useTaskGroup(model, projectCode),
+      ...Fields.useFailed(),
+      Fields.useDelayTime(model),
+      ...Fields.useTimeoutAlarm(model),
+      ...Fields.useHttp(model),
+      Fields.usePreTasks(model)
+    ] as IJsonItem[],
+    model
+  }
+}

+ 8 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/types.ts

@@ -63,6 +63,13 @@ interface ITaskParams {
   executorCores?: number
   mainArgs?: string
   others?: string
+  httpMethod?: string
+  httpCheckCondition?: string
+  httpParams?: []
+  url?: string
+  condition?: string
+  connectTimeout?: number
+  socketTimeout?: number
 }
 
 type ITaskType = TaskType
@@ -91,6 +98,7 @@ interface INodeData extends Omit<ITaskParams, 'resourceList' | 'mainJar'> {
   postTaskOptions?: []
   resourceList?: number[]
   mainJar?: number
+  timeoutSetting?: boolean
 }
 
 interface ITaskData

+ 9 - 0
dolphinscheduler-ui-next/src/views/projects/task/components/node/use-task.ts

@@ -21,6 +21,7 @@ import { useSubProcess } from './tasks/use-sub-process'
 import { usePython } from './tasks/use-python'
 import { useSpark } from './tasks/use-spark'
 import { useMr } from './tasks/use-mr'
+import { useHttp } from './tasks/use-http'
 import { IJsonItem, INodeData, ITaskData } from './types'
 
 export function useTask({
@@ -84,5 +85,13 @@ export function useTask({
       data
     })
   }
+  if (taskType === 'HTTP') {
+    node = useHttp({
+      projectCode,
+      from,
+      readonly,
+      data
+    })
+  }
   return node
 }