You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampark.apache.org by be...@apache.org on 2024/06/22 16:28:48 UTC
(incubator-streampark) 01/01: [Improve] job name validator improvement
This is an automated email from the ASF dual-hosted git repository.
benjobs pushed a commit to branch k8s-FE
in repository https://gitbox.apache.org/repos/asf/incubator-streampark.git
commit 8250fb0a3fb05558fdca6df78729960cc8125274
Author: benjobs <be...@gmail.com>
AuthorDate: Sun Jun 23 00:28:32 2024 +0800
[Improve] job name validator improvement
---
.../src/locales/lang/en/flink/app.ts | 12 ++++-
.../src/locales/lang/zh-CN/flink/app.ts | 39 +++++++++-------
.../src/locales/lang/zh-CN/setting/flinkCluster.ts | 14 +++---
.../flink/app/hooks/useCreateAndEditSchema.ts | 52 ++++++++++++++--------
.../src/views/flink/app/hooks/useFlinkRender.tsx | 40 +++++++++++++++++
5 files changed, 116 insertions(+), 41 deletions(-)
diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
index ff29d9980..32aa9b540 100644
--- a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
+++ b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
@@ -275,8 +275,18 @@ export default {
'The application name already exists in YARN, cannot be repeated. Please check',
appNameExistsInK8sMessage:
'The application name already exists in Kubernetes,cannot be repeated. Please check',
+ appNameValid: 'The job name is invalid',
+ appNameRole: 'The job name must follow these rules: ',
appNameNotValid:
'The application name is invalid, must be (Chinese or English or "-" or "_"), two consecutive spaces cannot appear.Please check',
+ K8sSessionClusterIdRole: 'The K8s clusterId must follow the following rules:',
+ appNameK8sClusterIdRole:
+ 'The current deployment mode is K8s Application mode, and the job name will be used as the clusterId in K8s. Therefore, the job name must follow the following rules:',
+ appNameK8sClusterIdRoleLength: 'must be no more than 45 characters',
+ appNameK8sClusterIdRoleRegexp:
+ 'must only contain lowercase alphanumeric characters and "-",The required format is [a-z]([-a-z0-9]*[a-z0-9])',
+ appNameRoleContent:
+ 'must be (Chinese or English or "-" or "_"), two consecutive spaces cannot appear.Please check',
flinkClusterIsRequiredMessage: 'Flink Cluster is required',
flinkSqlIsRequiredMessage: 'Flink SQL is required',
tagsPlaceholder: 'Please enter tags,if more than one, separate them with commas(,)',
@@ -296,7 +306,7 @@ export default {
flinkImagePlaceholder:
'Please enter the tag of Flink base docker image, such as: flink:1.13.0-scala_2.11-java8',
flinkImageIsRequiredMessage: 'Flink Base Docker Image is required',
- k8sRestExposedTypePlaceholder: 'kubernetes.rest-service.exposed.type',
+ k8sRestExposedTypePlaceholder: 'Kubernetes Rest-Service Exposed Type',
hadoopXmlConfigFileTips:
'Automatically copy configuration files from system environment parameters',
dynamicPropertiesPlaceholder:
diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
index 2aee8d0cb..a3d55c7fa 100644
--- a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
+++ b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
@@ -47,10 +47,10 @@ export default {
yarnQueue: 'Yarn队列',
mavenPom: 'maven pom',
uploadJar: '上传依赖Jar文件',
- kubernetesNamespace: 'K8S命名空间',
- kubernetesClusterId: 'K8S ClusterId',
- flinkBaseDockerImage: 'Flink基础docker镜像',
- restServiceExposedType: 'K8S服务对外类型',
+ kubernetesNamespace: 'Kubernetes 命名空间',
+ kubernetesClusterId: 'Kubernetes ClusterId',
+ flinkBaseDockerImage: 'Flink 基础docker镜像',
+ restServiceExposedType: 'Rest-Service Exposed Type',
resourceFrom: '资源来源',
uploadJobJar: '上传jar文件',
selectJobJar: '选择jar文件',
@@ -71,7 +71,7 @@ export default {
hadoopUser: 'Hadoop User',
restoreModeTip: 'flink 1.15开始支持restore模式,一般情况下不用设置该参数',
release: {
- releaseTitle: '该应用程序的当前启动正在进行中.',
+ releaseTitle: '该作业正在启动中.',
releaseDesc: '您确定要强制进行另一次构建吗',
releaseFail: '发布作业失败',
releasing: '当前作业正在发布中',
@@ -153,11 +153,11 @@ export default {
errorLog: '错误日志',
errorSummary: '错误摘要',
errorStack: '错误堆栈',
- logTitle: '启动日志 : 应用名称 [ {0} ]',
+ logTitle: '启动日志 : 作业名称 [ {0} ]',
refreshTime: '上次刷新时间',
refresh: '刷新',
start: '启动作业',
- stop: '停止应用',
+ stop: '停止作业',
savepoint: '触发 Savepoint',
recheck: '关联的项目已更新,需要重新发布此作业',
changed: '作业已更新',
@@ -265,10 +265,19 @@ export default {
appNamePlaceholder: '请输入作业名称',
appNameIsRequiredMessage: '作业名称必填',
appNameNotUniqueMessage: '作业名称必须唯一, 输入的作业名称已经存在',
- appNameExistsInYarnMessage: '应用程序名称已经在YARN集群中存在,不能重复。请检查',
- appNameExistsInK8sMessage: '该应用程序名称已经在K8S集群中存在,不能重复。请检查',
+ appNameExistsInYarnMessage: '作业名称已经在YARN集群中存在,不能重复。请检查',
+ appNameExistsInK8sMessage: '该作业名称已经在 Kubernetes 集群中存在,不能重复。请检查',
+ appNameValid: '作业名称不合法',
+ appNameRole: '作业必须遵循以下规则:',
+ K8sSessionClusterIdRole: 'Kubernetes 集群ID必要遵循以下规则:',
+ appNameK8sClusterIdRole:
+ '当前部署模式是 Kubernetes Application 模式,会将作业名称作为 Kubernetes 的 clusterId,因此作业名称要遵循以下规则:',
+ appNameK8sClusterIdRoleLength: '不应超过 45 个字符',
+ appNameK8sClusterIdRoleRegexp:
+ '只能由小写字母、数字、字符、和"-" 组成,必须满足正则格式 [a-z]([-a-z0-9]*[a-z0-9])',
+ appNameRoleContent: '字符必须是(中文 或 英文 或 "-" 或 "_"),不能出现两个连续的空格',
appNameNotValid:
- '应用程序名称无效。字符必须是(中文 或 英文 或 "-" 或 "_"),不能出现两个连续的空格,请检查',
+ '作业名称无效。字符必须是(中文 或 英文 或 "-" 或 "_"),不能出现两个连续的空格,请检查',
flinkClusterIsRequiredMessage: 'Flink集群必填',
flinkSqlIsRequiredMessage: 'Flink SQL必填',
tagsPlaceholder: '请输入标签,如果超过一个,用逗号(,)分隔',
@@ -279,15 +288,15 @@ export default {
totalMemoryOptionsPlaceholder: '请选择要设置的资源参数',
tmPlaceholder: '请选择要设置的资源参数',
yarnQueuePlaceholder: '请输入yarn队列标签名称',
- descriptionPlaceholder: '请输入此应用程序的描述',
- kubernetesNamespacePlaceholder: '请输入K8S命名空间, 如: default',
- kubernetesClusterIdPlaceholder: '请选择K8S ClusterId',
+ descriptionPlaceholder: '请输入此作业的描述',
+ kubernetesNamespacePlaceholder: '请输入 Kubernetes 命名空间, 如: default',
+ kubernetesClusterIdPlaceholder: '请选择 Kubernetes ClusterId',
kubernetesClusterIdRequire:
'小写字母、数字、“-”,并且必须以字母数字字符开头和结尾,并且不超过45个字符',
- kubernetesClusterIdIsRequiredMessage: 'K8S ClusterId必填',
+ kubernetesClusterIdIsRequiredMessage: 'Kubernetes ClusterId 必填',
flinkImagePlaceholder: '请输入Flink基础docker镜像的标签,如:flink:1.13.0-scala_2.11-java8',
flinkImageIsRequiredMessage: 'Flink基础docker镜像是必填的',
- k8sRestExposedTypePlaceholder: 'K8S服务对外类型',
+ k8sRestExposedTypePlaceholder: 'Kubernetes Rest-Service Exposed Type',
hadoopXmlConfigFileTips: '从系统环境参数自动复制配置文件',
dynamicPropertiesPlaceholder: '$key=$value,如果有多个参数,可以换行输入(-D <arg>)',
},
diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/setting/flinkCluster.ts b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/setting/flinkCluster.ts
index 4e926d749..9cfdb9b84 100644
--- a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/setting/flinkCluster.ts
+++ b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/setting/flinkCluster.ts
@@ -32,12 +32,12 @@ export default {
addNew: '全新集群',
yarnQueue: 'Yarn队列',
yarnSessionClusterId: 'Yarn Session模式集群ID',
- k8sNamespace: 'k8s命名空间',
- k8sClusterId: 'k8s集群ID',
- serviceAccount: 'k8s命名空间绑定的服务账号',
- k8sConf: 'k8s环境Kube配置文件',
- flinkImage: 'Flink基础docker镜像',
- k8sRestExposedType: 'K8S服务对外类型',
+ k8sNamespace: 'Kubernetes 命名空间',
+ k8sClusterId: 'Kubernetes 集群 ID',
+ serviceAccount: 'Kubernetes 服务账号',
+ k8sConf: 'Kube 配置文件',
+ flinkImage: 'Flink 基础 Docker 镜像',
+ k8sRestExposedType: 'Kubernetes Rest exposed-type',
resolveOrder: '类加载顺序',
taskSlots: '任务槽数',
jmOptions: 'JM内存',
@@ -54,7 +54,7 @@ export default {
addressNoRemoteMode: '请输入集群地址,例如:http://host:port',
yarnSessionClusterId: '请输入Yarn Session模式集群ID',
k8sConf: '示例:~/.kube/config',
- flinkImage: '请输入Flink基础docker镜像的标签,如:flink:1.13.0-scala_2.11-java8',
+ flinkImage: '请输入 Flink 基础 docker 镜像的标签,如:flink:1.13.0-scala_2.11-java8',
k8sRestExposedType: 'kubernetes.rest-service.exposed.type',
resolveOrder: 'classloader.resolve-order',
taskSlots: '每个TaskManager的插槽数',
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts
index 25847a28f..d3263d2a1 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts
@@ -29,6 +29,7 @@ import {
renderTotalMemory,
renderYarnQueue,
renderFlinkCluster,
+ renderJobName,
} from './useFlinkRender';
import { fetchCheckName } from '/@/api/flink/app';
@@ -279,26 +280,33 @@ export const useCreateAndEditSchema = (
});
/* Detect job name field */
- async function getJobNameCheck(_rule: RuleObject, value: StoreValue) {
+ async function getJobNameCheck(_rule: RuleObject, value: StoreValue, model: Recordable) {
if (value === null || value === undefined || value === '') {
return Promise.reject(t('flink.app.addAppTips.appNameIsRequiredMessage'));
- } else {
- const params = { jobName: value };
- if (edit?.appId) Object.assign(params, { id: edit.appId });
- const res = await fetchCheckName(params);
- switch (parseInt(res)) {
- case 0:
- return Promise.resolve();
- case 1:
- return Promise.reject(t('flink.app.addAppTips.appNameNotUniqueMessage'));
- case 2:
- return Promise.reject(t('flink.app.addAppTips.appNameExistsInYarnMessage'));
- case 3:
- return Promise.reject(t('flink.app.addAppTips.appNameExistsInK8sMessage'));
- default:
- return Promise.reject(t('flink.app.addAppTips.appNameNotValid'));
+ }
+ if (model.executionMode == ExecModeEnum.KUBERNETES_APPLICATION) {
+ const regexp = /^(?=.{1,45}$)[a-z]([-a-z0-9]*[a-z0-9])$/;
+ if (!regexp.test(value)) {
+ return Promise.reject(t('flink.app.addAppTips.appNameValid'));
}
}
+ const params = { jobName: value };
+ if (edit?.appId) {
+ Object.assign(params, { id: edit.appId });
+ }
+ const res = await fetchCheckName(params);
+ switch (parseInt(res)) {
+ case 0:
+ return Promise.resolve();
+ case 1:
+ return Promise.reject(t('flink.app.addAppTips.appNameNotUniqueMessage'));
+ case 2:
+ return Promise.reject(t('flink.app.addAppTips.appNameExistsInYarnMessage'));
+ case 3:
+ return Promise.reject(t('flink.app.addAppTips.appNameExistsInK8sMessage'));
+ default:
+ return Promise.reject(t('flink.app.addAppTips.appNameValid'));
+ }
}
const getFlinkFormOtherSchemas = computed((): FormSchema[] => {
@@ -313,8 +321,16 @@ export const useCreateAndEditSchema = (
label: t('flink.app.appName'),
component: 'Input',
componentProps: { placeholder: t('flink.app.addAppTips.appNamePlaceholder') },
- dynamicRules: () => {
- return [{ required: true, trigger: 'blur', validator: getJobNameCheck }];
+ render: (param) => renderJobName(param),
+ dynamicRules: ({ model }) => {
+ return [
+ {
+ required: true,
+ trigger: 'blur',
+ validator: (rule: RuleObject, value: StoreValue) =>
+ getJobNameCheck(rule, value, model),
+ },
+ ];
},
},
{
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx
index 45b22f1d5..62975b584 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx
@@ -44,6 +44,7 @@ import {
FailoverStrategyEnum,
RestoreModeEnum,
ClusterStateEnum,
+ ExecModeEnum,
} from '/@/enums/flinkEnum';
import { useI18n } from '/@/hooks/web/useI18n';
import { fetchYarnQueueList } from '/@/api/setting/yarnQueue';
@@ -299,6 +300,45 @@ export const renderFlinkCluster = (clusters, { model, field }: RenderCallbackPar
);
};
+export const renderJobName = ({ model, field }: RenderCallbackParams) => {
+ return (
+ <div>
+ <Input
+ name="jobName"
+ placeholder={t('flink.app.addAppTips.appNamePlaceholder')}
+ value={model[field]}
+ onInput={(e: ChangeEvent) => (model[field] = e?.target?.value)}
+ />
+ <p class="conf-desc mt-10px">
+ <span class="note-info">
+ <Tag color="#2db7f5" class="tag-note">
+ {t('flink.app.noteInfo.note')}
+ </Tag>
+ {model.executionMode == ExecModeEnum.KUBERNETES_APPLICATION && (
+ <span>
+ {t('flink.app.addAppTips.appNameK8sClusterIdRole')}
+ <div>
+ <Tag color="orange"> 1.</Tag>
+ {t('flink.app.addAppTips.appNameK8sClusterIdRoleLength')}
+ </div>
+ <div>
+ <Tag color="orange"> 2.</Tag>
+ {t('flink.app.addAppTips.appNameK8sClusterIdRoleRegexp')}
+ </div>
+ </span>
+ )}
+ {model.executionMode != ExecModeEnum.KUBERNETES_APPLICATION && (
+ <span>
+ <span>{t('flink.app.addAppTips.appNameRole')}</span>
+ <span>{t('flink.app.addAppTips.appNameRoleContent')}</span>
+ </span>
+ )}
+ </span>
+ </p>
+ </div>
+ );
+};
+
/* render memory option */
export const renderDynamicProperties = ({ model, field }: RenderCallbackParams) => {
return (