Skip to content

Commit b77c887

Browse files
authored
[crmsh-4.6] Dev: ra: Show parameters more clearly (#1735)
backport #1733 The extra code lines are for the test case output of external/ssh, which is dropped on the master branch
2 parents d3a574f + 1d4a696 commit b77c887

File tree

3 files changed

+176
-140
lines changed

3 files changed

+176
-140
lines changed

crmsh/ra.py

+119-81
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,9 @@ def __init__(self, ra_class, ra_type, ra_provider="heartbeat", exclude_from_comp
327327
self.meta_string = meta_string
328328

329329
def __str__(self):
330-
return "%s:%s:%s" % (self.ra_class, self.ra_provider, self.ra_type) \
331-
if self.ra_class == "ocf" \
332-
else "%s:%s" % (self.ra_class, self.ra_type)
330+
if self.ra_class == "ocf":
331+
return f"{self.ra_class}:{self.ra_provider}:{self.ra_type}"
332+
return f"{self.ra_class}:{self.ra_type}"
333333

334334
def error(self, s):
335335
logger.error("%s: %s", self, s)
@@ -359,7 +359,7 @@ def add_ra_params(self, ra):
359359
for n in ra.ra_elem.xpath("//parameters/parameter"):
360360
params_node.append(copy.deepcopy(n))
361361

362-
def mk_ra_node(self):
362+
def mk_ra_node(self) -> etree._Element:
363363
'''
364364
Return the resource_agent node.
365365
'''
@@ -393,30 +393,50 @@ def params(self):
393393
completion:
394394
If true, filter some (advanced) parameters out.
395395
'''
396-
ident = "ra_params-%s" % self
396+
ident = f"ra_params-{self}"
397397
if cache.is_cached(ident):
398398
return cache.retrieve(ident)
399+
399400
if self.mk_ra_node() is None:
400401
return None
401-
d = {}
402-
for c in self.ra_elem.xpath("//parameters/parameter"):
403-
name = c.get("name")
402+
403+
params_dict = {}
404+
for param in self.ra_elem.xpath("//parameters/parameter"):
405+
name = param.get("name")
404406
if not name or name in self.excluded_from_completion:
405407
continue
406-
required = c.get("required") if not (c.get("deprecated") or c.get("obsoletes")) else "0"
407-
unique = c.get("unique")
408-
typ, default = _param_type_default(c)
409-
d[name] = {
408+
409+
deprecated = param.get("deprecated", "0")
410+
required = param.get("required", "0") if deprecated != "1" else "0"
411+
obsoletes = param.get("obsoletes")
412+
advanced = param.get("advanced", "0")
413+
generated = param.get("generated", "0")
414+
unique = param.get("unique")
415+
param_type, param_default = _param_type_default(param)
416+
417+
params_dict[name] = {
410418
"required": required,
419+
"deprecated": deprecated,
420+
"obsoletes": obsoletes,
421+
"advanced": advanced,
422+
"generated": generated,
411423
"unique": unique,
412-
"type": typ,
413-
"default": default,
424+
"type": param_type,
425+
"default": param_default,
426+
"options": self.get_selecte_value_list(param),
427+
"shortdesc": self.get_shortdesc(param),
428+
"longdesc": get_nodes_text(param, "longdesc")
414429
}
415-
items = list(d.items())
416-
# Sort the dictionary by required and then alphabetically
417-
items.sort(key=lambda item: (item[1]["required"] != '1', item[0]))
418-
d = dict(items)
419-
return cache.store(ident, d)
430+
431+
items = list(params_dict.items())
432+
# Sort the dictionary by:
433+
# 1. Required parameters first
434+
# 2. Alphabetically by name
435+
# 3. Deprecated parameters last
436+
items.sort(key=lambda x: (x[1]["deprecated"] == "1", x[1]["required"] != "1", x[0]))
437+
params_dict = dict(items)
438+
439+
return cache.store(ident, params_dict)
420440

421441
def actions(self):
422442
'''
@@ -710,73 +730,89 @@ def meta_pretty(self):
710730
'''
711731
Print the RA meta-data in a human readable form.
712732
'''
733+
# get self.ra_elem
713734
if self.mk_ra_node() is None:
714735
return ''
715736
l = []
716-
title = self.meta_title()
717-
l.append(title)
737+
# get title
738+
l.append(self.meta_title())
739+
# get longdesc
718740
longdesc = get_nodes_text(self.ra_elem, "longdesc")
719741
if longdesc:
720742
l.append(longdesc)
721-
if self.ra_class != "heartbeat":
722-
params = self.meta_parameters()
723-
if params:
724-
l.append(params.rstrip())
743+
# get parameters
744+
params = self.meta_parameters()
745+
if params:
746+
l.append(params.rstrip())
747+
# get actions
725748
actions = self.meta_actions()
726749
if actions:
727750
l.append(actions)
751+
728752
return '\n\n'.join(l)
729753

730-
def get_shortdesc(self, n):
731-
name = n.get("name")
732-
shortdesc = get_nodes_text(n, "shortdesc")
733-
longdesc = get_nodes_text(n, "longdesc")
734-
if shortdesc and shortdesc not in (name, longdesc, self.ra_type):
735-
return shortdesc
754+
def get_shortdesc(self, n) -> str:
755+
shortdesc_in_attr = n.get("shortdesc")
756+
if shortdesc_in_attr:
757+
return shortdesc_in_attr
758+
shortdesc_in_content = get_nodes_text(n, "shortdesc")
759+
if shortdesc_in_content:
760+
return shortdesc_in_content
736761
return ''
737762

738763
def meta_title(self):
739-
s = str(self)
764+
name = str(self)
740765
shortdesc = self.get_shortdesc(self.ra_elem)
741-
if shortdesc:
742-
s = "%s (%s)" % (shortdesc, s)
743-
return s
766+
return f"{name} - {shortdesc}" if shortdesc else name
744767

745-
def format_parameter(self, n):
746-
def meta_param_head():
747-
name = n.get("name")
748-
if not name:
749-
return None
750-
s = name
751-
if n.get("required") == "1":
752-
s = s + "*"
753-
typ, default = _param_type_default(n)
768+
def format_parameter(self, name: str, parameter_dict: dict) -> str:
769+
770+
def format_header(name: str, parameter_dict: dict) -> str:
771+
header_str = f"{name}"
772+
if parameter_dict.get("required") == "1":
773+
header_str += "*"
774+
if parameter_dict.get("deprecated") == "1":
775+
header_str += " (deprecated)"
776+
obsoletes = parameter_dict.get("obsoletes")
777+
if obsoletes:
778+
header_str += f" (obsoletes: {obsoletes})"
779+
780+
typ, default = parameter_dict.get("type"), parameter_dict.get("default")
754781
if typ and default:
755-
s = "%s (%s, [%s])" % (s, typ, default)
782+
header_str += f" ({typ}, [{default}]):"
756783
elif typ:
757-
s = "%s (%s)" % (s, typ)
758-
shortdesc = self.get_shortdesc(n)
759-
s = "%s: %s" % (s, shortdesc)
760-
return s
761-
head = meta_param_head()
762-
if not head:
763-
self.error("no name attribute for parameter")
764-
return ""
765-
l = [head]
766-
longdesc = get_nodes_text(n, "longdesc")
767-
select_values = self.get_selecte_value_list(n)
768-
if n.get("advanced") == "1":
769-
l.append(self.ra_tab + "*** Advanced Use Only ***")
770-
if n.get("generated") == "1":
771-
l.append(self.ra_tab + "*** Automatically generated by pacemaker ***")
772-
if n.find("deprecated") is not None:
773-
l.append(self.ra_tab + "*** Deprecated ***")
784+
header_str += f" ({typ}):"
785+
786+
attr_str_map = {
787+
"advanced": "Advanced Use Only",
788+
"generated": "Automatically generated by pacemaker"
789+
}
790+
attr_str_list = [
791+
desc for attr, desc in attr_str_map.items()
792+
if parameter_dict.get(attr) == "1"
793+
]
794+
if attr_str_list:
795+
header_str += f" *** {'; '.join(attr_str_list)} ***"
796+
797+
shortdesc = parameter_dict.get("shortdesc")
798+
if shortdesc:
799+
header_str += f" {shortdesc}"
800+
801+
return header_str
802+
803+
header_str = format_header(name, parameter_dict)
804+
details = [header_str]
805+
806+
longdesc = parameter_dict.get("longdesc")
774807
if longdesc:
775-
l.append(self.ra_tab + longdesc.replace("\n", "\n" + self.ra_tab))
808+
details.append(self.ra_tab + longdesc.replace("\n", "\n" + self.ra_tab))
809+
810+
select_values = parameter_dict.get("options")
776811
if select_values:
777-
l.append(self.ra_tab + "Allowed values: " + ', '.join(select_values))
778-
l.append('')
779-
return '\n'.join(l)
812+
details.append(self.ra_tab + "Allowed values: " + ', '.join(select_values))
813+
814+
details.append('')
815+
return '\n'.join(details)
780816

781817
def get_selecte_value_list(self, node):
782818
"""
@@ -787,23 +823,25 @@ def get_selecte_value_list(self, node):
787823
return []
788824
return [x.get("value") for x in content.findall("option")]
789825

790-
def meta_parameter(self, param):
791-
if self.mk_ra_node() is None:
826+
def meta_parameter(self, param) -> str:
827+
parameters_dict = self.params()
828+
if not parameters_dict:
792829
return ''
793-
for c in self.ra_elem.xpath("//parameters/parameter"):
794-
if c.get("name") == param:
795-
return self.format_parameter(c)
830+
if param in parameters_dict:
831+
return self.format_parameter(param, parameters_dict[param])
832+
return ''
796833

797-
def meta_parameters(self):
798-
if self.mk_ra_node() is None:
834+
def meta_parameters(self) -> str:
835+
parameters_dict = self.params()
836+
if not parameters_dict:
799837
return ''
800-
l = []
801-
for c in self.ra_elem.xpath("//parameters/parameter"):
802-
s = self.format_parameter(c)
803-
if s:
804-
l.append(s)
805-
if l:
806-
return "Parameters (*: required, []: default):\n\n" + '\n'.join(l)
838+
parameter_str_list = []
839+
for name, parameter_dict in parameters_dict.items():
840+
res = self.format_parameter(name, parameter_dict)
841+
if res:
842+
parameter_str_list.append(res)
843+
if parameter_str_list:
844+
return "## Parameters (*: required, []: default):\n\n" + '\n'.join(parameter_str_list)
807845

808846
def meta_actions(self):
809847
def meta_action_head(n):
@@ -825,7 +863,7 @@ def meta_action_head(n):
825863
l.append(self.ra_tab + s)
826864
if not l:
827865
return None
828-
return "Operations' defaults (advisory minimum):\n\n" + '\n'.join(l)
866+
return "## Operations' defaults (advisory minimum):\n\n" + '\n'.join(l)
829867

830868

831869
def get_ra(r):

crmsh/ui_ra.py

-2
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,6 @@ def do_info(self, context, *args):
137137
else:
138138
ra_class, ra_provider, ra_type = ra.disambiguate_ra_type(args[0])
139139
agent = ra.RAInfo(ra_class, ra_type, ra_provider)
140-
if agent.mk_ra_node() is None:
141-
return False
142140
try:
143141
utils.page_string(agent.meta_pretty())
144142
except Exception as msg:

0 commit comments

Comments
 (0)