import { TooltipModule } from 'ngx-bootstrap/tooltip';
import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
+import { OrchestratorDocModalComponent } from '../../shared/components/orchestrator-doc-modal/orchestrator-doc-modal.component';
import { SharedModule } from '../../shared/shared.module';
import { PerformanceCounterModule } from '../performance-counter/performance-counter.module';
import { CephSharedModule } from '../shared/ceph-shared.module';
OsdReweightModalComponent,
SilenceMatcherModalComponent,
OsdDevicesSelectionModalComponent,
- OsdCreationPreviewModalComponent
+ OsdCreationPreviewModalComponent,
+ OrchestratorDocModalComponent
],
imports: [
CommonModule,
constructor(private http: HttpClient) {}
- status() {
- return this.http.get(`${this.url}/status`);
+ status(): Observable<{ available: boolean; description: string }> {
+ return this.http.get<{ available: boolean; description: string }>(`${this.url}/status`);
}
identifyDevice(hostname: string, device: string, duration: number) {
import { LoadingPanelComponent } from './loading-panel/loading-panel.component';
import { ModalComponent } from './modal/modal.component';
import { NotificationsSidebarComponent } from './notifications-sidebar/notifications-sidebar.component';
+import { OrchestratorDocModalComponent } from './orchestrator-doc-modal/orchestrator-doc-modal.component';
+import { OrchestratorDocPanelComponent } from './orchestrator-doc-panel/orchestrator-doc-panel.component';
import { PwdExpirationNotificationComponent } from './pwd-expiration-notification/pwd-expiration-notification.component';
import { RefreshSelectorComponent } from './refresh-selector/refresh-selector.component';
import { SelectBadgesComponent } from './select-badges/select-badges.component';
ConfigOptionComponent,
AlertPanelComponent,
FormModalComponent,
- PwdExpirationNotificationComponent
+ PwdExpirationNotificationComponent,
+ OrchestratorDocPanelComponent,
+ OrchestratorDocModalComponent
],
providers: [],
exports: [
RefreshSelectorComponent,
ConfigOptionComponent,
AlertPanelComponent,
- PwdExpirationNotificationComponent
+ PwdExpirationNotificationComponent,
+ OrchestratorDocPanelComponent
],
entryComponents: [
ModalComponent,
--- /dev/null
+<cd-modal [modalRef]="bsModalRef">
+ <ng-container class="modal-title"
+ i18n>{{ actionDescription }} {{ itemDescription }}</ng-container>
+
+ <ng-container class="modal-content">
+ <div class="modal-body">
+ <cd-orchestrator-doc-panel></cd-orchestrator-doc-panel>
+ </div>
+ <div class="modal-footer">
+ <cd-back-button [back]="bsModalRef.hide"
+ name="Close"
+ i18n-name>
+ </cd-back-button>
+ </div>
+ </ng-container>
+</cd-modal>
--- /dev/null
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { ComponentsModule } from '../components.module';
+import { OrchestratorDocModalComponent } from './orchestrator-doc-modal.component';
+
+describe('OrchestratorDocModalComponent', () => {
+ let component: OrchestratorDocModalComponent;
+ let fixture: ComponentFixture<OrchestratorDocModalComponent>;
+
+ configureTestBed({
+ imports: [ComponentsModule, HttpClientTestingModule, RouterTestingModule],
+ providers: [BsModalRef, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OrchestratorDocModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, OnInit } from '@angular/core';
+
+import { BsModalRef } from 'ngx-bootstrap/modal';
+
+@Component({
+ selector: 'cd-orchestrator-doc-modal',
+ templateUrl: './orchestrator-doc-modal.component.html',
+ styleUrls: ['./orchestrator-doc-modal.component.scss']
+})
+export class OrchestratorDocModalComponent implements OnInit {
+ actionDescription: string;
+ itemDescription: string;
+
+ constructor(public bsModalRef: BsModalRef) {}
+
+ ngOnInit() {}
+
+ onSubmit() {
+ this.bsModalRef.hide();
+ }
+}
--- /dev/null
+<cd-alert-panel type="info"
+ i18n>Orchestrator is not available. Please consult the
+ <a href="{{ docsUrl }}"
+ target="_blank">documentation</a> on how to
+ configure and enable the functionality.</cd-alert-panel>
--- /dev/null
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../services/summary.service';
+import { ComponentsModule } from '../components.module';
+import { OrchestratorDocPanelComponent } from './orchestrator-doc-panel.component';
+
+describe('OrchestratorDocPanelComponent', () => {
+ let component: OrchestratorDocPanelComponent;
+ let fixture: ComponentFixture<OrchestratorDocPanelComponent>;
+
+ configureTestBed({
+ imports: [ComponentsModule, HttpClientTestingModule, RouterTestingModule],
+ providers: [CephReleaseNamePipe, SummaryService, i18nProviders]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OrchestratorDocPanelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, OnInit } from '@angular/core';
+
+import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe';
+import { SummaryService } from '../../services/summary.service';
+
+@Component({
+ selector: 'cd-orchestrator-doc-panel',
+ templateUrl: './orchestrator-doc-panel.component.html',
+ styleUrls: ['./orchestrator-doc-panel.component.scss']
+})
+export class OrchestratorDocPanelComponent implements OnInit {
+ docsUrl: string;
+
+ constructor(
+ private cephReleaseNamePipe: CephReleaseNamePipe,
+ private summaryService: SummaryService
+ ) {}
+
+ ngOnInit() {
+ const subs = this.summaryService.subscribe((summary: any) => {
+ if (!summary) {
+ return;
+ }
+
+ const releaseName = this.cephReleaseNamePipe.transform(summary.version);
+ this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/orchestrator_cli/`;
+
+ setTimeout(() => {
+ subs.unsubscribe();
+ }, 0);
+ });
+ }
+}
--- /dev/null
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { BsModalService, ModalModule } from 'ngx-bootstrap/modal';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { OrchestratorService } from '../api/orchestrator.service';
+import { DepCheckerService } from './dep-checker.service';
+
+describe('DepCheckerService', () => {
+ configureTestBed({
+ providers: [BsModalService, DepCheckerService, OrchestratorService],
+ imports: [HttpClientTestingModule, ModalModule.forRoot()]
+ });
+
+ it('should be created', () => {
+ const service: DepCheckerService = TestBed.get(DepCheckerService);
+ expect(service).toBeTruthy();
+ });
+});
--- /dev/null
+import { Injectable } from '@angular/core';
+
+import { BsModalService } from 'ngx-bootstrap/modal';
+
+import { OrchestratorService } from '../api/orchestrator.service';
+import { OrchestratorDocModalComponent } from '../components/orchestrator-doc-modal/orchestrator-doc-modal.component';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class DepCheckerService {
+ constructor(private orchService: OrchestratorService, private modalService: BsModalService) {}
+
+ /**
+ * Check if orchestrator is available. Display an information modal if not.
+ * If orchestrator is available, then the provided function will be called.
+ * This helper function can be used with table actions.
+ * @param {string} actionDescription name of the action.
+ * @param {string} itemDescription the item's name that the action operates on.
+ * @param {Function} func the function to be called if orchestrator is available.
+ */
+ checkOrchestratorOrModal(actionDescription: string, itemDescription: string, func: Function) {
+ this.orchService.status().subscribe((status) => {
+ if (status.available) {
+ func();
+ } else {
+ this.modalService.show(OrchestratorDocModalComponent, {
+ initialState: {
+ actionDescription: actionDescription,
+ itemDescription: itemDescription
+ }
+ });
+ }
+ });
+ }
+}