]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: get object bucket policies for a bucket 54048/head
authorNizamudeen A <nia@redhat.com>
Tue, 17 Oct 2023 04:34:33 +0000 (10:04 +0530)
committerNizamudeen A <nia@redhat.com>
Thu, 2 Nov 2023 07:13:23 +0000 (12:43 +0530)
Getting the bucket details will also fetch the bucket policy if its set.

Fixes: https://tracker.ceph.com/issues/63221
Signed-off-by: Nizamudeen A <nia@redhat.com>
src/pybind/mgr/dashboard/controllers/rgw.py
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts
src/pybind/mgr/dashboard/services/rgw_client.py

index 65c809ebec02d17292547bfeb533836a3cbc3e05..f7b9ed8ecf37f8ce67ce6259c2ff05ccfb83348c 100644 (file)
@@ -276,6 +276,10 @@ class RgwBucket(RgwRESTController):
                                              retention_period_days,
                                              retention_period_years)
 
+    def _get_policy(self, bucket: str):
+        rgw_client = RgwClient.admin_instance()
+        return rgw_client.get_bucket_policy(bucket)
+
     @staticmethod
     def strip_tenant_from_bucket_name(bucket_name):
         # type (str) -> str
@@ -328,6 +332,7 @@ class RgwBucket(RgwRESTController):
         result['encryption'] = encryption['Status']
         result['versioning'] = versioning['Status']
         result['mfa_delete'] = versioning['MfaDelete']
+        result['policy'] = self._get_policy(bucket_name)
 
         # Append the locking configuration.
         locking = self._get_locking(result['owner'], daemon_name, bucket_name)
index c947e4490625b9e94b64df826170f83f736903af..f2447feab2642bf512131e58eb4d38e0e176eb25 100644 (file)
 <ng-container *ngIf="selection">
-  <table class="table table-striped table-bordered">
-    <tbody>
-      <tr>
-        <td i18n
-            class="bold w-25">Versioning</td>
-        <td class="w-75">{{ selection.versioning }}</td>
-      </tr>
-      <tr>
-        <td i18n
-            class="bold">Encryption</td>
-        <td>{{ selection.encryption }}</td>
-      </tr>
-      <tr>
-        <td i18n
-            class="bold">MFA Delete</td>
-        <td>{{ selection.mfa_delete }}</td>
-      </tr>
-      <tr>
-        <td i18n
-            class="bold">Index type</td>
-        <td>{{ selection.index_type }}</td>
-      </tr>
-      <tr>
-        <td i18n
-            class="bold">Placement rule</td>
-        <td>{{ selection.placement_rule }}</td>
-      </tr>
-      <tr>
-        <td i18n
-            class="bold">Last modification time</td>
-        <td>{{ selection.mtime | cdDate }}</td>
-      </tr>
-    </tbody>
-  </table>
+  <nav ngbNav
+       #nav="ngbNav"
+       class="nav-tabs"
+       cdStatefulTab="rgw-bucket-details">
+    <ng-container ngbNavItem="details">
+      <a ngbNavLink
+         i18n>Details</a>
+      <ng-template ngbNavContent>
 
-  <!-- Bucket quota -->
-  <div>
-    <legend i18n>Bucket quota</legend>
-    <table class="table table-striped table-bordered">
-      <tbody>
-        <tr>
-          <td i18n
-              class="bold w-25">Enabled</td>
-          <td class="w-75">{{ selection.bucket_quota.enabled | booleanText }}</td>
-        </tr>
-        <ng-container *ngIf="selection.bucket_quota.enabled">
-          <tr>
-            <td i18n
-                class="bold">Maximum size</td>
-            <td *ngIf="selection.bucket_quota.max_size <= -1"
-                i18n>Unlimited</td>
-            <td *ngIf="selection.bucket_quota.max_size > -1">
-              {{ selection.bucket_quota.max_size | dimless }}
-            </td>
-          </tr>
-          <tr>
-            <td i18n
-                class="bold">Maximum objects</td>
-            <td *ngIf="selection.bucket_quota.max_objects <= -1"
-                i18n>Unlimited</td>
-            <td *ngIf="selection.bucket_quota.max_objects > -1">
-              {{ selection.bucket_quota.max_objects }}
-            </td>
-          </tr>
-        </ng-container>
-      </tbody>
-    </table>
-  </div>
+        <table class="table table-striped table-bordered">
+          <tbody>
+            <tr>
+              <td i18n
+                  class="bold w-25">Versioning</td>
+              <td class="w-75">{{ selection.versioning }}</td>
+            </tr>
+            <tr>
+              <td i18n
+                  class="bold">Encryption</td>
+              <td>{{ selection.encryption }}</td>
+            </tr>
+            <tr>
+              <td i18n
+                  class="bold">MFA Delete</td>
+              <td>{{ selection.mfa_delete }}</td>
+            </tr>
+            <tr>
+              <td i18n
+                  class="bold">Index type</td>
+              <td>{{ selection.index_type }}</td>
+            </tr>
+            <tr>
+              <td i18n
+                  class="bold">Placement rule</td>
+              <td>{{ selection.placement_rule }}</td>
+            </tr>
+            <tr>
+              <td i18n
+                  class="bold">Last modification time</td>
+              <td>{{ selection.mtime | cdDate }}</td>
+            </tr>
+          </tbody>
+        </table>
 
-  <!-- Locking -->
-  <legend i18n>Locking</legend>
-  <table class="table table-striped table-bordered">
-    <tbody>
-      <tr>
-        <td i18n
-            class="bold w-25">Enabled</td>
-        <td class="w-75">{{ selection.lock_enabled | booleanText }}</td>
-      </tr>
-      <ng-container *ngIf="selection.lock_enabled">
-        <tr>
-          <td i18n
-              class="bold">Mode</td>
-          <td>{{ selection.lock_mode }}</td>
-        </tr>
-        <tr>
-          <td i18n
-              class="bold">Days</td>
-          <td>{{ selection.lock_retention_period_days }}</td>
-        </tr>
-      </ng-container>
-    </tbody>
-  </table>
+        <!-- Bucket quota -->
+        <div>
+          <legend i18n>Bucket quota</legend>
+          <table class="table table-striped table-bordered">
+            <tbody>
+              <tr>
+                <td i18n
+                    class="bold w-25">Enabled</td>
+                <td class="w-75">{{ selection.bucket_quota.enabled | booleanText }}</td>
+              </tr>
+              <ng-container *ngIf="selection.bucket_quota.enabled">
+                <tr>
+                  <td i18n
+                      class="bold">Maximum size</td>
+                  <td *ngIf="selection.bucket_quota.max_size <= -1"
+                      i18n>Unlimited</td>
+                  <td *ngIf="selection.bucket_quota.max_size > -1">
+                    {{ selection.bucket_quota.max_size | dimless }}
+                  </td>
+                </tr>
+                <tr>
+                  <td i18n
+                      class="bold">Maximum objects</td>
+                  <td *ngIf="selection.bucket_quota.max_objects <= -1"
+                      i18n>Unlimited</td>
+                  <td *ngIf="selection.bucket_quota.max_objects > -1">
+                    {{ selection.bucket_quota.max_objects }}
+                  </td>
+                </tr>
+              </ng-container>
+            </tbody>
+          </table>
+        </div>
+
+        <!-- Locking -->
+        <legend i18n>Locking</legend>
+        <table class="table table-striped table-bordered">
+          <tbody>
+            <tr>
+              <td i18n
+                  class="bold w-25">Enabled</td>
+              <td class="w-75">{{ selection.lock_enabled | booleanText }}</td>
+            </tr>
+            <ng-container *ngIf="selection.lock_enabled">
+              <tr>
+                <td i18n
+                    class="bold">Mode</td>
+                <td>{{ selection.lock_mode }}</td>
+              </tr>
+              <tr>
+                <td i18n
+                    class="bold">Days</td>
+                <td>{{ selection.lock_retention_period_days }}</td>
+              </tr>
+            </ng-container>
+          </tbody>
+        </table>
+      </ng-template>
+    </ng-container>
+
+    <ng-container ngbNavItem="permissions">
+      <a ngbNavLink
+         i18n>Permissions</a>
+      <ng-template ngbNavContent>
+
+        <table class="table table-striped table-bordered">
+          <tbody>
+            <tr>
+              <td i18n
+                  class="bold w-25">Policy</td>
+              <td><pre>{{ selection.policy | json}}</pre></td>
+            </tr>
+          </tbody>
+        </table>
+      </ng-template>
+    </ng-container>
+  </nav>
+
+  <div [ngbNavOutlet]="nav"></div>
 </ng-container>
index 59f62952a5075b8dcc46a09d06ef4bc5cde54784..be6aa09182ca62b224098a0612eff545c3b14dd1 100644 (file)
@@ -8,6 +8,7 @@ import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
 import { SharedModule } from '~/app/shared/shared.module';
 import { configureTestBed } from '~/testing/unit-test-helper';
 import { RgwBucketDetailsComponent } from './rgw-bucket-details.component';
+import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
 
 describe('RgwBucketDetailsComponent', () => {
   let component: RgwBucketDetailsComponent;
@@ -17,7 +18,7 @@ describe('RgwBucketDetailsComponent', () => {
 
   configureTestBed({
     declarations: [RgwBucketDetailsComponent],
-    imports: [SharedModule, HttpClientTestingModule]
+    imports: [SharedModule, HttpClientTestingModule, NgbNavModule]
   });
 
   beforeEach(() => {
index f9a351367daadbcbf5aaf5a091cad91a06546b8c..0ecbe0536dffec32bb717c769007f172eafb5ef0 100644 (file)
@@ -18,6 +18,7 @@ export class RgwBucketDetailsComponent implements OnChanges {
       this.rgwBucketService.get(this.selection.bid).subscribe((bucket: object) => {
         bucket['lock_retention_period_days'] = this.rgwBucketService.getLockDays(bucket);
         this.selection = bucket;
+        this.selection.policy = JSON.parse(this.selection.policy) || {};
       });
     }
   }
index 20c0397458b21e5b7f8f3cb6dee9523bfee7d9ff..2d3226bab3e0044bb1397981301785cfc37378bf 100644 (file)
@@ -852,6 +852,27 @@ class RgwClient(RestClient):
                    f' For more information about the format look at {link}')
             raise DashboardException(msg=msg, component='rgw')
 
+    @RestClient.api_get('/{bucket_name}?policy')
+    def get_bucket_policy(self, bucket_name: str, request=None):
+        """
+        Gets the bucket policy for a bucket.
+        :param bucket_name: The name of the bucket.
+        :type bucket_name: str
+        :rtype: None
+        """
+        # pylint: disable=unused-argument
+
+        try:
+            request = request()
+            return request
+        except RequestException as e:
+            if e.content:
+                content = json_str_to_object(e.content)
+                if content.get(
+                        'Code') == 'NoSuchBucketPolicy':
+                    return None
+            raise e
+
     def perform_validations(self, retention_period_days, retention_period_years, mode):
         try:
             retention_period_days = int(retention_period_days) if retention_period_days else 0