You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by zh...@apache.org on 2022/02/17 05:51:27 UTC

[dolphinscheduler] branch dev updated: [Feature][UI Next] Add k8s namespace. (#8411)

This is an automated email from the ASF dual-hosted git repository.

zhongjiajie pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new d912929  [Feature][UI Next] Add k8s namespace. (#8411)
d912929 is described below

commit d9129297abac14aba74e87009477fc3502ac116b
Author: songjianet <17...@qq.com>
AuthorDate: Thu Feb 17 13:51:21 2022 +0800

    [Feature][UI Next] Add k8s namespace. (#8411)
---
 .../src/layouts/content/use-dataList.ts            |   8 +-
 .../src/locales/modules/en_US.ts                   |  24 +++
 .../src/locales/modules/zh_CN.ts                   |  24 +++
 .../src/router/modules/security.ts                 |  10 +
 .../src/service/modules/k8s-namespace/index.ts     |  62 +++++++
 .../src/service/modules/k8s-namespace/types.ts     |  52 ++++++
 .../views/security/environment-manage/index.tsx    |  13 +-
 .../components/k8s-namespace-modal.tsx             | 194 ++++++++++++++++++++
 .../k8s-namespace-manage/components/use-modal.ts   |  99 ++++++++++
 .../k8s-namespace-manage/index.module.scss         |  32 ++++
 .../index.tsx                                      |  25 +--
 .../security/k8s-namespace-manage/use-table.ts     | 201 +++++++++++++++++++++
 .../security/token-manage/components/use-modal.ts  |   1 -
 13 files changed, 729 insertions(+), 16 deletions(-)

diff --git a/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts b/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
index 21d5f5f..0118e93 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
+++ b/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
@@ -45,7 +45,8 @@ import {
   GroupOutlined,
   ContainerOutlined,
   ApartmentOutlined,
-  BarsOutlined
+  BarsOutlined,
+  CloudServerOutlined
 } from '@vicons/antd'
 import { useMenuStore } from '@/store/menu/menu'
 import { useUserStore } from '@/store/user/user'
@@ -282,6 +283,11 @@ export function useDataList() {
                   icon: renderIcon(EnvironmentOutlined)
                 },
                 {
+                  label: t('menu.k8s_namespace_manage'),
+                  key: `/security/k8s-namespace-manage`,
+                  icon: renderIcon(CloudServerOutlined)
+                },
+                {
                   label: t('menu.token_manage'),
                   key: `/security/token-manage`,
                   icon: renderIcon(SafetyOutlined)
diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
index 1034bc6..d161cd9 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
@@ -73,6 +73,7 @@ const menu = {
   worker_group_manage: 'Worker Group Manage',
   yarn_queue_manage: 'Yarn Queue Manage',
   environment_manage: 'Environment Manage',
+  k8s_namespace_manage: 'K8S Namespace Manage',
   token_manage: 'Token Manage',
   task_group_manage: 'Task Group Manage',
   task_group_option: 'Task Group Option',
@@ -803,6 +804,29 @@ const security = {
     botToken: 'Bot Token',
     chatId: 'Channel Chat Id',
     parseMode: 'Parse Mode'
+  },
+  k8s_namespace: {
+    create_namespace: 'Create Namespace',
+    edit_namespace: 'Edit Namespace',
+    search_tips: 'Please enter keywords',
+    k8s_namespace: 'K8S Namespace',
+    k8s_namespace_tips: 'Please enter k8s namespace',
+    k8s_cluster: 'K8S Cluster',
+    k8s_cluster_tips: 'Please enter k8s cluster',
+    owner: 'Owner',
+    owner_tips: 'Please enter owner',
+    tag: 'Tag',
+    tag_tips: 'Please enter tag',
+    limit_cpu: 'Limit CPU',
+    limit_cpu_tips: 'Please enter limit CPU',
+    limit_memory: 'Limit Memory',
+    limit_memory_tips: 'Please enter limit memory',
+    create_time: 'Create Time',
+    update_time: 'Update Time',
+    operation: 'Operation',
+    edit: 'Edit',
+    delete: 'Delete',
+    delete_confirm: 'Delete?'
   }
 }
 
diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
index c17ff86..22d096f 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
@@ -73,6 +73,7 @@ const menu = {
   worker_group_manage: 'Worker分组管理',
   yarn_queue_manage: 'Yarn队列管理',
   environment_manage: '环境管理',
+  k8s_namespace_manage: 'K8S命名空间管理',
   token_manage: '令牌管理',
   task_group_manage: '任务组管理',
   task_group_option: '任务组配置',
@@ -794,6 +795,29 @@ const security = {
     botToken: '机器人Token',
     chatId: '频道ID',
     parseMode: '解析类型'
+  },
+  k8s_namespace: {
+    create_namespace: '创建命名空间',
+    edit_namespace: '编辑命名空间',
+    search_tips: '请输入关键词',
+    k8s_namespace: 'K8S命名空间',
+    k8s_namespace_tips: '请输入k8s命名空间',
+    k8s_cluster: 'K8S集群',
+    k8s_cluster_tips: '请输入k8s集群',
+    owner: '负责人',
+    owner_tips: '请输入负责人',
+    tag: '标签',
+    tag_tips: '请输入标签',
+    limit_cpu: '最大CPU',
+    limit_cpu_tips: '请输入最大CPU',
+    limit_memory: '最大内存',
+    limit_memory_tips: '请输入最大内存',
+    create_time: '创建时间',
+    update_time: '更新时间',
+    operation: '操作',
+    edit: '编辑',
+    delete: '删除',
+    delete_confirm: '确定删除吗?'
   }
 }
 
diff --git a/dolphinscheduler-ui-next/src/router/modules/security.ts b/dolphinscheduler-ui-next/src/router/modules/security.ts
index bc694a1..7190f3b 100644
--- a/dolphinscheduler-ui-next/src/router/modules/security.ts
+++ b/dolphinscheduler-ui-next/src/router/modules/security.ts
@@ -108,6 +108,16 @@ export default {
         showSide: true,
         auth: ['ADMIN_USER']
       }
+    },
+    {
+      path: '/security/k8s-namespace-manage',
+      name: 'k8s-namespace-manage',
+      component: components['security-k8s-namespace-manage'],
+      meta: {
+        title: 'K8S命名空间管理',
+        showSide: true,
+        auth: ['ADMIN_USER']
+      }
     }
   ]
 }
diff --git a/dolphinscheduler-ui-next/src/service/modules/k8s-namespace/index.ts b/dolphinscheduler-ui-next/src/service/modules/k8s-namespace/index.ts
new file mode 100644
index 0000000..69aaae9
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/service/modules/k8s-namespace/index.ts
@@ -0,0 +1,62 @@
+/*
+ * 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 { axios } from '@/service/service'
+import { ListReq, K8SReq } from './types'
+
+export function queryNamespaceListPaging(params: ListReq): any {
+  return axios({
+    url: '/k8s-namespace',
+    method: 'get',
+    params
+  })
+}
+
+export function verifyNamespaceK8s(params: K8SReq): any {
+  return axios({
+    url: '/k8s-namespace/verify',
+    method: 'post',
+    params
+  })
+}
+
+export function createK8sNamespace(params: K8SReq): any {
+  return axios({
+    url: '/k8s-namespace',
+    method: 'post',
+    params
+  })
+}
+
+export function updateK8sNamespace(params: K8SReq, id: number): any {
+  return axios({
+    url: `/k8s-namespace/${id}`,
+    method: 'put',
+    params: {
+      ...params,
+      id
+    }
+  })
+}
+
+export function delNamespaceById(id: number): any {
+  return axios({
+    url: '/k8s-namespace/delete',
+    method: 'post',
+    params: { id }
+  })
+}
diff --git a/dolphinscheduler-ui-next/src/service/modules/k8s-namespace/types.ts b/dolphinscheduler-ui-next/src/service/modules/k8s-namespace/types.ts
new file mode 100644
index 0000000..a29a1cf
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/service/modules/k8s-namespace/types.ts
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+interface ListReq {
+  pageNo: number
+  pageSize: number
+  searchVal?: string
+}
+
+interface K8SReq {
+  namespace: string
+  k8s: string
+  owner?: string
+  tag?: string
+  limitsCpu?: number | string
+  limitsMemory?: number | string
+}
+
+interface NamespaceItem extends K8SReq {
+  id: number
+  createTime: string
+  updateTime: string
+  podRequestCpu?: any
+  podRequestMemory?: any
+  podReplicas?: any
+  onlineJobNum?: any
+}
+
+interface NamespaceListRes {
+  totalList: NamespaceItem[]
+  total: number
+  totalPage: number
+  pageSize: number
+  currentPage: number
+  start: number
+}
+
+export { ListReq, K8SReq, NamespaceItem, NamespaceListRes }
diff --git a/dolphinscheduler-ui-next/src/views/security/environment-manage/index.tsx b/dolphinscheduler-ui-next/src/views/security/environment-manage/index.tsx
index f60d2d6..12a87ba 100644
--- a/dolphinscheduler-ui-next/src/views/security/environment-manage/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/security/environment-manage/index.tsx
@@ -105,7 +105,12 @@ const environmentManage = defineComponent({
         <NCard>
           <div class={styles['search-card']}>
             <div>
-              <NButton size='small' type='primary' onClick={handleModalChange} class='btn-create-environment'>
+              <NButton
+                size='small'
+                type='primary'
+                onClick={handleModalChange}
+                class='btn-create-environment'
+              >
                 {t('security.environment.create_environment')}
               </NButton>
             </div>
@@ -129,7 +134,11 @@ const environmentManage = defineComponent({
           </div>
         </NCard>
         <Card class={styles['table-card']}>
-          <NDataTable row-class-name='items' columns={this.columns} data={this.tableData} />
+          <NDataTable
+            row-class-name='items'
+            columns={this.columns}
+            data={this.tableData}
+          />
           <div class={styles.pagination}>
             <NPagination
               v-model:page={this.page}
diff --git a/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/components/k8s-namespace-modal.tsx b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/components/k8s-namespace-modal.tsx
new file mode 100644
index 0000000..7c5dbe5
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/components/k8s-namespace-modal.tsx
@@ -0,0 +1,194 @@
+/*
+ * 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 { defineComponent, PropType, toRefs, watch } from 'vue'
+import Modal from '@/components/modal'
+import {
+  NForm,
+  NFormItem,
+  NInput,
+  NInputGroup,
+  NInputGroupLabel
+} from 'naive-ui'
+import { useModal } from './use-modal'
+import { useI18n } from 'vue-i18n'
+
+const K8sNamespaceModal = defineComponent({
+  name: 'YarnQueueModal',
+  props: {
+    showModalRef: {
+      type: Boolean as PropType<boolean>,
+      default: false
+    },
+    statusRef: {
+      type: Number as PropType<number>,
+      default: 0
+    },
+    row: {
+      type: Object as PropType<any>,
+      default: {}
+    }
+  },
+  emits: ['cancelModal', 'confirmModal'],
+  setup(props, ctx) {
+    const { variables, handleValidate } = useModal(props, ctx)
+    const { t } = useI18n()
+
+    const cancelModal = () => {
+      if (props.statusRef === 0) {
+        variables.model.namespace = ''
+        variables.model.k8s = ''
+        variables.model.tag = ''
+        variables.model.limitsCpu = ''
+        variables.model.limitsMemory = ''
+        variables.model.owner = ''
+      }
+      ctx.emit('cancelModal', props.showModalRef)
+    }
+
+    const confirmModal = () => {
+      handleValidate(props.statusRef)
+    }
+
+    watch(
+      () => props.statusRef,
+      () => {
+        if (props.statusRef === 0) {
+          variables.model.namespace = ''
+          variables.model.k8s = ''
+          variables.model.tag = ''
+          variables.model.limitsCpu = ''
+          variables.model.limitsMemory = ''
+          variables.model.owner = ''
+        } else {
+          variables.model.id = props.row.id
+          variables.model.namespace = props.row.namespace
+          variables.model.k8s = props.row.k8s
+          variables.model.tag = props.row.tag
+          variables.model.limitsCpu = props.row.limitsCpu + ''
+          variables.model.limitsMemory = props.row.limitsMemory + ''
+          variables.model.owner = props.row.owner
+        }
+      }
+    )
+
+    watch(
+      () => props.row,
+      () => {
+        variables.model.id = props.row.id
+        variables.model.namespace = props.row.namespace
+        variables.model.k8s = props.row.k8s
+        variables.model.tag = props.row.tag
+        variables.model.limitsCpu = props.row.limitsCpu + ''
+        variables.model.limitsMemory = props.row.limitsMemory + ''
+        variables.model.owner = props.row.owner
+      }
+    )
+
+    return { t, ...toRefs(variables), cancelModal, confirmModal }
+  },
+  render() {
+    const { t } = this
+    return (
+      <div>
+        <Modal
+          title={
+            this.statusRef === 0
+              ? t('security.k8s_namespace.create_namespace')
+              : t('security.k8s_namespace.edit_namespace')
+          }
+          show={this.showModalRef}
+          onCancel={this.cancelModal}
+          onConfirm={this.confirmModal}
+          confirmDisabled={!this.model.namespace || !this.model.k8s}
+        >
+          {{
+            default: () => (
+              <NForm
+                model={this.model}
+                rules={this.rules}
+                ref='k8sNamespaceFormRef'
+              >
+                <NFormItem
+                  label={t('security.k8s_namespace.k8s_namespace')}
+                  path='namespace'
+                >
+                  <NInput
+                    placeholder={t('security.k8s_namespace.k8s_namespace_tips')}
+                    v-model={[this.model.namespace, 'value']}
+                  />
+                </NFormItem>
+                <NFormItem
+                  label={t('security.k8s_namespace.k8s_cluster')}
+                  path='k8s'
+                >
+                  <NInput
+                    placeholder={t('security.k8s_namespace.k8s_cluster_tips')}
+                    v-model={[this.model.k8s, 'value']}
+                  />
+                </NFormItem>
+                <NFormItem label={t('security.k8s_namespace.tag')} path='tag'>
+                  <NInput
+                    placeholder={t('security.k8s_namespace.tag_tips')}
+                    v-model={[this.model.tag, 'value']}
+                  />
+                </NFormItem>
+                <NFormItem
+                  label={t('security.k8s_namespace.limit_cpu')}
+                  path='limitsCpu'
+                >
+                  <NInputGroup>
+                    <NInput
+                      placeholder={t('security.k8s_namespace.limit_cpu_tips')}
+                      v-model={[this.model.limitsCpu, 'value']}
+                    />
+                    <NInputGroupLabel>CORE</NInputGroupLabel>
+                  </NInputGroup>
+                </NFormItem>
+                <NFormItem
+                  label={t('security.k8s_namespace.limit_memory')}
+                  path='limitsMemory'
+                >
+                  <NInputGroup>
+                    <NInput
+                      placeholder={t(
+                        'security.k8s_namespace.limit_memory_tips'
+                      )}
+                      v-model={[this.model.limitsMemory, 'value']}
+                    />
+                    <NInputGroupLabel>GB</NInputGroupLabel>
+                  </NInputGroup>
+                </NFormItem>
+                <NFormItem
+                  label={t('security.k8s_namespace.owner')}
+                  path='owner'
+                >
+                  <NInput
+                    placeholder={t('security.k8s_namespace.owner_tips')}
+                    v-model={[this.model.owner, 'value']}
+                  />
+                </NFormItem>
+              </NForm>
+            )
+          }}
+        </Modal>
+      </div>
+    )
+  }
+})
+
+export default K8sNamespaceModal
diff --git a/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/components/use-modal.ts b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/components/use-modal.ts
new file mode 100644
index 0000000..26206d8
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/components/use-modal.ts
@@ -0,0 +1,99 @@
+/*
+ * 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, ref, SetupContext } from 'vue'
+import { useI18n } from 'vue-i18n'
+import {
+  verifyNamespaceK8s,
+  createK8sNamespace,
+  updateK8sNamespace
+} from '@/service/modules/k8s-namespace'
+
+export function useModal(
+  props: any,
+  ctx: SetupContext<('cancelModal' | 'confirmModal')[]>
+) {
+  const { t } = useI18n()
+
+  const variables = reactive({
+    k8sNamespaceFormRef: ref(),
+    model: {
+      id: ref<number>(-1),
+      namespace: ref(''),
+      k8s: ref(''),
+      owner: ref(''),
+      tag: ref(''),
+      limitsCpu: ref(''),
+      limitsMemory: ref('')
+    },
+    rules: {
+      namespace: {
+        required: true,
+        trigger: ['input', 'blur'],
+        validator() {
+          if (variables.model.namespace === '') {
+            return new Error(t('security.k8s_namespace.k8s_namespace_tips'))
+          }
+        }
+      },
+      k8s: {
+        required: true,
+        trigger: ['input', 'blur'],
+        validator() {
+          if (variables.model.k8s === '') {
+            return new Error(t('security.k8s_namespace.k8s_cluster_tips'))
+          }
+        }
+      }
+    }
+  })
+
+  const handleValidate = (statusRef: number) => {
+    variables.k8sNamespaceFormRef.validate((errors: any) => {
+      if (!errors) {
+        statusRef === 0 ? submitK8SNamespaceModal() : updateK8SNamespaceModal()
+      } else {
+        return
+      }
+    })
+  }
+
+  const submitK8SNamespaceModal = () => {
+    verifyNamespaceK8s(variables.model).then(() => {
+      createK8sNamespace(variables.model).then(() => {
+        variables.model.namespace = ''
+        variables.model.k8s = ''
+        variables.model.tag = ''
+        variables.model.limitsCpu = ''
+        variables.model.limitsMemory = ''
+        variables.model.owner = ''
+        ctx.emit('confirmModal', props.showModalRef)
+      })
+    })
+  }
+
+  const updateK8SNamespaceModal = () => {
+    updateK8sNamespace(variables.model, variables.model.id).then((res: any) => {
+      ctx.emit('confirmModal', props.showModalRef)
+    })
+  }
+
+  return {
+    variables,
+    handleValidate
+  }
+}
diff --git a/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/index.module.scss b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/index.module.scss
new file mode 100644
index 0000000..12e457b
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/index.module.scss
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+.search-card {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.table-card {
+  margin-top: 8px;
+
+  .pagination {
+    margin-top: 20px;
+    display: flex;
+    justify-content: center;
+  }
+}
diff --git a/dolphinscheduler-ui-next/src/views/security/environment-manage/index.tsx b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/index.tsx
similarity index 87%
copy from dolphinscheduler-ui-next/src/views/security/environment-manage/index.tsx
copy to dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/index.tsx
index f60d2d6..1ae290d 100644
--- a/dolphinscheduler-ui-next/src/views/security/environment-manage/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/index.tsx
@@ -22,17 +22,18 @@ import {
   NDataTable,
   NIcon,
   NInput,
-  NPagination
+  NPagination,
+  NSpace
 } from 'naive-ui'
 import { SearchOutlined } from '@vicons/antd'
 import { useI18n } from 'vue-i18n'
 import { useTable } from './use-table'
 import Card from '@/components/card'
-import EnvironmentModal from './components/environment-modal'
+import K8sNamespaceModal from './components/k8s-namespace-modal'
 import styles from './index.module.scss'
 
-const environmentManage = defineComponent({
-  name: 'environment-manage',
+const k8sNamespaceManage = defineComponent({
+  name: 'k8s-namespace-manage',
   setup() {
     const { t } = useI18n()
     const { variables, getTableData, createColumns } = useTable()
@@ -105,16 +106,16 @@ const environmentManage = defineComponent({
         <NCard>
           <div class={styles['search-card']}>
             <div>
-              <NButton size='small' type='primary' onClick={handleModalChange} class='btn-create-environment'>
-                {t('security.environment.create_environment')}
+              <NButton size='small' type='primary' onClick={handleModalChange}>
+                {t('security.k8s_namespace.create_namespace')}
               </NButton>
             </div>
-            <div class={styles.box}>
+            <NSpace>
               <NInput
                 size='small'
                 clearable
                 v-model={[this.searchVal, 'value']}
-                placeholder={t('security.environment.search_tips')}
+                placeholder={t('security.k8s_namespace.search_tips')}
               />
               <NButton size='small' type='primary' onClick={onSearch}>
                 {{
@@ -125,11 +126,11 @@ const environmentManage = defineComponent({
                   )
                 }}
               </NButton>
-            </div>
+            </NSpace>
           </div>
         </NCard>
         <Card class={styles['table-card']}>
-          <NDataTable row-class-name='items' columns={this.columns} data={this.tableData} />
+          <NDataTable columns={this.columns} data={this.tableData} />
           <div class={styles.pagination}>
             <NPagination
               v-model:page={this.page}
@@ -143,7 +144,7 @@ const environmentManage = defineComponent({
             />
           </div>
         </Card>
-        <EnvironmentModal
+        <K8sNamespaceModal
           showModalRef={this.showModalRef}
           statusRef={this.statusRef}
           row={this.row}
@@ -155,4 +156,4 @@ const environmentManage = defineComponent({
   }
 })
 
-export default environmentManage
+export default k8sNamespaceManage
diff --git a/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/use-table.ts b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/use-table.ts
new file mode 100644
index 0000000..a14408c
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/security/k8s-namespace-manage/use-table.ts
@@ -0,0 +1,201 @@
+/*
+ * 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 { useAsyncState } from '@vueuse/core'
+import { reactive, h, ref } from 'vue'
+import { NButton, NPopconfirm, NSpace, NTooltip } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import { format } from 'date-fns'
+import { DeleteOutlined, EditOutlined } from '@vicons/antd'
+import {
+  queryNamespaceListPaging,
+  delNamespaceById
+} from '@/service/modules/k8s-namespace'
+import type {
+  NamespaceListRes,
+  NamespaceItem
+} from '@/service/modules/k8s-namespace/types'
+
+export function useTable() {
+  const { t } = useI18n()
+
+  const handleEdit = (row: NamespaceItem) => {
+    variables.showModalRef = true
+    variables.statusRef = 1
+    variables.row = row
+  }
+
+  const handleDelete = (row: NamespaceItem) => {
+    delNamespaceById(row.id).then(() => {
+      getTableData({
+        pageSize: variables.pageSize,
+        pageNo:
+          variables.tableData.length === 1 && variables.page > 1
+            ? variables.page - 1
+            : variables.page,
+        searchVal: variables.searchVal
+      })
+    })
+  }
+
+  const createColumns = (variables: any) => {
+    variables.columns = [
+      {
+        title: '#',
+        key: 'index'
+      },
+      {
+        title: t('security.k8s_namespace.k8s_namespace'),
+        key: 'namespace'
+      },
+      {
+        title: t('security.k8s_namespace.k8s_cluster'),
+        key: 'k8s'
+      },
+      {
+        title: t('security.k8s_namespace.owner'),
+        key: 'owner'
+      },
+      {
+        title: t('security.k8s_namespace.tag'),
+        key: 'tag'
+      },
+      {
+        title: t('security.k8s_namespace.limit_cpu'),
+        key: 'limitsCpu'
+      },
+      {
+        title: t('security.k8s_namespace.limit_memory'),
+        key: 'limitsMemory'
+      },
+      {
+        title: t('security.k8s_namespace.create_time'),
+        key: 'createTime'
+      },
+      {
+        title: t('security.k8s_namespace.update_time'),
+        key: 'updateTime'
+      },
+      {
+        title: t('security.k8s_namespace.operation'),
+        key: 'operation',
+        render(row: NamespaceItem) {
+          return h(NSpace, null, {
+            default: () => [
+              h(
+                NTooltip,
+                {},
+                {
+                  trigger: () =>
+                    h(
+                      NButton,
+                      {
+                        circle: true,
+                        type: 'info',
+                        size: 'small',
+                        onClick: () => {
+                          handleEdit(row)
+                        }
+                      },
+                      {
+                        icon: () => h(EditOutlined)
+                      }
+                    ),
+                  default: () => t('security.k8s_namespace.edit')
+                }
+              ),
+              h(
+                NPopconfirm,
+                {
+                  onPositiveClick: () => {
+                    handleDelete(row)
+                  }
+                },
+                {
+                  trigger: () =>
+                    h(
+                      NTooltip,
+                      {},
+                      {
+                        trigger: () =>
+                          h(
+                            NButton,
+                            {
+                              circle: true,
+                              type: 'error',
+                              size: 'small'
+                            },
+                            {
+                              icon: () => h(DeleteOutlined)
+                            }
+                          ),
+                        default: () => t('security.k8s_namespace.delete')
+                      }
+                    ),
+                  default: () => t('security.k8s_namespace.delete_confirm')
+                }
+              )
+            ]
+          })
+        }
+      }
+    ]
+  }
+
+  const variables = reactive({
+    columns: [],
+    tableData: [],
+    page: ref(1),
+    pageSize: ref(10),
+    searchVal: ref(null),
+    totalPage: ref(1),
+    showModalRef: ref(false),
+    statusRef: ref(0),
+    row: {}
+  })
+
+  const getTableData = (params: any) => {
+    const { state } = useAsyncState(
+      queryNamespaceListPaging({ ...params }).then((res: NamespaceListRes) => {
+        variables.tableData = res.totalList.map((item, index) => {
+          item.createTime = format(
+            new Date(item.createTime),
+            'yyyy-MM-dd HH:mm:ss'
+          )
+          item.updateTime = format(
+            new Date(item.updateTime),
+            'yyyy-MM-dd HH:mm:ss'
+          )
+          return {
+            index: index + 1,
+            ...item
+          }
+        }) as any
+        variables.totalPage = res.totalPage
+      }),
+      {}
+    )
+
+    return state
+  }
+
+  return {
+    variables,
+    getTableData,
+    createColumns
+  }
+}
diff --git a/dolphinscheduler-ui-next/src/views/security/token-manage/components/use-modal.ts b/dolphinscheduler-ui-next/src/views/security/token-manage/components/use-modal.ts
index 811ceea..2249635 100644
--- a/dolphinscheduler-ui-next/src/views/security/token-manage/components/use-modal.ts
+++ b/dolphinscheduler-ui-next/src/views/security/token-manage/components/use-modal.ts
@@ -64,7 +64,6 @@ export function useModal(
         required: true,
         trigger: ['input', 'blur'],
         validator() {
-          console.log(variables.model.expireTime)
           if (!variables.model.expireTime) {
             return new Error(t('security.token.expiration_time_tips'))
           }