Skip to content

Commit 75dc145

Browse files
committed
Adds infrahubctl info command
1 parent 322a0d1 commit 75dc145

File tree

3 files changed

+197
-6
lines changed

3 files changed

+197
-6
lines changed

changelog/109.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Adds `infrahubctl info` command to display information of the connectivity status of the SDK.

infrahub_sdk/ctl/cli_commands.py

Lines changed: 178 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import functools
55
import importlib
66
import logging
7+
import platform
78
import sys
89
from pathlib import Path
910
from typing import TYPE_CHECKING, Any, Callable
@@ -12,7 +13,11 @@
1213
import typer
1314
import ujson
1415
from rich.console import Console
16+
from rich.layout import Layout
1517
from rich.logging import RichHandler
18+
from rich.panel import Panel
19+
from rich.pretty import Pretty
20+
from rich.table import Table
1621
from rich.traceback import Traceback
1722

1823
from .. import __version__ as sdk_version
@@ -34,6 +39,7 @@
3439
from ..ctl.utils import (
3540
catch_exception,
3641
execute_graphql_query,
42+
get_user_permissions,
3743
load_yamlfile_from_disk_and_exit,
3844
parse_cli_vars,
3945
)
@@ -392,11 +398,177 @@ def protocols(
392398

393399
@app.command(name="version")
394400
@catch_exception(console=console)
395-
def version(_: str = CONFIG_PARAM) -> None:
396-
"""Display the version of Infrahub and the version of the Python SDK in use."""
401+
def version() -> None:
402+
"""Display the version of Python and the version of the Python SDK in use."""
397403

398-
client = initialize_client_sync()
399-
response = client.execute_graphql(query="query { InfrahubInfo { version }}")
404+
console.print(f"Python: v{platform.python_version()}\nPython SDK: v{sdk_version}")
400405

401-
infrahub_version = response["InfrahubInfo"]["version"]
402-
console.print(f"Infrahub: v{infrahub_version}\nPython SDK: v{sdk_version}")
406+
407+
@app.command(name="info")
408+
@catch_exception(console=console)
409+
def info(detail: bool = typer.Option(False, help="Display detailed information."), _: str = CONFIG_PARAM) -> None: # noqa: PLR0915
410+
"""Display the status of the Python SDK."""
411+
412+
query = """
413+
query GET_PROFILE_DETAILS {
414+
AccountProfile {
415+
id
416+
display_label
417+
account_type {
418+
value
419+
__typename
420+
updated_at
421+
}
422+
status {
423+
label
424+
value
425+
updated_at
426+
__typename
427+
}
428+
description {
429+
value
430+
updated_at
431+
__typename
432+
}
433+
label {
434+
value
435+
updated_at
436+
__typename
437+
}
438+
member_of_groups {
439+
count
440+
edges {
441+
node {
442+
display_label
443+
group_type {
444+
value
445+
}
446+
... on CoreAccountGroup {
447+
id
448+
roles {
449+
count
450+
edges {
451+
node {
452+
permissions {
453+
count
454+
edges {
455+
node {
456+
display_label
457+
identifier {
458+
value
459+
}
460+
}
461+
}
462+
}
463+
}
464+
}
465+
}
466+
display_label
467+
}
468+
}
469+
}
470+
}
471+
__typename
472+
name {
473+
value
474+
updated_at
475+
__typename
476+
}
477+
}
478+
}
479+
"""
480+
481+
info: dict[str, Any] = {
482+
"error": None,
483+
"status": ":x:",
484+
"infrahub_version": "N/A",
485+
"user_info": None,
486+
"groups": {},
487+
}
488+
try:
489+
client = initialize_client_sync()
490+
version_response = client.execute_graphql(query="query { InfrahubInfo { version }}")
491+
info["infrahub_version"] = version_response["InfrahubInfo"]["version"]
492+
info["user_info"] = client.execute_graphql(query=query)
493+
info["status"] = ":white_heavy_check_mark:"
494+
info["groups"] = get_user_permissions(info["user_info"]["AccountProfile"]["member_of_groups"]["edges"])
495+
except Exception as e:
496+
info["error"] = f"{e!s} ({e.__class__.__name__})"
497+
498+
if detail:
499+
layout = Layout()
500+
501+
# Layout structure
502+
new_console = Console(height=45)
503+
layout = Layout()
504+
layout.split_column(
505+
Layout(name="body", ratio=1),
506+
)
507+
layout["body"].split_row(
508+
Layout(name="left"),
509+
Layout(name="right"),
510+
)
511+
512+
layout["left"].split_column(
513+
Layout(name="connection_status", size=7),
514+
Layout(name="client_info", ratio=1),
515+
)
516+
517+
layout["right"].split_column(
518+
Layout(name="version_info", size=7),
519+
Layout(name="infrahub_info", ratio=1),
520+
)
521+
522+
# Connection status panel
523+
connection_status = Table(show_header=False, box=None)
524+
connection_status.add_row("Server Address:", client.config.address)
525+
connection_status.add_row("Status:", info["status"])
526+
if info["error"]:
527+
connection_status.add_row("Error Reason:", info["error"])
528+
layout["connection_status"].update(Panel(connection_status, title="Connection Status"))
529+
530+
# Version information panel
531+
version_info = Table(show_header=False, box=None)
532+
version_info.add_row("Python Version:", platform.python_version())
533+
version_info.add_row("Infrahub Version", info["infrahub_version"])
534+
version_info.add_row("Infrahub SDK:", sdk_version)
535+
layout["version_info"].update(Panel(version_info, title="Version Information"))
536+
537+
# SDK client configuration panel
538+
pretty_model = Pretty(client.config.dict(), expand_all=True)
539+
layout["client_info"].update(Panel(pretty_model, title="Client Info"))
540+
541+
# Infrahub information planel
542+
infrahub_info = Table(show_header=False, box=None)
543+
if info["user_info"]:
544+
infrahub_info.add_row("User:", info["user_info"]["AccountProfile"]["display_label"])
545+
infrahub_info.add_row("Description:", info["user_info"]["AccountProfile"]["description"]["value"])
546+
infrahub_info.add_row("Status:", info["user_info"]["AccountProfile"]["status"]["label"])
547+
infrahub_info.add_row(
548+
"Number of Groups:", str(info["user_info"]["AccountProfile"]["member_of_groups"]["count"])
549+
)
550+
551+
if groups := info["groups"]:
552+
infrahub_info.add_row("Groups:", "")
553+
for k, v in info["groups"].items():
554+
infrahub_info.add_row("", k, v)
555+
556+
layout["infrahub_info"].update(Panel(infrahub_info, title="Infrahub Info"))
557+
558+
new_console.print(layout)
559+
else:
560+
# Simple output
561+
table = Table(show_header=False, box=None)
562+
table.add_row("Address:", client.config.address)
563+
table.add_row("Connection Status", info["status"])
564+
if info["error"]:
565+
table.add_row("Connection Error:", info["error"])
566+
567+
table.add_row("Python Version:", platform.python_version())
568+
table.add_row("SDK Version:", sdk_version)
569+
table.add_row("Infrahub Version:", info["infrahub_version"])
570+
if groups := info["groups"]:
571+
table.add_row("Groups:")
572+
for k, v in groups.items():
573+
table.add_row("", k, v)
574+
console.print(table)

infrahub_sdk/ctl/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,21 @@ def load_yamlfile_from_disk_and_exit(
214214
raise typer.Exit(1)
215215

216216
return data_files
217+
218+
219+
def get_user_permissions(data: list[dict]) -> dict:
220+
groups = {}
221+
for group in data:
222+
group_name = group["node"]["display_label"]
223+
permissions = []
224+
225+
roles = group["node"].get("roles", {}).get("edges", [])
226+
for role in roles:
227+
role_permissions = role["node"].get("permissions", {}).get("edges", [])
228+
for permission in role_permissions:
229+
permissions.append(permission["node"]["identifier"]["value"])
230+
231+
permissions_str = ", ".join(permissions)
232+
groups[group_name] = permissions_str
233+
234+
return groups

0 commit comments

Comments
 (0)