Skip to content

Commit e9cfe31

Browse files
committed
Rollup kubectl commands to a common library
1 parent c3c2616 commit e9cfe31

File tree

8 files changed

+486
-167
lines changed

8 files changed

+486
-167
lines changed

src/kube_galaxy/cmd/status.py

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import subprocess
55
from pathlib import Path
66

7+
from kube_galaxy.pkg.utils.client import get_context, get_nodes
8+
from kube_galaxy.pkg.utils.errors import ClusterError
79
from kube_galaxy.pkg.utils.logging import info, print_dict, section
810

911

@@ -49,37 +51,23 @@ def status() -> None:
4951
if shutil.which("kubectl"):
5052
info("")
5153
try:
52-
result = subprocess.run(
53-
["kubectl", "get", "nodes"],
54-
capture_output=True,
55-
text=True,
56-
check=False,
57-
)
58-
if result.returncode == 0 and result.stdout:
59-
lines = result.stdout.strip().split("\n")
54+
nodes_output = get_nodes()
55+
if nodes_output:
56+
lines = nodes_output.strip().split("\n")
6057
info(f"Cluster Nodes: {len(lines) - 1}") # Subtract header
6158
for line in lines[1:]: # Skip header
6259
if line:
6360
info(f" {line}")
64-
except Exception:
61+
except (ClusterError, Exception):
6562
pass
6663

6764
# Show active cluster
6865
if shutil.which("kubectl"):
6966
info("")
7067
try:
71-
result = subprocess.run(
72-
["kubectl", "config", "current-context"],
73-
capture_output=True,
74-
text=True,
75-
check=False,
76-
)
77-
if result.returncode == 0:
78-
context = result.stdout.strip()
79-
info(f"Active Cluster: {context}")
80-
else:
81-
info("Active Cluster: none")
82-
except Exception:
68+
context = get_context()
69+
info(f"Active Cluster: {context}")
70+
except (ClusterError, Exception):
8371
info("Active Cluster: error checking")
8472

8573

src/kube_galaxy/cmd/test.py

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Test command handler."""
22

3-
import subprocess
43
from pathlib import Path
54

65
import typer
@@ -9,6 +8,8 @@
98
from kube_galaxy.pkg.manifest.loader import load_manifest
109
from kube_galaxy.pkg.manifest.validator import validate_manifest
1110
from kube_galaxy.pkg.testing.spread import collect_test_results, run_spread_tests
11+
from kube_galaxy.pkg.utils.client import get_context, verify_connectivity
12+
from kube_galaxy.pkg.utils.errors import ClusterError
1213
from kube_galaxy.pkg.utils.logging import error, exception, info, section, success, warning
1314

1415

@@ -22,25 +23,10 @@ def spread(manifest_path: str) -> None:
2223

2324
try:
2425
# Check if kubectl can connect
25-
result = subprocess.run(
26-
["kubectl", "cluster-info"],
27-
capture_output=True,
28-
text=True,
29-
check=False,
30-
)
31-
if result.returncode != 0:
32-
error("No Kubernetes cluster available. Please set up a cluster first.")
33-
info("You can create a test cluster with: kube-galaxy setup")
34-
raise typer.Exit(code=1)
26+
verify_connectivity()
3527

3628
# Get cluster context
37-
result = subprocess.run(
38-
["kubectl", "config", "current-context"],
39-
capture_output=True,
40-
text=True,
41-
check=True,
42-
)
43-
cluster_context = result.stdout.strip()
29+
cluster_context = get_context()
4430
success(f"Connected to cluster: {cluster_context}")
4531

4632
# Run spread tests from manifest
@@ -57,7 +43,7 @@ def spread(manifest_path: str) -> None:
5743

5844
success("Spread tests completed")
5945

60-
except Exception as e:
46+
except ClusterError as e:
6147
exception("Spread tests failed", e)
6248
raise typer.Exit(code=1) from e
6349

src/kube_galaxy/pkg/components/_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from kube_galaxy.pkg.arch.detector import ArchInfo
1919
from kube_galaxy.pkg.literals import Commands, Permissions, SystemPaths, Timeouts
2020
from kube_galaxy.pkg.manifest.models import ComponentConfig, InstallMethod, Manifest
21+
from kube_galaxy.pkg.utils.client import apply_manifest
2122
from kube_galaxy.pkg.utils.components import (
2223
download_file,
2324
extract_archive,
@@ -243,8 +244,7 @@ def bootstrap_hook(self) -> None:
243244
raise ComponentError(
244245
f"{comp_name} manifest not downloaded. Run download hook first."
245246
)
246-
run(["kubectl", "apply", "-f", str(self.manifest_path)], check=True)
247-
info(f"Applied manifest for {comp_name}")
247+
apply_manifest(self.manifest_path)
248248

249249
pass
250250

src/kube_galaxy/pkg/components/kubeadm.py

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
from kube_galaxy.pkg.components import ClusterComponentBase, register_component
1616
from kube_galaxy.pkg.literals import Commands, SystemPaths, URLs
17+
from kube_galaxy.pkg.utils.client import (
18+
get_api_server_status,
19+
verify_connectivity,
20+
wait_for_nodes,
21+
)
1722
from kube_galaxy.pkg.utils.errors import ComponentError
1823
from kube_galaxy.pkg.utils.logging import info
1924
from kube_galaxy.pkg.utils.shell import run
@@ -184,26 +189,9 @@ def verify_hook(self) -> None:
184189
185190
Checks cluster connectivity and waits for nodes/pods to be ready.
186191
"""
187-
188-
# Check cluster info
189-
run(["kubectl", "cluster-info"], check=True)
190-
191-
# Wait for nodes to be ready
192-
run(
193-
["kubectl", "wait", "--for=condition=Ready", "nodes", "--all", "--timeout=300s"],
194-
check=True,
195-
)
196-
197-
# Wait for api-server to be ready
198-
run(
199-
[
200-
"kubectl",
201-
"get",
202-
"--raw=/readyz",
203-
"--request-timeout=300s",
204-
],
205-
check=True,
206-
)
192+
verify_connectivity()
193+
wait_for_nodes(timeout=300)
194+
get_api_server_status(timeout=300)
207195

