Skip to content

Commit a784b71

Browse files
Naman MunetNaman Munet
authored andcommitted
mgr/dashboard: RGW sync policy crud operations
sync group crud ops added Fixes: https://tracker.ceph.com/issues/66798 Signed-off-by: Naman Munet <[email protected]>
1 parent 94f9a2b commit a784b71

16 files changed

+666
-42
lines changed

src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/multisite.e2e.spec.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,23 @@ describe('Multisite page', () => {
2424
it('should show empty table in Sync Policy page', () => {
2525
multisite.getTab('Sync Policy').click();
2626
multisite.getDataTables().should('exist');
27-
multisite.getTableCount('total').should('eq', 0);
27+
});
28+
});
29+
30+
describe('create, edit & delete sync group policy', () => {
31+
it('should create policy', () => {
32+
multisite.navigateTo('create');
33+
multisite.create('test', 'Enabled');
34+
multisite.getFirstTableCell('test').should('exist');
35+
});
36+
37+
it('should edit policy status', () => {
38+
multisite.edit('test', 'Forbidden');
39+
});
40+
41+
it('should delete policy', () => {
42+
multisite.getTab('Sync Policy').click();
43+
multisite.delete('test');
2844
});
2945
});
3046
});
Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,42 @@
11
import { PageHelper } from '../page-helper.po';
22

