Skip to content

Commit

Permalink
Merge pull request ceph#56349 from rhcs-dashboard/add-landing-page-up…
Browse files Browse the repository at this point in the history
…grade-notification

mgr/dashboard: add upgrade notification

Reviewed-by: Ankush Behl <[email protected]>
Reviewed-by: Nizamudeen A <[email protected]>
  • Loading branch information
Pegonzal authored May 15, 2024
2 parents ae197d8 + 882c747 commit 196e2c9
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<ng-template #inProgress>
<h5 i18n>
<i [ngClass]="[icons.spin, icons.spinner]"></i>
Upgrade in progress {{executingTasks?.progress}}%
Upgrading {{executingTasks?.progress}}%
</h5>
</ng-template>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ describe('UpgradeComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(UpgradeComponent);
component = fixture.componentInstance;
upgradeInfoSpy = spyOn(TestBed.inject(UpgradeService), 'list').and.callFake(() => of(null));
upgradeInfoSpy = spyOn(TestBed.inject(UpgradeService), 'listCached').and.callFake(() =>
of(null)
);
getHealthSpy = spyOn(TestBed.inject(HealthService), 'getMinimalHealth');
upgradeStatusSpy = spyOn(TestBed.inject(UpgradeService), 'status');
getHealthSpy.and.returnValue(of(healthPayload));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Observable, ReplaySubject, Subscription, of } from 'rxjs';
import { catchError, publishReplay, refCount, shareReplay, switchMap, tap } from 'rxjs/operators';
import { catchError, shareReplay, switchMap } from 'rxjs/operators';
import { DaemonService } from '~/app/shared/api/daemon.service';
import { HealthService } from '~/app/shared/api/health.service';
import { UpgradeService } from '~/app/shared/api/upgrade.service';
Expand All @@ -13,8 +13,6 @@ import { UpgradeInfoInterface } from '~/app/shared/models/upgrade.interface';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { NotificationService } from '~/app/shared/services/notification.service';
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';
import { ExecutingTask } from '~/app/shared/models/executing-task';
import { Router } from '@angular/router';
import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.service';
Expand Down Expand Up @@ -43,9 +41,9 @@ export class UpgradeComponent implements OnInit, OnDestroy {

upgradeStatus$: Observable<any>;
subject = new ReplaySubject<any>();
private subs = new Subscription();

constructor(
private modalService: ModalService,
private summaryService: SummaryService,
private upgradeService: UpgradeService,
private healthService: HealthService,
Expand Down Expand Up @@ -76,22 +74,21 @@ export class UpgradeComponent implements OnInit, OnDestroy {
}
];

this.summaryService.subscribe((summary) => {
const version = summary.version.replace('ceph version ', '').split('-');
this.version = version[0];
this.executingTasks = summary.executing_tasks.filter((tasks) =>
tasks.name.includes('progress/Upgrade')
)[0];
});
this.subs.add(
this.summaryService.subscribe((summary) => {
const version = summary.version.replace('ceph version ', '').split('-');
this.version = version[0];
this.executingTasks = summary.executing_tasks.filter((tasks) =>
tasks.name.includes('progress/Upgrade')
)[0];
})
);

this.interval = this.refreshIntervalService.intervalData$.subscribe(() => {
this.fetchStatus();
});

this.info$ = this.upgradeService.list().pipe(
tap((upgradeInfo: UpgradeInfoInterface) => (this.upgradableVersions = upgradeInfo.versions)),
publishReplay(1),
refCount(),
this.info$ = this.upgradeService.listCached().pipe(
catchError((err) => {
err.preventDefault();
this.errorMessage = $localize`Not retrieving upgrades`;
Expand All @@ -110,9 +107,7 @@ export class UpgradeComponent implements OnInit, OnDestroy {
}

startUpgradeModal() {
this.modalRef = this.modalService.show(UpgradeStartModalComponent, {
versions: this.upgradableVersions
});
this.modalRef = this.upgradeService.startUpgradeModal();
}

fetchStatus() {
Expand Down Expand Up @@ -141,5 +136,6 @@ export class UpgradeComponent implements OnInit, OnDestroy {

ngOnDestroy() {
this.interval?.unsubscribe();
this.subs?.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
<dt>Orchestrator</dt>
<dd i18n>{{ detailsCardData.orchestrator || 'Orchestrator is not available' }}</dd>
<dt>Ceph version</dt>
<dd>{{ detailsCardData.cephVersion }}</dd>
<dd>
{{ detailsCardData.cephVersion }}
<cd-upgradable></cd-upgradable>
</dd>
<dt>Cluster API</dt>
<dd>
<a routerLink="/api-docs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit
hardwareSummary$: Observable<any>;
hardwareSubject = new BehaviorSubject<any>([]);
managedByConfig$: Observable<any>;
private subs = new Subscription();

constructor(
private summaryService: SummaryService,
Expand Down Expand Up @@ -133,6 +134,7 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit
ngOnDestroy() {
this.interval.unsubscribe();
this.prometheusService.unsubscribe();
this.subs?.unsubscribe();
}

getHealth() {
Expand All @@ -152,11 +154,13 @@ export class DashboardV3Component extends PrometheusListHelper implements OnInit
this.orchestratorService.getName().subscribe((data: string) => {
this.detailsCardData.orchestrator = data;
});
this.summaryService.subscribe((summary) => {
const version = summary.version.replace('ceph version ', '').split(' ');
this.detailsCardData.cephVersion =
version[0] + ' ' + version.slice(2, version.length).join(' ');
});
this.subs.add(
this.summaryService.subscribe((summary) => {
const version = summary.version.replace('ceph version ', '').split(' ');
this.detailsCardData.cephVersion =
version[0] + ' ' + version.slice(2, version.length).join(' ');
})
);
}

getCapacityCardData() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ApiClient } from './api-client';
import { map } from 'rxjs/operators';
import { map, shareReplay, tap } from 'rxjs/operators';
import { SummaryService } from '../services/summary.service';
import { UpgradeInfoInterface, UpgradeStatusInterface } from '../models/upgrade.interface';
import { Observable } from 'rxjs';
import { UpgradeStartModalComponent } from '~/app/ceph/cluster/upgrade/upgrade-form/upgrade-start-modal.component';
import { ModalService } from '../services/modal.service';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';

const CACHE_SIZE = 1;

@Injectable({
providedIn: 'root'
Expand All @@ -25,7 +30,14 @@ export class UpgradeService extends ApiClient {
'nfs'
];

constructor(private http: HttpClient, private summaryService: SummaryService) {
_listData$: Observable<UpgradeInfoInterface>;
_upgradableVersions: string[];

constructor(
private http: HttpClient,
private summaryService: SummaryService,
private modalService: ModalService
) {
super();
}

Expand Down Expand Up @@ -75,4 +87,22 @@ export class UpgradeService extends ApiClient {
status(): Observable<UpgradeStatusInterface> {
return this.http.get<UpgradeStatusInterface>(`${this.baseURL}/status`);
}

listCached(): Observable<UpgradeInfoInterface> {
if (!this._listData$) {
this._listData$ = this.list().pipe(
tap(
(upgradeInfo: UpgradeInfoInterface) => (this._upgradableVersions = upgradeInfo.versions)
),
shareReplay(CACHE_SIZE)
);
}
return this._listData$;
}

startUpgradeModal(): NgbModalRef {
return this.modalService.show(UpgradeStartModalComponent, {
versions: this._upgradableVersions
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { VerticalNavigationComponent } from './vertical-navigation/vertical-navi
import { CardGroupComponent } from './card-group/card-group.component';
import { HelpTextComponent } from './help-text/help-text.component';
import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset/form-advanced-fieldset.component';
import { UpgradableComponent } from './upgradable/upgradable.component';

@NgModule({
imports: [
Expand Down Expand Up @@ -115,7 +116,8 @@ import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset/form-adv
VerticalNavigationComponent,
CardGroupComponent,
HelpTextComponent,
FormAdvancedFieldsetComponent
FormAdvancedFieldsetComponent,
UpgradableComponent
],
providers: [],
exports: [
Expand Down Expand Up @@ -152,7 +154,8 @@ import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset/form-adv
VerticalNavigationComponent,
CardGroupComponent,
HelpTextComponent,
FormAdvancedFieldsetComponent
FormAdvancedFieldsetComponent,
UpgradableComponent
]
})
export class ComponentsModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<div *ngIf="upgradeStatus$ | async as status; else isUpgradable">
<ng-container *ngIf="status.is_paused || status.in_progress; else isUpgradable">
<h5 *ngIf="status.is_paused; else inProgress"
i18n>
Upgrade is paused
</h5>
<ng-template #inProgress>
<a href="#/upgrade/progress"
i18n>
<i [ngClass]="[icons.spin, icons.spinner]"></i>
Upgrading {{executingTask?.progress}}%
</a>
</ng-template>
</ng-container>
</div>

<ng-template #isUpgradable>
<div *ngIf="upgradeInfo$ | async as info"
i18n>
<h5 *ngIf="info.versions.length > 0"
(click)="upgradeModal()">
<i [ngClass]="icons.up"></i>
Upgrade available
</h5>
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { UpgradableComponent } from './upgradable.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('UpgradableComponent', () => {
let component: UpgradableComponent;
let fixture: ComponentFixture<UpgradableComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UpgradableComponent],
imports: [HttpClientTestingModule]
}).compileComponents();

fixture = TestBed.createComponent(UpgradableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Component } from '@angular/core';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { Observable, Subscription } from 'rxjs';
import { UpgradeService } from '../../api/upgrade.service';
import { UpgradeInfoInterface, UpgradeStatusInterface } from '../../models/upgrade.interface';
import { OrchestratorService } from '../../api/orchestrator.service';
import { Icons } from '~/app/shared/enum/icons.enum';
import { SummaryService } from '../../services/summary.service';
import { ExecutingTask } from '../../models/executing-task';

@Component({
selector: 'cd-upgradable',
templateUrl: './upgradable.component.html',
styleUrls: ['./upgradable.component.scss']
})
export class UpgradableComponent {
orchAvailable: boolean = false;
upgradeInfo$: Observable<UpgradeInfoInterface>;
upgradeStatus$: Observable<UpgradeStatusInterface>;
upgradeModalRef: NgbModalRef;
executingTask: ExecutingTask;
private subs = new Subscription();

icons = Icons;

constructor(
private orchestratorService: OrchestratorService,
private summaryService: SummaryService,
private upgradeService: UpgradeService
) {}

ngOnInit() {
this.orchestratorService.status().subscribe((status: any) => {
this.orchAvailable = status.available;
if (this.orchAvailable && status.upgrade_status?.available) {
this.upgradeInfo$ = this.upgradeService.listCached();
this.upgradeStatus$ = this.upgradeService.status();
}
});

this.subs.add(
this.summaryService.subscribe((summary) => {
this.executingTask = summary.executing_tasks.filter((tasks) =>
tasks.name.includes('progress/Upgrade')
)[0];
})
);
}

ngOnDestroy() {
this.subs?.unsubscribe();
}

upgradeModal() {
this.upgradeModalRef = this.upgradeService.startUpgradeModal();
}
}

0 comments on commit 196e2c9

Please sign in to comment.