]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard:Mark placement targets as non-required in bucket form 55953/head
authorAfreen <afreen23.git@gmail.com>
Fri, 1 Mar 2024 07:26:25 +0000 (12:56 +0530)
committerAfreen <afreen23.git@gmail.com>
Thu, 21 Mar 2024 10:35:53 +0000 (16:05 +0530)
Fixes https://tracker.ceph.com/issues/64708

- adds info text explaining about placement targets
- adds fieldset to security, policy and tags for a11y
- removes placement target as required field
- when no placement target provided, request omits placement_target
  field
- hides placement atrgets ection for edit form since its not possible to
  edit after creation
- updates rgw-bucket.service.spec.ts unit test
- minor cleanups related to unncesseary css present, and changes in help
  text for object locking
- updated e2e tests for buckets to incorporate changes

Signed-off-by: Afreen <afreen23.git@gmail.com>
src/pybind/mgr/dashboard/frontend/cypress/e2e/rgw/buckets.po.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/rgw-bucket.service.ts

index d121608490f917455c6460450ab090b094a20d7e..53756f0a2569a8a0d82f6deff346d52be67c4f70 100644 (file)
@@ -41,7 +41,6 @@ export class BucketsPageHelper extends PageHelper {
 
     // Select bucket placement target:
     this.selectPlacementTarget(placementTarget);
-    cy.get('#placement-target').should('have.class', 'ng-valid');
 
     if (isLocking) {
       cy.get('#lock_enabled').click({ force: true });
@@ -70,7 +69,8 @@ export class BucketsPageHelper extends PageHelper {
   edit(name: string, new_owner: string, isLocking = false) {
     this.navigateEdit(name);
 
-    cy.get('input[name=placement-target]').should('have.value', 'default-placement');
+    // Placement target is not allowed to be edited and should be hidden
+    cy.get('input[name=placement-target]').should('not.exist');
     this.selectOwner(new_owner);
 
     // If object locking is enabled versioning shouldn't be visible
@@ -171,15 +171,6 @@ export class BucketsPageHelper extends PageHelper {
     // Check that error message was printed under owner drop down field
     cy.get('#owner + .invalid-feedback').should('have.text', 'This field is required.');
 
-    // Check invalid placement target input
-    this.selectOwner(BucketsPageHelper.USERS[1]);
-    // The drop down error message will not appear unless a valid option is previously selected.
-    this.selectPlacementTarget('default-placement');
-    this.selectPlacementTarget('-- Select a placement target --');
-    cy.get('@nameInputField').click(); // Trigger validation
-    cy.get('#placement-target').should('have.class', 'ng-invalid');
-    cy.get('#placement-target + .invalid-feedback').should('have.text', 'This field is required.');
-
     // Clicks the Create Bucket button but the page doesn't move.
     // Done by testing for the breadcrumb
     cy.contains('button', 'Create Bucket').click(); // Clicks Create Bucket button
index 41b7f11629779a9ffd9d47f987f209b70bc3292c..108b1ba6ce56911e1555b512440931efda6ca361 100644 (file)
         </div>
 
         <!-- Placement target -->
-        <div class="form-group row">
+        <div class="form-group row"
+             *ngIf="!editing">
           <label class="cd-col-form-label"
-                 [ngClass]="{required: !editing}"
                  for="placement-target"
                  i18n>Placement target</label>
           <div class="cd-col-form-input">
-            <ng-template #placementTargetSelect>
-              <select id="placement-target"
-                      name="placement-target"
-                      formControlName="placement-target"
-                      class="form-select">
-                <option i18n
-                        *ngIf="placementTargets === null"
-                        [ngValue]="null">Loading...</option>
-                <option i18n
-                        *ngIf="placementTargets !== null"
-                        [ngValue]="null">-- Select a placement target --</option>
-                <option *ngFor="let placementTarget of placementTargets"
-                        [value]="placementTarget.name">{{ placementTarget.description }}</option>
-              </select>
-              <span class="invalid-feedback"
-                    *ngIf="bucketForm.showError('placement-target', frm, 'required')"
-                    i18n>This field is required.</span>
-            </ng-template>
-            <ng-container *ngIf="editing; else placementTargetSelect">
-              <input id="placement-target"
-                     name="placement-target"
-                     formControlName="placement-target"
-                     class="form-control"
-                     type="text"
-                     readonly>
-            </ng-container>
+            <select id="placement-target"
+                    name="placement-target"
+                    formControlName="placement-target"
+                    class="form-select">
+              <option i18n
+                      *ngIf="placementTargets === null"
+                      [ngValue]="null">Loading...</option>
+              <option i18n
+                      *ngIf="placementTargets !== null"
+                      [ngValue]="null">-- Select a placement target --</option>
+              <option *ngFor="let placementTarget of placementTargets"
+                      [value]="placementTarget.name">{{ placementTarget.description }}</option>
+            </select>
+            <cd-help-text>
+              <span i18n>
+                When creating a bucket, a placement target can be provided as part of the LocationConstraint to override the default placement targets from the user and zonegroup.
+              </span>
+            </cd-help-text>
           </div>
         </div>
 
           <legend class="cd-header"
                   i18n>
             Object Locking
-            <cd-help-text class="bc-legend-help">
-                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.
+            <cd-help-text>
+                Store objects using a write-once-read-many (WORM) model to prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely.
                 Object Locking works only in versioned buckets.
             </cd-help-text>
           </legend>
           </div>
         </fieldset>
 
+        <!-- Security -->
         <fieldset>
           <legend class="cd-header"
                   i18n>Security</legend>
         </fieldset>
 
         <!-- Tags -->
-        <legend class="cd-header"
-                i18n>Tags
-          <cd-helper>Tagging gives you a way to categorize storage</cd-helper>
-        </legend>
-        <span *ngFor="let tag of tags; let i=index;">
-          <ng-container *ngTemplateOutlet="tagTpl; context:{index: i, tag: tag}"></ng-container>
-        </span>
+        <fieldset>
+          <legend class="cd-header"
+                  i18n>Tags
+            <cd-helper>Tagging gives you a way to categorize storage</cd-helper>
+          </legend>
+          <span *ngFor="let tag of tags; let i=index;">
+            <ng-container *ngTemplateOutlet="tagTpl; context:{index: i, tag: tag}"></ng-container>
+          </span>
 
-        <div class="row">
-          <div class="col-12">
-            <strong *ngIf="tags.length > 19"
-                    class="text-warning"
-                    i18n>Maximum of 20 tags reached</strong>
-            <button type="button"
-                    id="add-tag"
-                    class="btn btn-light float-end my-3"
-                    [disabled]="tags.length > 19"
-                    (click)="showTagModal()">
-              <i [ngClass]="[icons.add]"></i>
-              <ng-container i18n>Add tag</ng-container>
-            </button>
+          <div class="row">
+            <div class="col-12">
+              <strong *ngIf="tags.length > 19"
+                      class="text-warning"
+                      i18n>Maximum of 20 tags reached</strong>
+              <button type="button"
+                      id="add-tag"
+                      class="btn btn-light float-end my-3"
+                      [disabled]="tags.length > 19"
+                      (click)="showTagModal()">
+                <i [ngClass]="[icons.add]"></i>
+                <ng-container i18n>Add tag</ng-container>
+              </button>
+            </div>
           </div>
-        </div>
+        </fieldset>
 
         <!-- Policies -->
-        <legend class="cd-header"
-                i18n>Policies
-        </legend>
-        <div class="row">
-          <div class="col-12">
-            <div class="form-group row">
+        <fieldset>
+          <legend class="cd-header"
+                  i18n>Policies
+          </legend>
+          <div class="row">
+            <div class="col-12">
+              <div class="form-group row">
 
-              <!-- Bucket policy -->
-              <label i18n
-                     class="cd-col-form-label"
-                     for="id">Bucket policy</label>
-              <div class="cd-col-form-input">
-                <textarea #bucketPolicyTextArea
-                          class="form-control resize-vertical"
-                          id="bucket_policy"
-                          formControlName="bucket_policy"
-                          (change)="bucketPolicyOnChange()">
-                </textarea>
-                <span class="invalid-feedback"
-                      *ngIf="bucketForm.showError('bucket_policy', frm, 'invalidJson')"
-                      i18n>Invalid json text</span>
-                <button type="button"
-                        id="clear-bucket-policy"
-                        class="btn btn-light my-3"
-                        (click)="clearBucketPolicy()"
-                        i18n>
-                  <i [ngClass]="[icons.destroy]"></i>
-                  Clear
-                </button>
-                <div class="btn-group float-end"
-                     role="group"
-                     aria-label="bucket-policy-helpers">
-                  <button type="button"
-                          id="example-generator-button"
-                          class="btn btn-light my-3"
-                          (click)="openUrl('https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html?icmpid=docs_amazons3_console')"
-                          i18n>
-                    <i [ngClass]="[icons.externalUrl]"></i>
-                    Policy examples
-                  </button>
+                <!-- Bucket policy -->
+                <label i18n
+                       class="cd-col-form-label"
+                       for="id">Bucket policy</label>
+                <div class="cd-col-form-input">
+                  <textarea #bucketPolicyTextArea
+                            class="form-control resize-vertical"
+                            id="bucket_policy"
+                            formControlName="bucket_policy"
+                            (change)="bucketPolicyOnChange()">
+                  </textarea>
+                  <span class="invalid-feedback"
+                        *ngIf="bucketForm.showError('bucket_policy', frm, 'invalidJson')"
+                        i18n>Invalid json text</span>
                   <button type="button"
-                          id="example-generator-button"
+                          id="clear-bucket-policy"
                           class="btn btn-light my-3"
-                          (click)="openUrl('https://awspolicygen.s3.amazonaws.com/policygen.html')"
+                          (click)="clearBucketPolicy()"
                           i18n>
-                    <i [ngClass]="[icons.externalUrl]"></i>
-                    Policy generator
+                    <i [ngClass]="[icons.destroy]"></i>
+                    Clear
                   </button>
+                  <div class="btn-group float-end"
+                       role="group"
+                       aria-label="bucket-policy-helpers">
+                    <button type="button"
+                            id="example-generator-button"
+                            class="btn btn-light my-3"
+                            (click)="openUrl('https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html?icmpid=docs_amazons3_console')"
+                            i18n>
+                      <i [ngClass]="[icons.externalUrl]"></i>
+                      Policy examples
+                    </button>
+                    <button type="button"
+                            id="example-generator-button"
+                            class="btn btn-light my-3"
+                            (click)="openUrl('https://awspolicygen.s3.amazonaws.com/policygen.html')"
+                            i18n>
+                      <i [ngClass]="[icons.externalUrl]"></i>
+                      Policy generator
+                    </button>
+                  </div>
                 </div>
               </div>
-            </div>
 
-            <div class="form-group row">
+              <div class="form-group row">
 
-              <!-- ACL -->
-              <label class="cd-col-form-label"
-                     i18n>ACL
-                <cd-helper>Any changes to the ACL will overwrite previous one.
-                  You can choose any of the available options to modify the spcified user group.</cd-helper>
-              </label>
-              <div class="cd-col-form-input">
-                <div class="input-group">
-                  <span class="input-group-text"
-                        for="grantee"
-                        i18n>Grantee
-                    <cd-helper>Select a grantee (user group) to modify it's permisions</cd-helper>
-                  </span>
-                  <select id="grantee"
-                          name="grantee"
-                          class="form-input form-select"
-                          formControlName="grantee"
-                          (change)="onSelectionFilter()">
-                    <option *ngFor="let item of grantees"
-                            [value]="item"
-                            i18n>{{ item }}</option>
-                  </select>
-                  <span class="invalid-feedback"
-                        *ngIf="bucketForm.showError('grantee', frm, 'required')"
-                        i18n>This field is required.</span>
-                  <span class="input-group-text"
-                        for="aclPermission"
-                        i18n>Permissions
-                    <cd-helper>Select the permision to give to the selected grantee.
-                        Regardless, the owner of the bucket will always have
-                          FULL CONTROL access</cd-helper>
+                <!-- ACL -->
+                <label class="cd-col-form-label"
+                       i18n>ACL
+                  <cd-helper>Any changes to the ACL will overwrite previous one.
+                    You can choose any of the available options to modify the spcified user group.</cd-helper>
+                </label>
+                <div class="cd-col-form-input">
+                  <div class="input-group">
+                    <span class="input-group-text"
+                          for="grantee"
+                          i18n>Grantee
+                      <cd-helper>Select a grantee (user group) to modify it's permisions</cd-helper>
                     </span>
-                  <select id="aclPermission"
-                          name="aclPermission"
-                          class="form-input form-select"
-                          formControlName="aclPermission">
-                    <option *ngFor="let permission of aclPermissions"
-                            [value]="permission"
-                            i18n>{{ permission }}</option>
-                  </select>
-                  <span class="invalid-feedback"
-                        *ngIf="bucketForm.showError('aclPermission', frm, 'required')"
-                        i18n>This field is required.</span>
+                    <select id="grantee"
+                            name="grantee"
+                            class="form-input form-select"
+                            formControlName="grantee"
+                            (change)="onSelectionFilter()">
+                      <option *ngFor="let item of grantees"
+                              [value]="item"
+                              i18n>{{ item }}</option>
+                    </select>
+                    <span class="invalid-feedback"
+                          *ngIf="bucketForm.showError('grantee', frm, 'required')"
+                          i18n>This field is required.</span>
+                    <span class="input-group-text"
+                          for="aclPermission"
+                          i18n>Permissions
+                      <cd-helper>Select the permision to give to the selected grantee.
+                          Regardless, the owner of the bucket will always have
+                            FULL CONTROL access</cd-helper>
+                      </span>
+                    <select id="aclPermission"
+                            name="aclPermission"
+                            class="form-input form-select"
+                            formControlName="aclPermission">
+                      <option *ngFor="let permission of aclPermissions"
+                              [value]="permission"
+                              i18n>{{ permission }}</option>
+                    </select>
+                    <span class="invalid-feedback"
+                          *ngIf="bucketForm.showError('aclPermission', frm, 'required')"
+                          i18n>This field is required.</span>
+                  </div>
                 </div>
               </div>
             </div>
           </div>
-        </div>
-
+        </fieldset>
       </div>
+
       <div class="card-footer">
         <cd-form-button-panel (submitActionEvent)="submit()"
                               [form]="bucketForm"
index 6857874411ae2e0363781dc84f0f9e5f038bf383..061dee0225c83768fffc7840328bfde1c5df86c9 100644 (file)
@@ -125,7 +125,7 @@ export class RgwBucketFormComponent extends CdForm implements OnInit, AfterViewC
       ],
       owner: [null, [Validators.required]],
       kms_provider: ['vault'],
-      'placement-target': [null, this.editing ? [] : [Validators.required]],
+      'placement-target': [null],
       versioning: [null],
       'mfa-delete': [null],
       'mfa-token-serial': [''],
index f40fd17cfc087041e7dc0376a4d1fe5c09ff6785..eaed2c4abac2fd96a4018dba98b02f5c563be85c 100644 (file)
@@ -53,7 +53,7 @@ describe('RgwBucketService', () => {
         'foo',
         'bar',
         'default',
-        'default-placement',
+        null,
         false,
         'COMPLIANCE',
         '5',
@@ -66,7 +66,7 @@ describe('RgwBucketService', () => {
       )
       .subscribe();
     const req = httpTesting.expectOne(
-      `api/rgw/bucket?bucket=foo&uid=bar&zonegroup=default&placement_target=default-placement&lock_enabled=false&lock_mode=COMPLIANCE&lock_retention_period_days=5&encryption_state=true&encryption_type=aws%253Akms&key_id=qwerty1&tags=null&bucket_policy=null&canned_acl=private&${RgwHelper.DAEMON_QUERY_PARAM}`
+      `api/rgw/bucket?bucket=foo&uid=bar&zonegroup=default&lock_enabled=false&lock_mode=COMPLIANCE&lock_retention_period_days=5&encryption_state=true&encryption_type=aws%253Akms&key_id=qwerty1&tags=null&bucket_policy=null&canned_acl=private&${RgwHelper.DAEMON_QUERY_PARAM}`
     );
     expect(req.request.method).toBe('POST');
   });
index e8e123bf9f2562256589d2ce70194d914b664f1a..ddeeadf5e49baee39fb3ca085e76047af4452261 100644 (file)
@@ -65,25 +65,28 @@ export class RgwBucketService extends ApiClient {
     cannedAcl: string
   ) {
     return this.rgwDaemonService.request((params: HttpParams) => {
+      const paramsObject = {
+        bucket,
+        uid,
+        zonegroup,
+        lock_enabled: String(lockEnabled),
+        lock_mode,
+        lock_retention_period_days,
+        encryption_state: String(encryption_state),
+        encryption_type,
+        key_id,
+        tags: tags,
+        bucket_policy: bucketPolicy,
+        canned_acl: cannedAcl,
+        daemon_name: params.get('daemon_name')
+      };
+
+      if (placementTarget) {
+        paramsObject['placement_target'] = placementTarget;
+      }
+
       return this.http.post(this.url, null, {
-        params: new HttpParams({
-          fromObject: {
-            bucket,
-            uid,
-            zonegroup,
-            placement_target: placementTarget,
-            lock_enabled: String(lockEnabled),
-            lock_mode,
-            lock_retention_period_days,
-            encryption_state: String(encryption_state),
-            encryption_type,
-            key_id,
-            tags: tags,
-            bucket_policy: bucketPolicy,
-            canned_acl: cannedAcl,
-            daemon_name: params.get('daemon_name')
-          }
-        })
+        params: new HttpParams({ fromObject: paramsObject })
       });
     });
   }