k8s-helper-cli 0.5.0__tar.gz → 0.5.2__tar.gz
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_cli-0.5.0/src/k8s_helper_cli.egg-info → k8s_helper_cli-0.5.2}/PKG-INFO +1 -1
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/pyproject.toml +1 -1
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper/__init__.py +1 -1
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper/cli.py +274 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper/core.py +665 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2/src/k8s_helper_cli.egg-info}/PKG-INFO +1 -1
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/LICENSE +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/README.md +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/setup.cfg +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper/config.py +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper/utils.py +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper_cli.egg-info/SOURCES.txt +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper_cli.egg-info/dependency_links.txt +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper_cli.egg-info/entry_points.txt +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper_cli.egg-info/requires.txt +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper_cli.egg-info/top_level.txt +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/tests/test_core.py +0 -0
- {k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/tests/test_integration.py +0 -0
@@ -1886,5 +1886,279 @@ def update_prometheus_target(
|
|
1886
1886
|
console.print(f"❌ Error updating Prometheus target: {e}")
|
1887
1887
|
|
1888
1888
|
|
1889
|
+
# ======================
|
1890
|
+
# HELM-BASED MONITORING COMMANDS
|
1891
|
+
# ======================
|
1892
|
+
@app.command()
|
1893
|
+
def setup_monitoring_stack(
|
1894
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Namespace for monitoring stack"),
|
1895
|
+
grafana_service_type: str = typer.Option("NodePort", "--service-type", "-t", help="Grafana service type: NodePort, LoadBalancer, ClusterIP"),
|
1896
|
+
prometheus_storage_size: str = typer.Option("10Gi", "--prometheus-storage", help="Prometheus storage size"),
|
1897
|
+
grafana_storage_size: str = typer.Option("5Gi", "--grafana-storage", help="Grafana storage size"),
|
1898
|
+
wait: bool = typer.Option(True, "--wait/--no-wait", help="Wait for deployments to be ready"),
|
1899
|
+
install_ingress: bool = typer.Option(False, "--install-ingress", help="Install ingress for external access")
|
1900
|
+
):
|
1901
|
+
"""Deploy monitoring stack using official Helm charts (auto-installs Helm if needed)"""
|
1902
|
+
|
1903
|
+
# Validate service type
|
1904
|
+
valid_service_types = ["NodePort", "LoadBalancer", "ClusterIP"]
|
1905
|
+
if grafana_service_type not in valid_service_types:
|
1906
|
+
console.print(f"❌ Invalid service type: {grafana_service_type}")
|
1907
|
+
console.print(f"💡 Valid options: {', '.join(valid_service_types)}")
|
1908
|
+
return
|
1909
|
+
|
1910
|
+
console.print(f"🚀 Setting up Helm-based monitoring stack in namespace: {namespace}")
|
1911
|
+
console.print(f"🔧 Grafana service type: {grafana_service_type}")
|
1912
|
+
console.print(f"💾 Prometheus storage: {prometheus_storage_size}")
|
1913
|
+
console.print(f"💾 Grafana storage: {grafana_storage_size}")
|
1914
|
+
console.print(f"⚙️ Note: Helm will be automatically installed if not present")
|
1915
|
+
|
1916
|
+
# Show what will be deployed
|
1917
|
+
console.print("\n📋 Components to deploy via Helm:")
|
1918
|
+
console.print(" • Prometheus Operator (kube-prometheus-stack)")
|
1919
|
+
console.print(" • Grafana with persistent storage")
|
1920
|
+
console.print(" • AlertManager for alerts")
|
1921
|
+
console.print(" • Node Exporter for node metrics")
|
1922
|
+
console.print(" • kube-state-metrics for cluster state")
|
1923
|
+
console.print(" • Prometheus rules and dashboards")
|
1924
|
+
if install_ingress:
|
1925
|
+
console.print(" • Ingress for external access")
|
1926
|
+
|
1927
|
+
try:
|
1928
|
+
client = K8sClient()
|
1929
|
+
|
1930
|
+
with console.status("Deploying Helm monitoring stack..."):
|
1931
|
+
result = client.setup_helm_monitoring(
|
1932
|
+
namespace=namespace,
|
1933
|
+
grafana_service_type=grafana_service_type,
|
1934
|
+
prometheus_storage_size=prometheus_storage_size,
|
1935
|
+
grafana_storage_size=grafana_storage_size,
|
1936
|
+
wait_for_ready=wait,
|
1937
|
+
install_ingress=install_ingress
|
1938
|
+
)
|
1939
|
+
|
1940
|
+
if result['success']:
|
1941
|
+
console.print("✅ Helm monitoring stack deployed successfully!")
|
1942
|
+
|
1943
|
+
# Show deployment summary
|
1944
|
+
console.print(f"\n📋 Deployment Summary:")
|
1945
|
+
console.print(f"📍 Namespace: {result['namespace']}")
|
1946
|
+
console.print(f"🎯 Helm Release: {result['release_name']}")
|
1947
|
+
|
1948
|
+
if result.get('prometheus', {}).get('deployed'):
|
1949
|
+
console.print("✅ Prometheus Operator: Deployed")
|
1950
|
+
else:
|
1951
|
+
console.print("❌ Prometheus Operator: Failed to deploy")
|
1952
|
+
|
1953
|
+
if result.get('grafana', {}).get('deployed'):
|
1954
|
+
console.print("✅ Grafana: Deployed")
|
1955
|
+
if result['grafana'].get('admin_password'):
|
1956
|
+
console.print(f"🔑 Grafana admin password: {result['grafana']['admin_password']}")
|
1957
|
+
else:
|
1958
|
+
console.print("🔑 Grafana admin password: admin")
|
1959
|
+
else:
|
1960
|
+
console.print("❌ Grafana: Failed to deploy")
|
1961
|
+
|
1962
|
+
# Show access information
|
1963
|
+
console.print(f"\n🔗 Access Information:")
|
1964
|
+
|
1965
|
+
if result.get('grafana_url'):
|
1966
|
+
console.print(f"🔗 Grafana URL: [blue]{result['grafana_url']}[/blue]")
|
1967
|
+
else:
|
1968
|
+
console.print(f"💡 Grafana: kubectl port-forward -n {namespace} svc/kube-prometheus-stack-grafana 3000:80")
|
1969
|
+
|
1970
|
+
if result.get('prometheus_url'):
|
1971
|
+
console.print(f"🔗 Prometheus URL: [blue]{result['prometheus_url']}[/blue]")
|
1972
|
+
else:
|
1973
|
+
console.print(f"💡 Prometheus: kubectl port-forward -n {namespace} svc/kube-prometheus-stack-prometheus 9090:9090")
|
1974
|
+
|
1975
|
+
if result.get('alertmanager_url'):
|
1976
|
+
console.print(f"🔗 AlertManager URL: [blue]{result['alertmanager_url']}[/blue]")
|
1977
|
+
else:
|
1978
|
+
console.print(f"💡 AlertManager: kubectl port-forward -n {namespace} svc/kube-prometheus-stack-alertmanager 9093:9093")
|
1979
|
+
|
1980
|
+
# Show next steps
|
1981
|
+
console.print(f"\n🚀 Next Steps:")
|
1982
|
+
console.print(f" 1. Access Grafana with admin/admin (or password shown above)")
|
1983
|
+
console.print(f" 2. Explore pre-configured dashboards")
|
1984
|
+
console.print(f" 3. Set up custom alerts in AlertManager")
|
1985
|
+
console.print(f" 4. Add custom Prometheus targets if needed")
|
1986
|
+
console.print(f"\n💡 Useful commands:")
|
1987
|
+
console.print(f" • Check status: k8s-helper monitoring-stack-status -n {namespace}")
|
1988
|
+
console.print(f" • List dashboards: kubectl get configmaps -n {namespace} | grep dashboard")
|
1989
|
+
console.print(f" • View Helm release: helm list -n {namespace}")
|
1990
|
+
|
1991
|
+
else:
|
1992
|
+
console.print(f"❌ Failed to deploy Helm monitoring stack: {result.get('error', 'Unknown error')}")
|
1993
|
+
|
1994
|
+
# Show suggestion if provided
|
1995
|
+
if result.get('suggestion'):
|
1996
|
+
console.print(f"💡 {result['suggestion']}")
|
1997
|
+
|
1998
|
+
console.print("\n🛠️ Troubleshooting:")
|
1999
|
+
if 'Helm' in str(result.get('error', '')):
|
2000
|
+
console.print(" • Helm installation failed - you may need to install manually")
|
2001
|
+
console.print(" • Visit: https://helm.sh/docs/intro/install/")
|
2002
|
+
console.print(" • Restart your terminal after installation")
|
2003
|
+
else:
|
2004
|
+
console.print(" • Check cluster connectivity: kubectl get nodes")
|
2005
|
+
console.print(" • Verify namespace permissions")
|
2006
|
+
console.print(f" • View Helm status: helm status -n {namespace} kube-prometheus-stack")
|
2007
|
+
|
2008
|
+
except Exception as e:
|
2009
|
+
console.print(f"❌ Error setting up Helm monitoring: {e}")
|
2010
|
+
console.print("\n🛠️ Troubleshooting:")
|
2011
|
+
console.print(" • Ensure Helm is installed and configured")
|
2012
|
+
console.print(" • Check if kubectl is configured correctly")
|
2013
|
+
console.print(" • Verify you have cluster admin permissions")
|
2014
|
+
|
2015
|
+
|
2016
|
+
@app.command()
|
2017
|
+
def monitoring_stack_status(
|
2018
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
2019
|
+
output: str = output_option
|
2020
|
+
):
|
2021
|
+
"""Show status of Helm-based monitoring stack"""
|
2022
|
+
try:
|
2023
|
+
client = K8sClient()
|
2024
|
+
|
2025
|
+
with console.status("Checking Helm monitoring stack status..."):
|
2026
|
+
info = client.get_helm_monitoring_info(namespace)
|
2027
|
+
|
2028
|
+
if 'error' in info:
|
2029
|
+
console.print(f"❌ Error getting monitoring status: {info['error']}")
|
2030
|
+
return
|
2031
|
+
|
2032
|
+
if output == "table":
|
2033
|
+
# Helm release info
|
2034
|
+
console.print(f"🎯 Helm Release: {info.get('release_name', 'kube-prometheus-stack')}")
|
2035
|
+
console.print(f"📊 Release Status: {info.get('release_status', 'Unknown')}")
|
2036
|
+
console.print(f"📅 Last Deployed: {info.get('last_deployed', 'Unknown')}")
|
2037
|
+
|
2038
|
+
# Overview table
|
2039
|
+
table = Table(title=f"Monitoring Stack Status - {namespace}")
|
2040
|
+
table.add_column("Component", style="cyan")
|
2041
|
+
table.add_column("Status", style="green")
|
2042
|
+
table.add_column("URL", style="blue")
|
2043
|
+
|
2044
|
+
# Components status
|
2045
|
+
components = ['prometheus', 'grafana', 'alertmanager']
|
2046
|
+
for component in components:
|
2047
|
+
if component in info:
|
2048
|
+
comp_info = info[component]
|
2049
|
+
status = "🟢 Running" if comp_info.get('running') else "🔴 Not Running"
|
2050
|
+
url = comp_info.get('url', 'Port-forward required')
|
2051
|
+
table.add_row(component.capitalize(), status, url)
|
2052
|
+
|
2053
|
+
console.print(table)
|
2054
|
+
|
2055
|
+
# Show pod status
|
2056
|
+
if info.get('pods'):
|
2057
|
+
pod_table = Table(title="Pod Status")
|
2058
|
+
pod_table.add_column("Pod", style="cyan")
|
2059
|
+
pod_table.add_column("Status", style="green")
|
2060
|
+
pod_table.add_column("Ready", style="blue")
|
2061
|
+
|
2062
|
+
for pod in info['pods']:
|
2063
|
+
pod_table.add_row(
|
2064
|
+
pod['name'],
|
2065
|
+
pod['status'],
|
2066
|
+
f"{pod['ready']}/{pod['total']}"
|
2067
|
+
)
|
2068
|
+
|
2069
|
+
console.print(pod_table)
|
2070
|
+
|
2071
|
+
elif output == "json":
|
2072
|
+
console.print(format_json_output(info))
|
2073
|
+
elif output == "yaml":
|
2074
|
+
console.print(format_yaml_output(info))
|
2075
|
+
|
2076
|
+
except Exception as e:
|
2077
|
+
console.print(f"❌ Error checking Helm monitoring status: {e}")
|
2078
|
+
|
2079
|
+
|
2080
|
+
@app.command()
|
2081
|
+
def delete_monitoring_stack(
|
2082
|
+
namespace: str = typer.Option("monitoring", "--namespace", "-n", help="Monitoring namespace"),
|
2083
|
+
release_name: str = typer.Option("kube-prometheus-stack", "--release-name", help="Helm release name"),
|
2084
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation prompt")
|
2085
|
+
):
|
2086
|
+
"""Delete Helm-based monitoring stack"""
|
2087
|
+
if not force:
|
2088
|
+
if not typer.confirm(f"Are you sure you want to delete the Helm monitoring stack '{release_name}' in namespace '{namespace}'?"):
|
2089
|
+
console.print("❌ Operation cancelled")
|
2090
|
+
return
|
2091
|
+
|
2092
|
+
try:
|
2093
|
+
client = K8sClient()
|
2094
|
+
|
2095
|
+
console.print(f"🗑️ Deleting Helm monitoring stack: {release_name}")
|
2096
|
+
|
2097
|
+
with console.status("Uninstalling Helm release..."):
|
2098
|
+
result = client.delete_helm_monitoring(namespace, release_name)
|
2099
|
+
|
2100
|
+
if result['success']:
|
2101
|
+
console.print(f"✅ Helm monitoring stack '{release_name}' deleted successfully")
|
2102
|
+
console.print(f"📋 Cleaned up {result.get('resources_deleted', 0)} resources")
|
2103
|
+
else:
|
2104
|
+
console.print(f"❌ Failed to delete Helm monitoring stack: {result.get('error', 'Unknown error')}")
|
2105
|
+
|
2106
|
+
except Exception as e:
|
2107
|
+
console.print(f"❌ Error deleting Helm monitoring: {e}")
|
2108
|
+
|
2109
|
+
|
2110
|
+
@app.command()
|
2111
|
+
def install_helm(
|
2112
|
+
force: bool = typer.Option(False, "--force", help="Force reinstall even if Helm is already installed")
|
2113
|
+
):
|
2114
|
+
"""Install Helm automatically on your system"""
|
2115
|
+
try:
|
2116
|
+
client = K8sClient()
|
2117
|
+
|
2118
|
+
# Check if Helm is already installed
|
2119
|
+
if not force and client._check_helm_available():
|
2120
|
+
console.print("✅ Helm is already installed on your system")
|
2121
|
+
|
2122
|
+
import subprocess
|
2123
|
+
try:
|
2124
|
+
result = subprocess.run(['helm', 'version'], capture_output=True, text=True)
|
2125
|
+
console.print(f"📋 Version: {result.stdout.strip()}")
|
2126
|
+
except:
|
2127
|
+
pass
|
2128
|
+
|
2129
|
+
console.print("💡 Use --force to reinstall")
|
2130
|
+
return
|
2131
|
+
|
2132
|
+
console.print("🔧 Installing Helm automatically...")
|
2133
|
+
|
2134
|
+
with console.status("Installing Helm..."):
|
2135
|
+
result = client._install_helm_automatically()
|
2136
|
+
|
2137
|
+
if result['success']:
|
2138
|
+
console.print(f"✅ {result['message']}")
|
2139
|
+
console.print(f"📦 Installation method: {result['method']}")
|
2140
|
+
|
2141
|
+
# Test the installation
|
2142
|
+
if client._check_helm_available():
|
2143
|
+
console.print("✅ Helm installation verified successfully")
|
2144
|
+
console.print("\n🚀 You can now use Helm-based monitoring commands:")
|
2145
|
+
console.print(" • k8s-helper setup-monitoring-stack")
|
2146
|
+
console.print(" • k8s-helper monitoring-stack-status")
|
2147
|
+
console.print(" • k8s-helper delete-monitoring-stack")
|
2148
|
+
else:
|
2149
|
+
console.print("⚠️ Helm was installed but may not be in your PATH")
|
2150
|
+
console.print("💡 You may need to restart your terminal")
|
2151
|
+
else:
|
2152
|
+
console.print(f"❌ Failed to install Helm: {result.get('error', 'Unknown error')}")
|
2153
|
+
console.print("\n🛠️ Manual installation:")
|
2154
|
+
console.print(" • Windows: choco install kubernetes-helm")
|
2155
|
+
console.print(" • macOS: brew install helm")
|
2156
|
+
console.print(" • Linux: curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash")
|
2157
|
+
console.print(" • Visit: https://helm.sh/docs/intro/install/")
|
2158
|
+
|
2159
|
+
except Exception as e:
|
2160
|
+
console.print(f"❌ Error installing Helm: {e}")
|
2161
|
+
|
2162
|
+
|
1889
2163
|
if __name__ == "__main__":
|
1890
2164
|
app()
|
@@ -1694,6 +1694,261 @@ class K8sClient:
|
|
1694
1694
|
except (subprocess.TimeoutExpired, FileNotFoundError):
|
1695
1695
|
return False
|
1696
1696
|
|
1697
|
+
def _install_helm_automatically(self) -> Dict[str, Any]:
|
1698
|
+
"""Automatically install Helm based on the operating system"""
|
1699
|
+
import subprocess
|
1700
|
+
import platform
|
1701
|
+
import os
|
1702
|
+
import tempfile
|
1703
|
+
import urllib.request
|
1704
|
+
|
1705
|
+
result = {
|
1706
|
+
'success': False,
|
1707
|
+
'method': None,
|
1708
|
+
'error': None,
|
1709
|
+
'message': None
|
1710
|
+
}
|
1711
|
+
|
1712
|
+
system = platform.system().lower()
|
1713
|
+
print(f"🔧 Attempting to install Helm on {system}...")
|
1714
|
+
|
1715
|
+
try:
|
1716
|
+
if system == 'windows':
|
1717
|
+
# Try to install via Chocolatey first, then Scoop, then direct download
|
1718
|
+
methods = [
|
1719
|
+
{
|
1720
|
+
'name': 'Chocolatey',
|
1721
|
+
'check_cmd': ['choco', '--version'],
|
1722
|
+
'install_cmd': ['choco', 'install', 'kubernetes-helm', '-y']
|
1723
|
+
},
|
1724
|
+
{
|
1725
|
+
'name': 'Scoop',
|
1726
|
+
'check_cmd': ['scoop', '--version'],
|
1727
|
+
'install_cmd': ['scoop', 'install', 'helm']
|
1728
|
+
}
|
1729
|
+
]
|
1730
|
+
|
1731
|
+
for method in methods:
|
1732
|
+
try:
|
1733
|
+
# Check if package manager is available
|
1734
|
+
subprocess.run(method['check_cmd'], capture_output=True, check=True, timeout=10)
|
1735
|
+
print(f"📦 Installing Helm via {method['name']}...")
|
1736
|
+
|
1737
|
+
# Install Helm
|
1738
|
+
install_result = subprocess.run(
|
1739
|
+
method['install_cmd'],
|
1740
|
+
capture_output=True,
|
1741
|
+
text=True,
|
1742
|
+
timeout=300 # 5 minutes timeout
|
1743
|
+
)
|
1744
|
+
|
1745
|
+
if install_result.returncode == 0:
|
1746
|
+
result['success'] = True
|
1747
|
+
result['method'] = method['name']
|
1748
|
+
result['message'] = f"Helm installed successfully via {method['name']}"
|
1749
|
+
print(f"✅ {result['message']}")
|
1750
|
+
return result
|
1751
|
+
else:
|
1752
|
+
print(f"⚠️ {method['name']} installation failed: {install_result.stderr}")
|
1753
|
+
|
1754
|
+
except (subprocess.TimeoutExpired, subprocess.CalledProcessError, FileNotFoundError):
|
1755
|
+
print(f"⚠️ {method['name']} not available")
|
1756
|
+
continue
|
1757
|
+
|
1758
|
+
# If package managers fail, try direct download
|
1759
|
+
print("📦 Attempting direct download installation...")
|
1760
|
+
result = self._install_helm_direct_download()
|
1761
|
+
|
1762
|
+
elif system == 'linux':
|
1763
|
+
# Try different Linux package managers and methods
|
1764
|
+
methods = [
|
1765
|
+
{
|
1766
|
+
'name': 'Snap',
|
1767
|
+
'check_cmd': ['snap', '--version'],
|
1768
|
+
'install_cmd': ['sudo', 'snap', 'install', 'helm', '--classic']
|
1769
|
+
},
|
1770
|
+
{
|
1771
|
+
'name': 'Script',
|
1772
|
+
'script_url': 'https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3'
|
1773
|
+
}
|
1774
|
+
]
|
1775
|
+
|
1776
|
+
# Try snap first
|
1777
|
+
try:
|
1778
|
+
subprocess.run(['snap', '--version'], capture_output=True, check=True, timeout=10)
|
1779
|
+
print("📦 Installing Helm via Snap...")
|
1780
|
+
|
1781
|
+
install_result = subprocess.run(
|
1782
|
+
['sudo', 'snap', 'install', 'helm', '--classic'],
|
1783
|
+
capture_output=True,
|
1784
|
+
text=True,
|
1785
|
+
timeout=300
|
1786
|
+
)
|
1787
|
+
|
1788
|
+
if install_result.returncode == 0:
|
1789
|
+
result['success'] = True
|
1790
|
+
result['method'] = 'Snap'
|
1791
|
+
result['message'] = "Helm installed successfully via Snap"
|
1792
|
+
print(f"✅ {result['message']}")
|
1793
|
+
return result
|
1794
|
+
|
1795
|
+
except (subprocess.TimeoutExpired, subprocess.CalledProcessError, FileNotFoundError):
|
1796
|
+
print("⚠️ Snap not available")
|
1797
|
+
|
1798
|
+
# Try installation script
|
1799
|
+
print("📦 Installing Helm via official installation script...")
|
1800
|
+
try:
|
1801
|
+
script_result = subprocess.run([
|
1802
|
+
'bash', '-c',
|
1803
|
+
'curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash'
|
1804
|
+
], capture_output=True, text=True, timeout=300)
|
1805
|
+
|
1806
|
+
if script_result.returncode == 0:
|
1807
|
+
result['success'] = True
|
1808
|
+
result['method'] = 'Installation Script'
|
1809
|
+
result['message'] = "Helm installed successfully via installation script"
|
1810
|
+
print(f"✅ {result['message']}")
|
1811
|
+
return result
|
1812
|
+
else:
|
1813
|
+
print(f"⚠️ Script installation failed: {script_result.stderr}")
|
1814
|
+
|
1815
|
+
except (subprocess.TimeoutExpired, subprocess.CalledProcessError):
|
1816
|
+
print("⚠️ Script installation failed")
|
1817
|
+
|
1818
|
+
elif system == 'darwin': # macOS
|
1819
|
+
# Try Homebrew
|
1820
|
+
try:
|
1821
|
+
subprocess.run(['brew', '--version'], capture_output=True, check=True, timeout=10)
|
1822
|
+
print("📦 Installing Helm via Homebrew...")
|
1823
|
+
|
1824
|
+
install_result = subprocess.run(
|
1825
|
+
['brew', 'install', 'helm'],
|
1826
|
+
capture_output=True,
|
1827
|
+
text=True,
|
1828
|
+
timeout=300
|
1829
|
+
)
|
1830
|
+
|
1831
|
+
if install_result.returncode == 0:
|
1832
|
+
result['success'] = True
|
1833
|
+
result['method'] = 'Homebrew'
|
1834
|
+
result['message'] = "Helm installed successfully via Homebrew"
|
1835
|
+
print(f"✅ {result['message']}")
|
1836
|
+
return result
|
1837
|
+
|
1838
|
+
except (subprocess.TimeoutExpired, subprocess.CalledProcessError, FileNotFoundError):
|
1839
|
+
print("⚠️ Homebrew not available, trying installation script...")
|
1840
|
+
|
1841
|
+
# Fallback to installation script
|
1842
|
+
try:
|
1843
|
+
script_result = subprocess.run([
|
1844
|
+
'bash', '-c',
|
1845
|
+
'curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash'
|
1846
|
+
], capture_output=True, text=True, timeout=300)
|
1847
|
+
|
1848
|
+
if script_result.returncode == 0:
|
1849
|
+
result['success'] = True
|
1850
|
+
result['method'] = 'Installation Script'
|
1851
|
+
result['message'] = "Helm installed successfully via installation script"
|
1852
|
+
print(f"✅ {result['message']}")
|
1853
|
+
return result
|
1854
|
+
|
1855
|
+
except (subprocess.TimeoutExpired, subprocess.CalledProcessError):
|
1856
|
+
print("⚠️ Script installation failed")
|
1857
|
+
|
1858
|
+
# If we reach here, all methods failed
|
1859
|
+
result['error'] = f"Could not install Helm automatically on {system}"
|
1860
|
+
print(f"❌ {result['error']}")
|
1861
|
+
|
1862
|
+
except Exception as e:
|
1863
|
+
result['error'] = f"Error during Helm installation: {str(e)}"
|
1864
|
+
print(f"❌ {result['error']}")
|
1865
|
+
|
1866
|
+
return result
|
1867
|
+
|
1868
|
+
def _install_helm_direct_download(self) -> Dict[str, Any]:
|
1869
|
+
"""Install Helm via direct download (Windows fallback)"""
|
1870
|
+
import subprocess
|
1871
|
+
import tempfile
|
1872
|
+
import zipfile
|
1873
|
+
import urllib.request
|
1874
|
+
import os
|
1875
|
+
import platform
|
1876
|
+
|
1877
|
+
result = {
|
1878
|
+
'success': False,
|
1879
|
+
'method': 'Direct Download',
|
1880
|
+
'error': None,
|
1881
|
+
'message': None
|
1882
|
+
}
|
1883
|
+
|
1884
|
+
try:
|
1885
|
+
# Determine architecture
|
1886
|
+
arch = platform.machine().lower()
|
1887
|
+
if arch == 'amd64' or arch == 'x86_64':
|
1888
|
+
arch = 'amd64'
|
1889
|
+
elif arch == 'arm64':
|
1890
|
+
arch = 'arm64'
|
1891
|
+
else:
|
1892
|
+
arch = 'amd64' # Default fallback
|
1893
|
+
|
1894
|
+
# Download URL for latest Helm
|
1895
|
+
download_url = f"https://get.helm.sh/helm-v3.13.0-windows-{arch}.zip"
|
1896
|
+
|
1897
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
1898
|
+
zip_path = os.path.join(temp_dir, "helm.zip")
|
1899
|
+
|
1900
|
+
print(f"📥 Downloading Helm from {download_url}...")
|
1901
|
+
urllib.request.urlretrieve(download_url, zip_path)
|
1902
|
+
|
1903
|
+
print("📦 Extracting Helm...")
|
1904
|
+
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
1905
|
+
zip_ref.extractall(temp_dir)
|
1906
|
+
|
1907
|
+
# Find helm.exe
|
1908
|
+
helm_exe = None
|
1909
|
+
for root, dirs, files in os.walk(temp_dir):
|
1910
|
+
if 'helm.exe' in files:
|
1911
|
+
helm_exe = os.path.join(root, 'helm.exe')
|
1912
|
+
break
|
1913
|
+
|
1914
|
+
if helm_exe:
|
1915
|
+
# Try to move to a directory in PATH
|
1916
|
+
target_locations = [
|
1917
|
+
os.path.expanduser("~/bin"),
|
1918
|
+
"C:\\Program Files\\Helm",
|
1919
|
+
os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Microsoft', 'WindowsApps')
|
1920
|
+
]
|
1921
|
+
|
1922
|
+
for target_dir in target_locations:
|
1923
|
+
try:
|
1924
|
+
os.makedirs(target_dir, exist_ok=True)
|
1925
|
+
target_path = os.path.join(target_dir, 'helm.exe')
|
1926
|
+
|
1927
|
+
import shutil
|
1928
|
+
shutil.copy2(helm_exe, target_path)
|
1929
|
+
|
1930
|
+
# Test if it works
|
1931
|
+
test_result = subprocess.run([target_path, 'version'],
|
1932
|
+
capture_output=True, timeout=10)
|
1933
|
+
if test_result.returncode == 0:
|
1934
|
+
result['success'] = True
|
1935
|
+
result['message'] = f"Helm installed to {target_path}"
|
1936
|
+
print(f"✅ {result['message']}")
|
1937
|
+
print(f"💡 Please add {target_dir} to your PATH if not already present")
|
1938
|
+
return result
|
1939
|
+
|
1940
|
+
except (OSError, subprocess.TimeoutExpired):
|
1941
|
+
continue
|
1942
|
+
|
1943
|
+
result['error'] = "Downloaded Helm but could not install to PATH"
|
1944
|
+
else:
|
1945
|
+
result['error'] = "Could not find helm.exe in downloaded archive"
|
1946
|
+
|
1947
|
+
except Exception as e:
|
1948
|
+
result['error'] = f"Direct download failed: {str(e)}"
|
1949
|
+
|
1950
|
+
return result
|
1951
|
+
|
1697
1952
|
def _install_kube_state_metrics(self, namespace: str) -> Dict[str, Any]:
|
1698
1953
|
"""Install kube-state-metrics using Helm if available, or manual YAML if not"""
|
1699
1954
|
import subprocess
|
@@ -3083,3 +3338,413 @@ scrape_configs:
|
|
3083
3338
|
except Exception as e:
|
3084
3339
|
print(f"⚠️ Could not restart Prometheus deployment: {e}")
|
3085
3340
|
return False
|
3341
|
+
|
3342
|
+
# ======================
|
3343
|
+
# HELM-BASED MONITORING METHODS
|
3344
|
+
# ======================
|
3345
|
+
|
3346
|
+
def setup_helm_monitoring(self, namespace: str = "monitoring",
|
3347
|
+
grafana_service_type: str = "NodePort",
|
3348
|
+
prometheus_storage_size: str = "10Gi",
|
3349
|
+
grafana_storage_size: str = "5Gi",
|
3350
|
+
wait_for_ready: bool = True,
|
3351
|
+
install_ingress: bool = False) -> Dict:
|
3352
|
+
"""Deploy monitoring stack using official Helm charts"""
|
3353
|
+
import subprocess
|
3354
|
+
import tempfile
|
3355
|
+
import os
|
3356
|
+
|
3357
|
+
try:
|
3358
|
+
# Check if Helm is available, and install if not
|
3359
|
+
if not self._check_helm_available():
|
3360
|
+
print("🔧 Helm not found. Attempting automatic installation...")
|
3361
|
+
install_result = self._install_helm_automatically()
|
3362
|
+
|
3363
|
+
if not install_result['success']:
|
3364
|
+
return {
|
3365
|
+
'success': False,
|
3366
|
+
'error': f"Helm is required but could not be installed automatically. {install_result.get('error', '')}",
|
3367
|
+
'suggestion': 'Please install Helm manually: https://helm.sh/docs/intro/install/'
|
3368
|
+
}
|
3369
|
+
else:
|
3370
|
+
print(f"✅ {install_result['message']}")
|
3371
|
+
|
3372
|
+
# Verify installation worked
|
3373
|
+
if not self._check_helm_available():
|
3374
|
+
return {
|
3375
|
+
'success': False,
|
3376
|
+
'error': 'Helm was installed but is not accessible. You may need to restart your terminal or add Helm to your PATH.',
|
3377
|
+
'suggestion': 'Please restart your terminal and try again, or install Helm manually.'
|
3378
|
+
}
|
3379
|
+
|
3380
|
+
print("✅ Helm is available")
|
3381
|
+
|
3382
|
+
# Create namespace if it doesn't exist
|
3383
|
+
try:
|
3384
|
+
self.core_v1.create_namespace(
|
3385
|
+
body=client.V1Namespace(metadata=client.V1ObjectMeta(name=namespace))
|
3386
|
+
)
|
3387
|
+
print(f"✅ Created namespace: {namespace}")
|
3388
|
+
except ApiException as e:
|
3389
|
+
if e.status == 409: # Already exists
|
3390
|
+
print(f"✅ Namespace {namespace} already exists")
|
3391
|
+
else:
|
3392
|
+
print(f"⚠️ Could not create namespace: {e}")
|
3393
|
+
|
3394
|
+
# Add Prometheus community Helm repository
|
3395
|
+
print("📦 Adding Prometheus community Helm repository...")
|
3396
|
+
try:
|
3397
|
+
subprocess.run([
|
3398
|
+
'helm', 'repo', 'add', 'prometheus-community',
|
3399
|
+
'https://prometheus-community.github.io/helm-charts'
|
3400
|
+
], check=True, capture_output=True)
|
3401
|
+
|
3402
|
+
subprocess.run(['helm', 'repo', 'update'], check=True, capture_output=True)
|
3403
|
+
print("✅ Helm repository added and updated")
|
3404
|
+
except subprocess.CalledProcessError as e:
|
3405
|
+
return {
|
3406
|
+
'success': False,
|
3407
|
+
'error': f'Failed to add Helm repository: {e.stderr.decode() if e.stderr else str(e)}'
|
3408
|
+
}
|
3409
|
+
|
3410
|
+
# Create Helm values file
|
3411
|
+
helm_values = {
|
3412
|
+
'grafana': {
|
3413
|
+
'enabled': True,
|
3414
|
+
'persistence': {
|
3415
|
+
'enabled': True,
|
3416
|
+
'size': grafana_storage_size
|
3417
|
+
},
|
3418
|
+
'service': {
|
3419
|
+
'type': grafana_service_type
|
3420
|
+
},
|
3421
|
+
'adminPassword': 'admin',
|
3422
|
+
'datasources': {
|
3423
|
+
'datasources.yaml': {
|
3424
|
+
'apiVersion': 1,
|
3425
|
+
'datasources': [{
|
3426
|
+
'name': 'Prometheus',
|
3427
|
+
'type': 'prometheus',
|
3428
|
+
'url': 'http://kube-prometheus-stack-prometheus:9090',
|
3429
|
+
'access': 'proxy',
|
3430
|
+
'isDefault': True
|
3431
|
+
}]
|
3432
|
+
}
|
3433
|
+
},
|
3434
|
+
'dashboardProviders': {
|
3435
|
+
'dashboardproviders.yaml': {
|
3436
|
+
'apiVersion': 1,
|
3437
|
+
'providers': [{
|
3438
|
+
'name': 'default',
|
3439
|
+
'orgId': 1,
|
3440
|
+
'folder': '',
|
3441
|
+
'type': 'file',
|
3442
|
+
'disableDeletion': False,
|
3443
|
+
'editable': True,
|
3444
|
+
'options': {
|
3445
|
+
'path': '/var/lib/grafana/dashboards/default'
|
3446
|
+
}
|
3447
|
+
}]
|
3448
|
+
}
|
3449
|
+
},
|
3450
|
+
'dashboards': {
|
3451
|
+
'default': {
|
3452
|
+
'kubernetes-cluster-dashboard': {
|
3453
|
+
'gnetId': 7249,
|
3454
|
+
'revision': 1,
|
3455
|
+
'datasource': 'Prometheus'
|
3456
|
+
},
|
3457
|
+
'kubernetes-pod-dashboard': {
|
3458
|
+
'gnetId': 6417,
|
3459
|
+
'revision': 1,
|
3460
|
+
'datasource': 'Prometheus'
|
3461
|
+
},
|
3462
|
+
'node-exporter-dashboard': {
|
3463
|
+
'gnetId': 1860,
|
3464
|
+
'revision': 27,
|
3465
|
+
'datasource': 'Prometheus'
|
3466
|
+
}
|
3467
|
+
}
|
3468
|
+
}
|
3469
|
+
},
|
3470
|
+
'prometheus': {
|
3471
|
+
'enabled': True,
|
3472
|
+
'prometheusSpec': {
|
3473
|
+
'retention': '30d',
|
3474
|
+
'storageSpec': {
|
3475
|
+
'volumeClaimTemplate': {
|
3476
|
+
'spec': {
|
3477
|
+
'accessModes': ['ReadWriteOnce'],
|
3478
|
+
'resources': {
|
3479
|
+
'requests': {
|
3480
|
+
'storage': prometheus_storage_size
|
3481
|
+
}
|
3482
|
+
}
|
3483
|
+
}
|
3484
|
+
}
|
3485
|
+
},
|
3486
|
+
'serviceMonitorSelectorNilUsesHelmValues': False
|
3487
|
+
}
|
3488
|
+
},
|
3489
|
+
'alertmanager': {
|
3490
|
+
'enabled': True
|
3491
|
+
},
|
3492
|
+
'nodeExporter': {
|
3493
|
+
'enabled': True
|
3494
|
+
},
|
3495
|
+
'kubeStateMetrics': {
|
3496
|
+
'enabled': True
|
3497
|
+
},
|
3498
|
+
'defaultRules': {
|
3499
|
+
'create': True,
|
3500
|
+
'rules': {
|
3501
|
+
'alertmanager': True,
|
3502
|
+
'etcd': True,
|
3503
|
+
'general': True,
|
3504
|
+
'k8s': True,
|
3505
|
+
'kubeApiserver': True,
|
3506
|
+
'kubePrometheusNodeRecording': True,
|
3507
|
+
'kubernetesApps': True,
|
3508
|
+
'kubernetesResources': True,
|
3509
|
+
'kubernetesStorage': True,
|
3510
|
+
'kubernetesSystem': True,
|
3511
|
+
'network': True,
|
3512
|
+
'node': True,
|
3513
|
+
'prometheus': True,
|
3514
|
+
'prometheusOperator': True
|
3515
|
+
}
|
3516
|
+
}
|
3517
|
+
}
|
3518
|
+
|
3519
|
+
# Add ingress if requested
|
3520
|
+
if install_ingress:
|
3521
|
+
helm_values['grafana']['ingress'] = {
|
3522
|
+
'enabled': True,
|
3523
|
+
'hosts': [f'grafana.{namespace}.local'],
|
3524
|
+
'paths': ['/']
|
3525
|
+
}
|
3526
|
+
|
3527
|
+
# Write values to temporary file
|
3528
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f:
|
3529
|
+
yaml.dump(helm_values, f, default_flow_style=False)
|
3530
|
+
values_file = f.name
|
3531
|
+
|
3532
|
+
try:
|
3533
|
+
# Install the Helm chart
|
3534
|
+
print("🚀 Installing kube-prometheus-stack via Helm...")
|
3535
|
+
helm_cmd = [
|
3536
|
+
'helm', 'install', 'kube-prometheus-stack',
|
3537
|
+
'prometheus-community/kube-prometheus-stack',
|
3538
|
+
'--namespace', namespace,
|
3539
|
+
'--values', values_file
|
3540
|
+
]
|
3541
|
+
|
3542
|
+
if wait_for_ready:
|
3543
|
+
helm_cmd.append('--wait')
|
3544
|
+
helm_cmd.extend(['--timeout', '10m'])
|
3545
|
+
|
3546
|
+
result = subprocess.run(helm_cmd, capture_output=True, text=True, check=True)
|
3547
|
+
print("✅ Helm chart installed successfully")
|
3548
|
+
|
3549
|
+
# Wait a bit for pods to start
|
3550
|
+
if wait_for_ready:
|
3551
|
+
print("⏳ Waiting for pods to be ready...")
|
3552
|
+
time.sleep(30)
|
3553
|
+
|
3554
|
+
# Get service information
|
3555
|
+
services_info = self._get_helm_monitoring_services(namespace)
|
3556
|
+
|
3557
|
+
return {
|
3558
|
+
'success': True,
|
3559
|
+
'namespace': namespace,
|
3560
|
+
'release_name': 'kube-prometheus-stack',
|
3561
|
+
'prometheus': {'deployed': True},
|
3562
|
+
'grafana': {
|
3563
|
+
'deployed': True,
|
3564
|
+
'admin_password': 'admin'
|
3565
|
+
},
|
3566
|
+
'grafana_url': services_info.get('grafana_url'),
|
3567
|
+
'prometheus_url': services_info.get('prometheus_url'),
|
3568
|
+
'alertmanager_url': services_info.get('alertmanager_url')
|
3569
|
+
}
|
3570
|
+
|
3571
|
+
finally:
|
3572
|
+
# Clean up temporary file
|
3573
|
+
os.unlink(values_file)
|
3574
|
+
|
3575
|
+
except subprocess.CalledProcessError as e:
|
3576
|
+
error_msg = e.stderr.decode() if e.stderr else str(e)
|
3577
|
+
return {
|
3578
|
+
'success': False,
|
3579
|
+
'error': f'Helm installation failed: {error_msg}'
|
3580
|
+
}
|
3581
|
+
except Exception as e:
|
3582
|
+
return {
|
3583
|
+
'success': False,
|
3584
|
+
'error': f'Failed to setup Helm monitoring: {str(e)}'
|
3585
|
+
}
|
3586
|
+
|
3587
|
+
def get_helm_monitoring_info(self, namespace: str = "monitoring") -> Dict:
|
3588
|
+
"""Get information about the Helm-based monitoring stack"""
|
3589
|
+
import subprocess
|
3590
|
+
|
3591
|
+
try:
|
3592
|
+
# Check if Helm release exists
|
3593
|
+
try:
|
3594
|
+
result = subprocess.run([
|
3595
|
+
'helm', 'status', 'kube-prometheus-stack',
|
3596
|
+
'--namespace', namespace
|
3597
|
+
], capture_output=True, text=True, check=True)
|
3598
|
+
|
3599
|
+
# Parse Helm status
|
3600
|
+
lines = result.stdout.split('\n')
|
3601
|
+
release_info = {}
|
3602
|
+
for line in lines:
|
3603
|
+
if 'STATUS:' in line:
|
3604
|
+
release_info['release_status'] = line.split('STATUS:')[1].strip()
|
3605
|
+
elif 'LAST DEPLOYED:' in line:
|
3606
|
+
release_info['last_deployed'] = line.split('LAST DEPLOYED:')[1].strip()
|
3607
|
+
|
3608
|
+
except subprocess.CalledProcessError:
|
3609
|
+
return {'error': 'Helm release not found. Use setup-helm-monitoring to deploy first.'}
|
3610
|
+
|
3611
|
+
# Get services information
|
3612
|
+
services_info = self._get_helm_monitoring_services(namespace)
|
3613
|
+
|
3614
|
+
# Get pod status
|
3615
|
+
pods_info = self._get_monitoring_pods_status(namespace)
|
3616
|
+
|
3617
|
+
return {
|
3618
|
+
'release_name': 'kube-prometheus-stack',
|
3619
|
+
'release_status': release_info.get('release_status', 'Unknown'),
|
3620
|
+
'last_deployed': release_info.get('last_deployed', 'Unknown'),
|
3621
|
+
'prometheus': {
|
3622
|
+
'running': any(pod['name'].startswith('prometheus-kube-prometheus-stack-prometheus')
|
3623
|
+
for pod in pods_info if pod['status'] == 'Running'),
|
3624
|
+
'url': services_info.get('prometheus_url', 'Port-forward required')
|
3625
|
+
},
|
3626
|
+
'grafana': {
|
3627
|
+
'running': any(pod['name'].startswith('kube-prometheus-stack-grafana')
|
3628
|
+
for pod in pods_info if pod['status'] == 'Running'),
|
3629
|
+
'url': services_info.get('grafana_url', 'Port-forward required')
|
3630
|
+
},
|
3631
|
+
'alertmanager': {
|
3632
|
+
'running': any(pod['name'].startswith('alertmanager-kube-prometheus-stack-alertmanager')
|
3633
|
+
for pod in pods_info if pod['status'] == 'Running'),
|
3634
|
+
'url': services_info.get('alertmanager_url', 'Port-forward required')
|
3635
|
+
},
|
3636
|
+
'pods': pods_info
|
3637
|
+
}
|
3638
|
+
|
3639
|
+
except Exception as e:
|
3640
|
+
return {'error': f'Failed to get monitoring info: {str(e)}'}
|
3641
|
+
|
3642
|
+
def delete_helm_monitoring(self, namespace: str = "monitoring",
|
3643
|
+
release_name: str = "kube-prometheus-stack") -> Dict:
|
3644
|
+
"""Delete Helm-based monitoring stack"""
|
3645
|
+
import subprocess
|
3646
|
+
|
3647
|
+
try:
|
3648
|
+
# Uninstall Helm release
|
3649
|
+
result = subprocess.run([
|
3650
|
+
'helm', 'uninstall', release_name,
|
3651
|
+
'--namespace', namespace
|
3652
|
+
], capture_output=True, text=True, check=True)
|
3653
|
+
|
3654
|
+
print(f"✅ Helm release '{release_name}' uninstalled")
|
3655
|
+
|
3656
|
+
# Count remaining resources (optional cleanup)
|
3657
|
+
try:
|
3658
|
+
# Delete PVCs that might remain
|
3659
|
+
pvcs = self.core_v1.list_namespaced_persistent_volume_claim(namespace=namespace)
|
3660
|
+
pvc_count = 0
|
3661
|
+
for pvc in pvcs.items:
|
3662
|
+
if 'prometheus' in pvc.metadata.name or 'grafana' in pvc.metadata.name:
|
3663
|
+
self.core_v1.delete_namespaced_persistent_volume_claim(
|
3664
|
+
name=pvc.metadata.name,
|
3665
|
+
namespace=namespace
|
3666
|
+
)
|
3667
|
+
pvc_count += 1
|
3668
|
+
|
3669
|
+
if pvc_count > 0:
|
3670
|
+
print(f"✅ Cleaned up {pvc_count} persistent volume claims")
|
3671
|
+
|
3672
|
+
except Exception as cleanup_error:
|
3673
|
+
print(f"⚠️ Could not clean up some resources: {cleanup_error}")
|
3674
|
+
|
3675
|
+
return {
|
3676
|
+
'success': True,
|
3677
|
+
'resources_deleted': pvc_count
|
3678
|
+
}
|
3679
|
+
|
3680
|
+
except subprocess.CalledProcessError as e:
|
3681
|
+
error_msg = e.stderr.decode() if e.stderr else str(e)
|
3682
|
+
return {
|
3683
|
+
'success': False,
|
3684
|
+
'error': f'Failed to uninstall Helm release: {error_msg}'
|
3685
|
+
}
|
3686
|
+
except Exception as e:
|
3687
|
+
return {
|
3688
|
+
'success': False,
|
3689
|
+
'error': f'Failed to delete monitoring stack: {str(e)}'
|
3690
|
+
}
|
3691
|
+
|
3692
|
+
def _get_helm_monitoring_services(self, namespace: str) -> Dict:
|
3693
|
+
"""Get service URLs for Helm monitoring components"""
|
3694
|
+
services_info = {}
|
3695
|
+
|
3696
|
+
try:
|
3697
|
+
# Get services
|
3698
|
+
services = self.core_v1.list_namespaced_service(namespace=namespace)
|
3699
|
+
|
3700
|
+
for service in services.items:
|
3701
|
+
service_name = service.metadata.name
|
3702
|
+
|
3703
|
+
if 'grafana' in service_name:
|
3704
|
+
url = self._get_service_url(service, namespace, 80)
|
3705
|
+
if url:
|
3706
|
+
services_info['grafana_url'] = url
|
3707
|
+
|
3708
|
+
elif 'prometheus' in service_name and 'operated' not in service_name:
|
3709
|
+
url = self._get_service_url(service, namespace, 9090)
|
3710
|
+
if url:
|
3711
|
+
services_info['prometheus_url'] = url
|
3712
|
+
|
3713
|
+
elif 'alertmanager' in service_name and 'operated' not in service_name:
|
3714
|
+
url = self._get_service_url(service, namespace, 9093)
|
3715
|
+
if url:
|
3716
|
+
services_info['alertmanager_url'] = url
|
3717
|
+
|
3718
|
+
except Exception as e:
|
3719
|
+
print(f"⚠️ Could not get service information: {e}")
|
3720
|
+
|
3721
|
+
return services_info
|
3722
|
+
|
3723
|
+
def _get_monitoring_pods_status(self, namespace: str) -> List[Dict]:
|
3724
|
+
"""Get status of monitoring pods"""
|
3725
|
+
pods_info = []
|
3726
|
+
|
3727
|
+
try:
|
3728
|
+
pods = self.core_v1.list_namespaced_pod(namespace=namespace)
|
3729
|
+
|
3730
|
+
for pod in pods.items:
|
3731
|
+
if any(component in pod.metadata.name for component in
|
3732
|
+
['prometheus', 'grafana', 'alertmanager', 'node-exporter', 'kube-state-metrics']):
|
3733
|
+
|
3734
|
+
ready_containers = 0
|
3735
|
+
total_containers = len(pod.status.container_statuses) if pod.status.container_statuses else 0
|
3736
|
+
|
3737
|
+
if pod.status.container_statuses:
|
3738
|
+
ready_containers = sum(1 for cs in pod.status.container_statuses if cs.ready)
|
3739
|
+
|
3740
|
+
pods_info.append({
|
3741
|
+
'name': pod.metadata.name,
|
3742
|
+
'status': pod.status.phase,
|
3743
|
+
'ready': ready_containers,
|
3744
|
+
'total': total_containers
|
3745
|
+
})
|
3746
|
+
|
3747
|
+
except Exception as e:
|
3748
|
+
print(f"⚠️ Could not get pod status: {e}")
|
3749
|
+
|
3750
|
+
return pods_info
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{k8s_helper_cli-0.5.0 → k8s_helper_cli-0.5.2}/src/k8s_helper_cli.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|