mirror of
https://github.com/ceph/ceph
synced 2025-02-21 18:17:42 +00:00
Merge pull request #52493 from rhcs-dashboard/cluster-upgrade-ui
mgr/dashboard: cluster upgrade start UI Reviewed-by: Pegonzal <pegonzal@redhat.com> Reviewed-by: cloudbehl <NOT@FOUND> Reviewed-by: Nizamudeen A <nia@redhat.com>
This commit is contained in:
commit
172133f18b
@ -58,6 +58,7 @@ import { ServiceFormComponent } from './services/service-form/service-form.compo
|
||||
import { ServicesComponent } from './services/services.component';
|
||||
import { TelemetryComponent } from './telemetry/telemetry.component';
|
||||
import { UpgradeComponent } from './upgrade/upgrade.component';
|
||||
import { UpgradeStartModalComponent } from './upgrade/upgrade-form/upgrade-start-modal.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -118,7 +119,8 @@ import { UpgradeComponent } from './upgrade/upgrade.component';
|
||||
PlacementPipe,
|
||||
CreateClusterComponent,
|
||||
CreateClusterReviewComponent,
|
||||
UpgradeComponent
|
||||
UpgradeComponent,
|
||||
UpgradeStartModalComponent
|
||||
],
|
||||
providers: [NgbActiveModal]
|
||||
})
|
||||
|
@ -0,0 +1,49 @@
|
||||
<cd-modal [modalRef]="activeModal">
|
||||
<ng-container class="modal-title">
|
||||
<ng-container i18n>Upgrade Cluster</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container class="modal-content">
|
||||
<form name="upgradeForm"
|
||||
class="form"
|
||||
#formDir="ngForm"
|
||||
[formGroup]="upgradeForm"
|
||||
novalidate>
|
||||
<div class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label required"
|
||||
for="availableVersions"
|
||||
i18n>New Version</label>
|
||||
<div class="cd-col-form-input">
|
||||
<select id="availableVersions"
|
||||
name="availableVersions"
|
||||
class="form-select"
|
||||
formControlName="availableVersions">
|
||||
<option *ngIf="versions === null"
|
||||
ngValue="null"
|
||||
i18n>Loading...</option>
|
||||
<option *ngIf="versions !== null && versions.length === 0"
|
||||
[ngValue]="null"
|
||||
i18n>-- No version available --</option>
|
||||
<option *ngIf="versions !== null && versions.length > 0"
|
||||
[ngValue]="null"
|
||||
i18n>-- Select a version --</option>
|
||||
<option *ngFor="let version of versions"
|
||||
[value]="version">{{ version }}</option>
|
||||
</select>
|
||||
<span class="invalid-feedback"
|
||||
*ngIf="upgradeForm.showError('availableVersions', formDir, 'required')"
|
||||
i18n>This field is required!</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<cd-form-button-panel *ngIf="versions"
|
||||
(submitActionEvent)="startUpgrade()"
|
||||
[form]="upgradeForm"
|
||||
[submitText]="actionLabels.START_UPGRADE"></cd-form-button-panel>
|
||||
</div>
|
||||
</form>
|
||||
</ng-container>
|
||||
</cd-modal>
|
@ -0,0 +1,30 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UpgradeComponent } from '../upgrade.component';
|
||||
import { configureTestBed } from '~/testing/unit-test-helper';
|
||||
import { UpgradeService } from '~/app/shared/api/upgrade.service';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { SharedModule } from '~/app/shared/shared.module';
|
||||
|
||||
describe('UpgradeComponent', () => {
|
||||
let component: UpgradeComponent;
|
||||
let fixture: ComponentFixture<UpgradeComponent>;
|
||||
|
||||
configureTestBed({
|
||||
imports: [HttpClientTestingModule, SharedModule],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
declarations: [UpgradeComponent],
|
||||
providers: [UpgradeService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UpgradeComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,66 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl, Validators } from '@angular/forms';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { Icons } from '~/app/shared/enum/icons.enum';
|
||||
import { Permission } from '~/app/shared/models/permissions';
|
||||
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
|
||||
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { UpgradeService } from '~/app/shared/api/upgrade.service';
|
||||
import { UpgradeInfoInterface } from '~/app/shared/models/upgrade.interface';
|
||||
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
|
||||
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
|
||||
import { NotificationService } from '~/app/shared/services/notification.service';
|
||||
|
||||
@Component({
|
||||
selector: 'cd-upgrade-start-modal.component',
|
||||
templateUrl: './upgrade-start-modal.component.html',
|
||||
styleUrls: ['./upgrade-start-modal.component.scss']
|
||||
})
|
||||
export class UpgradeStartModalComponent implements OnInit {
|
||||
permission: Permission;
|
||||
upgradeInfoError$: Observable<any>;
|
||||
upgradeInfo$: Observable<UpgradeInfoInterface>;
|
||||
upgradeForm: CdFormGroup;
|
||||
icons = Icons;
|
||||
versions: string[];
|
||||
|
||||
constructor(
|
||||
public actionLabels: ActionLabelsI18n,
|
||||
private authStorageService: AuthStorageService,
|
||||
public activeModal: NgbActiveModal,
|
||||
private upgradeService: UpgradeService,
|
||||
private notificationService: NotificationService
|
||||
) {
|
||||
this.permission = this.authStorageService.getPermissions().configOpt;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.upgradeForm = new CdFormGroup({
|
||||
availableVersions: new FormControl(null, [Validators.required])
|
||||
});
|
||||
}
|
||||
|
||||
startUpgrade() {
|
||||
this.upgradeService.start(this.upgradeForm.getValue('availableVersions')).subscribe({
|
||||
next: () => {
|
||||
this.notificationService.show(
|
||||
NotificationType.success,
|
||||
$localize`Started upgrading the cluster`
|
||||
);
|
||||
},
|
||||
error: (error) => {
|
||||
this.upgradeForm.setErrors({ cdSubmitButton: true });
|
||||
this.notificationService.show(
|
||||
NotificationType.error,
|
||||
$localize`Failed to start the upgrade`,
|
||||
error
|
||||
);
|
||||
},
|
||||
complete: () => {
|
||||
this.activeModal.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -40,6 +40,7 @@
|
||||
id="upgrade"
|
||||
aria-label="Upgrade now"
|
||||
[disabled]="(healthData.mgr_map | mgrSummary).total <= 1"
|
||||
(click)="startUpgradeModal()"
|
||||
i18n>Upgrade now</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -56,7 +56,7 @@ describe('UpgradeComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UpgradeComponent);
|
||||
component = fixture.componentInstance;
|
||||
upgradeInfoSpy = spyOn(TestBed.inject(UpgradeService), 'list');
|
||||
upgradeInfoSpy = spyOn(TestBed.inject(UpgradeService), 'list').and.callFake(() => of(null));
|
||||
getHealthSpy = spyOn(TestBed.inject(HealthService), 'getMinimalHealth');
|
||||
getHealthSpy.and.returnValue(of(healthPayload));
|
||||
fixture.detectChanges();
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { catchError, ignoreElements } from 'rxjs/operators';
|
||||
import { catchError, ignoreElements, tap } from 'rxjs/operators';
|
||||
import { HealthService } from '~/app/shared/api/health.service';
|
||||
import { UpgradeService } from '~/app/shared/api/upgrade.service';
|
||||
import { Icons } from '~/app/shared/enum/icons.enum';
|
||||
import { Permission } from '~/app/shared/models/permissions';
|
||||
import { UpgradeInfoInterface } from '~/app/shared/models/upgrade.interface';
|
||||
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { SummaryService } from '~/app/shared/services/summary.service';
|
||||
import { ModalService } from '~/app/shared/services/modal.service';
|
||||
import { UpgradeStartModalComponent } from './upgrade-form/upgrade-start-modal.component';
|
||||
|
||||
@Component({
|
||||
selector: 'cd-upgrade',
|
||||
@ -21,10 +24,13 @@ export class UpgradeComponent implements OnInit {
|
||||
permission: Permission;
|
||||
healthData$: Observable<any>;
|
||||
fsid$: Observable<any>;
|
||||
modalRef: NgbModalRef;
|
||||
upgradableVersions: string[];
|
||||
|
||||
icons = Icons;
|
||||
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
private summaryService: SummaryService,
|
||||
private upgradeService: UpgradeService,
|
||||
private authStorageService: AuthStorageService,
|
||||
@ -38,7 +44,11 @@ export class UpgradeComponent implements OnInit {
|
||||
const version = summary.version.replace('ceph version ', '').split('-');
|
||||
this.version = version[0];
|
||||
});
|
||||
this.upgradeInfo$ = this.upgradeService.list();
|
||||
this.upgradeInfo$ = this.upgradeService
|
||||
.list()
|
||||
.pipe(
|
||||
tap((upgradeInfo: UpgradeInfoInterface) => (this.upgradableVersions = upgradeInfo.versions))
|
||||
);
|
||||
this.upgradeInfoError$ = this.upgradeInfo$?.pipe(
|
||||
ignoreElements(),
|
||||
catchError((error) => of(error))
|
||||
@ -46,4 +56,10 @@ export class UpgradeComponent implements OnInit {
|
||||
this.healthData$ = this.healthService.getMinimalHealth();
|
||||
this.fsid$ = this.healthService.getClusterFsid();
|
||||
}
|
||||
|
||||
startUpgradeModal() {
|
||||
this.modalRef = this.modalService.show(UpgradeStartModalComponent, {
|
||||
versions: this.upgradableVersions.sort()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -57,4 +57,11 @@ describe('UpgradeService', () => {
|
||||
expectedVersions
|
||||
);
|
||||
});
|
||||
|
||||
it('should start the upgrade', () => {
|
||||
service.start('18.1.0').subscribe();
|
||||
const req = httpTesting.expectOne('api/cluster/upgrade/start');
|
||||
expect(req.request.method).toBe('POST');
|
||||
expect(req.request.body).toEqual({ version: '18.1.0' });
|
||||
});
|
||||
});
|
||||
|
@ -41,4 +41,8 @@ export class UpgradeService extends ApiClient {
|
||||
upgradeInfo.versions = upgradableVersions;
|
||||
return upgradeInfo;
|
||||
}
|
||||
|
||||
start(version: string) {
|
||||
return this.http.post(`${this.baseURL}/start`, { version: version });
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,7 @@ export class ActionLabelsI18n {
|
||||
EXPORT: string;
|
||||
IMPORT: any;
|
||||
MIGRATE: string;
|
||||
START_UPGRADE: string;
|
||||
|
||||
constructor() {
|
||||
/* Create a new item */
|
||||
@ -215,6 +216,8 @@ export class ActionLabelsI18n {
|
||||
this.REMOVE_SCHEDULING = $localize`Remove Scheduling`;
|
||||
this.PROMOTE = $localize`Promote`;
|
||||
this.DEMOTE = $localize`Demote`;
|
||||
|
||||
this.START_UPGRADE = $localize`Start Upgrade`;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user