|
30 | 30 | get_workload, |
31 | 31 | list_workloads, |
32 | 32 | ) |
| 33 | +from ..deployer.__utils__ import safe_json, safe_yaml |
33 | 34 | from ..detector import supported_backends |
34 | 35 | from .__types__ import SubCommand |
35 | 36 |
|
|
77 | 78 | "_DRIVER_CAPABILITIES", |
78 | 79 | ) |
79 | 80 |
|
| 81 | +_IGNORE_SENSITIVE_ENVS_SUFFIX = ( |
| 82 | + "_KEY", |
| 83 | + "_key", |
| 84 | + "_TOKEN", |
| 85 | + "_token", |
| 86 | + "_SECRET", |
| 87 | + "_secret", |
| 88 | + "_PASSWORD", |
| 89 | + "_password", |
| 90 | + "_PASS", |
| 91 | + "_pass", |
| 92 | +) |
| 93 | + |
80 | 94 |
|
81 | 95 | class CreateRunnerWorkloadSubCommand(SubCommand): |
82 | 96 | """ |
@@ -966,6 +980,72 @@ def sockets(self): |
966 | 980 | pty.PseudoTerminal(None, exec_op).start() |
967 | 981 |
|
968 | 982 |
|
| 983 | +class InspectWorkloadSubCommand(SubCommand): |
| 984 | + """ |
| 985 | + Command to diagnose a workload deployment. |
| 986 | + """ |
| 987 | + |
| 988 | + @staticmethod |
| 989 | + def register(parser: _SubParsersAction): |
| 990 | + inspect_parser = parser.add_parser( |
| 991 | + "inspect", |
| 992 | + help="Inspect a workload deployment", |
| 993 | + ) |
| 994 | + |
| 995 | + inspect_parser.add_argument( |
| 996 | + "--namespace", |
| 997 | + type=str, |
| 998 | + help="Namespace of the workloads", |
| 999 | + ) |
| 1000 | + |
| 1001 | + inspect_parser.add_argument( |
| 1002 | + "name", |
| 1003 | + type=str, |
| 1004 | + help="Name of the workload", |
| 1005 | + ) |
| 1006 | + |
| 1007 | + inspect_parser.set_defaults(func=InspectWorkloadSubCommand) |
| 1008 | + |
| 1009 | + def __init__(self, args: Namespace): |
| 1010 | + self.namespace = args.namespace |
| 1011 | + self.name = args.name |
| 1012 | + |
| 1013 | + if not self.name: |
| 1014 | + msg = "The name argument is required." |
| 1015 | + raise ValueError(msg) |
| 1016 | + |
| 1017 | + def run(self): |
| 1018 | + workload = get_workload(self.name, self.namespace) |
| 1019 | + if not workload: |
| 1020 | + print(f"Workload '{self.name}' not found.") |
| 1021 | + return |
| 1022 | + |
| 1023 | + if hasattr(workload, "_d_containers"): |
| 1024 | + result = [] |
| 1025 | + for c in workload._d_containers: # noqa: SLF001 |
| 1026 | + c_attrs = c.attrs |
| 1027 | + # Mask sensitive environment variables |
| 1028 | + if "Env" in c_attrs["Config"]: |
| 1029 | + for i, env in enumerate(c_attrs["Config"]["Env"] or []): |
| 1030 | + env_name, _ = env.split("=", maxsplit=1) |
| 1031 | + if env_name.endswith(_IGNORE_SENSITIVE_ENVS_SUFFIX): |
| 1032 | + c_attrs["Config"]["Env"][i] = f"{env_name}=******" |
| 1033 | + result.append(c_attrs) |
| 1034 | + print(safe_json(result, indent=2)) |
| 1035 | + elif hasattr(workload, "_k_pod"): |
| 1036 | + k_pod = workload._k_pod # noqa: SLF001 |
| 1037 | + # Remove managed fields to reduce output size |
| 1038 | + k_pod.metadata.managed_fields = None |
| 1039 | + # Mask sensitive environment variables |
| 1040 | + for c in k_pod.spec.containers: |
| 1041 | + for env in c.env or []: |
| 1042 | + if env.name.endswith(_IGNORE_SENSITIVE_ENVS_SUFFIX): |
| 1043 | + env.value = "******" |
| 1044 | + print(safe_yaml(k_pod, indent=2, sort_keys=False)) |
| 1045 | + else: |
| 1046 | + print("No detailed inspection information available for this workload.") |
| 1047 | + |
| 1048 | + |
969 | 1049 | def format_workloads_json(sts: list[WorkloadStatus]) -> str: |
970 | 1050 | return json.dumps([st.to_dict() for st in sts], indent=2) |
971 | 1051 |
|
|
0 commit comments