From: Pedro Gonzalez Gomez Date: Wed, 12 Feb 2025 19:24:57 +0000 (+0100) Subject: mgr/dashboard: add xlmtodict import and fix lifecycle get request X-Git-Tag: v19.2.3~269^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=215ffebd693cbbb70fa9843730113060682cc03d;p=ceph.git mgr/dashboard: add xlmtodict import and fix lifecycle get request Fixes: https://tracker.ceph.com/issues/70128 Signed-off-by: Pedro Gonzalez Gomez (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 --- diff --git a/ceph.spec.in b/ceph.spec.in index 4af3f04b3983..9bc6c9d3875c 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -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 diff --git a/debian/control b/debian/control index 041dfcc7980e..9a82b5827401 100644 --- a/debian/control +++ b/debian/control @@ -99,6 +99,7 @@ Build-Depends: automake, python3-coverage , python3-dateutil , python3-grpcio , + python3-xmltodict , python3-openssl , python3-prettytable , python3-requests , diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html index 2be85ea07de0..6eb1a8672eef 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html @@ -136,26 +136,24 @@
{{ selection.bucket_policy | json}}
-
- Lifecycle -
- - -
- -
+ Lifecycle +
+ + +
+
{{selection.lifecycle | json}}
{{ (selection.lifecycle | xml:{'Rules':'Rule'}) || '-'}}
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts index 15382c9fc31a..a4f48ce91902 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.ts @@ -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 = {}; 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(); + } } diff --git a/src/pybind/mgr/dashboard/requirements.txt b/src/pybind/mgr/dashboard/requirements.txt index 27b161591246..50204b855dec 100644 --- a/src/pybind/mgr/dashboard/requirements.txt +++ b/src/pybind/mgr/dashboard/requirements.txt @@ -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 diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py index 8f11d9514e4f..aadd0760479c 100755 --- a/src/pybind/mgr/dashboard/services/rgw_client.py +++ b/src/pybind/mgr/dashboard/services/rgw_client.py @@ -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): diff --git a/src/pybind/mgr/tox.ini b/src/pybind/mgr/tox.ini index 17b7e64d63a4..6c51a639714d 100644 --- a/src/pybind/mgr/tox.ini +++ b/src/pybind/mgr/tox.ini @@ -80,6 +80,7 @@ deps = types-requests types-PyYAML types-jwt + types-xmltodict commands = mypy --config-file=../../mypy.ini \ -m alerts \