Skip to content

Commit

Permalink
Merge pull request #287 from wilhelmguo/feature/kubernetes_cronjob_su…
Browse files Browse the repository at this point in the history
…pport

Kubernetes cronjob and job support
  • Loading branch information
wilhelmguo authored Feb 19, 2019
2 parents c66f702 + cff394d commit 355476a
Show file tree
Hide file tree
Showing 19 changed files with 614 additions and 10 deletions.
6 changes: 6 additions & 0 deletions src/frontend/src/app/admin/admin-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -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
]
}
Expand Down
6 changes: 5 additions & 1 deletion src/frontend/src/app/admin/admin.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down Expand Up @@ -104,7 +106,9 @@ import { KubeDaemonsetModule } from './kubernetes/daemonset/kube-daemonset.modul
KubeSecretModule,
KubeIngressModule,
KubeStatefulsetModule,
KubeDaemonsetModule
KubeDaemonsetModule,
KubeCronjobModule,
KubeJobModule
],
providers: [
AdminAuthCheckGuard,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<div class="clr-row">
<div class="clr-col-lg-12 clr-col-md-12 clr-col-sm-12 clr-col-xs-12">
<div class="table-search">
<div class="table-search-left">
<button class="wayne-button normal" (click)="createResource()">
{{'ADMIN.KUBERNETES.CRONJOB.CREATE' | translate}}
</button>
<button class="wayne-button normal" (click)="retrieveResource()">
{{'ADMIN.KUBERNETES.ACTION.REFRESH' | translate}}
</button>
<wayne-filter-box (confirm)="onConfirmEvent()" (cancel)="onCancelEvent()">
<wayne-checkbox-group [(ngModel)]="showList">
<wayne-checkbox value="name">{{'ADMIN.KUBERNETES.CRONJOB.LIST.NAME' | translate}}</wayne-checkbox>
<wayne-checkbox value="label">{{'ADMIN.KUBERNETES.CRONJOB.LIST.LABEL' | translate}}</wayne-checkbox>
<wayne-checkbox value="schedule">{{'ADMIN.KUBERNETES.CRONJOB.LIST.SCHEDULE' | translate}}</wayne-checkbox>
<wayne-checkbox value="suspend">{{'ADMIN.KUBERNETES.CRONJOB.LIST.SUSPEND' | translate}}</wayne-checkbox>
<wayne-checkbox value="active">{{'ADMIN.KUBERNETES.CRONJOB.LIST.ACTIVE' | translate}}</wayne-checkbox>
<wayne-checkbox value="lastSchedule">{{'ADMIN.KUBERNETES.CRONJOB.LIST.LAST_SCHEDULE' | translate}}</wayne-checkbox>
<wayne-checkbox value="age">{{'ADMIN.KUBERNETES.CRONJOB.LIST.AGE' | translate}}</wayne-checkbox>
</wayne-checkbox-group>
</wayne-filter-box>
<label for="namespace_name" class="clr-col-md-3">{{'ADMIN.KUBERNETES.LABEL.NAMESPACE' | translate}}</label>
<wayne-select [(ngModel)]="namespace" (change)="retrieveResource()"
searchable
name="namespace_name"
[placeholder]="'PLACEHOLDER.CHOOSE' | translate"
style="margin-left: 12px;">
<wayne-option *ngFor="let ns of namespaces" [value]="ns">{{ns}}</wayne-option>
</wayne-select>
</div>
</div>

<wayne-list-cronjob
[resources]="resources"
[showState]="showState"
(delete)="onDeleteResourceEvent($event)"
(edit)="onEditResourceEvent($event)"
[page]="pageState.page"
[cluster]="cluster"
(migration)="migration($event)"
(paginate)="retrieveResource($event)">
</wayne-list-cronjob>
</div>
</div>
<kube-migration></kube-migration>
<deletion-dialog (outputObj)="confirmDeleteEvent($event)"></deletion-dialog>
<wayne-ace-editor (createOutputObj)="onCreateResourceEvent($event)" (outputObj)="onSaveResourceEvent($event)"></wayne-ace-editor>
<wayne-float-window value="{{ cluster }}">
<wayne-float-window-item *ngFor="let cluster of clusters" [value]="cluster"
(click)="jumpToHref(cluster)"></wayne-float-window-item>
</wayne-float-window>
Original file line number Diff line number Diff line change
@@ -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);
}

}
Original file line number Diff line number Diff line change
@@ -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 {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<clr-datagrid (clrDgRefresh)="refresh($event)">
<clr-dg-column class="col-app-name" [clrDgField]="'name'">
<ng-container *clrDgHideableColumn="showState['name']">
{{'ADMIN.KUBERNETES.CRONJOB.LIST.NAME' | translate}}
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="showState['label']">
{{'ADMIN.KUBERNETES.CRONJOB.LIST.LABEL' | translate}}
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="showState['schedule']">
{{'ADMIN.KUBERNETES.CRONJOB.LIST.SCHEDULE' | translate}}
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="showState['suspend']">
{{'ADMIN.KUBERNETES.CRONJOB.LIST.SUSPEND' | translate}}
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="showState['active']">
{{'ADMIN.KUBERNETES.CRONJOB.LIST.ACTIVE' | translate}}
</ng-container>
</clr-dg-column>
<clr-dg-column>
<ng-container *clrDgHideableColumn="showState['lastSchedule']">
{{'ADMIN.KUBERNETES.CRONJOB.LIST.LAST_SCHEDULE' | translate}}
</ng-container>
</clr-dg-column>
<clr-dg-column [clrDgField]="'creationTimestamp'">
<ng-container *clrDgHideableColumn="showState['age']">
{{'ADMIN.KUBERNETES.CRONJOB.LIST.AGE' | translate}}
</ng-container>
</clr-dg-column>


<clr-dg-row *ngFor="let obj of resources" [clrDgItem]="obj">
<clr-dg-action-overflow>
<button class="action-item" (click)="onEditEvent(obj)">{{'ADMIN.KUBERNETES.ACTION.EDIT' | translate}}</button>
<button class="action-item" (click)="onDeleteEvent(obj)">{{'ADMIN.KUBERNETES.ACTION.DELETE' | translate}}</button>
<button class="action-item" (click)="migrationResource(obj)">{{'ADMIN.KUBERNETES.ACTION.MIGRATION' | translate}}</button>
</clr-dg-action-overflow>
<clr-dg-cell class="col-app-name"> {{ obj.metadata.name }} </clr-dg-cell>
<clr-dg-cell>
<div *ngFor="let label of obj.metadata.labels | keyvalue" class="version-text">
<a href="javascript:" (click)="versionDetail(label.key + ': ' + label.value)">{{label.key}}: {{label.value}}</a>
</div>
</clr-dg-cell>
<clr-dg-cell> {{ obj.spec.schedule }} </clr-dg-cell>
<clr-dg-cell> {{ obj.spec.suspend }} </clr-dg-cell>
<clr-dg-cell> {{ getActiveJobs(obj) }} </clr-dg-cell>
<clr-dg-cell> {{ obj.status.lastScheduleTime | relativeTime }} </clr-dg-cell>
<clr-dg-cell> {{ obj.metadata.creationTimestamp | relativeTime}} </clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>
<wayne-paginate
[(currentPage)]="currentPage"
[total]="page.totalCount"
[pageSizes]="[10, 20, 50]"
(sizeChange)="pageSizeChange($event)">
</wayne-paginate>
</clr-dg-footer>
</clr-datagrid>
Original file line number Diff line number Diff line change
@@ -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<any>();

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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<clr-modal [(clrModalOpen)]="modalOpened" [clrModalSize]="'xl'" #modal>
<h3 class="modal-title">迁移资源
<wayne-modal-operate [modal]="modal" *ngIf="modalOpened"></wayne-modal-operate>
</h3>
<div class="modal-body">
<form #ngForm="ngForm">
<section class="form-block">
<div class="form-group" style="padding-left: 135px;">
<label for="app" class="clr-col-md-3 form-group-label-override required">应用</label>
<div class="select form-control">
<wayne-select name="app" [(ngModel)]="selectedApp"
searchable
[placeholder]="'PLACEHOLDER.CHOOSE' | translate">
<wayne-option *ngFor="let app of apps" [value]="app">{{app.name}}</wayne-option>
</wayne-select>
</div>
</div>
<div class="form-group" style="padding-left: 135px;">
<label class="clr-col-md-3 form-group-label-override">模版</label>
<wayne-ace-editor-box></wayne-ace-editor-box>

</div>
</section>
</form>
<div class="modal-footer">

<button type="button" class="btn btn-outline" (click)="onCancel()">{{'BUTTON.CANCEL' | translate}}</button>
<button type="button" class="btn btn-primary" [disabled]="!isValid"
(click)="onSubmit()">{{'BUTTON.SUBMIT' | translate}}</button>
</div>
</div>
</clr-modal>
Original file line number Diff line number Diff line change
@@ -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;
}

}
Loading

0 comments on commit 355476a

Please sign in to comment.