Skip to content

Commit fe98f3f

Browse files
authored
Merge pull request ceph#55866 from afreen23/fix-rgw-locking
mgr/dashboard: Locking improvements in bucket create form Reviewed-by: Pedro Gonzalez Gomez <[email protected]> Reviewed-by: Ankush Behl <[email protected]> Reviewed-by: Nizamudeen A <[email protected]>
2 parents fce2ded + 014d446 commit fe98f3f

File tree

8 files changed

+115
-29
lines changed

8 files changed

+115
-29
lines changed

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

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -213,30 +213,34 @@
213213
</div>
214214
</fieldset>
215215

216-
<!-- Locking -->
217-
<fieldset>
216+
<!-- Object Locking -->
217+
<fieldset *ngIf="!editing || (editing && bucketForm.getValue('lock_enabled'))">
218218
<legend class="cd-header"
219-
i18n>Locking</legend>
220-
221-
<!-- Locking enabled -->
219+
i18n>
220+
Object Locking
221+
<cd-help-text class="bc-legend-help">
222+
Store objects using a write-once-read-many (WORM) model to help you prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely.
223+
Object Locking works only in versioned buckets.
224+
</cd-help-text>
225+
</legend>
226+
<!-- Object Locking enable -->
222227
<div class="form-group row">
223-
<div class="cd-col-form-offset">
224-
<div class="custom-control custom-checkbox">
225-
<input class="custom-control-input"
226-
id="lock_enabled"
227-
formControlName="lock_enabled"
228-
type="checkbox">
229-
<label class="custom-control-label"
230-
for="lock_enabled"
231-
i18n>Enabled</label>
232-
<cd-helper>
233-
<span i18n>Enables locking for the objects in the bucket. Locking can only be enabled while creating a bucket.</span>
234-
</cd-helper>
235-
</div>
228+
<label class="cd-col-form-label pt-0"
229+
for="lock_enabled"
230+
i18n>
231+
Enable
232+
</label>
233+
<div class="cd-col-form-input">
234+
<input class="form-check-input"
235+
id="lock_enabled"
236+
formControlName="lock_enabled"
237+
type="checkbox"/>
238+
<cd-help-text>
239+
<span i18n>Enables locking for the objects in the bucket. Locking can only be enabled while creating a bucket.</span>
240+
</cd-help-text>
236241
</div>
237242
</div>
238-
239-
<!-- Locking mode -->
243+
<!-- Object Locking mode -->
240244
<div *ngIf="bucketForm.getValue('lock_enabled')"
241245
class="form-group row">
242246
<label class="cd-col-form-label"
@@ -248,27 +252,42 @@
248252
name="lock_mode"
249253
id="lock_mode">
250254
<option i18n
251-
value="COMPLIANCE">Compliance</option>
255+
value="COMPLIANCE" >
256+
Compliance
257+
</option>
252258
<option i18n
253-
value="GOVERNANCE">Governance</option>
259+
value="GOVERNANCE">
260+
Governance
261+
</option>
254262
</select>
263+
<cd-help-text>
264+
<span *ngIf="bucketForm.getValue('lock_mode') === 'COMPLIANCE'"
265+
i18n>
266+
In COMPLIANCE an object version cannot be overwritten or deleted for the duration of the period.
267+
</span>
268+
<span *ngIf="bucketForm.getValue('lock_mode') === 'GOVERNANCE'"
269+
i18n>
270+
In GOVERNANCE mode, users cannot overwrite or delete an object version or alter its lock settings unless they have special permissions.
271+
</span>
272+
</cd-help-text>
255273
</div>
256274
</div>
257-
258275
<!-- Retention period (days) -->
259276
<div *ngIf="bucketForm.getValue('lock_enabled')"
260277
class="form-group row">
261278
<label class="cd-col-form-label"
262279
for="lock_retention_period_days">
263280
<ng-container i18n>Days</ng-container>
264-
<cd-helper i18n>The number of days that you want to specify for the default retention period that will be applied to new objects placed in this bucket.</cd-helper>
265281
</label>
266282
<div class="cd-col-form-input">
267283
<input class="form-control"
268284
type="number"
269285
id="lock_retention_period_days"
270286
formControlName="lock_retention_period_days"
271-
min="0">
287+
min="1">
288+
<cd-help-text>
289+
<span i18n>The number of days that you want to specify for the default retention period that will be applied to new objects placed in this bucket.</span>
290+
</cd-help-text>
272291
<span class="invalid-feedback"
273292
*ngIf="bucketForm.showError('lock_retention_period_days', frm, 'pattern')"
274293
i18n>The entered value must be a positive integer.</span>
@@ -277,6 +296,24 @@
277296
i18n>Retention Days must be a positive integer.</span>
278297
</div>
279298
</div>
299+
<!-- Alerts -->
300+
<div class="form-group row">
301+
<div class="cd-col-form-label"></div>
302+
<div class="cd-col-form-input">
303+
<cd-alert-panel
304+
type="info"
305+
*ngIf="bucketForm.getValue('lock_enabled')"
306+
class="me-1"
307+
i18n-title>
308+
Bucket Versioning can't be disabled when Object Locking is enabled.
309+
</cd-alert-panel>
310+
<cd-alert-panel
311+
type="warning"
312+
*ngIf="bucketForm.getValue('lock_enabled')">
313+
Enabling Object Locking will allow the configuration of GOVERNANCE or COMPLIANCE modes, which will help ensure that an object version cannot be overwritten or deleted for the specified period.
314+
</cd-alert-panel>
315+
</div>
316+
</div>
280317
</fieldset>
281318

