--- /dev/null
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { configureTestBed } from '../../../testing/unit-test-helper';
+import { SettingsService } from './settings.service';
+
+describe('SettingsService', () => {
+ let service: SettingsService;
+ let httpTesting: HttpTestingController;
+
+ configureTestBed({
+ providers: [SettingsService],
+ imports: [HttpClientTestingModule]
+ });
+
+ beforeEach(() => {
+ service = TestBed.get(SettingsService);
+ httpTesting = TestBed.get(HttpTestingController);
+ });
+
+ afterEach(() => {
+ httpTesting.verify();
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should get protocol', () => {
+ service.getGrafanaApiUrl().subscribe();
+ const req = httpTesting.expectOne('api/settings/GRAFANA_API_URL');
+ expect(req.request.method).toBe('GET');
+ });
+});
--- /dev/null
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { ApiModule } from './api.module';
+
+@Injectable({
+ providedIn: ApiModule
+})
+export class SettingsService {
+ constructor(private http: HttpClient) {}
+
+ getGrafanaApiUrl() {
+ return this.http.get('api/settings/GRAFANA_API_URL');
+ }
+}
import { ChartsModule } from 'ng2-charts/ng2-charts';
import { AlertModule, ModalModule, PopoverModule, TooltipModule } from 'ngx-bootstrap';
+import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { DirectivesModule } from '../directives/directives.module';
import { PipesModule } from '../pipes/pipes.module';
import { ConfirmationModalComponent } from './confirmation-modal/confirmation-modal.component';
import { DeletionModalComponent } from './deletion-modal/deletion-modal.component';
import { ErrorPanelComponent } from './error-panel/error-panel.component';
+import { GrafanaComponent } from './grafana/grafana.component';
import { HelperComponent } from './helper/helper.component';
import { InfoPanelComponent } from './info-panel/info-panel.component';
import { LoadingPanelComponent } from './loading-panel/loading-panel.component';
ReactiveFormsModule,
PipesModule,
ModalModule.forRoot(),
- DirectivesModule
+ DirectivesModule,
+ BsDropdownModule
],
declarations: [
ViewCacheComponent,
ModalComponent,
DeletionModalComponent,
ConfirmationModalComponent,
- WarningPanelComponent
+ WarningPanelComponent,
+ GrafanaComponent
],
providers: [],
exports: [
InfoPanelComponent,
UsageBarComponent,
ModalComponent,
- WarningPanelComponent
+ WarningPanelComponent,
+ GrafanaComponent
],
entryComponents: [ModalComponent, DeletionModalComponent, ConfirmationModalComponent]
})
--- /dev/null
+<!-- Embed dashboard -->
+<cd-loading-panel *ngIf="loading && grafanaExist"
+ i18n>
+ Loading panel data...
+</cd-loading-panel>
+<cd-info-panel *ngIf="!grafanaExist">
+ <ng-container i18n>
+ Please consult the <a href="http://docs.ceph.com/docs/luminous/mgr/dashboard/" target="_blank">documentation</a> on how to configure and enable the monitoring functionality.
+ </ng-container>
+</cd-info-panel>
+<div class="row" *ngIf="grafanaExist">
+ <div class="col-md-12">
+ <div dropdown>
+ <button dropdownToggle
+ class="btn btn-sm dropdown-toggle"
+ data-toggle="dropdown"
+ title="Advanced Settings">
+ <i class="fa fa-cog"></i>
+ <span class="caret"></span>
+ </button>
+ <ul *dropdownMenu
+ class="dropdown-menu">
+ <li>
+ <a i18n
+ class="dropdown-item"
+ (click)="timePickerToggle()">{{ modeText }}
+ </a>
+ </li>
+ </ul>
+ </div>
+ <div class="grafana-container">
+ <iframe #iframe
+ id="iframe"
+ [src]="grafanaSrc"
+ class="grafana"
+ [ngClass]="panelStyle"
+ frameborder="0"
+ scrolling="no">
+ </iframe>
+ </div>
+ </div>
+</div>
--- /dev/null
+.grafana {
+ width: 100%;
+ height: 600px;
+ z-index: 0;
+}
+
+.grafana_one {
+ height: 400px;
+}
+
+.grafana_two {
+ height: 750px;
+}
+
+.grafana_three {
+ height: 900px;
+}
+
+button {
+ margin-bottom: 10px;
+ margin-left: 10px;
+ float: right;
+ i {
+ font-size: 14px;
+ padding: 2px;
+ }
+}
+
+.dropdown-menu {
+ top: 20px;
+ right: 20px;
+ left: auto;
+}
--- /dev/null
+import { HttpClientModule } from '@angular/common/http';
+
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AlertModule } from 'ngx-bootstrap';
+
+import { configureTestBed } from '../../../../testing/unit-test-helper';
+import { SettingsService } from '../../../shared/api/settings.service';
+import { InfoPanelComponent } from '../info-panel/info-panel.component';
+import { LoadingPanelComponent } from '../loading-panel/loading-panel.component';
+import { GrafanaComponent } from './grafana.component';
+
+describe('GrafanaComponent', () => {
+ let component: GrafanaComponent;
+ let fixture: ComponentFixture<GrafanaComponent>;
+
+ configureTestBed({
+ declarations: [GrafanaComponent, InfoPanelComponent, LoadingPanelComponent],
+ imports: [AlertModule.forRoot(), HttpClientModule],
+ providers: [SettingsService]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(GrafanaComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
--- /dev/null
+import { Component, Input, OnChanges, OnInit } from '@angular/core';
+
+import { DomSanitizer } from '@angular/platform-browser';
+import { SafeUrl } from '@angular/platform-browser';
+
+import { SettingsService } from '../../../shared/api/settings.service';
+
+@Component({
+ selector: 'cd-grafana',
+ templateUrl: './grafana.component.html',
+ styleUrls: ['./grafana.component.scss']
+})
+export class GrafanaComponent implements OnInit, OnChanges {
+ grafanaSrc: SafeUrl;
+ url: string;
+ protocol: string;
+ host: string;
+ dashboardPath: string;
+ port: number;
+ baseUrl: any;
+ panelStyle: any;
+ grafanaExist = false;
+ mode = '&kiosk';
+ modeFlag = false;
+ modeText = 'Change time selection';
+ loading = true;
+ styles = {};
+
+ @Input()
+ grafanaPath: string;
+ @Input()
+ grafanaStyle: string;
+ grafanaUrl: any;
+
+ constructor(private sanitizer: DomSanitizer, private settingsService: SettingsService) {}
+
+ ngOnInit() {
+ this.styles = {
+ one: 'grafana_one',
+ two: 'grafana_two',
+ three: 'grafana_three'
+ };
+ this.settingsService.getGrafanaApiUrl().subscribe((data: any) => {
+ this.grafanaUrl = data.value;
+ if (this.grafanaUrl === '') {
+ this.grafanaExist = false;
+ return;
+ } else {
+ this.getFrame();
+ }
+ });
+ this.panelStyle = this.styles[this.grafanaStyle];
+ }
+
+ getFrame() {
+ this.baseUrl = this.grafanaUrl + '/d/';
+ this.grafanaExist = true;
+ this.loading = false;
+ this.url = this.baseUrl + this.grafanaPath + '&refresh=2s' + this.mode;
+ this.grafanaSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
+ }
+
+ timePickerToggle() {
+ this.modeFlag = true;
+ this.mode = this.mode ? '' : '&kiosk';
+ if (this.modeText === 'Return to default') {
+ this.modeText = 'Change time selection';
+ this.reset();
+ } else {
+ this.modeText = 'Return to default';
+ }
+ this.getFrame();
+ this.modeFlag = false;
+ }
+
+ reset() {
+ this.mode = '&kiosk';
+ this.modeText = 'Change time selection';
+ this.getFrame();
+ }
+
+ ngOnChanges(changes) {
+ this.getFrame();
+ }
+}
RGW_API_SSL_VERIFY = (True, bool)
# Grafana settings
- GRAFANA_API_URL = ('http://localhost:3000', str)
+ GRAFANA_API_URL = ('', str)
GRAFANA_API_USERNAME = ('admin', str)
GRAFANA_API_PASSWORD = ('admin', str)
GRAFANA_API_TOKEN = ('', str)