add exec
This commit is contained in:
parent
76d55bdf01
commit
24256b767d
1 changed files with 152 additions and 58 deletions
210
pvc_inspector.py
210
pvc_inspector.py
|
|
@ -15,6 +15,7 @@ import time
|
||||||
import typer
|
import typer
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
import yaml
|
import yaml
|
||||||
|
import os
|
||||||
|
|
||||||
logging.basicConfig(level=logging.WARNING)
|
logging.basicConfig(level=logging.WARNING)
|
||||||
|
|
||||||
|
|
@ -458,6 +459,157 @@ sleep 3600
|
||||||
return inspector_job
|
return inspector_job
|
||||||
|
|
||||||
|
|
||||||
|
PROTECTED_NAMESPACES = {
|
||||||
|
"kube-system",
|
||||||
|
"kube-public",
|
||||||
|
"kube-node-lease",
|
||||||
|
"argo-events",
|
||||||
|
"argo-rollouts",
|
||||||
|
"argo-workflows",
|
||||||
|
"argocd",
|
||||||
|
"cert-manager",
|
||||||
|
"ingress-nginx",
|
||||||
|
"monitoring",
|
||||||
|
"prometheus",
|
||||||
|
"istio-system",
|
||||||
|
"linkerd",
|
||||||
|
}
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def exec_inspector(
|
||||||
|
namespace: Optional[str] = typer.Option(
|
||||||
|
None,
|
||||||
|
help="Kubernetes namespace. If not specified, will search for inspectors across all namespaces.",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Execute a shell in a running inspector pod. If multiple inspectors are found,
|
||||||
|
presents a fuzzy finder to select one.
|
||||||
|
"""
|
||||||
|
config.load_kube_config()
|
||||||
|
batch_api = client.BatchV1Api()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if namespace:
|
||||||
|
logging.debug(f"Listing jobs in namespace {namespace}")
|
||||||
|
jobs = batch_api.list_namespaced_job(
|
||||||
|
namespace=namespace, label_selector="app=pvc-inspector"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logging.debug("Listing jobs in all namespaces")
|
||||||
|
jobs = batch_api.list_job_for_all_namespaces(
|
||||||
|
label_selector="app=pvc-inspector"
|
||||||
|
)
|
||||||
|
|
||||||
|
running_inspectors = []
|
||||||
|
for job in jobs.items:
|
||||||
|
# Get the pod for this job
|
||||||
|
v1 = client.CoreV1Api()
|
||||||
|
pods = v1.list_namespaced_pod(
|
||||||
|
namespace=job.metadata.namespace,
|
||||||
|
label_selector=f"job-name={job.metadata.name}"
|
||||||
|
)
|
||||||
|
for pod in pods.items:
|
||||||
|
if pod.status.phase == "Running":
|
||||||
|
running_inspectors.append((pod.metadata.name, pod.metadata.namespace))
|
||||||
|
|
||||||
|
if not running_inspectors:
|
||||||
|
typer.echo("No running inspector pods found.")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
if len(running_inspectors) == 1:
|
||||||
|
pod_name, pod_namespace = running_inspectors[0]
|
||||||
|
else:
|
||||||
|
pod_name, pod_namespace = fuzzy_select(running_inspectors)
|
||||||
|
if not pod_name:
|
||||||
|
typer.echo("No inspector selected.")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
# Execute the shell
|
||||||
|
typer.echo(f"Connecting to inspector {pod_namespace}/{pod_name}...")
|
||||||
|
os.execvp("kubectl", ["kubectl", "exec", "-it", "-n", pod_namespace, pod_name, "--", "sh", "-l"])
|
||||||
|
|
||||||
|
except client.exceptions.ApiException as e:
|
||||||
|
logging.error(f"Failed to list jobs: {e}")
|
||||||
|
typer.echo(f"Failed to list jobs: {e}", err=True)
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def cleanup_inspectors(
|
||||||
|
namespace: Optional[str] = typer.Option(
|
||||||
|
None,
|
||||||
|
help="Kubernetes namespace. If not specified, will cleanup in all namespaces.",
|
||||||
|
),
|
||||||
|
yes: bool = typer.Option(
|
||||||
|
False,
|
||||||
|
"--yes", "-y",
|
||||||
|
help="Skip confirmation prompt.",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Delete all PVC inspector jobs in the specified namespace or all namespaces
|
||||||
|
"""
|
||||||
|
config.load_kube_config()
|
||||||
|
batch_api = client.BatchV1Api()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if namespace:
|
||||||
|
if namespace in PROTECTED_NAMESPACES:
|
||||||
|
typer.echo(f"Error: Cannot cleanup in protected namespace {namespace}")
|
||||||
|
raise typer.Exit(1)
|
||||||
|
logging.debug(f"Listing jobs in namespace {namespace}")
|
||||||
|
jobs = batch_api.list_namespaced_job(
|
||||||
|
namespace=namespace, label_selector="app=pvc-inspector"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logging.debug("Listing jobs in all namespaces")
|
||||||
|
jobs = batch_api.list_job_for_all_namespaces(
|
||||||
|
label_selector="app=pvc-inspector"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Filter out jobs in protected namespaces
|
||||||
|
jobs.items = [job for job in jobs.items if job.metadata.namespace not in PROTECTED_NAMESPACES]
|
||||||
|
|
||||||
|
if not jobs.items:
|
||||||
|
typer.echo("No PVC inspector jobs found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Show confirmation prompt
|
||||||
|
if not yes:
|
||||||
|
job_list = "\n".join(f" {job.metadata.namespace}/{job.metadata.name}" for job in jobs.items)
|
||||||
|
typer.echo(f"The following inspector jobs will be deleted:\n{job_list}")
|
||||||
|
if not typer.confirm("Are you sure you want to continue?"):
|
||||||
|
typer.echo("Operation cancelled.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Delete each job
|
||||||
|
for job in jobs.items:
|
||||||
|
try:
|
||||||
|
logging.debug(
|
||||||
|
f"Deleting job {job.metadata.namespace}/{job.metadata.name}"
|
||||||
|
)
|
||||||
|
batch_api.delete_namespaced_job(
|
||||||
|
name=job.metadata.name,
|
||||||
|
namespace=job.metadata.namespace,
|
||||||
|
body=client.V1DeleteOptions(propagation_policy="Background"),
|
||||||
|
)
|
||||||
|
typer.echo(f"Deleted job: {job.metadata.namespace}/{job.metadata.name}")
|
||||||
|
except client.exceptions.ApiException as e:
|
||||||
|
logging.error(
|
||||||
|
f"Failed to delete job {job.metadata.namespace}/{job.metadata.name}: {e}"
|
||||||
|
)
|
||||||
|
typer.echo(
|
||||||
|
f"Failed to delete job {job.metadata.namespace}/{job.metadata.name}: {e}",
|
||||||
|
err=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
except client.exceptions.ApiException as e:
|
||||||
|
logging.error(f"Failed to list jobs: {e}")
|
||||||
|
typer.echo(f"Failed to list jobs: {e}", err=True)
|
||||||
|
raise typer.Exit(1)
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def create_inspector(
|
def create_inspector(
|
||||||
namespace: Optional[str] = typer.Option(
|
namespace: Optional[str] = typer.Option(
|
||||||
|
|
@ -490,63 +642,5 @@ def create_inspector(
|
||||||
typer.echo(yaml.dump(clean_dict(inspector_job), sort_keys=False))
|
typer.echo(yaml.dump(clean_dict(inspector_job), sort_keys=False))
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
|
||||||
def cleanup_inspectors(
|
|
||||||
namespace: Optional[str] = typer.Option(
|
|
||||||
None,
|
|
||||||
help="Kubernetes namespace. If not specified, will cleanup in all namespaces.",
|
|
||||||
),
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Delete all PVC inspector jobs in the specified namespace or all namespaces
|
|
||||||
"""
|
|
||||||
config.load_kube_config()
|
|
||||||
batch_api = client.BatchV1Api()
|
|
||||||
|
|
||||||
try:
|
|
||||||
if namespace:
|
|
||||||
logging.debug(f"Listing jobs in namespace {namespace}")
|
|
||||||
jobs = batch_api.list_namespaced_job(
|
|
||||||
namespace=namespace, label_selector="app=pvc-inspector"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
logging.debug("Listing jobs in all namespaces")
|
|
||||||
jobs = batch_api.list_job_for_all_namespaces(
|
|
||||||
label_selector="app=pvc-inspector"
|
|
||||||
)
|
|
||||||
|
|
||||||
if not jobs.items:
|
|
||||||
typer.echo("No PVC inspector jobs found.")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Delete each job
|
|
||||||
for job in jobs.items:
|
|
||||||
try:
|
|
||||||
logging.debug(
|
|
||||||
f"Deleting job {job.metadata.namespace}/{job.metadata.name}"
|
|
||||||
)
|
|
||||||
batch_api.delete_namespaced_job(
|
|
||||||
name=job.metadata.name,
|
|
||||||
namespace=job.metadata.namespace,
|
|
||||||
body=client.V1DeleteOptions(propagation_policy="Background"),
|
|
||||||
)
|
|
||||||
typer.echo(f"Deleted job: {job.metadata.namespace}/{job.metadata.name}")
|
|
||||||
except client.exceptions.ApiException as e:
|
|
||||||
logging.error(
|
|
||||||
f"Failed to delete job {job.metadata.namespace}/{job.metadata.name}: {e}"
|
|
||||||
)
|
|
||||||
typer.echo(
|
|
||||||
f"Failed to delete job {job.metadata.namespace}/{job.metadata.name}: {e}",
|
|
||||||
err=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
except client.exceptions.ApiException as e:
|
|
||||||
logging.error(f"Failed to list jobs: {e}")
|
|
||||||
typer.echo(f"Failed to list jobs: {e}", err=True)
|
|
||||||
raise typer.Exit(1)
|
|
||||||
|
|
||||||
typer.echo("Cleanup complete.")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app()
|
app()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue