kdebug 0.3.4__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kdebug-0.3.4 → kdebug-0.4.0}/.gitignore +4 -0
- {kdebug-0.3.4 → kdebug-0.4.0}/PKG-INFO +1 -1
- {kdebug-0.3.4 → kdebug-0.4.0}/pyproject.toml +1 -1
- {kdebug-0.3.4 → kdebug-0.4.0}/src/kdebug/__init__.py +1 -1
- {kdebug-0.3.4 → kdebug-0.4.0}/src/kdebug/cli.py +65 -19
- {kdebug-0.3.4 → kdebug-0.4.0}/README.md +0 -0
- {kdebug-0.3.4 → kdebug-0.4.0}/src/kdebug/completions/__init__.py +0 -0
- {kdebug-0.3.4 → kdebug-0.4.0}/src/kdebug/completions/_kdebug +0 -0
- {kdebug-0.3.4 → kdebug-0.4.0}/src/kdebug/completions/kdebug.bash +0 -0
- {kdebug-0.3.4 → kdebug-0.4.0}/src/kdebug/completions/kdebug.fish +0 -0
|
@@ -466,9 +466,7 @@ def select_pod(args) -> Optional[Dict]:
|
|
|
466
466
|
# Validate cluster connection and namespace before proceeding
|
|
467
467
|
error = validate_cluster_connection(namespace)
|
|
468
468
|
if error:
|
|
469
|
-
print(
|
|
470
|
-
f"{colorize('✗ Error:', Colors.RED)} {error}"
|
|
471
|
-
)
|
|
469
|
+
print(f"{colorize('✗ Error:', Colors.RED)} {error}")
|
|
472
470
|
return None
|
|
473
471
|
|
|
474
472
|
# Direct pod selection
|
|
@@ -495,12 +493,12 @@ def select_pod(args) -> Optional[Dict]:
|
|
|
495
493
|
return pods[0]
|
|
496
494
|
|
|
497
495
|
# Interactive mode - no pod or controller specified
|
|
498
|
-
print(f"\n{colorize('Starting interactive pod selection...', Colors.
|
|
496
|
+
print(f"\n{colorize('Starting interactive pod selection...', Colors.CYAN)}")
|
|
499
497
|
|
|
500
498
|
# Direct pod selection via TUI
|
|
501
499
|
pod_name = select_pod_interactive(namespace)
|
|
502
500
|
if not pod_name:
|
|
503
|
-
print(f"\n{colorize('Selection cancelled', Colors.
|
|
501
|
+
print(f"\n{colorize('Selection cancelled', Colors.CYAN)}")
|
|
504
502
|
return None
|
|
505
503
|
|
|
506
504
|
return {"name": pod_name, "namespace": namespace}
|
|
@@ -703,6 +701,42 @@ def check_pod_security_context(pod_name: str, namespace: str) -> Dict:
|
|
|
703
701
|
return {"can_run_as_root": True, "reason": "Unable to parse pod spec"}
|
|
704
702
|
|
|
705
703
|
|
|
704
|
+
def get_container_run_as_user(
|
|
705
|
+
pod_name: str, namespace: str, target_container: Optional[str]
|
|
706
|
+
) -> Optional[int]:
|
|
707
|
+
"""Detect the runAsUser UID from the target container or pod security context."""
|
|
708
|
+
cmd = f"{kubectl_base_cmd()} get pod {pod_name} -n {namespace} -o json"
|
|
709
|
+
output = run_command(cmd, check=False)
|
|
710
|
+
|
|
711
|
+
if not output:
|
|
712
|
+
return None
|
|
713
|
+
|
|
714
|
+
try:
|
|
715
|
+
pod_data = json.loads(output)
|
|
716
|
+
spec = pod_data.get("spec", {})
|
|
717
|
+
|
|
718
|
+
# Check container-level securityContext first (overrides pod-level)
|
|
719
|
+
if target_container:
|
|
720
|
+
for container in spec.get("containers", []):
|
|
721
|
+
if container.get("name") == target_container:
|
|
722
|
+
container_uid = container.get("securityContext", {}).get(
|
|
723
|
+
"runAsUser"
|
|
724
|
+
)
|
|
725
|
+
if container_uid is not None:
|
|
726
|
+
return int(container_uid)
|
|
727
|
+
break
|
|
728
|
+
|
|
729
|
+
# Fall back to pod-level securityContext
|
|
730
|
+
pod_uid = spec.get("securityContext", {}).get("runAsUser")
|
|
731
|
+
if pod_uid is not None:
|
|
732
|
+
return int(pod_uid)
|
|
733
|
+
|
|
734
|
+
except (json.JSONDecodeError, ValueError, TypeError):
|
|
735
|
+
pass
|
|
736
|
+
|
|
737
|
+
return None
|
|
738
|
+
|
|
739
|
+
|
|
706
740
|
def launch_debug_container(
|
|
707
741
|
pod_name: str,
|
|
708
742
|
namespace: str,
|
|
@@ -710,6 +744,7 @@ def launch_debug_container(
|
|
|
710
744
|
target_container: Optional[str],
|
|
711
745
|
existing_containers: List[str],
|
|
712
746
|
as_root: bool = False,
|
|
747
|
+
run_as_user: Optional[int] = None,
|
|
713
748
|
) -> Optional[str]:
|
|
714
749
|
"""Launch a debug container attached to the pod and return its name."""
|
|
715
750
|
print(f"Launching debug container for pod {colorize(pod_name, Colors.CYAN)}...")
|
|
@@ -727,12 +762,16 @@ def launch_debug_container(
|
|
|
727
762
|
file=sys.stderr,
|
|
728
763
|
)
|
|
729
764
|
print(f"{colorize('Tip:', Colors.CYAN)} Try without --as-root flag\n")
|
|
730
|
-
|
|
731
|
-
if existing_containers:
|
|
765
|
+
elif run_as_user is not None:
|
|
732
766
|
print(
|
|
733
|
-
f"
|
|
767
|
+
f"Running as UID {colorize(str(run_as_user), Colors.CYAN)} (matching target container)"
|
|
734
768
|
)
|
|
735
769
|
|
|
770
|
+
# if existing_containers:
|
|
771
|
+
# print(
|
|
772
|
+
# f"Existing ephemeral containers: {colorize(', '.join(existing_containers), Colors.BRIGHT_BLACK)}"
|
|
773
|
+
# )
|
|
774
|
+
|
|
736
775
|
# Build kubectl debug command
|
|
737
776
|
cmd_parts = [
|
|
738
777
|
f"nohup {kubectl_base_cmd()} debug -i --tty",
|
|
@@ -752,6 +791,10 @@ def launch_debug_container(
|
|
|
752
791
|
|
|
753
792
|
if as_root:
|
|
754
793
|
cmd_parts.append('--custom=<(echo \'{"securityContext":{"runAsUser":0}}\')')
|
|
794
|
+
elif run_as_user is not None:
|
|
795
|
+
cmd_parts.append(
|
|
796
|
+
f'--custom=<(echo \'{{"securityContext":{{"runAsUser":{run_as_user}}}}}\')'
|
|
797
|
+
)
|
|
755
798
|
|
|
756
799
|
cmd_parts.extend(
|
|
757
800
|
[
|
|
@@ -798,13 +841,12 @@ def exec_interactive(
|
|
|
798
841
|
) -> int:
|
|
799
842
|
"""Execute an interactive command in the debug container."""
|
|
800
843
|
print(f"\n{colorize('=' * 60, Colors.BLUE)}")
|
|
801
|
-
print(
|
|
802
|
-
|
|
803
|
-
)
|
|
844
|
+
print(f"{colorize('Starting interactive session', Colors.BOLD)} in:")
|
|
845
|
+
print(f"Pod: {colorize(pod_name, Colors.CYAN)}")
|
|
804
846
|
print(f"Container: {colorize(container_name, Colors.CYAN)}")
|
|
805
|
-
print(f"Command: {colorize(cmd, Colors.
|
|
847
|
+
print(f"Command: {colorize(cmd, Colors.CYAN)}")
|
|
806
848
|
if cd_into:
|
|
807
|
-
print(f"Directory: {colorize(cd_into, Colors.
|
|
849
|
+
print(f"Directory: {colorize(cd_into, Colors.CYAN)}")
|
|
808
850
|
print(f"{colorize('=' * 60, Colors.BLUE)}\n")
|
|
809
851
|
|
|
810
852
|
# If cd_into is specified, wrap command to cd first
|
|
@@ -1043,7 +1085,7 @@ def parse_controller_arg(value: str) -> Tuple[str, str]:
|
|
|
1043
1085
|
controller_type, controller_name = value.split("/", 1)
|
|
1044
1086
|
if not controller_name:
|
|
1045
1087
|
raise argparse.ArgumentTypeError(
|
|
1046
|
-
|
|
1088
|
+
"Missing controller name after '/'. Expected TYPE/NAME (e.g. sts/myapp)."
|
|
1047
1089
|
)
|
|
1048
1090
|
if controller_type.lower() not in CONTROLLER_ALIASES:
|
|
1049
1091
|
valid_types = ", ".join(sorted(CONTROLLER_ALIASES.keys()))
|
|
@@ -1200,15 +1242,13 @@ Usage:
|
|
|
1200
1242
|
)
|
|
1201
1243
|
|
|
1202
1244
|
print(f"\n{colorize('=' * 60, Colors.BLUE)}")
|
|
1245
|
+
print(f"{colorize('Namespace:', Colors.BOLD)} {colorize(namespace, Colors.CYAN)}")
|
|
1203
1246
|
print(f"{colorize('Target Pod:', Colors.BOLD)} {colorize(pod_name, Colors.CYAN)}")
|
|
1204
|
-
print(
|
|
1205
|
-
f"{colorize('Namespace:', Colors.BOLD)} {colorize(namespace, Colors.MAGENTA)}"
|
|
1206
|
-
)
|
|
1207
1247
|
print(
|
|
1208
1248
|
f"{colorize('Target Container:', Colors.BOLD)} {colorize(target_container, Colors.CYAN)}"
|
|
1209
1249
|
)
|
|
1210
1250
|
print(
|
|
1211
|
-
f"{colorize('Debug Image:', Colors.BOLD)} {colorize(args.debug_image, Colors.
|
|
1251
|
+
f"{colorize('Debug Image:', Colors.BOLD)} {colorize(args.debug_image, Colors.CYAN)}"
|
|
1212
1252
|
)
|
|
1213
1253
|
print(f"{colorize('=' * 60, Colors.BLUE)}\n")
|
|
1214
1254
|
|
|
@@ -1222,7 +1262,12 @@ Usage:
|
|
|
1222
1262
|
f"Found existing ephemeral containers: {colorize(', '.join(existing_containers), Colors.BRIGHT_BLACK)}"
|
|
1223
1263
|
)
|
|
1224
1264
|
# For simplicity, we'll create a new one. In production, you might want to reuse.
|
|
1225
|
-
print(f"{colorize('Creating new debug container...', Colors.
|
|
1265
|
+
print(f"{colorize('Creating new debug container...', Colors.MAGENTA)}")
|
|
1266
|
+
|
|
1267
|
+
# Detect target container UID for the debug container
|
|
1268
|
+
run_as_user = None
|
|
1269
|
+
if not args.as_root:
|
|
1270
|
+
run_as_user = get_container_run_as_user(pod_name, namespace, target_container)
|
|
1226
1271
|
|
|
1227
1272
|
# Launch debug container
|
|
1228
1273
|
debug_container = launch_debug_container(
|
|
@@ -1232,6 +1277,7 @@ Usage:
|
|
|
1232
1277
|
target_container,
|
|
1233
1278
|
existing_containers,
|
|
1234
1279
|
args.as_root,
|
|
1280
|
+
run_as_user,
|
|
1235
1281
|
)
|
|
1236
1282
|
|
|
1237
1283
|
if not debug_container:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|