Skip to content

Commit 9e890ed

Browse files
authored
Merge pull request #612 from pinheadmz/debug-sc
Add --debug option to run scenarios for faster development
2 parents 7bc5ba7 + 5f46b8a commit 9e890ed

File tree

2 files changed

+75
-34
lines changed

2 files changed

+75
-34
lines changed

src/warnet/control.py

+49-34
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717

1818
from .constants import COMMANDER_CHART, LOGGING_NAMESPACE
1919
from .k8s import (
20+
delete_pod,
2021
get_default_namespace,
2122
get_mission,
2223
get_pods,
24+
pod_log,
2325
snapshot_bitcoin_datadir,
26+
wait_for_pod,
2427
)
2528
from .process import run_command, stream_command
2629

@@ -160,8 +163,14 @@ def get_active_network(namespace):
160163

161164
@click.command(context_settings={"ignore_unknown_options": True})
162165
@click.argument("scenario_file", type=click.Path(exists=True, file_okay=True, dir_okay=False))
166+
@click.option(
167+
"--debug",
168+
is_flag=True,
169+
default=False,
170+
help="Stream scenario output and delete container when stopped",
171+
)
163172
@click.argument("additional_args", nargs=-1, type=click.UNPROCESSED)
164-
def run(scenario_file: str, additional_args: tuple[str]):
173+
def run(scenario_file: str, debug: bool, additional_args: tuple[str]):
165174
"""
166175
Run a scenario from a file.
167176
Pass `-- --help` to get individual scenario help
@@ -229,52 +238,58 @@ def run(scenario_file: str, additional_args: tuple[str]):
229238
print(f"Failed to start scenario: {scenario_name}")
230239
print(f"Error: {e.stderr}")
231240

241+
if debug:
242+
print("Waiting for commander pod to start...")
243+
wait_for_pod(name)
244+
_logs(pod_name=name, follow=True)
245+
print("Deleting pod...")
246+
delete_pod(name)
247+
232248

233249
@click.command()
234250
@click.argument("pod_name", type=str, default="")
235251
@click.option("--follow", "-f", is_flag=True, default=False, help="Follow logs")
236252
def logs(pod_name: str, follow: bool):
253+
return _logs(pod_name, follow)
254+
255+
256+
def _logs(pod_name: str, follow: bool):
237257
"""Show the logs of a pod"""
238-
follow_flag = "--follow" if follow else ""
239258
namespace = get_default_namespace()
240259

241-
if pod_name:
260+
if pod_name == "":
242261
try:
243-
command = f"kubectl logs pod/{pod_name} -n {namespace} {follow_flag}"
244-
stream_command(command)
245-
return
262+
pods = get_pods()
263+
pod_list = [item.metadata.name for item in pods.items]
246264
except Exception as e:
247-
print(f"Could not find the pod {pod_name}: {e}")
265+
print(f"Could not fetch any pods in namespace {namespace}: {e}")
266+
return
248267

249-
try:
250-
pods = run_command(f"kubectl get pods -n {namespace} -o json")
251-
pods = json.loads(pods)
252-
pod_list = [item["metadata"]["name"] for item in pods["items"]]
253-
except Exception as e:
254-
print(f"Could not fetch any pods in namespace {namespace}: {e}")
255-
return
268+
if not pod_list:
269+
print(f"Could not fetch any pods in namespace {namespace}")
270+
return
256271

257-
if not pod_list:
258-
print(f"Could not fetch any pods in namespace {namespace}")
259-
return
272+
q = [
273+
inquirer.List(
274+
name="pod",
275+
message="Please choose a pod",
276+
choices=pod_list,
277+
)
278+
]
279+
selected = inquirer.prompt(q, theme=GreenPassion())
280+
if selected:
281+
pod_name = selected["pod"]
282+
else:
283+
return # cancelled by user
260284

261-
q = [
262-
inquirer.List(
263-
name="pod",
264-
message="Please choose a pod",
265-
choices=pod_list,
266-
)
267-
]
268-
selected = inquirer.prompt(q, theme=GreenPassion())
269-
if selected:
270-
pod_name = selected["pod"]
271-
try:
272-
command = f"kubectl logs pod/{pod_name} -n {namespace} {follow_flag}"
273-
stream_command(command)
274-
except Exception as e:
275-
print(f"Please consider waiting for the pod to become available. Encountered: {e}")
276-
else:
277-
pass # cancelled by user
285+
try:
286+
stream = pod_log(pod_name, container_name=None, follow=follow)
287+
for line in stream.stream():
288+
print(line.decode("utf-8"), end=None)
289+
except Exception as e:
290+
print(e)
291+
except KeyboardInterrupt:
292+
print("Interrupted streaming log!")
278293

279294

280295
@click.command()

src/warnet/k8s.py

+26
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import sys
44
import tempfile
55
from pathlib import Path
6+
from time import sleep
67

78
import yaml
89
from kubernetes import client, config, watch
910
from kubernetes.client.models import CoreV1Event, V1PodList
11+
from kubernetes.client.rest import ApiException
1012
from kubernetes.dynamic import DynamicClient
1113
from kubernetes.stream import stream
1214

@@ -282,3 +284,27 @@ def get_ingress_ip_or_host():
282284
except Exception as e:
283285
print(f"Error getting ingress IP: {e}")
284286
return None
287+
288+
289+
def pod_log(pod_name, container_name=None, follow=False):
290+
sclient = get_static_client()
291+
try:
292+
return sclient.read_namespaced_pod_log(
293+
name=pod_name,
294+
namespace=get_default_namespace(),
295+
container=container_name,
296+
follow=follow,
297+
_preload_content=False,
298+
)
299+
except ApiException as e:
300+
raise Exception(json.loads(e.body.decode("utf-8"))["message"]) from None
301+
302+
303+
def wait_for_pod(pod_name, timeout_seconds=10):
304+
sclient = get_static_client()
305+
while timeout_seconds > 0:
306+
pod = sclient.read_namespaced_pod_status(name=pod_name, namespace=get_default_namespace())
307+
if pod.status.phase != "Pending":
308+
return
309+
sleep(1)
310+
timeout_seconds -= 1

0 commit comments

Comments
 (0)