Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

Commit 2aa1844

Browse files
committed
refactoring for bigger use
1 parent f73e159 commit 2aa1844

6 files changed

Lines changed: 89 additions & 57 deletions

File tree

src/java_toolkit/utils/pod_ps.py renamed to src/java_toolkit/common/utils/processes.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/local/bin/python3
22
import re
33
from typing import List
4+
from .remote_ns_cmd import run_cmd_in_proc_namespace
45

56
import psutil
67
import typer
@@ -14,6 +15,8 @@
1415
r"\d+:.+:/kubepods\.slice/kubepods-[^/]+\.slice/kubepods-[^/]+-pod([^/]+)\.slice/docker-([0-9a-f]{64})"
1516
)
1617

18+
ps_regex = re.compile(r"\s*(?P<pid>.*?)\s+(?P<cmd>.*?)\s+(?P<cmd_args>.*?)\n")
19+
1720
app = typer.Typer()
1821

1922

@@ -61,3 +64,25 @@ def get_pod_processes(pod_uid: str) -> ProcessList:
6164
processes.append(Process(pid=pid, exe=proc.exe(), cmdline=proc.cmdline()))
6265
return ProcessList(processes=processes)
6366

67+
def get_ns_processes(pid_in_ns: int, verbose: bool):
68+
cmd = "ps -o pid,comm,args | tail -n +2 "
69+
processes = run_cmd_in_proc_namespace(pid_in_ns, cmd, verbose)
70+
processes = processes.split('\n')
71+
return_proc_list=[]
72+
processes.remove(processes[0]) #title column
73+
for proc_line in processes:
74+
if "tail -n" in proc_line or "ps -o pid,comm,args" in proc_line:
75+
continue
76+
match = ps_regex.match(proc_line)
77+
pid = int(match.group("pid"))
78+
exe = match.group("cmd")
79+
cmdline = match.group("cmd_args")
80+
if cmdline is None:
81+
cmdline = []
82+
else:
83+
cmdline = cmdline.split(' ')
84+
return_proc_list.append(Process(pid=pid, exe=exe, cmdline=cmdline))
85+
return return_proc_list
86+
87+
88+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import subprocess
2+
import typer
3+
4+
5+
def run_command(cmd: str, verbose: bool):
6+
if verbose:
7+
typer.echo(f"Running {cmd}")
8+
proc = subprocess.Popen(
9+
cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT
10+
)
11+
(output, err) = proc.communicate()
12+
13+
proc.stdout.close()
14+
return_code = proc.wait()
15+
if return_code:
16+
raise subprocess.CalledProcessError(return_code, cmd)
17+
if verbose:
18+
typer.echo(output)
19+
return output, err
20+
21+
def run_cmd_in_proc_namespace(pid, command_to_run, verbose):
22+
NSENTER_CMD = "nsenter -t {} -p -m {}"
23+
nsenter_cmd_formatted = NSENTER_CMD.format(pid, command_to_run)
24+
return run_command(nsenter_cmd_formatted, verbose)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from .remote_ns_cmd import run_command
2+
from os.path import join, basename
3+
4+
class TmpRemotePodMounter(object):
5+
remote_mnt_path =""
6+
local_mnt_path =""
7+
src_dir =""
8+
verbose = False
9+
MKDIR_POD_CMD="mkdir -p {}"
10+
RMDIR_POD_CMD="rm -R {}"
11+
COPY_CMD="cp -R {} {}"
12+
ROOT_PROC_NS="/proc/{}/cwd",
13+
14+
def __init__(self, pid: str, src_dir: str, local_mnt_path: str, verbose: bool):
15+
self.verbose = verbose
16+
self.src_dir = src_dir
17+
self.local_mnt_path = local_mnt_path
18+
self.remote_mnt_path = join(self.ROOT_PROC_NS.format(pid), local_mnt_path)
19+
20+
def __enter__(self):
21+
mkdir_cmd = self.MKDIR_POD_CMD.format(self.remote_mnt_path)
22+
run_command(mkdir_cmd, self.verbose)
23+
cp_cmd=self.COPY_CMD.format(self.src_dir, self.remote_mnt_path)
24+
run_command(cp_cmd, self.verbose)
25+
return self
26+
27+
def get_mounted_jdk_dir(self):
28+
return join(self.local_mnt_path, basename(self.src_dir) )
29+
30+
def __exit__(self, exc_type, exc_val, exc_tb):
31+
rm_dir_cmd = self.RMDIR_POD_CMD.format(self.remote_mnt_path)
32+
run_command(rm_dir_cmd, self.verbose)