3+
const WAIT_TIMER = 1000;
34
const pages = {
4-
index: { url: '#/rgw/multisite', id: 'cd-rgw-multisite-details' }
5+
index: { url: '#/rgw/multisite', id: 'cd-rgw-multisite-details' },
6+
create: { url: '#/rgw/multisite/sync-policy/create', id: 'cd-rgw-multisite-sync-policy-form' },
7+
edit: { url: '#/rgw/multisite/sync-policy/edit', id: 'cd-rgw-multisite-sync-policy-form' }
58
};
69
export class MultisitePageHelper extends PageHelper {
710
pages = pages;
11+
12+
columnIndex = {
13+
status: 3
14+
};
15+
16+
@PageHelper.restrictTo(pages.create.url)
17+
create(group_id: string, status: string) {
18+
// Enter in group_id
19+
cy.get('#group_id').type(group_id);
20+
// Show Status
21+
this.selectOption('status', status);
22+
cy.get('#status').should('have.class', 'ng-valid');
23+
24+
// Click the create button and wait for policy to be made
25+
cy.contains('button', 'Create Sync Policy Group').wait(WAIT_TIMER).click();
26+
this.getFirstTableCell(group_id).should('exist');
27+
}
28+
29+
@PageHelper.restrictTo(pages.index.url)
30+
edit(group_id: string, status: string) {
31+
cy.visit(`${pages.edit.url}/${group_id}`);
32+
33+
// Change the status field
34+
this.selectOption('status', status);
35+
cy.contains('button', 'Edit Sync Policy Group').click();
36+
37+
this.searchTable(group_id);
38+
cy.get(`datatable-body-cell:nth-child(${this.columnIndex.status})`)
39+
.find('.badge-warning')
40+
.should('contain', status);
41+
}
842
}

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/models/rgw-multisite.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,9 @@ export class SystemKey {
5050
access_key: string;
5151
secret_key: string;
5252
}
53+
54+
export enum RgwMultisiteSyncPolicyStatus {
55+
ENABLED = 'enabled',
56+
FORBIDDEN = 'forbidden',
57+
ALLOWED = 'allowed'
58+
}

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<nav ngbNav
22
#nav="ngbNav"
33
class="nav-tabs"
4+
[(activeId)]="activeId"
45
(navChange)="onNavChange($event)">
56
<ng-container ngbNavItem="configuration">
67
<a ngbNavLink

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit {
9999
rgwModuleStatus: boolean;
100100
restartGatewayMessage = false;
101101
rgwModuleData: string | any[] = [];
102+
activeId: string;
102103

103104
constructor(
104105
private modalService: ModalService,
@@ -115,6 +116,10 @@ export class RgwMultisiteDetailsComponent implements OnDestroy, OnInit {
115116
private notificationService: NotificationService
116117
) {
117118
this.permission = this.authStorageService.getPermissions().rgw;
119+
const activeId = this.router.getCurrentNavigation()?.extras?.state?.activeId;
120+
if (activeId) {
121+
this.activeId = activeId;
122+
}
118123
}
119124

120125
openModal(entity: any, edit = false) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<div class="cd-col-form">
2+
<form
3+
name="bucketForm"
4+
#frm="ngForm"
5+
[formGroup]="syncPolicyForm"
6+
*cdFormLoading="loading"
7+
novalidate>
8+
<div class="card">
9+
<div
10+
i18n="form title"
11+
class="card-header">
12+
{{ action | titlecase }} {{ resource | upperFirst }}
13+
</div>
14+
15+
<div class="card-body">
16+
<!-- Group Id -->
17+
<div class="form-group row">
18+
<label
19+
class="cd-col-form-label required"
20+
for="group_id"
21+
i18n>Group Id</label>
22+
<div class="cd-col-form-input">
23+
<input
24+
id="group_id"
25+
name="group_id"
26+
class="form-control"
27+
type="text"
28+
i18n-placeholder
29+
placeholder="Group Id..."
30+
formControlName="group_id"
31+
[readonly]="editing"/>
32+
<span
33+
class="invalid-feedback"
34+
*ngIf="syncPolicyForm.showError('group_id', frm, 'required')"
35+
i18n>This field is required.</span>
36+
</div>
37+
</div>
38+
39+
<!-- Status -->
40+
<div class="form-group row">
41+
<label
42+
class="cd-col-form-label required"
43+
for="status"
44+
i18n>Status</label>
45+
<div class="cd-col-form-input">
46+
<select
47+
id="status"
48+
name="status"
49+
class="form-select"
50+
formControlName="status">
51+
<option
52+
i18n
53+
value="{{syncPolicyStatus.ENABLED}}">{{syncPolicyStatus.ENABLED | upperFirst }}</option>
54+
<option
55+
i18n
56+
value="{{syncPolicyStatus.ALLOWED}}">{{syncPolicyStatus.ALLOWED | upperFirst }}</option>
57+
<option
58+
i18n
59+
value="{{syncPolicyStatus.FORBIDDEN}}">{{syncPolicyStatus.FORBIDDEN | upperFirst }}</option>
60+
</select>
61+
<span
62+
class="invalid-feedback"
63+
*ngIf="syncPolicyForm.showError('status', frm, 'required')"
64+
i18n>This field is required.</span>
65+
</div>
66+
</div>
67+
68+
<!-- Bucket Name -->
69+
<div class="form-group row">
70+
<label
71+
class="cd-col-form-label"
72+
for="bucket_name"
73+
i18n>Bucket Name</label>
74+
<div class="cd-col-form-input">
75+
<input
76+
id="bucket_name"
77+
name="bucket_name"
78+
class="form-control"
79+
type="text"
80+
i18n-placeholder
81+
placeholder="Bucket Name..."
82+
formControlName="bucket_name"
83+
[readonly]="editing"
84+
[ngbTypeahead]="bucketDataSource"/>
85+
<span
86+
class="invalid-feedback"
87+
*ngIf="syncPolicyForm.showError('bucket_name', frm, 'bucketNameNotAllowed')"
88+
i18n>The bucket with chosen name does not exist.</span>
89+
</div>
90+
</div>
91+
</div>
92+
93+
<div class="card-footer">
94+
<cd-form-button-panel
95+
(submitActionEvent)="submit()"
96+
[form]="syncPolicyForm"
97+
[submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"
98+
wrappingClass="text-right"></cd-form-button-panel>
99+
</div>
100+
</div>
101+
</form>
102+
</div>

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-policy-form/rgw-multisite-sync-policy-form.component.scss

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { RgwMultisiteSyncPolicyFormComponent } from './rgw-multisite-sync-policy-form.component';
3+
import { HttpClientTestingModule } from '@angular/common/http/testing';
4+
import { ToastrModule } from 'ngx-toastr';
5+
import { ReactiveFormsModule } from '@angular/forms';
6+
import { PipesModule } from '~/app/shared/pipes/pipes.module';
7+
import { ComponentsModule } from '~/app/shared/components/components.module';
8+
import { RouterTestingModule } from '@angular/router/testing';
9+
10+
describe('RgwMultisiteSyncPolicyFormComponent', () => {
11+
let component: RgwMultisiteSyncPolicyFormComponent;
12+
let fixture: ComponentFixture<RgwMultisiteSyncPolicyFormComponent>;
13+
14+
beforeEach(async () => {
15+
await TestBed.configureTestingModule({
16+
declarations: [RgwMultisiteSyncPolicyFormComponent],
17+
imports: [
18+
HttpClientTestingModule,
19+
ReactiveFormsModule,
20+
ToastrModule.forRoot(),
21+
PipesModule,
22+
ComponentsModule,
23+
RouterTestingModule
24+
],
25+
providers: []
26+
}).compileComponents();
27+
28+
fixture = TestBed.createComponent(RgwMultisiteSyncPolicyFormComponent);
29+
component = fixture.componentInstance;
30+
fixture.detectChanges();
31+
});
32+
33+
it('should create', () => {
34+
expect(component).toBeTruthy();
35+
});
36+
});

0 commit comments

Comments
 (0)