]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add xlmtodict import and fix lifecycle get request 61781/head
authorPedro Gonzalez Gomez <pegonzal@redhat.com>
Wed, 12 Feb 2025 19:24:57 +0000 (20:24 +0100)
committerPedro Gonzalez Gomez <pegonzal@redhat.com>
Thu, 13 Mar 2025 20:50:18 +0000 (21:50 +0100)
Fixes: https://tracker.ceph.com/issues/70128
Signed-off-by: Pedro Gonzalez Gomez <pegonzal@redhat.com>
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 d72b5abcc62228f7ce7e8e22aff0ac06e28cde3f..8c022125ebabccad9f27e7e2a850c0e98ae01976 100644 (file)
@@ -695,6 +695,7 @@ Requires:       ceph-prometheus-alerts = %{_epoch_prefix}%{version}-%{release}
 Requires:       python%{python3_pkgversion}-grpcio
 Requires:       python%{python3_pkgversion}-grpcio-tools
 Requires:       python%{python3_pkgversion}-jmespath
+Requires:       python%{python3_pkgversion}-xmltodict
 %endif
 %if 0%{?fedora} || 0%{?rhel} || 0%{?openEuler}
 Requires:       python%{python3_pkgversion}-cherrypy
index 88c4c92238f0f1cea70b86a74c3d277a64dd56ce..6d3fa3263050a515c2a567b02205186f6d25afc7 100644 (file)
@@ -100,6 +100,7 @@ Build-Depends: automake,
                python3-dateutil <pkg.ceph.check>,
                python3-grpcio <pkg.ceph.check>,
                python3-jmespath (>=0.10) <pkg.ceph.check>,
+               python3-xmltodict <pkg.ceph.check>,
                python3-openssl <pkg.ceph.check>,
                python3-prettytable <pkg.ceph.check>,
                python3-requests <pkg.ceph.check>,
index 2c22cf80c609e64adc2046b385beb656521d38f9..49d4f4255c7afbb838f4bd465c0422db1a2dfc9d 100644 (file)
                     <button type="button"
                             class="btn btn-light"
                             [ngClass]="{'active': lifecycleFormat === 'json'}"
-                            (click)="lifecycleFormat = 'json'">
+                            (click)="updateLifecycleFormatTo('json')">
                           JSON
                     </button>
                     <button type="button"
                             class="btn btn-light"
                             [ngClass]="{'active': lifecycleFormat === 'xml'}"
-                            (click)="lifecycleFormat = 'xml'">
+                            (click)="updateLifecycleFormatTo('xml')">
                           XML
                     </button>
                   </div>
index b95faa3140eb63a9017a7dcc312c0446587addee..fe8ab3e6a3279e97564602ad310a31ebf80686f3 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';
 
@@ -24,7 +24,7 @@ export class RgwBucketDetailsComponent implements OnChanges {
   replicationStatus = $localize`Disabled`;
   bucketRateLimit: RgwRateLimitConfig;
 
-  constructor(private rgwBucketService: RgwBucketService) {}
+  constructor(private rgwBucketService: RgwBucketService, private cd: ChangeDetectorRef) {}
 
   ngOnChanges() {
     this.updateBucketDetails(this.extraxtDetailsfromResponse.bind(this));
@@ -102,4 +102,9 @@ export class RgwBucketDetailsComponent implements OnChanges {
       );
     }
   }
+
+  updateLifecycleFormatTo(format: 'json' | 'xml'): void {
+    this.lifecycleFormat = format;
+    this.cd.detectChanges();
+  }
 }
index be0bc1efb022ee7adcb2e528700b3ee04e808f7b..6f95477cb12998ada5244103f142fcbda6cddb62 100644 (file)
@@ -15,3 +15,4 @@ grpcio==1.46.5
 grpcio-tools==1.46.5
 jmespath
 lxml==4.8.0  # to fix https://github.com/xmlsec/python-xmlsec/issues/320
+xmltodict
index f29e4766d6156006f3b7d7fcb709f9c14b2e7f54..f9423da564e7ebc7d0015fd19ea9332b62a9ea73 100755 (executable)
@@ -16,6 +16,12 @@ from subprocess import SubprocessError
 from urllib.parse import urlparse
 
 import requests
+
+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
@@ -715,23 +721,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 366dc1ff87121597591bd8c569e0e442c5650e8c..c2deb627261ecb3f50da391ff5b68e90205ff88b 100644 (file)
@@ -82,6 +82,7 @@ deps =
     types-PyYAML
     types-jwt
     types-jmespath
+    types-xmltodict
 commands =
     mypy --config-file=../../mypy.ini \
            -m alerts \