src/java_toolkit/configs.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
{
22
"JDK_PATH": "/app/openjdk",
3-
"MKDIR_POD_CMD": "mkdir {DST_MOUNT_PATH}",
4-
"RMDIR_POD_CMD": "rm -R {DST_MOUNT_PATH}",
5-
"DST_MOUNT_PATH": "/proc/{PID}/cwd/mnt/robusta",
63
"COPY_CMD": "cp -R {JDK_PATH} {DST_MOUNT_PATH}",
74
"JDK_NAME": "openjdk",
85
"JMAP_CMD": "{JDK_PATH}/bin/jmap -J-Xshareclasses:nonfatal -histo {LOCAL_PID}",

src/java_toolkit/configs.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
JDK_PATH= "/app/openjdk"
2-
MKDIR_POD_CMD= 'mkdir -p {}'
3-
RMDIR_POD_CMD= "rm -R {}"
4-
DST_MOUNT_PATH= "/proc/{}/cwd/mnt/robusta"
52
LOCAL_MOUNT_PATH= "/mnt/robusta"
6-
COPY_CMD= "cp -R {} {}"
73
JDK_NAME= "openjdk"
84
JMAP_CMD= "{}/bin/jmap -J-Xshareclasses:nonfatal -histo:live {}"
95
JSTACK_CMD= "{}/bin/jstack -J-Xshareclasses:nonfatal -l {}"
10-
NSENTER_CMD= "nsenter -t {} -p -m {}"

src/java_toolkit/main.py

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,32 @@
11
#!/usr/local/bin/python3
22
import subprocess
33
import typer
4-
from .utils.pod_ps import get_pod_processes
4+
from .utils.process import get_pod_processes, get_ns_processes
5+
from .utils.remote_ns_cmd import run_cmd_in_proc_namespace
6+
from .utils.tmp_mount import TmpRemotePodMounter
57
from .configs import *
68
from os.path import join
79

810
app = typer.Typer()
911

10-
11-
def run_command(cmd: str, verbose: bool):
12-
if verbose:
13-
typer.echo(f"running {cmd}")
14-
output = subprocess.Popen(
15-
cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT
16-
)
17-
return_code = output.wait()
18-
if return_code:
19-
raise subprocess.CalledProcessError(return_code, cmd)
20-
if verbose:
21-
pass
22-
#typer.echo(output.decode())
23-
24-
25-
class JDKMounter(object):
26-
mnt_path =""
27-
verbose = False
28-
29-
def __init__(self, pid: str, verbose: bool):
30-
self.verbose = verbose
31-
self.mnt_path = DST_MOUNT_PATH.format(pid)
32-
33-
def __enter__(self):
34-
mkdir_cmd = MKDIR_POD_CMD.format(self.mnt_path)
35-
run_command(mkdir_cmd, self.verbose)
36-
cp_cmd=COPY_CMD.format(JDK_PATH, self.mnt_path)
37-
run_command(cp_cmd, self.verbose)
38-
return self
39-
40-
def get_mounted_jdk_dir(self):
41-
return join(LOCAL_MOUNT_PATH, JDK_NAME )
42-
43-
def __exit__(self, exc_type, exc_val, exc_tb):
44-
rm_dir_cmd = RMDIR_POD_CMD.format(self.mnt_path)
45-
run_command(rm_dir_cmd, self.verbose)
46-
47-
def run_cmd_in_proc_namespace(pid, command_to_run, verbose):
48-
nsenter_cmd_formatted = NSENTER_CMD.format(pid, command_to_run)
49-
run_command(nsenter_cmd_formatted, verbose)
50-
5112
@app.command()
5213
def pod_ps(pod_uid: str):
53-
typer.echo(get_pod_processes(pod_uid).json())
14+
app.echo(get_pod_processes(pod_uid).json())
5415

5516
@app.command()
56-
def find_pid(pod_uid: str, cmdline: str, exe: str):
57-
for proc in get_pod_processes(pod_uid).processes:
58-
if cmdline in " ".join(proc.cmdline) and exe in proc.exe:
59-
typer.echo(proc.pid)
17+
def pod_ns_ps(pid: str, verbose: bool = True):
18+
app.echo(get_ns_processes(pid, verbose).json())
6019

6120
@app.command()
6221
def jmap(pid: int, verbose: bool = True):
63-
with JDKMounter(pid, verbose) as jdk_mounter:
22+
with TmpRemotePodMounter(pid, JDK_PATH, LOCAL_MOUNT_PATH, verbose) as jdk_mounter:
6423
jstack_cmd = JMAP_CMD.format(jdk_mounter.get_mounted_jdk_dir(), 1)
6524
run_cmd_in_proc_namespace(pid, jstack_cmd, verbose)
6625

6726

6827
@app.command()
6928
def jstack(pid: int, verbose: bool = True):
70-
with JDKMounter(pid, verbose) as jdk_mounter:
29+
with TmpRemotePodMounter(pid, JDK_PATH, LOCAL_MOUNT_PATH, verbose) as jdk_mounter:
7130
jstack_cmd = JSTACK_CMD.format(jdk_mounter.get_mounted_jdk_dir(), 1)
7231
run_cmd_in_proc_namespace(pid, jstack_cmd, verbose)
7332

0 commit comments

Comments
 (0)