208196
def stop_hook(self) -> None:
209197
"""

src/kube_galaxy/pkg/testing/spread.py

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
task_path_for_component,
1919
validate_component_test_structure,
2020
)
21+
from kube_galaxy.pkg.utils.client import create_namespace, delete_namespace, verify_connectivity
2122
from kube_galaxy.pkg.utils.errors import ClusterError
2223
from kube_galaxy.pkg.utils.logging import error, info, section, success, warning
2324
from kube_galaxy.pkg.utils.shell import ShellError, run
@@ -111,9 +112,7 @@ def run_spread_tests(
111112
def _verify_test_prerequisites() -> None:
112113
"""Verify kubectl and spread are available."""
113114
try:
114-
info("Verifying cluster connectivity...")
115-
run(["kubectl", "cluster-info"], check=True, capture_output=True)
116-
success("Connected to Kubernetes cluster")
115+
verify_connectivity()
117116

118117
# Check for spread
119118
info("Verifying spread test framework...")
@@ -148,23 +147,15 @@ def _create_test_namespace(component_name: str) -> str:
148147
namespace = f"kube-galaxy-test-{component_name.lower().replace('_', '-')}"
149148

150149
try:
151-
info(f" Creating test namespace: {namespace}")
152-
153-
# Apply with labels
154-
run(["kubectl", "create", "namespace", namespace], check=True)
155-
156-
# Label namespace
157-
label = "app.kubernetes.io/managed-by=kube-galaxy"
158-
run(
159-
["kubectl", "label", "namespace", namespace, label, f"component={component_name}"],
160-
check=True,
161-
)
162-
163-
success(f"Namespace created: {namespace}")
150+
labels = {
151+
"app.kubernetes.io/managed-by": "kube-galaxy",
152+
"component": component_name,
153+
}
154+
create_namespace(namespace, labels)
164155
return namespace
165156

166-
except ShellError as exc:
167-
raise ClusterError(f"Failed to create namespace {namespace}: {exc}") from exc
157+
except ClusterError:
158+
raise
168159

169160

170161
def _cleanup_test_namespace(namespace: str, timeout: int = 60) -> None:
@@ -179,22 +170,9 @@ def _cleanup_test_namespace(namespace: str, timeout: int = 60) -> None:
179170
ClusterError: If namespace deletion fails
180171
"""
181172
try:
182-
info(f" Cleaning up namespace: {namespace}")
183-
184-
# Delete namespace
185-
run(
186-
["kubectl", "delete", "namespace", namespace, "--timeout", f"{timeout}s"],
187-
check=True,
188-
)
189-
190-
success(f"Namespace deleted: {namespace}")
191-
192-
except ShellError as exc:
193-
# Don't fail if namespace doesn't exist
194-
if "not found" in str(exc):
195-
warning(f" Namespace {namespace} not found (may already be deleted)")
196-
else:
197-
raise ClusterError(f"Failed to delete namespace {namespace}: {exc}") from exc
173+
delete_namespace(namespace, timeout)
174+
except ClusterError:
175+
raise
198176

199177

200178
def _generate_orchestration_spread_yaml(

0 commit comments

Comments
 (0)