diff --git a/src/frontend/src/app/admin/admin-routing.module.ts b/src/frontend/src/app/admin/admin-routing.module.ts
index ba7e288e2..2ace03934 100644
--- a/src/frontend/src/app/admin/admin-routing.module.ts
+++ b/src/frontend/src/app/admin/admin-routing.module.ts
@@ -76,6 +76,8 @@ import { KubeSecretComponent } from './kubernetes/secret/kube-secret.component';
import { KubeIngressComponent } from './kubernetes/ingress/kube-ingress.component';
import { KubeStatefulsetComponent } from './kubernetes/statefulset/kube-statefulset.component';
import { KubeDaemonsetComponent } from './kubernetes/daemonset/kube-daemonset.component';
+import { KubeCronjobComponent } from './kubernetes/cronjob/kube-cronjob.component';
+import { KubeJobComponent } from './kubernetes/job/kube-job.component';
const routes: Routes = [
@@ -172,6 +174,10 @@ const routes: Routes = [
{path: 'kubernetes/statefulset/:cluster', component: KubeStatefulsetComponent},
{path: 'kubernetes/daemonset', component: KubeDaemonsetComponent},
{path: 'kubernetes/daemonset/:cluster', component: KubeDaemonsetComponent},
+ {path: 'kubernetes/cronjob', component: KubeCronjobComponent},
+ {path: 'kubernetes/cronjob/:cluster', component: KubeCronjobComponent},
+ {path: 'kubernetes/job', component: KubeJobComponent},
+ {path: 'kubernetes/job/:cluster', component: KubeJobComponent},
...ADMINROUTES
]
}
diff --git a/src/frontend/src/app/admin/admin.module.ts b/src/frontend/src/app/admin/admin.module.ts
index 9093638f5..72a61fc33 100644
--- a/src/frontend/src/app/admin/admin.module.ts
+++ b/src/frontend/src/app/admin/admin.module.ts
@@ -56,6 +56,8 @@ import { KubeSecretModule } from './kubernetes/secret/kube-secret.module';
import { KubeIngressModule } from './kubernetes/ingress/kube-ingress.module';
import { KubeStatefulsetModule } from './kubernetes/statefulset/kube-statefulset.module';
import { KubeDaemonsetModule } from './kubernetes/daemonset/kube-daemonset.module';
+import { KubeCronjobModule } from './kubernetes/cronjob/kube-cronjob.module';
+import { KubeJobModule } from './kubernetes/job/kube-job.module';
@NgModule({
imports: [
@@ -104,7 +106,9 @@ import { KubeDaemonsetModule } from './kubernetes/daemonset/kube-daemonset.modul
KubeSecretModule,
KubeIngressModule,
KubeStatefulsetModule,
- KubeDaemonsetModule
+ KubeDaemonsetModule,
+ KubeCronjobModule,
+ KubeJobModule
],
providers: [
AdminAuthCheckGuard,
diff --git a/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.component.html b/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.component.html
new file mode 100644
index 000000000..e8078b21f
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.component.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.NAME' | translate}}
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.LABEL' | translate}}
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.SCHEDULE' | translate}}
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.SUSPEND' | translate}}
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.ACTIVE' | translate}}
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.LAST_SCHEDULE' | translate}}
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.AGE' | translate}}
+
+
+
+
+ {{ns}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.component.ts b/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.component.ts
new file mode 100644
index 000000000..82f70d72d
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.component.ts
@@ -0,0 +1,67 @@
+import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { MessageHandlerService } from '../../../shared/message-handler/message-handler.service';
+import { ClusterService } from '../../../shared/client/v1/cluster.service';
+import { AuthService } from '../../../shared/auth/auth.service';
+import { AceEditorComponent } from '../../../shared/ace-editor/ace-editor.component';
+import { KubernetesClient } from '../../../shared/client/v1/kubernetes/kubernetes';
+import { KubeResourceCronJob } from '../../../shared/shared.const';
+import { KubernetesNamespacedResource } from '../../../shared/base/kubernetes-namespaced/kubernetes-namespaced-resource';
+import { DeletionDialogComponent } from '../../../shared/deletion-dialog/deletion-dialog.component';
+import { MigrationComponent } from './migration/migration.component';
+import { ListCronjobComponent } from './list-cronjob/list-cronjob.component';
+
+const showState = {
+ 'name': {hidden: false},
+ 'label': {hidden: false},
+ 'schedule': {hidden: false},
+ 'suspend': {hidden: false},
+ 'active': {hidden: false},
+ 'lastSchedule': {hidden: false},
+ 'age': {hidden: false},
+};
+
+@Component({
+ selector: 'wayne-kube-cronjob',
+ templateUrl: './kube-cronjob.component.html'
+})
+
+export class KubeCronjobComponent extends KubernetesNamespacedResource implements OnInit, OnDestroy {
+ @ViewChild(ListCronjobComponent)
+ listResourceComponent: ListCronjobComponent;
+
+ @ViewChild(AceEditorComponent)
+ aceEditorModal: AceEditorComponent;
+
+ @ViewChild(DeletionDialogComponent)
+ deletionDialogComponent: DeletionDialogComponent;
+
+ @ViewChild(MigrationComponent)
+ migrationComponent: MigrationComponent;
+
+ constructor(public kubernetesClient: KubernetesClient,
+ public route: ActivatedRoute,
+ public router: Router,
+ public clusterService: ClusterService,
+ public authService: AuthService,
+ public messageHandlerService: MessageHandlerService) {
+ super(kubernetesClient, route, router, clusterService, authService, messageHandlerService);
+ super.registResourceType('cronjob');
+ super.registKubeResource(KubeResourceCronJob);
+ super.registShowSate(showState);
+ }
+
+ ngOnInit() {
+ super.ngOnInit();
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+
+ migration(obj: any) {
+ this.migrationComponent.openModal(this.cluster, obj);
+ }
+
+}
diff --git a/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.module.ts b/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.module.ts
new file mode 100644
index 000000000..f3e267a62
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/cronjob/kube-cronjob.module.ts
@@ -0,0 +1,31 @@
+import { NgModule } from '@angular/core';
+import { SharedModule } from '../../../shared/shared.module';
+import { ReactiveFormsModule } from '@angular/forms';
+import { KubeCronjobComponent } from './kube-cronjob.component';
+import { KubernetesClient } from '../../../shared/client/v1/kubernetes/kubernetes';
+import { DeletionDialogModule } from '../../../shared/deletion-dialog/deletion-dialog.module';
+import { MigrationComponent } from './migration/migration.component';
+import { ListCronjobComponent } from './list-cronjob/list-cronjob.component';
+
+@NgModule({
+ imports: [
+ SharedModule,
+ ReactiveFormsModule,
+ DeletionDialogModule
+ ],
+ providers: [
+ KubernetesClient
+ ],
+ exports: [
+ KubeCronjobComponent,
+ ListCronjobComponent
+ ],
+ declarations: [
+ KubeCronjobComponent,
+ ListCronjobComponent,
+ MigrationComponent
+ ]
+})
+
+export class KubeCronjobModule {
+}
diff --git a/src/frontend/src/app/admin/kubernetes/cronjob/list-cronjob/list-cronjob.component.html b/src/frontend/src/app/admin/kubernetes/cronjob/list-cronjob/list-cronjob.component.html
new file mode 100644
index 000000000..614d90d38
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/cronjob/list-cronjob/list-cronjob.component.html
@@ -0,0 +1,65 @@
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.NAME' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.LABEL' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.SCHEDULE' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.SUSPEND' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.ACTIVE' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.LAST_SCHEDULE' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.CRONJOB.LIST.AGE' | translate}}
+
+
+
+
+
+
+
+
+
+
+ {{ obj.metadata.name }}
+
+
+
+ {{ obj.spec.schedule }}
+ {{ obj.spec.suspend }}
+ {{ getActiveJobs(obj) }}
+ {{ obj.status.lastScheduleTime | relativeTime }}
+ {{ obj.metadata.creationTimestamp | relativeTime}}
+
+
+
+
+
+
diff --git a/src/frontend/src/app/admin/kubernetes/cronjob/list-cronjob/list-cronjob.component.ts b/src/frontend/src/app/admin/kubernetes/cronjob/list-cronjob/list-cronjob.component.ts
new file mode 100644
index 000000000..7eccf0f9a
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/cronjob/list-cronjob/list-cronjob.component.ts
@@ -0,0 +1,28 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { KubernetesNamespacedListResource } from '../../../../shared/base/kubernetes-namespaced/kubernetes-namespaced-list-resource';
+import { TplDetailService } from '../../../../shared/tpl-detail/tpl-detail.service';
+import { KubeCronJob } from '../../../../shared/model/v1/kubernetes/cronjob';
+
+@Component({
+ selector: 'wayne-list-cronjob',
+ templateUrl: './list-cronjob.component.html'
+})
+
+export class ListCronjobComponent extends KubernetesNamespacedListResource {
+ @Input() resources: any[];
+ @Input() showState: object;
+
+ @Output() migration = new EventEmitter();
+
+ constructor(public tplDetailService: TplDetailService) {
+ super(tplDetailService);
+ }
+
+ getActiveJobs(obj: KubeCronJob): number {
+ return obj.status.active ? obj.status.active.length : 0;
+ }
+
+ migrationResource(obj: any) {
+ this.migration.emit(obj);
+ }
+}
diff --git a/src/frontend/src/app/admin/kubernetes/cronjob/migration/migration.component.html b/src/frontend/src/app/admin/kubernetes/cronjob/migration/migration.component.html
new file mode 100644
index 000000000..488f54eea
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/cronjob/migration/migration.component.html
@@ -0,0 +1,32 @@
+
+ 迁移资源
+
+
+
+
diff --git a/src/frontend/src/app/admin/kubernetes/cronjob/migration/migration.component.ts b/src/frontend/src/app/admin/kubernetes/cronjob/migration/migration.component.ts
new file mode 100644
index 000000000..4ac9cbffb
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/cronjob/migration/migration.component.ts
@@ -0,0 +1,64 @@
+import { Component, OnInit } from '@angular/core';
+import { AppService } from '../../../../shared/client/v1/app.service';
+import { AceEditorService } from '../../../../shared/ace-editor/ace-editor.service';
+import { MessageHandlerService } from '../../../../shared/message-handler/message-handler.service';
+import { MigrationResource } from '../../../../shared/base/kubernetes-namespaced/migration-resource';
+import { KubernetesClient } from '../../../../shared/client/v1/kubernetes/kubernetes';
+import { KubeResourceCronJob } from '../../../../shared/shared.const';
+import { CronjobService } from '../../../../shared/client/v1/cronjob.service';
+import { CronjobTplService } from '../../../../shared/client/v1/cronjobtpl.service';
+import { Cronjob } from '../../../../shared/model/v1/cronjob';
+import { CronjobTpl } from '../../../../shared/model/v1/cronjobtpl';
+
+@Component({
+ selector: 'kube-migration',
+ templateUrl: 'migration.component.html'
+})
+export class MigrationComponent extends MigrationResource implements OnInit {
+
+ constructor(private cronjobService: CronjobService,
+ private cronjobTplService: CronjobTplService,
+ public appService: AppService,
+ public kubernetesClient: KubernetesClient,
+ public aceEditorService: AceEditorService,
+ public messageHandlerService: MessageHandlerService) {
+ super(kubernetesClient, appService, aceEditorService, messageHandlerService);
+ super.registKubeResource(KubeResourceCronJob);
+ }
+
+ ngOnInit(): void {
+ super.ngOnInit();
+ }
+
+ onSubmit() {
+ if (this.isSubmitOnGoing) {
+ return;
+ }
+ this.isSubmitOnGoing = true;
+ const resource = new Cronjob();
+ resource.name = this.obj.metadata.name;
+ resource.appId = this.selectedApp.id;
+ this.cronjobService.create(resource).subscribe(
+ resp => {
+ const data = resp.data;
+ const tpl = new CronjobTpl();
+ tpl.name = this.obj.metadata.name;
+ tpl.cronjobId = data.id;
+ tpl.template = JSON.stringify(this.obj);
+ tpl.description = 'migration from kubernetes. ';
+ this.cronjobTplService.create(tpl, this.selectedApp.id).subscribe(
+ () => {
+ this.messageHandlerService.showSuccess('资源创建成功!请前往前台手动发布到相应机房!');
+ },
+ error => {
+ this.messageHandlerService.handleError(error);
+ });
+ },
+ error => {
+ this.messageHandlerService.handleError(error);
+ }
+ );
+ this.modalOpened = false;
+ }
+
+}
diff --git a/src/frontend/src/app/admin/kubernetes/job/kube-job.component.html b/src/frontend/src/app/admin/kubernetes/job/kube-job.component.html
new file mode 100644
index 000000000..e6a2af7b5
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/job/kube-job.component.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+ {{'ADMIN.KUBERNETES.JOB.LIST.NAME' | translate}}
+ {{'ADMIN.KUBERNETES.JOB.LIST.LABEL' | translate}}
+ {{'ADMIN.KUBERNETES.JOB.LIST.AGE' | translate}}
+
+
+
+
+ {{ns}}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/frontend/src/app/admin/kubernetes/job/kube-job.component.ts b/src/frontend/src/app/admin/kubernetes/job/kube-job.component.ts
new file mode 100644
index 000000000..d5cb18a4e
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/job/kube-job.component.ts
@@ -0,0 +1,54 @@
+import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { MessageHandlerService } from '../../../shared/message-handler/message-handler.service';
+import { ClusterService } from '../../../shared/client/v1/cluster.service';
+import { AuthService } from '../../../shared/auth/auth.service';
+import { AceEditorComponent } from '../../../shared/ace-editor/ace-editor.component';
+import { KubernetesClient } from '../../../shared/client/v1/kubernetes/kubernetes';
+import { KubeResourceJob } from '../../../shared/shared.const';
+import { KubernetesNamespacedResource } from '../../../shared/base/kubernetes-namespaced/kubernetes-namespaced-resource';
+import { DeletionDialogComponent } from '../../../shared/deletion-dialog/deletion-dialog.component';
+import { ListJobComponent } from './list-job/list-job.component';
+
+const showState = {
+ 'name': {hidden: false},
+ 'label': {hidden: false},
+ 'age': {hidden: false},
+};
+
+@Component({
+ selector: 'wayne-kube-job',
+ templateUrl: './kube-job.component.html'
+})
+
+export class KubeJobComponent extends KubernetesNamespacedResource implements OnInit, OnDestroy {
+ @ViewChild(ListJobComponent)
+ listResourceComponent: ListJobComponent;
+
+ @ViewChild(AceEditorComponent)
+ aceEditorModal: AceEditorComponent;
+
+ @ViewChild(DeletionDialogComponent)
+ deletionDialogComponent: DeletionDialogComponent;
+
+ constructor(public kubernetesClient: KubernetesClient,
+ public route: ActivatedRoute,
+ public router: Router,
+ public clusterService: ClusterService,
+ public authService: AuthService,
+ public messageHandlerService: MessageHandlerService) {
+ super(kubernetesClient, route, router, clusterService, authService, messageHandlerService);
+ super.registResourceType('job');
+ super.registKubeResource(KubeResourceJob);
+ super.registShowSate(showState);
+ }
+
+ ngOnInit() {
+ super.ngOnInit();
+ }
+
+ ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+}
diff --git a/src/frontend/src/app/admin/kubernetes/job/kube-job.module.ts b/src/frontend/src/app/admin/kubernetes/job/kube-job.module.ts
new file mode 100644
index 000000000..2e733921f
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/job/kube-job.module.ts
@@ -0,0 +1,29 @@
+import { NgModule } from '@angular/core';
+import { SharedModule } from '../../../shared/shared.module';
+import { ReactiveFormsModule } from '@angular/forms';
+import { KubeJobComponent } from './kube-job.component';
+import { KubernetesClient } from '../../../shared/client/v1/kubernetes/kubernetes';
+import { DeletionDialogModule } from '../../../shared/deletion-dialog/deletion-dialog.module';
+import { ListJobComponent } from './list-job/list-job.component';
+
+@NgModule({
+ imports: [
+ SharedModule,
+ ReactiveFormsModule,
+ DeletionDialogModule
+ ],
+ providers: [
+ KubernetesClient
+ ],
+ exports: [
+ KubeJobComponent,
+ ListJobComponent
+ ],
+ declarations: [
+ KubeJobComponent,
+ ListJobComponent
+ ]
+})
+
+export class KubeJobModule {
+}
diff --git a/src/frontend/src/app/admin/kubernetes/job/list-job/list-job.component.html b/src/frontend/src/app/admin/kubernetes/job/list-job/list-job.component.html
new file mode 100644
index 000000000..434073bf7
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/job/list-job/list-job.component.html
@@ -0,0 +1,62 @@
+
+
+
+ {{'ADMIN.KUBERNETES.JOB.LIST.NAME' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.JOB.LIST.LABEL' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.JOB.LIST.IMAGES' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.JOB.LIST.STATUS' | translate}}
+
+
+
+
+ {{'ADMIN.KUBERNETES.JOB.LIST.AGE' | translate}}
+
+
+
+
+
+
+
+
+
+ {{ obj.metadata.name }}
+
+
+
+
+
+
+
+ {{obj.status.succeeded ? obj.status.succeeded : 0}}/{{obj.spec.completions }}
+
+
+
+ {{ obj.metadata.creationTimestamp | relativeTime}}
+
+
+
+
+
+
diff --git a/src/frontend/src/app/admin/kubernetes/job/list-job/list-job.component.ts b/src/frontend/src/app/admin/kubernetes/job/list-job/list-job.component.ts
new file mode 100644
index 000000000..27a3af5f4
--- /dev/null
+++ b/src/frontend/src/app/admin/kubernetes/job/list-job/list-job.component.ts
@@ -0,0 +1,18 @@
+import { Component, Input } from '@angular/core';
+import { KubernetesNamespacedListResource } from '../../../../shared/base/kubernetes-namespaced/kubernetes-namespaced-list-resource';
+import { TplDetailService } from '../../../../shared/tpl-detail/tpl-detail.service';
+
+@Component({
+ selector: 'wayne-list-job',
+ templateUrl: './list-job.component.html'
+})
+
+export class ListJobComponent extends KubernetesNamespacedListResource {
+ @Input() resources: any[];
+ @Input() showState: object;
+
+ constructor(public tplDetailService: TplDetailService) {
+ super(tplDetailService);
+ }
+
+}
diff --git a/src/frontend/src/app/admin/sidenav/sidenav.component.html b/src/frontend/src/app/admin/sidenav/sidenav.component.html
index fa3dabe2e..444fce176 100644
--- a/src/frontend/src/app/admin/sidenav/sidenav.component.html
+++ b/src/frontend/src/app/admin/sidenav/sidenav.component.html
@@ -56,6 +56,20 @@
DaemonSet
+
+
+ CronJob
+
+
+
+ Job
+
-
+
{{job.kubeJob.status.completionTime | date: "yyyy-MM-dd HH:mm:ss"}}
-
-
- {{pagesize}}
-
- {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} of {{pagination.totalItems}}
-
-
-
+
+
diff --git a/src/frontend/src/app/portal/cronjob/list-job/list-job.component.ts b/src/frontend/src/app/portal/cronjob/list-job/list-job.component.ts
index 2e7f98d5e..17953520a 100644
--- a/src/frontend/src/app/portal/cronjob/list-job/list-job.component.ts
+++ b/src/frontend/src/app/portal/cronjob/list-job/list-job.component.ts
@@ -34,6 +34,8 @@ export class ListJobComponent implements OnInit, OnDestroy {
subscription: Subscription;
componentName = '任务';
pageSizes: number[] = new Array(10, 20, 50);
+ currentPage = 1;
+ state: ClrDatagridStateInterface;
constructor(
private deletionDialogService: ConfirmationDialogService,
@@ -55,6 +57,13 @@ export class ListJobComponent implements OnInit, OnDestroy {
}
}
+ pageSizeChange(pageSize: number) {
+ this.state.page.to = pageSize - 1;
+ this.state.page.size = pageSize;
+ this.currentPage = 1;
+ this.paginate.emit(this.state);
+ }
+
get pageSize() {
return this._pageSize;
}
@@ -79,6 +88,7 @@ export class ListJobComponent implements OnInit, OnDestroy {
}
refresh(state?: ClrDatagridStateInterface) {
+ this.state = state;
this.paginate.emit(state);
}
diff --git a/src/frontend/src/assets/i18n/zh-Hans.json b/src/frontend/src/assets/i18n/zh-Hans.json
index b542f0d87..8e8cfcdc7 100644
--- a/src/frontend/src/assets/i18n/zh-Hans.json
+++ b/src/frontend/src/assets/i18n/zh-Hans.json
@@ -105,6 +105,7 @@
},
"CREATE": {},
"CRONJOB": {
+ "JOB": "任务列表",
"CONFIG": "计划任务配置",
"CONFIG_MESSAGE": "k8s 调度任务的时区是 UTC(+0),按小时定期执行的任务,请减去8小时调整为北京时区(+8)
例如想在北京时间每天11点(0 11 * * *)执行定时任务,则设置为(0 2 * * *)",
"CREATE": "创建计划任务",
@@ -691,6 +692,30 @@
"IMAGES": "镜像",
"STATUS": "状态"
}
+ },
+ "CRONJOB": {
+ "CREATE": "创建 CronJob",
+ "LIST": {
+ "NAME": "名称",
+ "LABEL": "标签",
+ "AGE": "启动时间",
+ "IMAGES": "镜像",
+ "SCHEDULE": "计划",
+ "SUSPEND": "挂起",
+ "ACTIVE": "活跃中",
+ "LAST_SCHEDULE": "最近调度",
+ "STATUS": "状态"
+ }
+ },
+ "JOB": {
+ "CREATE": "创建 Job",
+ "LIST": {
+ "NAME": "名称",
+ "LABEL": "标签",
+ "AGE": "启动时间",
+ "IMAGES": "镜像",
+ "STATUS": "状态"
+ }
}
}
}