From 3d204e8d0c3fb1d6f5914bb87024b2f03285c0a2 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 7 Feb 2026 11:58:42 +0100 Subject: [PATCH 1/7] Add new helper function to check if load balancer is up --- src/warnet/k8s.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/warnet/k8s.py b/src/warnet/k8s.py index 528dfe34f..b8b948c28 100644 --- a/src/warnet/k8s.py +++ b/src/warnet/k8s.py @@ -4,7 +4,7 @@ import tarfile import tempfile from pathlib import Path -from time import sleep +from time import time, sleep from typing import Optional import yaml @@ -334,6 +334,24 @@ def wait_for_ingress_controller(timeout=300): return wait_for_pod_ready(pod.metadata.name, INGRESS_NAMESPACE, timeout) +def wait_for_ingress_endpoint(timeout=300): + config.load_kube_config() + networking_v1 = client.NetworkingV1Api() + start = time() + while time() - start < timeout: + ingress = networking_v1.read_namespaced_ingress(CADDY_INGRESS_NAME, LOGGING_NAMESPACE) + lb_ingress = ingress.status.load_balancer.ingress + if lb_ingress and (lb_ingress[0].hostname or lb_ingress[0].ip): + return True + sleep(1) + msg = ( + f"Ingress endpoint not found within {timeout} seconds.\n" + + "If you are running Minikube please run 'minikube tunnel' in a separate terminal.\n" + + "If you are running in the cloud, you may need to wait a short while while the load balancer is provisioned" + ) + raise TimeoutError(msg) + + def get_ingress_ip_or_host(): config.load_kube_config() networking_v1 = client.NetworkingV1Api() From 3491dff28ef7aa818ae27218d8dac1040cee5a00 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 7 Feb 2026 16:56:11 +0100 Subject: [PATCH 2/7] Use wait_for_ingress_endpoint in dashboard cmd --- src/warnet/dashboard.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/warnet/dashboard.py b/src/warnet/dashboard.py index 199eb8ff4..2e1f36c2a 100644 --- a/src/warnet/dashboard.py +++ b/src/warnet/dashboard.py @@ -1,6 +1,6 @@ import click -from .k8s import get_ingress_ip_or_host, wait_for_ingress_controller +from .k8s import get_ingress_ip_or_host, wait_for_ingress_endpoint @click.command() @@ -8,19 +8,11 @@ def dashboard(): """Open the Warnet dashboard in default browser""" import webbrowser - wait_for_ingress_controller() + timeout = 300 + click.echo(f"Waiting {timeout} seconds for ingress endpoint ...") + wait_for_ingress_endpoint(timeout=timeout) ip = get_ingress_ip_or_host() - if not ip: - click.echo("Error: Could not get the IP address of the dashboard") - click.echo( - "If you are running Minikube please run 'minikube tunnel' in a separate terminal" - ) - click.echo( - "If you are running in the cloud, you may need to wait a short while while the load balancer is provisioned" - ) - return - url = f"http://{ip}" webbrowser.open(url) From ad3e6b760184ddcc59765cd4fa4f8b0100cb26d1 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Tue, 10 Feb 2026 23:31:47 +0100 Subject: [PATCH 3/7] Catch ApiException, ask if network has been deployed on 404 --- src/warnet/k8s.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/warnet/k8s.py b/src/warnet/k8s.py index b8b948c28..2329e15a1 100644 --- a/src/warnet/k8s.py +++ b/src/warnet/k8s.py @@ -339,7 +339,16 @@ def wait_for_ingress_endpoint(timeout=300): networking_v1 = client.NetworkingV1Api() start = time() while time() - start < timeout: - ingress = networking_v1.read_namespaced_ingress(CADDY_INGRESS_NAME, LOGGING_NAMESPACE) + try: + ingress = networking_v1.read_namespaced_ingress(CADDY_INGRESS_NAME, LOGGING_NAMESPACE) + except ApiException as e: + msg = ( + f'Failed to read ingress with name "{CADDY_INGRESS_NAME}" from namespace "{LOGGING_NAMESPACE}"\n' + + str(e).rstrip() + ) + if e.status == 404: + msg += "\n\nDid you deploy a network?" + raise Exception(msg) from None lb_ingress = ingress.status.load_balancer.ingress if lb_ingress and (lb_ingress[0].hostname or lb_ingress[0].ip): return True From 47aeee25513da4ac70ebe09cbdb1f83f41217665 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Tue, 10 Feb 2026 23:39:39 +0100 Subject: [PATCH 4/7] Print error w/o trace --- src/warnet/dashboard.py | 6 +++++- src/warnet/k8s.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/warnet/dashboard.py b/src/warnet/dashboard.py index 2e1f36c2a..dca71efa8 100644 --- a/src/warnet/dashboard.py +++ b/src/warnet/dashboard.py @@ -10,7 +10,11 @@ def dashboard(): timeout = 300 click.echo(f"Waiting {timeout} seconds for ingress endpoint ...") - wait_for_ingress_endpoint(timeout=timeout) + try: + wait_for_ingress_endpoint(timeout=timeout) + except Exception as e: + print(e) + return ip = get_ingress_ip_or_host() url = f"http://{ip}" diff --git a/src/warnet/k8s.py b/src/warnet/k8s.py index 2329e15a1..cb5d82b3f 100644 --- a/src/warnet/k8s.py +++ b/src/warnet/k8s.py @@ -348,7 +348,7 @@ def wait_for_ingress_endpoint(timeout=300): ) if e.status == 404: msg += "\n\nDid you deploy a network?" - raise Exception(msg) from None + raise Exception(msg) from e lb_ingress = ingress.status.load_balancer.ingress if lb_ingress and (lb_ingress[0].hostname or lb_ingress[0].ip): return True From 52ed772747efabb679955a5e0def238680aae2f9 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Tue, 10 Feb 2026 23:50:58 +0100 Subject: [PATCH 5/7] Use click.echo instead of print --- src/warnet/dashboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/warnet/dashboard.py b/src/warnet/dashboard.py index dca71efa8..d5ddca8ca 100644 --- a/src/warnet/dashboard.py +++ b/src/warnet/dashboard.py @@ -13,7 +13,7 @@ def dashboard(): try: wait_for_ingress_endpoint(timeout=timeout) except Exception as e: - print(e) + click.echo(e) return ip = get_ingress_ip_or_host() From 792720563451e3ddc8965b01c7ab19ef347a6be7 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Wed, 11 Feb 2026 10:39:28 +0100 Subject: [PATCH 6/7] Use sys.exit(1) --- src/warnet/dashboard.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/warnet/dashboard.py b/src/warnet/dashboard.py index d5ddca8ca..6eb693911 100644 --- a/src/warnet/dashboard.py +++ b/src/warnet/dashboard.py @@ -1,3 +1,5 @@ +import sys + import click from .k8s import get_ingress_ip_or_host, wait_for_ingress_endpoint @@ -14,7 +16,7 @@ def dashboard(): wait_for_ingress_endpoint(timeout=timeout) except Exception as e: click.echo(e) - return + sys.exit(1) ip = get_ingress_ip_or_host() url = f"http://{ip}" From afe8321b953445b3682eb53075b28a1dcbeb5fe8 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Wed, 11 Feb 2026 18:28:39 +0100 Subject: [PATCH 7/7] Mention caddy must be enabled to read ingress Co-authored-by: Matthew Zipkin --- src/warnet/k8s.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/warnet/k8s.py b/src/warnet/k8s.py index cb5d82b3f..9ae3ec42a 100644 --- a/src/warnet/k8s.py +++ b/src/warnet/k8s.py @@ -347,7 +347,7 @@ def wait_for_ingress_endpoint(timeout=300): + str(e).rstrip() ) if e.status == 404: - msg += "\n\nDid you deploy a network?" + msg += "\n\nDid you deploy a network with caddy enabled?" raise Exception(msg) from e lb_ingress = ingress.status.load_balancer.ingress if lb_ingress and (lb_ingress[0].hostname or lb_ingress[0].ip):