k8s-helper-cli 0.3.0__py3-none-any.whl → 0.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- k8s_helper/__init__.py +1 -1
- k8s_helper/cli.py +503 -0
- k8s_helper/core.py +957 -0
- {k8s_helper_cli-0.3.0.dist-info → k8s_helper_cli-0.4.1.dist-info}/METADATA +106 -1
- k8s_helper_cli-0.4.1.dist-info/RECORD +11 -0
- k8s_helper_cli-0.3.0.dist-info/RECORD +0 -11
- {k8s_helper_cli-0.3.0.dist-info → k8s_helper_cli-0.4.1.dist-info}/WHEEL +0 -0
- {k8s_helper_cli-0.3.0.dist-info → k8s_helper_cli-0.4.1.dist-info}/entry_points.txt +0 -0
- {k8s_helper_cli-0.3.0.dist-info → k8s_helper_cli-0.4.1.dist-info}/licenses/LICENSE +0 -0
- {k8s_helper_cli-0.3.0.dist-info → k8s_helper_cli-0.4.1.dist-info}/top_level.txt +0 -0
k8s_helper/__init__.py
CHANGED
k8s_helper/cli.py
CHANGED
@@ -10,6 +10,7 @@ from rich.panel import Panel
|
|
10
10
|
from rich.text import Text
|
11
11
|
import time
|
12
12
|
import time
|
13
|
+
from kubernetes.client.rest import ApiException
|
13
14
|
|
14
15
|
from .core import K8sClient
|
15
16
|
from .config import get_config
|
@@ -1348,3 +1349,505 @@ def service_url(
|
|
1348
1349
|
console.print("\n👋 Stopped watching")
|
1349
1350
|
else:
|
1350
1351
|
show_service_url()
|
1352
|
+
|
1353
|
+
|
1354
|
+
# ======================
|
1355
|
+
# MONITORING COMMANDS
|
1356
|
+
# ======================
|
1357
|
+
@app.command()
|
1358
|
+
def setup_monitoring(
|
1359
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Namespace for monitoring stack"),
|
1360
|
+
grafana_service_type: str = typer.Option("NodePort", "--service-type", "-t", help="Grafana service type: NodePort, LoadBalancer, ClusterIP"),
|
1361
|
+
import_dashboard: bool = typer.Option(True, "--import-dashboard/--no-dashboard", help="Import default Kubernetes dashboard"),
|
1362
|
+
wait: bool = typer.Option(True, "--wait/--no-wait", help="Wait for deployments to be ready"),
|
1363
|
+
show_info: bool = typer.Option(True, "--show-info/--no-show-info", help="Show monitoring stack information after setup")
|
1364
|
+
):
|
1365
|
+
"""Deploy complete monitoring stack with Prometheus and Grafana"""
|
1366
|
+
|
1367
|
+
# Validate service type
|
1368
|
+
valid_service_types = ["NodePort", "LoadBalancer", "ClusterIP"]
|
1369
|
+
if grafana_service_type not in valid_service_types:
|
1370
|
+
console.print(f"❌ Invalid service type: {grafana_service_type}")
|
1371
|
+
console.print(f"💡 Valid options: {', '.join(valid_service_types)}")
|
1372
|
+
return
|
1373
|
+
|
1374
|
+
console.print(f"🚀 Setting up monitoring stack in namespace: {namespace}")
|
1375
|
+
console.print(f"🔧 Grafana service type: {grafana_service_type}")
|
1376
|
+
|
1377
|
+
if import_dashboard:
|
1378
|
+
console.print("📊 Will import default Kubernetes dashboard")
|
1379
|
+
|
1380
|
+
# Show what will be deployed
|
1381
|
+
console.print("\n📋 Components to deploy:")
|
1382
|
+
console.print(" • Prometheus server with cluster monitoring configuration")
|
1383
|
+
console.print(" • Grafana with admin credentials (admin/admin123)")
|
1384
|
+
console.print(" • ServiceAccount and RBAC for Prometheus")
|
1385
|
+
console.print(" • ConfigMaps for Prometheus configuration")
|
1386
|
+
if import_dashboard:
|
1387
|
+
console.print(" • Default Kubernetes metrics dashboard")
|
1388
|
+
|
1389
|
+
try:
|
1390
|
+
client = K8sClient()
|
1391
|
+
|
1392
|
+
with console.status("Deploying monitoring stack..."):
|
1393
|
+
result = client.setup_monitoring(
|
1394
|
+
namespace=namespace,
|
1395
|
+
grafana_service_type=grafana_service_type,
|
1396
|
+
import_dashboard=import_dashboard,
|
1397
|
+
wait_for_ready=wait
|
1398
|
+
)
|
1399
|
+
|
1400
|
+
if result['success']:
|
1401
|
+
console.print("✅ Monitoring stack deployed successfully!")
|
1402
|
+
|
1403
|
+
# Show deployment summary
|
1404
|
+
console.print(f"\n📋 Deployment Summary:")
|
1405
|
+
console.print(f"📍 Namespace: {result['namespace']}")
|
1406
|
+
|
1407
|
+
if result['prometheus']['deployed']:
|
1408
|
+
console.print("✅ Prometheus: Deployed")
|
1409
|
+
else:
|
1410
|
+
console.print("❌ Prometheus: Failed to deploy")
|
1411
|
+
|
1412
|
+
if result['grafana']['deployed']:
|
1413
|
+
console.print("✅ Grafana: Deployed")
|
1414
|
+
console.print(f"🔑 Admin credentials: {result['grafana']['admin_user']}/{result['grafana']['admin_password']}")
|
1415
|
+
else:
|
1416
|
+
console.print("❌ Grafana: Failed to deploy")
|
1417
|
+
|
1418
|
+
if show_info:
|
1419
|
+
# Get and display monitoring information
|
1420
|
+
with console.status("Retrieving monitoring stack information..."):
|
1421
|
+
time.sleep(2) # Give services time to be ready
|
1422
|
+
info = client.get_monitoring_info(namespace)
|
1423
|
+
|
1424
|
+
console.print(f"\n🔗 Monitoring Stack Information:")
|
1425
|
+
|
1426
|
+
# Prometheus info
|
1427
|
+
if info['prometheus']['running']:
|
1428
|
+
console.print(f"✅ Prometheus: Running")
|
1429
|
+
if info['prometheus']['url']:
|
1430
|
+
console.print(f"🔗 Prometheus URL: [blue]{info['prometheus']['url']}[/blue]")
|
1431
|
+
else:
|
1432
|
+
console.print(f"💡 Prometheus: Access via port-forward: kubectl port-forward -n {namespace} svc/prometheus-service 9090:9090")
|
1433
|
+
else:
|
1434
|
+
console.print(f"⏳ Prometheus: Starting up...")
|
1435
|
+
|
1436
|
+
# Grafana info
|
1437
|
+
if info['grafana']['running']:
|
1438
|
+
console.print(f"✅ Grafana: Running")
|
1439
|
+
if info['grafana']['url']:
|
1440
|
+
console.print(f"🔗 Grafana URL: [blue]{info['grafana']['url']}[/blue]")
|
1441
|
+
else:
|
1442
|
+
console.print(f"💡 Grafana: Access via port-forward: kubectl port-forward -n {namespace} svc/grafana-service 3000:3000")
|
1443
|
+
|
1444
|
+
if info['grafana']['credentials']:
|
1445
|
+
creds = info['grafana']['credentials']
|
1446
|
+
console.print(f"🔑 Login: [green]{creds['username']}[/green] / [green]{creds['password']}[/green]")
|
1447
|
+
else:
|
1448
|
+
console.print(f"⏳ Grafana: Starting up...")
|
1449
|
+
|
1450
|
+
# Show services
|
1451
|
+
console.print(f"\n📋 Services:")
|
1452
|
+
for service in info['services']:
|
1453
|
+
console.print(f" • {service['name']} ({service['type']}) - IP: {service['cluster_ip']}")
|
1454
|
+
for port in service['ports']:
|
1455
|
+
port_info = f" Port: {port['port']} → {port['target_port']}"
|
1456
|
+
if 'node_port' in port:
|
1457
|
+
port_info += f" (NodePort: {port['node_port']})"
|
1458
|
+
console.print(port_info)
|
1459
|
+
|
1460
|
+
# Show next steps
|
1461
|
+
console.print(f"\n🚀 Next Steps:")
|
1462
|
+
console.print(f" 1. Access Grafana with the provided URL and credentials")
|
1463
|
+
console.print(f" 2. Verify Prometheus data source is configured")
|
1464
|
+
console.print(f" 3. Explore the imported Kubernetes dashboard")
|
1465
|
+
console.print(f" 4. Create custom dashboards and alerts as needed")
|
1466
|
+
console.print(f"\n💡 Useful commands:")
|
1467
|
+
console.print(f" • Check status: k8s-helper monitoring-status -n {namespace}")
|
1468
|
+
console.print(f" • Port-forward Grafana: kubectl port-forward -n {namespace} svc/grafana-service 3000:3000")
|
1469
|
+
console.print(f" • Port-forward Prometheus: kubectl port-forward -n {namespace} svc/prometheus-service 9090:9090")
|
1470
|
+
|
1471
|
+
else:
|
1472
|
+
console.print(f"❌ Failed to deploy monitoring stack: {result.get('error', 'Unknown error')}")
|
1473
|
+
|
1474
|
+
# Show partial deployment info
|
1475
|
+
if result['prometheus']['deployed']:
|
1476
|
+
console.print("✅ Prometheus was deployed successfully")
|
1477
|
+
if result['grafana']['deployed']:
|
1478
|
+
console.print("✅ Grafana was deployed successfully")
|
1479
|
+
|
1480
|
+
console.print("\n🛠️ Troubleshooting:")
|
1481
|
+
console.print(" • Check cluster connectivity: kubectl get nodes")
|
1482
|
+
console.print(" • Verify namespace permissions")
|
1483
|
+
console.print(" • Check resource availability in the cluster")
|
1484
|
+
console.print(f" • View monitoring namespace: kubectl get all -n {namespace}")
|
1485
|
+
|
1486
|
+
except Exception as e:
|
1487
|
+
console.print(f"❌ Error setting up monitoring: {e}")
|
1488
|
+
console.print("\n🛠️ Troubleshooting:")
|
1489
|
+
console.print(" • Ensure kubectl is configured and cluster is accessible")
|
1490
|
+
console.print(" • Check if you have sufficient permissions to create resources")
|
1491
|
+
console.print(" • Verify the cluster has enough resources available")
|
1492
|
+
|
1493
|
+
|
1494
|
+
@app.command()
|
1495
|
+
def monitoring_status(
|
1496
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
1497
|
+
output: str = output_option
|
1498
|
+
):
|
1499
|
+
"""Show status of monitoring stack"""
|
1500
|
+
try:
|
1501
|
+
client = K8sClient()
|
1502
|
+
|
1503
|
+
with console.status("Checking monitoring stack status..."):
|
1504
|
+
info = client.get_monitoring_info(namespace)
|
1505
|
+
|
1506
|
+
if 'error' in info:
|
1507
|
+
console.print(f"❌ Error getting monitoring status: {info['error']}")
|
1508
|
+
return
|
1509
|
+
|
1510
|
+
if output == "table":
|
1511
|
+
# Overview table
|
1512
|
+
table = Table(title=f"Monitoring Stack Status - {namespace}")
|
1513
|
+
table.add_column("Component", style="cyan")
|
1514
|
+
table.add_column("Status", style="green")
|
1515
|
+
table.add_column("URL", style="blue")
|
1516
|
+
|
1517
|
+
# Prometheus row
|
1518
|
+
prometheus_status = "🟢 Running" if info['prometheus']['running'] else "🔴 Not Running"
|
1519
|
+
prometheus_url = info['prometheus']['url'] or "Port-forward required"
|
1520
|
+
table.add_row("Prometheus", prometheus_status, prometheus_url)
|
1521
|
+
|
1522
|
+
# Grafana row
|
1523
|
+
grafana_status = "🟢 Running" if info['grafana']['running'] else "🔴 Not Running"
|
1524
|
+
grafana_url = info['grafana']['url'] or "Port-forward required"
|
1525
|
+
table.add_row("Grafana", grafana_status, grafana_url)
|
1526
|
+
|
1527
|
+
console.print(table)
|
1528
|
+
|
1529
|
+
# Credentials info
|
1530
|
+
if info['grafana']['credentials']:
|
1531
|
+
creds = info['grafana']['credentials']
|
1532
|
+
console.print(f"\n🔑 Grafana Credentials:")
|
1533
|
+
console.print(f" Username: [green]{creds['username']}[/green]")
|
1534
|
+
console.print(f" Password: [green]{creds['password']}[/green]")
|
1535
|
+
|
1536
|
+
# Services table
|
1537
|
+
if info['services']:
|
1538
|
+
services_table = Table(title="Services")
|
1539
|
+
services_table.add_column("Name", style="cyan")
|
1540
|
+
services_table.add_column("Type", style="magenta")
|
1541
|
+
services_table.add_column("Cluster IP", style="yellow")
|
1542
|
+
services_table.add_column("Ports", style="green")
|
1543
|
+
|
1544
|
+
for service in info['services']:
|
1545
|
+
ports_str = ", ".join([
|
1546
|
+
f"{port['port']}:{port['target_port']}" +
|
1547
|
+
(f" (NodePort: {port['node_port']})" if 'node_port' in port else "")
|
1548
|
+
for port in service['ports']
|
1549
|
+
])
|
1550
|
+
services_table.add_row(
|
1551
|
+
service['name'],
|
1552
|
+
service['type'],
|
1553
|
+
service['cluster_ip'],
|
1554
|
+
ports_str
|
1555
|
+
)
|
1556
|
+
|
1557
|
+
console.print(services_table)
|
1558
|
+
|
1559
|
+
elif output == "json":
|
1560
|
+
console.print(format_json_output(info))
|
1561
|
+
elif output == "yaml":
|
1562
|
+
console.print(format_yaml_output(info))
|
1563
|
+
|
1564
|
+
except Exception as e:
|
1565
|
+
console.print(f"❌ Error checking monitoring status: {e}")
|
1566
|
+
|
1567
|
+
|
1568
|
+
@app.command()
|
1569
|
+
def delete_monitoring(
|
1570
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
1571
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation prompt")
|
1572
|
+
):
|
1573
|
+
"""Delete monitoring stack"""
|
1574
|
+
if not force:
|
1575
|
+
if not typer.confirm(f"Are you sure you want to delete the monitoring stack in namespace '{namespace}'?"):
|
1576
|
+
console.print("❌ Operation cancelled")
|
1577
|
+
return
|
1578
|
+
|
1579
|
+
try:
|
1580
|
+
client = K8sClient()
|
1581
|
+
|
1582
|
+
console.print(f"🗑️ Deleting monitoring stack from namespace: {namespace}")
|
1583
|
+
|
1584
|
+
# Delete deployments
|
1585
|
+
deployments_to_delete = ["prometheus", "grafana"]
|
1586
|
+
for deployment in deployments_to_delete:
|
1587
|
+
try:
|
1588
|
+
with console.status(f"Deleting deployment {deployment}..."):
|
1589
|
+
client.apps_v1.delete_namespaced_deployment(name=deployment, namespace=namespace)
|
1590
|
+
console.print(f"✅ Deleted deployment: {deployment}")
|
1591
|
+
except ApiException as e:
|
1592
|
+
if e.status == 404:
|
1593
|
+
console.print(f"⚠️ Deployment {deployment} not found")
|
1594
|
+
else:
|
1595
|
+
console.print(f"❌ Error deleting deployment {deployment}: {e}")
|
1596
|
+
|
1597
|
+
# Delete services
|
1598
|
+
services_to_delete = ["prometheus-service", "grafana-service"]
|
1599
|
+
for service in services_to_delete:
|
1600
|
+
try:
|
1601
|
+
with console.status(f"Deleting service {service}..."):
|
1602
|
+
client.core_v1.delete_namespaced_service(name=service, namespace=namespace)
|
1603
|
+
console.print(f"✅ Deleted service: {service}")
|
1604
|
+
except ApiException as e:
|
1605
|
+
if e.status == 404:
|
1606
|
+
console.print(f"⚠️ Service {service} not found")
|
1607
|
+
else:
|
1608
|
+
console.print(f"❌ Error deleting service {service}: {e}")
|
1609
|
+
|
1610
|
+
# Delete ConfigMaps
|
1611
|
+
configmaps_to_delete = ["prometheus-config"]
|
1612
|
+
for configmap in configmaps_to_delete:
|
1613
|
+
try:
|
1614
|
+
with console.status(f"Deleting configmap {configmap}..."):
|
1615
|
+
client.core_v1.delete_namespaced_config_map(name=configmap, namespace=namespace)
|
1616
|
+
console.print(f"✅ Deleted configmap: {configmap}")
|
1617
|
+
except ApiException as e:
|
1618
|
+
if e.status == 404:
|
1619
|
+
console.print(f"⚠️ ConfigMap {configmap} not found")
|
1620
|
+
else:
|
1621
|
+
console.print(f"❌ Error deleting configmap {configmap}: {e}")
|
1622
|
+
|
1623
|
+
# Delete ServiceAccount
|
1624
|
+
try:
|
1625
|
+
with console.status("Deleting ServiceAccount prometheus..."):
|
1626
|
+
client.core_v1.delete_namespaced_service_account(name="prometheus", namespace=namespace)
|
1627
|
+
console.print("✅ Deleted ServiceAccount: prometheus")
|
1628
|
+
except ApiException as e:
|
1629
|
+
if e.status == 404:
|
1630
|
+
console.print("⚠️ ServiceAccount prometheus not found")
|
1631
|
+
else:
|
1632
|
+
console.print(f"❌ Error deleting ServiceAccount: {e}")
|
1633
|
+
|
1634
|
+
# Delete RBAC resources
|
1635
|
+
try:
|
1636
|
+
from kubernetes import client as k8s_client
|
1637
|
+
rbac_v1 = k8s_client.RbacAuthorizationV1Api()
|
1638
|
+
with console.status("Deleting RBAC resources..."):
|
1639
|
+
rbac_v1.delete_cluster_role(name="prometheus")
|
1640
|
+
rbac_v1.delete_cluster_role_binding(name="prometheus")
|
1641
|
+
console.print("✅ Deleted RBAC resources")
|
1642
|
+
except ApiException as e:
|
1643
|
+
if e.status == 404:
|
1644
|
+
console.print("⚠️ RBAC resources not found")
|
1645
|
+
else:
|
1646
|
+
console.print(f"❌ Error deleting RBAC resources: {e}")
|
1647
|
+
|
1648
|
+
console.print(f"✅ Monitoring stack cleanup completed for namespace: {namespace}")
|
1649
|
+
console.print(f"💡 To delete the namespace entirely: kubectl delete namespace {namespace}")
|
1650
|
+
|
1651
|
+
except Exception as e:
|
1652
|
+
console.print(f"❌ Error deleting monitoring stack: {e}")
|
1653
|
+
console.print("💡 You may need to clean up resources manually with kubectl")
|
1654
|
+
|
1655
|
+
|
1656
|
+
@app.command()
|
1657
|
+
def add_prometheus_target(
|
1658
|
+
job_name: str = typer.Argument(..., help="Name for the Prometheus job"),
|
1659
|
+
targets: str = typer.Argument(..., help="Comma-separated list of targets (e.g., 'service:port,1.2.3.4:9090')"),
|
1660
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
1661
|
+
metrics_path: str = typer.Option("/metrics", "--metrics-path", "-p", help="Path to metrics endpoint"),
|
1662
|
+
scrape_interval: str = typer.Option("15s", "--scrape-interval", "-i", help="Scrape interval (e.g., 15s, 30s, 1m)")
|
1663
|
+
):
|
1664
|
+
"""Add a new target to Prometheus monitoring"""
|
1665
|
+
if not validate_name(job_name):
|
1666
|
+
console.print(f"❌ Invalid job name: {job_name}")
|
1667
|
+
return
|
1668
|
+
|
1669
|
+
# Parse targets
|
1670
|
+
target_list = [target.strip() for target in targets.split(",") if target.strip()]
|
1671
|
+
|
1672
|
+
if not target_list:
|
1673
|
+
console.print("❌ No valid targets provided")
|
1674
|
+
return
|
1675
|
+
|
1676
|
+
console.print(f"🎯 Adding Prometheus target job: {job_name}")
|
1677
|
+
console.print(f"📋 Targets: {target_list}")
|
1678
|
+
console.print(f"📍 Namespace: {namespace}")
|
1679
|
+
console.print(f"🛣️ Metrics path: {metrics_path}")
|
1680
|
+
console.print(f"⏱️ Scrape interval: {scrape_interval}")
|
1681
|
+
|
1682
|
+
try:
|
1683
|
+
client = K8sClient()
|
1684
|
+
|
1685
|
+
with console.status("Adding Prometheus target..."):
|
1686
|
+
success = client.add_prometheus_target(
|
1687
|
+
job_name=job_name,
|
1688
|
+
targets=target_list,
|
1689
|
+
namespace=namespace,
|
1690
|
+
metrics_path=metrics_path,
|
1691
|
+
scrape_interval=scrape_interval
|
1692
|
+
)
|
1693
|
+
|
1694
|
+
if success:
|
1695
|
+
console.print(f"✅ Successfully added Prometheus target job '{job_name}'")
|
1696
|
+
console.print(f"🔄 Prometheus configuration updated and deployment restarted")
|
1697
|
+
console.print(f"\n💡 Next steps:")
|
1698
|
+
console.print(f" • Check targets in Prometheus UI: Status > Targets")
|
1699
|
+
console.print(f" • Verify metrics are being scraped")
|
1700
|
+
console.print(f" • Create Grafana dashboards for the new metrics")
|
1701
|
+
else:
|
1702
|
+
console.print(f"❌ Failed to add Prometheus target")
|
1703
|
+
|
1704
|
+
except Exception as e:
|
1705
|
+
console.print(f"❌ Error adding Prometheus target: {e}")
|
1706
|
+
|
1707
|
+
|
1708
|
+
@app.command()
|
1709
|
+
def remove_prometheus_target(
|
1710
|
+
job_name: str = typer.Argument(..., help="Name of the Prometheus job to remove"),
|
1711
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
1712
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation prompt")
|
1713
|
+
):
|
1714
|
+
"""Remove a target from Prometheus monitoring"""
|
1715
|
+
if not force:
|
1716
|
+
if not typer.confirm(f"Are you sure you want to remove Prometheus job '{job_name}'?"):
|
1717
|
+
console.print("❌ Operation cancelled")
|
1718
|
+
return
|
1719
|
+
|
1720
|
+
console.print(f"🗑️ Removing Prometheus target job: {job_name}")
|
1721
|
+
console.print(f"📍 Namespace: {namespace}")
|
1722
|
+
|
1723
|
+
try:
|
1724
|
+
client = K8sClient()
|
1725
|
+
|
1726
|
+
with console.status("Removing Prometheus target..."):
|
1727
|
+
success = client.remove_prometheus_target(
|
1728
|
+
job_name=job_name,
|
1729
|
+
namespace=namespace
|
1730
|
+
)
|
1731
|
+
|
1732
|
+
if success:
|
1733
|
+
console.print(f"✅ Successfully removed Prometheus target job '{job_name}'")
|
1734
|
+
console.print(f"🔄 Prometheus configuration updated and deployment restarted")
|
1735
|
+
else:
|
1736
|
+
console.print(f"❌ Failed to remove Prometheus target")
|
1737
|
+
|
1738
|
+
except Exception as e:
|
1739
|
+
console.print(f"❌ Error removing Prometheus target: {e}")
|
1740
|
+
|
1741
|
+
|
1742
|
+
@app.command()
|
1743
|
+
def list_prometheus_targets(
|
1744
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
1745
|
+
output: str = output_option
|
1746
|
+
):
|
1747
|
+
"""List all Prometheus monitoring targets"""
|
1748
|
+
try:
|
1749
|
+
client = K8sClient()
|
1750
|
+
|
1751
|
+
with console.status("Fetching Prometheus targets..."):
|
1752
|
+
result = client.list_prometheus_targets(namespace)
|
1753
|
+
|
1754
|
+
if 'error' in result:
|
1755
|
+
console.print(f"❌ Error getting Prometheus targets: {result['error']}")
|
1756
|
+
return
|
1757
|
+
|
1758
|
+
targets = result.get('targets', [])
|
1759
|
+
|
1760
|
+
if not targets:
|
1761
|
+
console.print(f"📋 No Prometheus targets found in namespace: {namespace}")
|
1762
|
+
console.print(f"💡 Add targets with: k8s-helper add-prometheus-target <job-name> <targets>")
|
1763
|
+
return
|
1764
|
+
|
1765
|
+
if output == "table":
|
1766
|
+
table = Table(title=f"Prometheus Targets - {namespace}")
|
1767
|
+
table.add_column("Job Name", style="cyan")
|
1768
|
+
table.add_column("Type", style="magenta")
|
1769
|
+
table.add_column("Targets", style="green")
|
1770
|
+
table.add_column("Metrics Path", style="blue")
|
1771
|
+
table.add_column("Scrape Interval", style="yellow")
|
1772
|
+
|
1773
|
+
for target in targets:
|
1774
|
+
job_type = target.get('type', 'static')
|
1775
|
+
job_type_display = "🔄 Kubernetes" if job_type == 'kubernetes_discovery' else "📍 Static"
|
1776
|
+
|
1777
|
+
targets_display = ", ".join(target.get('targets', []))
|
1778
|
+
if len(targets_display) > 50:
|
1779
|
+
targets_display = targets_display[:47] + "..."
|
1780
|
+
|
1781
|
+
table.add_row(
|
1782
|
+
target.get('job_name', 'unknown'),
|
1783
|
+
job_type_display,
|
1784
|
+
targets_display,
|
1785
|
+
target.get('metrics_path', '/metrics'),
|
1786
|
+
target.get('scrape_interval', 'default')
|
1787
|
+
)
|
1788
|
+
|
1789
|
+
console.print(table)
|
1790
|
+
console.print(f"\n📊 Total jobs: {result.get('total_jobs', 0)}")
|
1791
|
+
|
1792
|
+
elif output == "json":
|
1793
|
+
console.print(format_json_output(result))
|
1794
|
+
elif output == "yaml":
|
1795
|
+
console.print(format_yaml_output(result))
|
1796
|
+
|
1797
|
+
except Exception as e:
|
1798
|
+
console.print(f"❌ Error listing Prometheus targets: {e}")
|
1799
|
+
|
1800
|
+
|
1801
|
+
@app.command()
|
1802
|
+
def update_prometheus_target(
|
1803
|
+
job_name: str = typer.Argument(..., help="Name of the Prometheus job to update"),
|
1804
|
+
targets: str = typer.Argument(..., help="New comma-separated list of targets"),
|
1805
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
1806
|
+
metrics_path: Optional[str] = typer.Option(None, "--metrics-path", "-p", help="New metrics path"),
|
1807
|
+
scrape_interval: Optional[str] = typer.Option(None, "--scrape-interval", "-i", help="New scrape interval")
|
1808
|
+
):
|
1809
|
+
"""Update an existing Prometheus target"""
|
1810
|
+
if not validate_name(job_name):
|
1811
|
+
console.print(f"❌ Invalid job name: {job_name}")
|
1812
|
+
return
|
1813
|
+
|
1814
|
+
# Parse targets
|
1815
|
+
target_list = [target.strip() for target in targets.split(",") if target.strip()]
|
1816
|
+
|
1817
|
+
if not target_list:
|
1818
|
+
console.print("❌ No valid targets provided")
|
1819
|
+
return
|
1820
|
+
|
1821
|
+
console.print(f"🔄 Updating Prometheus target job: {job_name}")
|
1822
|
+
console.print(f"📋 New targets: {target_list}")
|
1823
|
+
console.print(f"📍 Namespace: {namespace}")
|
1824
|
+
|
1825
|
+
if metrics_path:
|
1826
|
+
console.print(f"🛣️ New metrics path: {metrics_path}")
|
1827
|
+
if scrape_interval:
|
1828
|
+
console.print(f"⏱️ New scrape interval: {scrape_interval}")
|
1829
|
+
|
1830
|
+
try:
|
1831
|
+
client = K8sClient()
|
1832
|
+
|
1833
|
+
with console.status("Updating Prometheus target..."):
|
1834
|
+
success = client.update_prometheus_target(
|
1835
|
+
job_name=job_name,
|
1836
|
+
targets=target_list,
|
1837
|
+
namespace=namespace,
|
1838
|
+
metrics_path=metrics_path,
|
1839
|
+
scrape_interval=scrape_interval
|
1840
|
+
)
|
1841
|
+
|
1842
|
+
if success:
|
1843
|
+
console.print(f"✅ Successfully updated Prometheus target job '{job_name}'")
|
1844
|
+
console.print(f"🔄 Prometheus configuration updated and deployment restarted")
|
1845
|
+
else:
|
1846
|
+
console.print(f"❌ Failed to update Prometheus target")
|
1847
|
+
|
1848
|
+
except Exception as e:
|
1849
|
+
console.print(f"❌ Error updating Prometheus target: {e}")
|
1850
|
+
|
1851
|
+
|
1852
|
+
if __name__ == "__main__":
|
1853
|
+
app()
|