282319
<fieldset>

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,20 @@ describe('RgwBucketFormComponent', () => {
272272
expect(control.disabled).toBeTruthy();
273273
});
274274

275-
it('should have the "lockDays" error', () => {
275+
it('should not have the "lockDays" error for 10 days', () => {
276276
formHelper.setValue('lock_enabled', true);
277277
const control = component.bucketForm.get('lock_retention_period_days');
278278
control.updateValueAndValidity();
279+
expect(control.value).toBe(10);
280+
expect(control.invalid).toBeFalsy();
281+
formHelper.expectValid(control);
282+
});
283+
284+
it('should have the "lockDays" error for 0 days', () => {
285+
formHelper.setValue('lock_enabled', true);
286+
formHelper.setValue('lock_retention_period_days', 0);
287+
const control = component.bucketForm.get('lock_retention_period_days');
288+
control.updateValueAndValidity();
279289
expect(control.value).toBe(0);
280290
expect(control.invalid).toBeTruthy();
281291
formHelper.expectError(control, 'lockDays');

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export class RgwBucketFormComponent extends CdForm implements OnInit, AfterViewC
150150
]
151151
],
152152
lock_mode: ['COMPLIANCE'],
153-
lock_retention_period_days: [0, [CdValidators.number(false), lockDaysValidator]],
153+
lock_retention_period_days: [10, [CdValidators.number(false), lockDaysValidator]],
154154
bucket_policy: ['{}', CdValidators.json()],
155155
grantee: [Grantee.Owner, [Validators.required]],
156156
aclPermission: [[aclPermission.FullControl], [Validators.required]]

src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import { CardRowComponent } from './card-row/card-row.component';
5454
import { CodeBlockComponent } from './code-block/code-block.component';
5555
import { VerticalNavigationComponent } from './vertical-navigation/vertical-navigation.component';
5656
import { CardGroupComponent } from './card-group/card-group.component';
57+
import { HelpTextComponent } from './help-text/help-text.component';
5758

5859
@NgModule({
5960
imports: [
@@ -111,7 +112,8 @@ import { CardGroupComponent } from './card-group/card-group.component';
111112
CardRowComponent,
112113
CodeBlockComponent,
113114
VerticalNavigationComponent,
114-
CardGroupComponent
115+
CardGroupComponent,
116+
HelpTextComponent
115117
],
116118
providers: [],
117119
exports: [
@@ -146,7 +148,8 @@ import { CardGroupComponent } from './card-group/card-group.component';
146148
CardRowComponent,
147149
CodeBlockComponent,
148150
VerticalNavigationComponent,
149-
CardGroupComponent
151+
CardGroupComponent,
152+
HelpTextComponent
150153
]
151154
})
152155
export class ComponentsModule {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="form-text text-muted">
2+
<ng-content></ng-content>
3+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
::ng-deep legend .text-muted {
2+
font-size: small;
3+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { HelpTextComponent } from './help-text.component';
4+
5+
describe('HelpTextComponent', () => {
6+
let component: HelpTextComponent;
7+
let fixture: ComponentFixture<HelpTextComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [HelpTextComponent]
12+
}).compileComponents();
13+
14+
fixture = TestBed.createComponent(HelpTextComponent);
15+
component = fixture.componentInstance;
16+
fixture.detectChanges();
17+
});
18+
19+
it('should create', () => {
20+
expect(component).toBeTruthy();
21+
});
22+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'cd-help-text',
5+
templateUrl: './help-text.component.html',
6+
styleUrls: ['./help-text.component.scss']
7+
})
8+
export class HelpTextComponent {}

0 commit comments

Comments
 (0)