comparison sat_frontends/jp/cmd_info.py @ 4035:9c76678a39e2

cli (info/disco): Add external services in results: rel 418
author Goffi <goffi@goffi.org>
date Fri, 07 Apr 2023 15:18:05 +0200
parents 04283582966f
children 524856bd7b19
comparison
equal deleted inserted replaced
4034:9496f28dadff 4035:9c76678a39e2
15 # GNU Affero General Public License for more details. 15 # GNU Affero General Public License for more details.
16 16
17 # You should have received a copy of the GNU Affero General Public License 17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 from pprint import pformat
21
22 from sat.core.i18n import _
23 from sat.tools.common import data_format, date_utils
24 from sat.tools.common.ansi import ANSI as A
25 from sat_frontends.jp import common
26 from sat_frontends.jp.constants import Const as C
27
20 from . import base 28 from . import base
21 from sat.core.i18n import _
22 from sat.tools.common.ansi import ANSI as A
23 from sat.tools.common import date_utils, data_format
24 from sat_frontends.jp.constants import Const as C
25 from sat_frontends.jp import common
26 29
27 __commands__ = ["Info"] 30 __commands__ = ["Info"]
28 31
29 32
30 class Disco(base.CommandBase): 33 class Disco(base.CommandBase):
42 self.parser.add_argument("jid", help=_("entity to discover")) 45 self.parser.add_argument("jid", help=_("entity to discover"))
43 self.parser.add_argument( 46 self.parser.add_argument(
44 "-t", 47 "-t",
45 "--type", 48 "--type",
46 type=str, 49 type=str,
47 choices=("infos", "items", "both"), 50 choices=("infos", "items", "both", "external", "all"),
48 default="both", 51 default="all",
49 help=_("type of data to discover"), 52 help=_("type of data to discover"),
50 ) 53 )
51 self.parser.add_argument("-n", "--node", default="", help=_("node to use")) 54 self.parser.add_argument("-n", "--node", default="", help=_("node to use"))
52 self.parser.add_argument( 55 self.parser.add_argument(
53 "-C", 56 "-C",
60 def default_output(self, data): 63 def default_output(self, data):
61 features = data.get("features", []) 64 features = data.get("features", [])
62 identities = data.get("identities", []) 65 identities = data.get("identities", [])
63 extensions = data.get("extensions", {}) 66 extensions = data.get("extensions", {})
64 items = data.get("items", []) 67 items = data.get("items", [])
68 external = data.get("external", [])
65 69
66 identities_table = common.Table( 70 identities_table = common.Table(
67 self.host, 71 self.host,
68 identities, 72 identities,
69 headers=(_("category"), _("type"), _("name")), 73 headers=(_("category"), _("type"), _("name")),
110 items_table = common.Table( 114 items_table = common.Table(
111 self.host, items, headers=(_("entity"), _("node"), _("name")), use_buffer=True 115 self.host, items, headers=(_("entity"), _("node"), _("name")), use_buffer=True
112 ) 116 )
113 117
114 template = [] 118 template = []
119 fmt_kwargs = {}
115 if features: 120 if features:
116 template.append(A.color(C.A_HEADER, _("Features")) + "\n\n{features}") 121 template.append(A.color(C.A_HEADER, _("Features")) + "\n\n{features}")
117 if identities: 122 if identities:
118 template.append(A.color(C.A_HEADER, _("Identities")) + "\n\n{identities}") 123 template.append(A.color(C.A_HEADER, _("Identities")) + "\n\n{identities}")
119 if extensions: 124 if extensions:
120 template.append(A.color(C.A_HEADER, _("Extensions")) + "\n\n{extensions}") 125 template.append(A.color(C.A_HEADER, _("Extensions")) + "\n\n{extensions}")
121 if items: 126 if items:
122 template.append(A.color(C.A_HEADER, _("Items")) + "\n\n{items}") 127 template.append(A.color(C.A_HEADER, _("Items")) + "\n\n{items}")
128 if external:
129 fmt_lines = []
130 for e in external:
131 data = {k: e[k] for k in sorted(e)}
132 host = data.pop("host")
133 type_ = data.pop("type")
134 fmt_lines.append(A.color(
135 "\t",
136 C.A_SUBHEADER,
137 host,
138 " ",
139 A.RESET,
140 "[",
141 C.A_LEVEL_COLORS[1],
142 type_,
143 A.RESET,
144 "]",
145 ))
146 extended = data.pop("extended", None)
147 for key, value in data.items():
148 fmt_lines.append(A.color(
149 "\t\t",
150 C.A_LEVEL_COLORS[2],
151 f"{key}: ",
152 C.A_LEVEL_COLORS[3],
153 str(value)
154 ))
155 if extended:
156 fmt_lines.append(A.color(
157 "\t\t",
158 C.A_HEADER,
159 "extended",
160 ))
161 nb_extended = len(extended)
162 for idx, form_data in enumerate(extended):
163 namespace = form_data.get("namespace")
164 if namespace:
165 fmt_lines.append(A.color(
166 "\t\t",
167 C.A_LEVEL_COLORS[2],
168 "namespace: ",
169 C.A_LEVEL_COLORS[3],
170 A.BOLD,
171 namespace
172 ))
173 for field_data in form_data["fields"]:
174 name = field_data.get("name")
175 if not name:
176 continue
177 field_type = field_data.get("type")
178 if "multi" in field_type:
179 value = ", ".join(field_data.get("values") or [])
180 else:
181 value = field_data.get("value")
182 if value is None:
183 continue
184 if field_type == "boolean":
185 value = C.bool(value)
186 fmt_lines.append(A.color(
187 "\t\t",
188 C.A_LEVEL_COLORS[2],
189 f"{name}: ",
190 C.A_LEVEL_COLORS[3],
191 A.BOLD,
192 str(value)
193 ))
194 if nb_extended>1 and idx < nb_extended-1:
195 fmt_lines.append("\n")
196
197 fmt_lines.append("\n")
198
199 template.append(
200 A.color(C.A_HEADER, _("External")) + "\n\n{external_formatted}"
201 )
202 fmt_kwargs["external_formatted"] = "\n".join(fmt_lines)
123 203
124 print( 204 print(
125 "\n\n".join(template).format( 205 "\n\n".join(template).format(
126 features="\n".join(features), 206 features="\n".join(features),
127 identities=identities_table.display().string, 207 identities=identities_table.display().string,
128 extensions="\n".join(extensions_tpl), 208 extensions="\n".join(extensions_tpl),
129 items=items_table.display().string, 209 items=items_table.display().string,
210 **fmt_kwargs,
130 ) 211 )
131 ) 212 )
132 213
133 async def start(self): 214 async def start(self):
134 infos_requested = self.args.type in ("infos", "both") 215 infos_requested = self.args.type in ("infos", "both", "all")
135 items_requested = self.args.type in ("items", "both") 216 items_requested = self.args.type in ("items", "both", "all")
217 exter_requested = self.args.type in ("external", "all")
218 if self.args.node:
219 if self.args.type == "external":
220 self.parser.error(
221 '--node can\'t be used with discovery of external services '
222 '(--type="external")'
223 )
224 else:
225 exter_requested = False
136 jids = await self.host.check_jids([self.args.jid]) 226 jids = await self.host.check_jids([self.args.jid])
137 jid = jids[0] 227 jid = jids[0]
228 data = {}
138 229
139 # infos 230 # infos
140 if not infos_requested: 231 if infos_requested:
141 infos = None
142 else:
143 try: 232 try:
144 infos = await self.host.bridge.discoInfos( 233 infos = await self.host.bridge.discoInfos(
145 jid, 234 jid,
146 node=self.args.node, 235 node=self.args.node,
147 use_cache=self.args.use_cache, 236 use_cache=self.args.use_cache,
149 ) 238 )
150 except Exception as e: 239 except Exception as e:
151 self.disp(_("error while doing discovery: {e}").format(e=e), error=True) 240 self.disp(_("error while doing discovery: {e}").format(e=e), error=True)
152 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 241 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
153 242
154 # items 243 else:
155 if not items_requested: 244 features, identities, extensions = infos
156 items = None 245 features.sort()
157 else: 246 identities.sort(key=lambda identity: identity[2])
247 data.update(
248 {"features": features, "identities": identities, "extensions": extensions}
249 )
250
251 # items
252 if items_requested:
158 try: 253 try:
159 items = await self.host.bridge.discoItems( 254 items = await self.host.bridge.discoItems(
160 jid, 255 jid,
161 node=self.args.node, 256 node=self.args.node,
162 use_cache=self.args.use_cache, 257 use_cache=self.args.use_cache,
163 profile_key=self.host.profile, 258 profile_key=self.host.profile,
164 ) 259 )
165 except Exception as e: 260 except Exception as e:
166 self.disp(_("error while doing discovery: {e}").format(e=e), error=True) 261 self.disp(_("error while doing discovery: {e}").format(e=e), error=True)
167 self.host.quit(C.EXIT_BRIDGE_ERRBACK) 262 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
168 263 else:
169 # output 264 items.sort(key=lambda item: item[2])
170 data = {} 265 data["items"] = items
171 266
172 if infos_requested: 267 # external
173 features, identities, extensions = infos 268 if exter_requested:
174 features.sort() 269 try:
175 identities.sort(key=lambda identity: identity[2]) 270 ext_services_s = await self.host.bridge.external_disco_get(
176 data.update( 271 jid,
177 {"features": features, "identities": identities, "extensions": extensions} 272 self.host.profile,
178 ) 273 )
179 274 except Exception as e:
180 if items_requested: 275 self.disp(
181 items.sort(key=lambda item: item[2]) 276 _("error while doing external service discovery: {e}").format(e=e),
182 data["items"] = items 277 error=True
183 278 )
279 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
280 else:
281 data["external"] = data_format.deserialise(
282 ext_services_s, type_check=list
283 )
284
285 # output
184 await self.output(data) 286 await self.output(data)
185 self.host.quit() 287 self.host.quit()
186 288
187 289
188 class Version(base.CommandBase): 290 class Version(base.CommandBase):