diff --git a/src/frontend/src/app/admin/cluster/list-cluster/list-cluster.component.html b/src/frontend/src/app/admin/cluster/list-cluster/list-cluster.component.html
index 1f906784e..d1d7b6fdb 100644
--- a/src/frontend/src/app/admin/cluster/list-cluster/list-cluster.component.html
+++ b/src/frontend/src/app/admin/cluster/list-cluster/list-cluster.component.html
@@ -9,6 +9,11 @@
{{'TITLE.NAME' | translate}}
+
+
+ displayname
+
+
Master
@@ -51,6 +56,7 @@
{{cluster.id}}
{{cluster.name}}
+ {{cluster.displayname}}
{{cluster.master}}
{{getClusterStatus(cluster.status)}}
diff --git a/src/frontend/src/app/admin/cluster/trash-cluster/trash-cluster.component.html b/src/frontend/src/app/admin/cluster/trash-cluster/trash-cluster.component.html
index f27fee456..9038edfcd 100644
--- a/src/frontend/src/app/admin/cluster/trash-cluster/trash-cluster.component.html
+++ b/src/frontend/src/app/admin/cluster/trash-cluster/trash-cluster.component.html
@@ -14,6 +14,11 @@
{{'TITLE.NAME' | translate}}
+
+
+ displayname
+
+
Master
@@ -41,6 +46,7 @@
{{cluster.id}}
{{cluster.name}}
+ {{cluster.displayname}}
{{cluster.master}}
{{cluster.description}}
{{cluster.user}}
diff --git a/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.html b/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.html
index 50a59d23e..fd69baec8 100644
--- a/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.html
+++ b/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.html
@@ -37,6 +37,7 @@
+
{{ns.id}}
diff --git a/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.ts b/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.ts
index 4e846979d..8fa17c892 100644
--- a/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.ts
+++ b/src/frontend/src/app/admin/namespace/list-namespace/list-namespace.component.ts
@@ -21,6 +21,7 @@ export class ListNamespaceComponent {
@Output() paginate = new EventEmitter();
@Output() delete = new EventEmitter();
@Output() edit = new EventEmitter();
+ @Output() migrate = new EventEmitter();
constructor(private router: Router,
private aceEditorService: AceEditorService) {
@@ -46,6 +47,10 @@ export class ListNamespaceComponent {
this.edit.emit(ns);
}
+ migrateNamespace(ns: Namespace) {
+ this.migrate.emit(ns);
+ }
+
goToLink(ns: Namespace, gate: string) {
let linkUrl = '';
switch (gate) {
diff --git a/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.html b/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.html
new file mode 100644
index 000000000..4b4682d72
--- /dev/null
+++ b/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.html
@@ -0,0 +1,17 @@
+
+ 命名空间迁移
+
+
+
+
\ No newline at end of file
diff --git a/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.scss b/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.spec.ts b/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.spec.ts
new file mode 100644
index 000000000..0f36cc819
--- /dev/null
+++ b/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MigrateNamespaceComponent } from './migrate-namespace.component';
+
+describe('MigrateNamespaceComponent', () => {
+ let component: MigrateNamespaceComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ MigrateNamespaceComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MigrateNamespaceComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.ts b/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.ts
new file mode 100644
index 000000000..35df16397
--- /dev/null
+++ b/src/frontend/src/app/admin/namespace/migrate-namespace/migrate-namespace.component.ts
@@ -0,0 +1,78 @@
+import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
+import { Namespace } from 'app/shared/model/v1/namespace';
+import { NgForm } from '@angular/forms';
+import { ModalComponent } from 'app/shared/modal/modal.component';
+import { ModalService } from 'app/shared/modal/modal.service';
+import { Subscription } from 'rxjs';
+import { NamespaceService } from 'app/shared/client/v1/namespace.service';
+import { MessageHandlerService } from 'app/shared/message-handler/message-handler.service';
+@Component({
+ selector: 'migrate-namespace',
+ templateUrl: './migrate-namespace.component.html',
+ styleUrls: ['./migrate-namespace.component.scss']
+})
+export class MigrateNamespaceComponent implements OnInit, OnDestroy {
+ namespaceForm: NgForm;
+ @ViewChild('namespaceForm', { static: false })
+ currentForm: NgForm;
+ @ViewChild(ModalComponent, { static: false })
+ modalComponent: ModalComponent;
+
+ currentNamespace: Namespace = new Namespace;
+ target: number;
+ namespaces: Namespace[] = [];
+ subscription: Subscription;
+ constructor(
+ private modalService: ModalService,
+ private namespaceService: NamespaceService,
+ private message: MessageHandlerService
+ ) {
+ this.subscription = this.modalService.modalObservable$.subscribe(res => {
+ switch (res.method) {
+ case 'cancel':
+ this.cancelEvent();
+ break;
+ case 'confirm':
+ this.confirmEvent();
+ break;
+ }
+ });
+ }
+
+ ngOnInit() {
+ }
+
+ ngOnDestroy() {
+ this.subscription.unsubscribe();
+ }
+
+ cancelEvent() {
+ this.namespaces = [];
+ this.modalComponent.opened = false;
+ }
+
+ confirmEvent() {
+ this.namespaceService.migrateNamespace(this.currentNamespace.id, Number(this.target))
+ .subscribe(
+ res => {
+ this.message.showSuccess(`${this.currentNamespace.name}迁移成功`);
+ this.modalComponent.opened = false;
+ },
+ error => this.message.error(error)
+ );
+ }
+
+ open(ns: Namespace, namespaceList: Namespace[]) {
+ this.target = undefined;
+ this.currentNamespace = ns;
+ this.modalComponent.opened = true;
+ this.namespaces = namespaceList.filter(namespace => {
+ return namespace.id !== ns.id;
+ }) || [];
+ }
+
+ public get isValid() {
+ return !!this.target;
+ }
+
+}
diff --git a/src/frontend/src/app/admin/namespace/namespace.component.html b/src/frontend/src/app/admin/namespace/namespace.component.html
index 078ab8915..a01922d5a 100644
--- a/src/frontend/src/app/admin/namespace/namespace.component.html
+++ b/src/frontend/src/app/admin/namespace/namespace.component.html
@@ -11,9 +11,10 @@
+
+ (migrate)="migrateNamespace($event)" (paginate)="retrieve($event)" [page]="pageState.page">
diff --git a/src/frontend/src/app/admin/namespace/namespace.component.ts b/src/frontend/src/app/admin/namespace/namespace.component.ts
index bf8f7bc82..ef96fe49a 100644
--- a/src/frontend/src/app/admin/namespace/namespace.component.ts
+++ b/src/frontend/src/app/admin/namespace/namespace.component.ts
@@ -12,6 +12,7 @@ import { NamespaceService } from '../../shared/client/v1/namespace.service';
import { PageState } from '../../shared/page/page-state';
import { ClusterService } from '../../shared/client/v1/cluster.service';
import { Cluster } from '../../shared/model/v1/cluster';
+import { MigrateNamespaceComponent } from './migrate-namespace/migrate-namespace.component';
@Component({
selector: 'wayne-namespace',
@@ -23,6 +24,8 @@ export class NamespaceComponent implements OnInit, OnDestroy {
listNamespace: ListNamespaceComponent;
@ViewChild(CreateEditNamespaceComponent, { static: false })
createEditNamespace: CreateEditNamespaceComponent;
+ @ViewChild(MigrateNamespaceComponent, {static: false})
+ migrateNamespaceComponent: MigrateNamespaceComponent;
pageState: PageState = new PageState();
changedNamespaces: Namespace[];
@@ -133,4 +136,15 @@ export class NamespaceComponent implements OnInit, OnDestroy {
editNamespace(ns: Namespace): void {
this.createEditNamespace.newOrEditNamespace(this.clusters, ns.id);
}
+
+ migrateNamespace(ns: Namespace): void {
+ const pageState = new PageState({
+ pageNo: 1,
+ pageSize: 10000
+ });
+ this.namespaceService.listNamespace(pageState, 'false')
+ .subscribe(res => {
+ this.migrateNamespaceComponent.open(ns, res.data.list);
+ });
+ }
}
diff --git a/src/frontend/src/app/admin/namespace/namespace.module.ts b/src/frontend/src/app/admin/namespace/namespace.module.ts
index fc301c551..def841b4b 100644
--- a/src/frontend/src/app/admin/namespace/namespace.module.ts
+++ b/src/frontend/src/app/admin/namespace/namespace.module.ts
@@ -5,6 +5,7 @@ import { ListNamespaceComponent } from './list-namespace/list-namespace.componen
import { TrashNamespaceComponent } from './trash-namespace/trash-namespace.component';
import { SharedModule } from '../../shared/shared.module';
import { NamespaceService } from '../../shared/client/v1/namespace.service';
+import { MigrateNamespaceComponent } from './migrate-namespace/migrate-namespace.component';
@NgModule({
imports: [
@@ -21,7 +22,8 @@ import { NamespaceService } from '../../shared/client/v1/namespace.service';
NamespaceComponent,
TrashNamespaceComponent,
ListNamespaceComponent,
- CreateEditNamespaceComponent
+ CreateEditNamespaceComponent,
+ MigrateNamespaceComponent
]
})
diff --git a/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.html b/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.html
index f1eb54d16..4661a3344 100644
--- a/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.html
+++ b/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.html
@@ -94,6 +94,10 @@
(click)="offlineDeployment(deploymentTpl)"
*ngIf="deploymentTpl.status && (authService.currentAppPermission.kubeDeployment.delete || authService.currentUser.admin)">
{{'BUTTON.DROP' | translate}}
+
diff --git a/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.ts b/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.ts
index efed32406..6d87a88b7 100644
--- a/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.ts
+++ b/src/frontend/src/app/portal/deployment/list-deployment/list-deployment.component.ts
@@ -174,6 +174,17 @@ export class ListDeploymentComponent implements OnInit, OnDestroy {
});
}
+ modifyReplicas(tpl: DeploymentTpl) {
+ this.deploymentService.getById(tpl.deploymentId, this.appId).subscribe(
+ status => {
+ const deployment = status.data;
+ this.publishDeploymentTpl.newPublishTpl(deployment, tpl, ResourcesActionType.MODIFY_REPLICA);
+ },
+ error => {
+ this.messageHandlerService.handleError(error);
+ });
+ }
+
published(success: boolean) {
if (success) {
this.refresh();
diff --git a/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.html b/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.html
index 5c171cbf2..664d427ad 100644
--- a/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.html
+++ b/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.html
@@ -14,8 +14,8 @@ {{title}}
-
-
+
部署份数超过系统最大限制{{replicaLimit}}
diff --git a/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.ts b/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.ts
index 890b3ad03..26f637b9d 100644
--- a/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.ts
+++ b/src/frontend/src/app/portal/deployment/publish-tpl/publish-tpl.component.ts
@@ -1,5 +1,5 @@
import { Component, EventEmitter, Output, ViewChild } from '@angular/core';
-import { forkJoin } from 'rxjs';
+import { forkJoin, ObservableInput } from 'rxjs';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import { NgForm } from '@angular/forms';
@@ -114,6 +114,9 @@ export class PublishDeploymentTplComponent {
case ResourcesActionType.OFFLINE:
this.title = '下线部署[' + this.deployment.name + ']';
break;
+ case ResourcesActionType.MODIFY_REPLICA:
+ this.title = `修改状态副本集[${this.deployment.name}]`;
+ break;
}
}
@@ -162,6 +165,9 @@ export class PublishDeploymentTplComponent {
case ResourcesActionType.OFFLINE:
this.offline();
break;
+ case ResourcesActionType.MODIFY_REPLICA:
+ this.modifyReplica();
+ break;
}
this.isSubmitOnGoing = false;
@@ -188,6 +194,24 @@ export class PublishDeploymentTplComponent {
});
}
+ modifyReplica() {
+ const observables: ObservableInput[] = [];
+ Object.getOwnPropertyNames(this.clusterMetas).forEach(cluster => {
+ if (this.clusterMetas[cluster].checked) {
+ observables.push(
+ this.deploymentClient.modifyReplica(this.appId, cluster, this.deployment.name, this.cacheService.kubeNamespace, {
+ num: Number(this.clusterMetas[cluster].value)
+ })
+ );
+ }
+ });
+ forkJoin(observables)
+ .subscribe(
+ res => this.messageHandlerService.showSuccess('修改成功'),
+ error => this.messageHandlerService.handleError(error)
+ );
+ }
+
deletePublishStatus(id: number) {
this.publishStatusService.deleteById(id).subscribe(
response => {
diff --git a/src/frontend/src/app/shared/client/v1/kubernetes/deployment.ts b/src/frontend/src/app/shared/client/v1/kubernetes/deployment.ts
index 6fd057c5b..fdaa73073 100644
--- a/src/frontend/src/app/shared/client/v1/kubernetes/deployment.ts
+++ b/src/frontend/src/app/shared/client/v1/kubernetes/deployment.ts
@@ -5,6 +5,7 @@ import { PageState } from '../../../page/page-state';
import { BaseClient } from './base-client';
import { KubeDeployment, ObjectMeta } from '../../../model/v1/kubernetes/deployment';
import { throwError } from 'rxjs';
+import { catchError } from 'rxjs/operators';
@Injectable()
export class DeploymentClient {
@@ -39,4 +40,12 @@ export class DeploymentClient {
.delete(`/api/v1/kubernetes/apps/${appId}/deployments/${name}/namespaces/${namespace}/clusters/${cluster}`)
.catch(error => throwError(error));
}
+
+ modifyReplica(appId: number, cluster: string, name: string, namespace: string, data: any) {
+ return this.http
+ .post(`/api/v1/kubernetes/apps/${appId}/deployments/${name}/namespaces/${namespace}/clusters/${cluster}/updatescale`, data)
+ .pipe(
+ catchError(error => throwError(error))
+ );
+ }
}
diff --git a/src/frontend/src/app/shared/client/v1/namespace.service.ts b/src/frontend/src/app/shared/client/v1/namespace.service.ts
index 7baf80554..9737d47cc 100644
--- a/src/frontend/src/app/shared/client/v1/namespace.service.ts
+++ b/src/frontend/src/app/shared/client/v1/namespace.service.ts
@@ -110,4 +110,13 @@ export class NamespaceService {
.get(`/api/v1/namespaces/${namespaceId}/history`, {params: params})
.catch(error => throwError(error));
}
+
+ migrateNamespace(sourceId: number, targetId: number) {
+ return this.http
+ .post(`/api/v1/namespaces/migration`, {
+ sourceId,
+ targetId
+ })
+ .catch(error => throwError(error));
+ }
}
diff --git a/src/frontend/src/app/shared/filter-box/filter-box.component.scss b/src/frontend/src/app/shared/filter-box/filter-box.component.scss
index 024920114..d26691822 100644
--- a/src/frontend/src/app/shared/filter-box/filter-box.component.scss
+++ b/src/frontend/src/app/shared/filter-box/filter-box.component.scss
@@ -9,6 +9,7 @@
right: -200px;
top: -12px;
z-index: 520;
+ filter: drop-shadow(1px 2px 4px #ccc);
&:before {
content: '';
@@ -20,7 +21,6 @@
width: 16px;
height: 16px;
background: #fff;
- box-shadow: 0 2px 8px 1px #dee6f3;
z-index: 1;
}
diff --git a/src/frontend/src/app/shared/modal/modal.component.html b/src/frontend/src/app/shared/modal/modal.component.html
new file mode 100644
index 000000000..b67ce91ed
--- /dev/null
+++ b/src/frontend/src/app/shared/modal/modal.component.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/frontend/src/app/shared/modal/modal.component.scss b/src/frontend/src/app/shared/modal/modal.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/frontend/src/app/shared/modal/modal.component.spec.ts b/src/frontend/src/app/shared/modal/modal.component.spec.ts
new file mode 100644
index 000000000..fc32a90f0
--- /dev/null
+++ b/src/frontend/src/app/shared/modal/modal.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ModalComponent } from './modal.component';
+
+describe('ModalComponent', () => {
+ let component: ModalComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ModalComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/frontend/src/app/shared/modal/modal.component.ts b/src/frontend/src/app/shared/modal/modal.component.ts
new file mode 100644
index 000000000..0adfd5bda
--- /dev/null
+++ b/src/frontend/src/app/shared/modal/modal.component.ts
@@ -0,0 +1,27 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { ModalService } from 'app/shared/modal/modal.service';
+
+@Component({
+ selector: 'wayne-modal',
+ templateUrl: './modal.component.html',
+ styleUrls: ['./modal.component.scss']
+})
+export class ModalComponent implements OnInit {
+ opened = false;
+ @Input() isValid = false;
+ constructor(
+ private modalService: ModalService
+ ) { }
+
+ ngOnInit() {
+ }
+
+ onSubmit() {
+ this.modalService.comfirm();
+ }
+
+ onCancel() {
+ this.modalService.cancel();
+ }
+
+}
diff --git a/src/frontend/src/app/shared/modal/modal.service.ts b/src/frontend/src/app/shared/modal/modal.service.ts
new file mode 100644
index 000000000..8c1893e16
--- /dev/null
+++ b/src/frontend/src/app/shared/modal/modal.service.ts
@@ -0,0 +1,18 @@
+import { Injectable } from '@angular/core';
+import { Subject } from 'rxjs/Subject';
+
+export class ModalService {
+ modalObservable = new Subject();
+
+ modalObservable$ = this.modalObservable.asObservable();
+
+ open() {
+ this.modalObservable.next({method: 'open'});
+ }
+ cancel() {
+ this.modalObservable.next({method: 'cancel'});
+ }
+ comfirm() {
+ this.modalObservable.next({method: 'confirm'});
+ }
+}
diff --git a/src/frontend/src/app/shared/shared.const.ts b/src/frontend/src/app/shared/shared.const.ts
index ae67776d2..3999035af 100644
--- a/src/frontend/src/app/shared/shared.const.ts
+++ b/src/frontend/src/app/shared/shared.const.ts
@@ -45,7 +45,7 @@ export const enum AlertType {
}
export const enum ResourcesActionType {
- PUBLISH, SCALE, RESTART, OFFLINE, UPDATE
+ PUBLISH, SCALE, RESTART, OFFLINE, UPDATE, MODIFY_REPLICA
}
export const enum TemplateState {
diff --git a/src/frontend/src/app/shared/shared.module.ts b/src/frontend/src/app/shared/shared.module.ts
index 9a3708450..9cfad84c2 100644
--- a/src/frontend/src/app/shared/shared.module.ts
+++ b/src/frontend/src/app/shared/shared.module.ts
@@ -54,6 +54,9 @@ import { ListEventComponent } from './list-event/list-event.component';
import { SideNavService } from './client/v1/sidenav.service';
import { SearchSectionComponent } from './tabs/search-section/search-section.component';
import { CollapseModule } from './collapse/collapse.module';
+import { ModalComponent } from './modal/modal.component';
+import { ModalService } from './modal/modal.service';
+
@NgModule({
imports: [
BrowserAnimationsModule,
@@ -97,7 +100,8 @@ import { CollapseModule } from './collapse/collapse.module';
DiffComponent,
ListPodComponent,
ListEventComponent,
- SearchSectionComponent
+ SearchSectionComponent,
+ ModalComponent
],
exports: [
BrowserAnimationsModule,
@@ -131,6 +135,7 @@ import { CollapseModule } from './collapse/collapse.module';
CheckboxComponent,
CheckboxGroupComponent,
DropDownComponent,
+ ModalComponent,
DropdownItemComponent,
RelativeTimeFilterPipe,
TranslateModule,
@@ -154,7 +159,8 @@ import { CollapseModule } from './collapse/collapse.module';
CopyService,
TabDragService,
SelectCopyService,
- DiffService
+ DiffService,
+ ModalService
]
})
export class SharedModule {
diff --git a/src/frontend/src/assets/i18n/zh-Hans.json b/src/frontend/src/assets/i18n/zh-Hans.json
index 885316b15..3b7258880 100644
--- a/src/frontend/src/assets/i18n/zh-Hans.json
+++ b/src/frontend/src/assets/i18n/zh-Hans.json
@@ -185,7 +185,8 @@
"CREATE_TMP": "创建部署模板",
"DELETE": "删除部署",
"EDIT": "编辑部署",
- "NUM": "部署份数"
+ "NUM": "部署份数",
+ "MODIFY_REPLICA": "修改副本数"
},
"DEPLOYMENT_ADMIN": {
"CREATE": {