]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add xlmtodict import and fix lifecycle get request 62393/head
authorPedro Gonzalez Gomez <pegonzal@redhat.com>
Wed, 12 Feb 2025 19:24:57 +0000 (20:24 +0100)
committerNaman Munet <naman.munet@ibm.com>
Wed, 19 Mar 2025 12:09:14 +0000 (17:39 +0530)
Fixes: https://tracker.ceph.com/issues/70128
Signed-off-by: Pedro Gonzalez Gomez <pegonzal@redhat.com>
(cherry picked from commit 567c9e76674f490cdb88f77545da197d54e5fe85)

 Conflicts:
ceph.spec.in
debian/control
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.ts
src/pybind/mgr/dashboard/services/rgw_client.py
src/pybind/mgr/tox.ini

accepted incoming and removed jmespath dependency

ceph.spec.in
debian/control
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.ts
src/pybind/mgr/dashboard/requirements.txt
src/pybind/mgr/dashboard/services/rgw_client.py
src/pybind/mgr/tox.ini

index 4af3f04b39830ffb5d8e45c0247ce04d83343651..9bc6c9d3875c8ba1e94f53a8e1e10cf2b64b47e7 100644 (file)
@@ -641,6 +641,7 @@ Requires:       python%{python3_pkgversion}-setuptools
 %if 0%{?fedora} || 0%{?rhel} >= 9
 Requires:       python%{python3_pkgversion}-grpcio
 Requires:       python%{python3_pkgversion}-grpcio-tools
+Requires:       python%{python3_pkgversion}-xmltodict
 %endif
 %if 0%{?fedora} || 0%{?rhel} || 0%{?openEuler}
 Requires:       python%{python3_pkgversion}-cherrypy
index 041dfcc7980e8d6a224dcd22f9f9bed187e2c747..9a82b582740126a62671320effd5115530f71112 100644 (file)
@@ -99,6 +99,7 @@ Build-Depends: automake,
                python3-coverage <pkg.ceph.check>,
                python3-dateutil <pkg.ceph.check>,
                python3-grpcio <pkg.ceph.check>,
+               python3-xmltodict <pkg.ceph.check>,
                python3-openssl <pkg.ceph.check>,
                python3-prettytable <pkg.ceph.check>,
                python3-requests <pkg.ceph.check>,
index 2be85ea07de01557c15001c60bc97cde06aac132..6eb1a8672eefe3c7a9b536558fc224c8f4785676 100644 (file)
                 <td><pre>{{ selection.bucket_policy | json}}</pre></td>
               </tr>
               <tr>
-                <div>
-                  <td i18n
-                      class="bold w-25">Lifecycle
-                    <div *ngIf="(selection.lifecycle | json) !== '{}'"
-                         class="input-group">
-                      <button type="button"
-                              class="btn btn-light"
-                              [ngClass]="{'active': lifecycleFormat === 'json'}"
-                              (click)="lifecycleFormat = 'json'">
-                            JSON
-                      </button>
-                      <button type="button"
-                              class="btn btn-light"
-                              [ngClass]="{'active': lifecycleFormat === 'xml'}"
-                              (click)="lifecycleFormat = 'xml'">
-                            XML
-                      </button>
-                    </div>
-                  </td>
-                </div>
+                <td i18n
+                    class="bold w-25">Lifecycle
+                  <div *ngIf="(selection.lifecycle | json) !== '{}'"
+                       class="input-group">
+                    <button type="button"
+                            class="btn btn-light"
+                            [ngClass]="{'active': lifecycleFormat === 'json'}"
+                            (click)="updateLifecycleFormatTo('json')">
+                          JSON
+                    </button>
+                    <button type="button"
+                            class="btn btn-light"
+                            [ngClass]="{'active': lifecycleFormat === 'xml'}"
+                            (click)="updateLifecycleFormatTo('xml')">
+                          XML
+                    </button>
+                  </div>
+                </td>
                 <td>
                   <pre *ngIf="lifecycleFormat === 'json'">{{selection.lifecycle | json}}</pre>
                   <pre *ngIf="lifecycleFormat === 'xml'">{{ (selection.lifecycle | xml:{'Rules':'Rule'}) || '-'}}</pre>
index 15382c9fc31ac01ef793f4afb68837d52a005306..a4f48ce91902d44ea7b713605059013f256a9532 100644 (file)
@@ -1,4 +1,4 @@
-import { Component, Input, OnChanges } from '@angular/core';
+import { ChangeDetectorRef, Component, Input, OnChanges } from '@angular/core';
 
 import { RgwBucketService } from '~/app/shared/api/rgw-bucket.service';
 
@@ -17,7 +17,7 @@ export class RgwBucketDetailsComponent implements OnChanges {
   aclPermissions: Record<string, string[]> = {};
   replicationStatus = $localize`Disabled`;
 
-  constructor(private rgwBucketService: RgwBucketService) {}
+  constructor(private rgwBucketService: RgwBucketService, private cd: ChangeDetectorRef) {}
 
   ngOnChanges() {
     if (this.selection) {
@@ -69,4 +69,9 @@ export class RgwBucketDetailsComponent implements OnChanges {
     });
     return data;
   }
+
+  updateLifecycleFormatTo(format: 'json' | 'xml'): void {
+    this.lifecycleFormat = format;
+    this.cd.detectChanges();
+  }
 }
index 27b1615912465f3670686a1df1532eec77369635..50204b855dec61f478a9d9dceca8e22f7f944fb0 100644 (file)
@@ -14,3 +14,4 @@ jsonpatch
 grpcio==1.46.5
 grpcio-tools==1.46.5
 lxml==4.8.0  # to fix https://github.com/xmlsec/python-xmlsec/issues/320
+xmltodict
index 8f11d9514e4f6ed804e17f268739661e8e029b66..aadd0760479c8e6ffb1b39cb0fadba5a4bec1c7e 100755 (executable)
@@ -13,6 +13,11 @@ from collections import defaultdict
 from enum import Enum
 from subprocess import SubprocessError
 
+try:
+    import xmltodict
+except ModuleNotFoundError:
+    logging.error("Module 'xmltodict' is not installed.")
+
 from mgr_util import build_url, name_to_config_section
 
 from .. import mgr
@@ -787,23 +792,30 @@ class RgwClient(RestClient):
     @RestClient.api_get('/{bucket_name}?lifecycle')
     def get_lifecycle(self, bucket_name, request=None):
         # pylint: disable=unused-argument
+
+        # xmltodict parser will prepend namespace to json keys as {ns0:key}
+        def remove_namespace(xml: str):
+            """Remove namespace in given xml string."""
+            root = ET.fromstring(xml)
+            for elem in root.iter():
+                tag_elements = elem.tag.split("}")  # tag: {ns}tagname
+                # Removing namespaces and attributes
+                elem.tag = tag_elements[1]
+                elem.attrib.clear()
+
+            return ET.tostring(root)
+
         try:
-            decoded_request = request(raw_content=True).decode("utf-8")  # type: ignore
-            result = {
-                'LifecycleConfiguration':
-                json.loads(
-                    decoded_request,
-                    object_pairs_hook=RgwClient._handle_rules
-                )
-            }
+            result = request(
+                raw_content=True, headers={'Accept': 'text/xml'}).decode()  # type: ignore
+            return xmltodict.parse(remove_namespace(result), process_namespaces=False)
         except RequestException as e:
             if e.content:
-                content = json_str_to_object(e.content)
-                if content.get(
-                        'Code') == 'NoSuchLifecycleConfiguration':
+                root = ET.fromstring(e.content)
+                code = root.find('Code')
+                if code is not None and code.text == 'NoSuchLifecycleConfiguration':
                     return None
             raise DashboardException(msg=str(e), component='rgw')
-        return result
 
     @staticmethod
     def dict_to_xml(data):
index 17b7e64d63a43a03ed765dea693eea826a70b19e..6c51a639714dfbdf6151da164264cf60856b40da 100644 (file)
@@ -80,6 +80,7 @@ deps =
     types-requests
     types-PyYAML
     types-jwt
+    types-xmltodict
 commands =
     mypy --config-file=../../mypy.ini \
            -m alerts \