From ec6e7ddede5bf2069269dcb810efbf9eb68f8bdd Mon Sep 17 00:00:00 2001 From: Aashish Sharma Date: Wed, 24 Jul 2024 11:07:27 +0530 Subject: [PATCH] mgr/dashboard: Zone details showing incorrect data for data pool values and compression info for Storage Classes Fixes: https://tracker.ceph.com/issues/67103 Signed-off-by: Aashish Sharma (cherry picked from commit 76af1c0b1be562d38f3d6323351b7b7d0462af48) --- .../rgw-multisite-zone-form.component.html | 6 +- .../rgw-multisite-zone-form.component.spec.ts | 119 +++++++++++++++--- .../rgw-multisite-zone-form.component.ts | 36 +++--- 3 files changed, 122 insertions(+), 39 deletions(-) diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.html index 98741bed3990..46461d71074a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.html @@ -241,9 +241,9 @@ formControlName="storageClass" (change)="getStorageClassData($event.target.value)" name="storageClass"> - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.spec.ts index e9da2f4ab17a..1e134eb0bf4b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.spec.ts @@ -1,37 +1,124 @@ -import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ReactiveFormsModule } from '@angular/forms'; +import { RgwMultisiteZoneFormComponent } from './rgw-multisite-zone-form.component'; // Adjust path as necessary +import { of } from 'rxjs'; +import { RgwZoneService } from '~/app/shared/api/rgw-zone.service'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ToastrModule } from 'ngx-toastr'; import { SharedModule } from '~/app/shared/shared.module'; - -import { RgwMultisiteZoneFormComponent } from './rgw-multisite-zone-form.component'; -import { configureTestBed } from '~/testing/unit-test-helper'; +import { RgwZone } from '../models/rgw-multisite'; describe('RgwMultisiteZoneFormComponent', () => { let component: RgwMultisiteZoneFormComponent; let fixture: ComponentFixture; - - configureTestBed({ - imports: [ - SharedModule, - ReactiveFormsModule, - RouterTestingModule, - HttpClientTestingModule, - ToastrModule.forRoot() - ], - providers: [NgbActiveModal], - declarations: [RgwMultisiteZoneFormComponent] - }); + let rgwZoneService: RgwZoneService; + let rgwZoneServiceSpy: jasmine.Spy; beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + SharedModule, + ReactiveFormsModule, + RouterTestingModule, + HttpClientTestingModule, + ToastrModule.forRoot() + ], + providers: [NgbActiveModal], + declarations: [RgwMultisiteZoneFormComponent] + }).compileComponents(); + fixture = TestBed.createComponent(RgwMultisiteZoneFormComponent); component = fixture.componentInstance; + rgwZoneService = TestBed.inject(RgwZoneService); + + rgwZoneServiceSpy = spyOn(rgwZoneService, 'get'); + + rgwZoneServiceSpy.and.returnValue( + of({ + placement_pools: [ + { + key: 'default-placement', + val: { + storage_classes: { + STANDARD: { + data_pool: 'standard-data-pool', + compression_type: 'gzip' + } + }, + index_pool: 'index-pool', + data_extra_pool: 'extra-data-pool' + } + } + ] + }) + ); + + component.info = { + parent: { + data: { + name: 'zonegroup2', + placement_targets: [ + { name: 'default-placement', tags: [], storage_classes: ['STANDARD'] } + ], + default_placement: 'default-placement' + } + }, + data: { + name: 'zone2', + parent: 'zonegroup2', + is_default: true, + is_master: true, + endpoints: ['http://192.168.100.100:80'], + access_key: 'zxcftyuuhgg', + secret_key: 'Qwsdcfgghuiioklpoozsd' + } + }; + + component.zone = new RgwZone(); + component.zone.name = component.info.data.name; + component.action = 'edit'; + fixture.detectChanges(); + + component.getZonePlacementData('default-placement'); }); it('should create', () => { expect(component).toBeTruthy(); }); + + it('should set correct values in the form on edit', () => { + expect(component.multisiteZoneForm.get('zoneName')?.value).toBe('zone2'); + expect(component.multisiteZoneForm.get('selectedZonegroup')?.value).toBe('zonegroup2'); + expect(component.multisiteZoneForm.get('default_zone')?.value).toBe(true); + expect(component.multisiteZoneForm.get('master_zone')?.value).toBe(true); + expect(component.multisiteZoneForm.get('zone_endpoints')?.value).toBe( + 'http://192.168.100.100:80' + ); + expect(component.multisiteZoneForm.get('access_key')?.value).toBe('zxcftyuuhgg'); + expect(component.multisiteZoneForm.get('secret_key')?.value).toBe('Qwsdcfgghuiioklpoozsd'); + expect(component.multisiteZoneForm.get('placementTarget')?.value).toBe('default-placement'); + expect(component.multisiteZoneForm.get('storageClass')?.value).toBe('STANDARD'); + expect(component.multisiteZoneForm.get('storageDataPool')?.value).toBe('standard-data-pool'); + expect(component.multisiteZoneForm.get('storageCompression')?.value).toBe('gzip'); + }); + + it('should create a new zone', () => { + component.action = 'create'; + const createSpy = spyOn(rgwZoneService, 'create').and.returnValue(of({})); + component.submit(); + expect(createSpy).toHaveBeenCalledWith( + { + endpoints: 'http://192.168.100.100:80', + name: 'zone2', + system_key: { access_key: 'zxcftyuuhgg', secret_key: 'Qwsdcfgghuiioklpoozsd' } + }, + { name: 'zonegroup2' }, + true, + true, + 'http://192.168.100.100:80' + ); + }); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts index 21106c53eb3b..bd7dde62c368 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-zone-form/rgw-multisite-zone-form.component.ts @@ -207,23 +207,20 @@ export class RgwMultisiteZoneFormComponent implements OnInit { getZonePlacementData(placementTarget: string) { this.zone = new RgwZone(); this.zone.name = this.info.data.name; - if (this.placementTargets) { - this.placementTargets.forEach((placement: any) => { - if (placement.name === placementTarget) { - let storageClasses = placement.storage_classes; - this.storageClassList = Object.entries(storageClasses).map(([key, value]) => ({ - key, - value - })); - } - }); - } this.rgwZoneService.get(this.zone).subscribe((zoneInfo: RgwZone) => { this.zoneInfo = zoneInfo; if (this.zoneInfo && this.zoneInfo['placement_pools']) { + const placementPoolKeys = this.zoneInfo['placement_pools'].map((plc_pool) => plc_pool.key); + this.placementTargets = this.placementTargets.filter((placement: { name: string }) => + placementPoolKeys.includes(placement.name) + ); this.zoneInfo['placement_pools'].forEach((plc_pool) => { if (plc_pool.key === placementTarget) { let storageClasses = plc_pool.val.storage_classes; + this.storageClassList = Object.entries(storageClasses).map(([key, value]) => ({ + key, + value + })); let placementDataPool = storageClasses['STANDARD'] ? storageClasses['STANDARD']['data_pool'] : ''; @@ -232,9 +229,8 @@ export class RgwMultisiteZoneFormComponent implements OnInit { this.poolList.push({ poolname: placementDataPool }); this.poolList.push({ poolname: placementIndexPool }); this.poolList.push({ poolname: placementDataExtraPool }); - this.multisiteZoneForm.get('storageClass').setValue(this.storageClassList[0]['value']); - this.multisiteZoneForm.get('storageDataPool').setValue(placementDataPool); - this.multisiteZoneForm.get('storageCompression').setValue(this.compressionTypes[0]); + this.multisiteZoneForm.get('storageClass').setValue(this.storageClassList[0]['key']); + this.getStorageClassData(this.storageClassList[0]['key']); this.multisiteZoneForm.get('placementDataPool').setValue(placementDataPool); this.multisiteZoneForm.get('placementIndexPool').setValue(placementIndexPool); this.multisiteZoneForm.get('placementDataExtraPool').setValue(placementDataExtraPool); @@ -245,14 +241,14 @@ export class RgwMultisiteZoneFormComponent implements OnInit { } getStorageClassData(storageClass: string) { - let storageClassSelected = this.storageClassList.find((x) => x['value'] == storageClass)[ - 'value' - ]; - this.poolList.push({ poolname: storageClassSelected.data_pool }); - this.multisiteZoneForm.get('storageDataPool').setValue(storageClassSelected.data_pool); + let storageClassSelected = this.storageClassList.find((sc) => sc['key'] === storageClass); + this.poolList.push({ poolname: storageClassSelected['value']['data_pool'] }); + this.multisiteZoneForm + .get('storageDataPool') + .setValue(storageClassSelected['value']['data_pool']); this.multisiteZoneForm .get('storageCompression') - .setValue(storageClassSelected.compression_type); + .setValue(storageClassSelected['value']['compression_type']); } submit() { -- 2.47.3