Skip to content

Commit 87612f4

Browse files
committed
mgr/dashboard: fix lifecycle issues
Fixes: https://tracker.ceph.com/issues/68434 Signed-off-by: Pedro Gonzalez Gomez <[email protected]>
1 parent e0bf430 commit 87612f4

File tree

6 files changed

+61
-15
lines changed

6 files changed

+61
-15
lines changed

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-details/rgw-bucket-details.component.html

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,14 @@
158158
</div>
159159
</td>
160160
<td>
161-
<pre *ngIf="lifecycleFormat === 'json'">{{selection.lifecycle | json}}</pre>
162-
<pre *ngIf="lifecycleFormat === 'xml'">{{ (selection.lifecycle | xml) || '-'}}</pre>
161+
<cds-code-snippet display="multi"
162+
*ngIf="lifecycleFormat === 'json'">
163+
{{selection.lifecycle | json}}
164+
</cds-code-snippet>
165+
<cds-code-snippet display="multi"
166+
*ngIf="lifecycleFormat === 'xml'">
167+
{{ (selection.lifecycle | xml:{'Rules':'Rule'}) || '-'}}
168+
</cds-code-snippet>
163169
</td>
164170
</tr>
165171
<tr>

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ import {
7070
IconModule,
7171
LoadingModule,
7272
ModalModule,
73-
ProgressIndicatorModule
73+
ProgressIndicatorModule,
74+
CodeSnippetModule
7475
} from 'carbon-components-angular';
7576
import { CephSharedModule } from '../shared/ceph-shared.module';
7677

@@ -94,6 +95,7 @@ import { CephSharedModule } from '../shared/ceph-shared.module';
9495
ModalModule,
9596
GridModule,
9697
ProgressIndicatorModule,
98+
CodeSnippetModule,
9799
ButtonModule,
98100
LoadingModule,
99101
IconModule,

src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/xml.pipe.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ import { JsonToXmlService } from '../services/json-to-xml.service';
77
export class XmlPipe implements PipeTransform {
88
constructor(private jsonToXmlService: JsonToXmlService) {}
99

10-
transform(value: string, valueFormat: string = 'json'): string {
10+
transform(
11+
value: string,
12+
replaceKey: Record<string, string> = {},
13+
valueFormat: string = 'json'
14+
): string {
1115
if (valueFormat === 'json') {
12-
value = this.jsonToXmlService.format(value);
16+
value = this.jsonToXmlService.format(value, replaceKey);
1317
}
1418
return value;
1519
}

src/pybind/mgr/dashboard/frontend/src/app/shared/services/json-to-xml.service.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,39 @@ import { Injectable } from '@angular/core';
66
export class JsonToXmlService {
77
constructor() {}
88

9-
format(json: any, indentSize: number = 2, currentIndent: number = 0): string {
9+
format(
10+
json: any,
11+
replaceKey: Record<string, string> = null,
12+
indentSize: number = 2,
13+
currentIndent: number = 0
14+
): string {
1015
if (!json) return null;
1116
let xml = '';
1217
if (typeof json === 'string') {
1318
json = JSON.parse(json);
1419
}
1520

16-
for (const key in json) {
21+
for (let key in json) {
1722
if (json.hasOwnProperty(key)) {
1823
const value = json[key];
1924
const indentation = ' '.repeat(currentIndent);
20-
25+
if (replaceKey) {
26+
const [oldKey, newKey] = Object.entries(replaceKey)[0];
27+
if (key === oldKey) {
28+
key = newKey;
29+
}
30+
}
2131
if (Array.isArray(value)) {
2232
value.forEach((item) => {
2333
xml +=
2434
`${indentation}<${key}>\n` +
25-
this.format(item, indentSize, currentIndent + indentSize) +
35+
this.format(item, replaceKey, indentSize, currentIndent + indentSize) +
2636
`${indentation}</${key}>\n`;
2737
});
2838
} else if (typeof value === 'object') {
2939
xml +=
3040
`${indentation}<${key}>\n` +
31-
this.format(value, indentSize, currentIndent + indentSize) +
41+
this.format(value, replaceKey, indentSize, currentIndent + indentSize) +
3242
`${indentation}</${key}>\n`;
3343
} else {
3444
xml += `${indentation}<${key}>${value}</${key}>\n`;

src/pybind/mgr/dashboard/frontend/src/styles/_carbon-defaults.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,10 @@ Dashboard page
142142
cd-dashboard {
143143
font-size: 12px;
144144
}
145+
146+
/******************************************
147+
Code snippet
148+
******************************************/
149+
.cds--snippet {
150+
width: fit-content;
151+
}

src/pybind/mgr/dashboard/services/rgw_client.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import time
1111
import uuid
1212
import xml.etree.ElementTree as ET # noqa: N814
13+
from collections import defaultdict
1314
from enum import Enum
1415
from subprocess import SubprocessError
1516
from urllib.parse import urlparse
@@ -700,12 +701,28 @@ def set_tags(self, bucket_name, tags, request=None):
700701
raise DashboardException(msg=str(e), component='rgw')
701702
return result
702703

704+
@staticmethod
705+
def _handle_rules(pairs):
706+
result = defaultdict(list)
707+
for key, value in pairs:
708+
if key == 'Rule':
709+
result['Rules'].append(value)
710+
else:
711+
result[key] = value
712+
return result
713+
703714
@RestClient.api_get('/{bucket_name}?lifecycle')
704715
def get_lifecycle(self, bucket_name, request=None):
705716
# pylint: disable=unused-argument
706717
try:
707-
result = request() # type: ignore
708-
result = {'LifecycleConfiguration': result}
718+
decoded_request = request(raw_content=True).decode("utf-8") # type: ignore
719+
result = {
720+
'LifecycleConfiguration':
721+
json.loads(
722+
decoded_request,
723+
object_pairs_hook=RgwClient._handle_rules
724+
)
725+
}
709726
except RequestException as e:
710727
if e.content:
711728
content = json_str_to_object(e.content)
@@ -757,15 +774,15 @@ def set_lifecycle(self, bucket_name, lifecycle, request=None):
757774
lifecycle = RgwClient.dict_to_xml(lifecycle)
758775
try:
759776
if lifecycle and '<LifecycleConfiguration>' not in str(lifecycle):
760-
lifecycle = f'<LifecycleConfiguration>{lifecycle}</LifecycleConfiguration>'
777+
lifecycle = f'<LifecycleConfiguration>\n{lifecycle}\n</LifecycleConfiguration>'
761778
result = request(data=lifecycle) # type: ignore
762779
except RequestException as e:
780+
msg = ''
763781
if e.content:
764782
content = json_str_to_object(e.content)
765783
if content.get("Code") == "MalformedXML":
766784
msg = "Invalid Lifecycle document"
767-
raise DashboardException(msg=msg, component='rgw')
768-
raise DashboardException(msg=str(e), component='rgw')
785+
raise DashboardException(msg=msg or str(e), component='rgw')
769786
return result
770787

771788
@RestClient.api_delete('/{bucket_name}?lifecycle')

0 commit comments

Comments
 (0)