Skip to content

Commit 36a313f

Browse files
author
Naman Munet
committed
mgr/dashboard: fix bucket rate limit API on owner change
Fixes: https://tracker.ceph.com/issues/70874 PR covers & fixes below scenarios: Whenever we change the owner of bucket from non-tenanted to tenanted and vice-versa with the rate-limit changes, there was issue in sending bucket name Scenario 1: Changing the bucket owner from tenanted to non-tenanted Scenario 2: Changing the bucket owner from non-tenanted to tenanted Scenario 3: Keeping the owner(tenanted) same and changing only rate limit Signed-off-by: Naman Munet <[email protected]>
1 parent b60d533 commit 36a313f

File tree

2 files changed

+122
-8
lines changed

2 files changed

+122
-8
lines changed

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { RgwBucketFormComponent } from './rgw-bucket-form.component';
2121
import { RgwRateLimitComponent } from '../rgw-rate-limit/rgw-rate-limit.component';
2222
import { CheckboxModule, SelectModule } from 'carbon-components-angular';
2323
import { NO_ERRORS_SCHEMA } from '@angular/core';
24+
import { By } from '@angular/platform-browser';
25+
import { LoadingStatus } from '~/app/shared/forms/cd-form';
2426

2527
describe('RgwBucketFormComponent', () => {
2628
let component: RgwBucketFormComponent;
@@ -30,6 +32,7 @@ describe('RgwBucketFormComponent', () => {
3032
let rgwBucketServiceGetSpy: jasmine.Spy;
3133
let enumerateSpy: jasmine.Spy;
3234
let formHelper: FormHelper;
35+
let childComponent: RgwRateLimitComponent;
3336

3437
configureTestBed({
3538
declarations: [RgwBucketFormComponent, RgwRateLimitComponent],
@@ -338,4 +341,90 @@ describe('RgwBucketFormComponent', () => {
338341
component.deleteTag(0);
339342
expect(updateValidationSpy).toHaveBeenCalled();
340343
});
344+
345+
describe('should call bucket ratelimit API with correct bucket name', () => {
346+
beforeEach(() => {
347+
component.loading = LoadingStatus.Ready;
348+
fixture.detectChanges();
349+
childComponent = fixture.debugElement.query(By.directive(RgwRateLimitComponent))
350+
.componentInstance;
351+
});
352+
it('Scenario 1: tenanted owner with tenanted bucket name', () => {
353+
const rateLimitSpy = spyOn(rgwBucketService, 'updateBucketRateLimit').and.returnValue(
354+
observableOf([])
355+
);
356+
component.editing = true;
357+
formHelper.setMultipleValues({
358+
bid: 'tenant/bucket1',
359+
owner: 'tenant$user1'
360+
});
361+
childComponent.form.patchValue({
362+
rate_limit_enabled: true,
363+
rate_limit_max_readOps: 100,
364+
rate_limit_max_writeOps: 200,
365+
rate_limit_max_readBytes: '10MB',
366+
rate_limit_max_writeBytes: '20MB',
367+
rate_limit_max_readOps_unlimited: true, // Unlimited
368+
rate_limit_max_writeOps_unlimited: true, // Unlimited
369+
rate_limit_max_readBytes_unlimited: true, // Unlimited
370+
rate_limit_max_writeBytes_unlimited: true // Unlimited
371+
});
372+
childComponent.form.get('rate_limit_enabled').markAsDirty();
373+
const rateLimitConfig = childComponent.getRateLimitFormValue();
374+
component.updateBucketRateLimit();
375+
expect(rateLimitSpy).toHaveBeenCalledWith('tenant/bucket1', rateLimitConfig);
376+
});
377+
378+
it('Scenario 2: non tenanted owner with tenanted bucket name', () => {
379+
const rateLimitSpy = spyOn(rgwBucketService, 'updateBucketRateLimit').and.returnValue(
380+
observableOf([])
381+
);
382+
component.editing = true;
383+
formHelper.setMultipleValues({
384+
bid: 'tenant/bucket1',
385+
owner: 'non_tenanted_user'
386+
});
387+
childComponent.form.patchValue({
388+
rate_limit_enabled: true,
389+
rate_limit_max_readOps: 100,
390+
rate_limit_max_writeOps: 200,
391+
rate_limit_max_readBytes: '10MB',
392+
rate_limit_max_writeBytes: '20MB',
393+
rate_limit_max_readOps_unlimited: true, // Unlimited
394+
rate_limit_max_writeOps_unlimited: true, // Unlimited
395+
rate_limit_max_readBytes_unlimited: true, // Unlimited
396+
rate_limit_max_writeBytes_unlimited: true // Unlimited
397+
});
398+
childComponent.form.get('rate_limit_enabled').markAsDirty();
399+
const rateLimitConfig = childComponent.getRateLimitFormValue();
400+
component.updateBucketRateLimit();
401+
expect(rateLimitSpy).toHaveBeenCalledWith('bucket1', rateLimitConfig);
402+
});
403+
404+
it('Scenario 3: tenanted owner and with non-tenanted bucket name', () => {
405+
const rateLimitSpy = spyOn(rgwBucketService, 'updateBucketRateLimit').and.returnValue(
406+
observableOf([])
407+
);
408+
component.editing = true;
409+
formHelper.setMultipleValues({
410+
bid: 'bucket1',
411+
owner: 'tenant$user1'
412+
});
413+
childComponent.form.patchValue({
414+
rate_limit_enabled: true,
415+
rate_limit_max_readOps: 100,
416+
rate_limit_max_writeOps: 200,
417+
rate_limit_max_readBytes: '10MB',
418+
rate_limit_max_writeBytes: '20MB',
419+
rate_limit_max_readOps_unlimited: true, // Unlimited
420+
rate_limit_max_writeOps_unlimited: true, // Unlimited
421+
rate_limit_max_readBytes_unlimited: true, // Unlimited
422+
rate_limit_max_writeBytes_unlimited: true // Unlimited
423+
});
424+
childComponent.form.get('rate_limit_enabled').markAsDirty();
425+
const rateLimitConfig = childComponent.getRateLimitFormValue();
426+
component.updateBucketRateLimit();
427+
expect(rateLimitSpy).toHaveBeenCalledWith('tenant/bucket1', rateLimitConfig);
428+
});
429+
});
341430
});

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -412,17 +412,42 @@ export class RgwBucketFormComponent extends CdForm implements OnInit, AfterViewC
412412
}
413413

414414
updateBucketRateLimit() {
415+
/**
416+
* Whenever we change the owner of bucket from non-tenanted to tenanted
417+
* and vice-versa with the rate-limit changes there was issue in sending
418+
* bucket name, hence the below logic caters to it.
419+
*
420+
* Scenario 1: Changing the bucket owner from tenanted to non-tenanted
421+
* Scenario 2: Changing the bucket owner from non-tenanted to tenanted
422+
* Scenario 3: Keeping the owner(tenanted) same and changing only rate limit
423+
*/
424+
const owner = this.bucketForm.getValue('owner');
425+
const bidInput = this.bucketForm.getValue('bid');
426+
427+
let bid: string;
428+
429+
const hasOwnerWithDollar = owner.includes('$');
430+
const bidHasSlash = bidInput.includes('/');
431+
432+
if (bidHasSlash && hasOwnerWithDollar) {
433+
bid = bidInput;
434+
} else if (hasOwnerWithDollar) {
435+
const ownerPrefix = owner.split('$')[0];
436+
bid = `${ownerPrefix}/${bidInput}`;
437+
} else if (bidHasSlash) {
438+
bid = bidInput.split('/')[1];
439+
} else {
440+
bid = bidInput;
441+
}
415442
// Check if bucket ratelimit has been modified.
416443
const rateLimitConfig: RgwRateLimitConfig = this.rateLimitComponent.getRateLimitFormValue();
417444
if (!!rateLimitConfig) {
418-
this.rgwBucketService
419-
.updateBucketRateLimit(this.bucketForm.getValue('bid'), rateLimitConfig)
420-
.subscribe(
421-
() => {},
422-
(error: any) => {
423-
this.notificationService.show(NotificationType.error, error);
424-
}
425-
);
445+
this.rgwBucketService.updateBucketRateLimit(bid, rateLimitConfig).subscribe(
446+
() => {},
447+
(error: any) => {
448+
this.notificationService.show(NotificationType.error, error);
449+
}
450+
);
426451
}
427452
}
428453

0 commit comments

Comments
 (0)