switching context

This commit is contained in:
vy.boyko 2025-10-25 21:47:10 +03:00
parent 68f9d01469
commit 9548206532
3 changed files with 114 additions and 3 deletions

View File

@ -5,6 +5,7 @@
## Особенности ## Особенности
- 🎯 Интерактивное меню с навигацией стрелками - 🎯 Интерактивное меню с навигацией стрелками
- 🔄 Переключение между Kubernetes контекстами/кластерами
- ⭐ Избранные namespaces для быстрого доступа - ⭐ Избранные namespaces для быстрого доступа
- 🎨 Красивый вывод с использованием Rich - 🎨 Красивый вывод с использованием Rich
- 📦 Управление namespaces, deployments, pods, ConfigMaps - 📦 Управление namespaces, deployments, pods, ConfigMaps
@ -57,6 +58,14 @@ poetry run k8s-tool
### Основные функции ### Основные функции
#### Переключение контекста Kubernetes
Быстрое переключение между различными Kubernetes кластерами/контекстами:
- Просмотр всех доступных контекстов в виде таблицы
- Отображение текущего активного контекста (✓)
- Переключение на другой контекст
- Автоматическая переинициализация подключения к новому кластеру
- После переключения контекста namespace сбрасывается и нужно выбрать заново
#### Выбор Namespace #### Выбор Namespace
Выберите namespace для работы. Все последующие операции будут выполняться в выбранном namespace. Выберите namespace для работы. Все последующие операции будут выполняться в выбранном namespace.

View File

@ -19,11 +19,52 @@ class K8sClient:
config.load_kube_config() config.load_kube_config()
self.v1 = client.CoreV1Api() self.v1 = client.CoreV1Api()
self.apps_v1 = client.AppsV1Api() self.apps_v1 = client.AppsV1Api()
console.print("[green]✓[/green] Connected to Kubernetes cluster") self.current_context = self.get_current_context()
console.print(f"[green]✓[/green] Connected to Kubernetes cluster")
if self.current_context:
console.print(f"[dim]Current context: {self.current_context}[/dim]")
except Exception as e: except Exception as e:
console.print(f"[red]✗[/red] Failed to connect to Kubernetes: {e}") console.print(f"[red]✗[/red] Failed to connect to Kubernetes: {e}")
raise raise
def get_contexts(self) -> List[Dict[str, str]]:
"""Get list of available contexts."""
try:
contexts, active_context = config.list_kube_config_contexts()
return [{
'name': ctx['name'],
'cluster': ctx['context'].get('cluster', ''),
'user': ctx['context'].get('user', ''),
'is_active': ctx['name'] == active_context['name']
} for ctx in contexts]
except Exception as e:
console.print(f"[red]Error fetching contexts:[/red] {e}")
return []
def get_current_context(self) -> Optional[str]:
"""Get current context name."""
try:
contexts, active_context = config.list_kube_config_contexts()
return active_context['name'] if active_context else None
except Exception as e:
console.print(f"[red]Error getting current context:[/red] {e}")
return None
def switch_context(self, context_name: str) -> bool:
"""Switch to a different context."""
try:
# Load the new context
config.load_kube_config(context=context_name)
# Reinitialize API clients
self.v1 = client.CoreV1Api()
self.apps_v1 = client.AppsV1Api()
self.current_context = context_name
console.print(f"[green]✓[/green] Switched to context: [cyan]{context_name}[/cyan]")
return True
except Exception as e:
console.print(f"[red]Error switching context:[/red] {e}")
return False
def get_namespaces(self) -> List[str]: def get_namespaces(self) -> List[str]:
"""Get list of all namespaces.""" """Get list of all namespaces."""
try: try:
@ -232,3 +273,22 @@ class K8sClient:
) )
console.print(table) console.print(table)
def display_contexts_table(self, contexts: List[Dict[str, str]]):
"""Display contexts in a table."""
table = Table(title="Kubernetes Contexts")
table.add_column("Name", style="cyan")
table.add_column("Cluster", style="magenta")
table.add_column("User", style="yellow")
table.add_column("Active", style="green")
for ctx in contexts:
active_mark = "" if ctx['is_active'] else ""
table.add_row(
ctx['name'],
ctx['cluster'],
ctx['user'],
active_mark
)
console.print(table)

View File

@ -63,12 +63,18 @@ class K8sTool:
def _main_menu(self): def _main_menu(self):
"""Display main menu.""" """Display main menu."""
# Display current context
current_context = self.k8s_client.current_context or "[dim]unknown[/dim]"
console.print(f"[bold]Current context:[/bold] [cyan]{current_context}[/cyan]")
# Display current namespace
namespace_info = f"[cyan]{self.current_namespace}[/cyan]" if self.current_namespace else "[dim]not selected[/dim]" namespace_info = f"[cyan]{self.current_namespace}[/cyan]" if self.current_namespace else "[dim]not selected[/dim]"
is_favorite = self.config.is_favorite(self.current_namespace) if self.current_namespace else False is_favorite = self.config.is_favorite(self.current_namespace) if self.current_namespace else False
fav_indicator = "" if is_favorite else "" fav_indicator = "" if is_favorite else ""
console.print(f"\n[bold]Current namespace:[/bold] {namespace_info}{fav_indicator}") console.print(f"[bold]Current namespace:[/bold] {namespace_info}{fav_indicator}")
choices = [ choices = [
"Switch Context",
"Select Namespace", "Select Namespace",
"Manage Favorites", "Manage Favorites",
"List Deployments", "List Deployments",
@ -86,7 +92,9 @@ class K8sTool:
style=custom_style style=custom_style
).ask() ).ask()
if action == "Select Namespace": if action == "Switch Context":
self._switch_context()
elif action == "Select Namespace":
self._select_namespace() self._select_namespace()
elif action == "Manage Favorites": elif action == "Manage Favorites":
self._manage_favorites() self._manage_favorites()
@ -144,6 +152,40 @@ class K8sTool:
fav_text = " (favorite)" if is_fav else "" fav_text = " (favorite)" if is_fav else ""
console.print(f"[green]✓[/green] Namespace set to: [cyan]{namespace}[/cyan]{fav_text}") console.print(f"[green]✓[/green] Namespace set to: [cyan]{namespace}[/cyan]{fav_text}")
def _switch_context(self):
"""Switch Kubernetes context."""
console.print("[dim]Fetching contexts...[/dim]")
contexts = self.k8s_client.get_contexts()
if not contexts:
console.print("[red]No contexts found[/red]")
return
# Show contexts table
self.k8s_client.display_contexts_table(contexts)
# Filter out current context for selection
available_contexts = [ctx['name'] for ctx in contexts if not ctx['is_active']]
if not available_contexts:
console.print("[yellow]Only one context available[/yellow]")
return
# Add option to view current
choices = available_contexts + [questionary.Separator(), "Cancel"]
selected = questionary.select(
"Select context to switch to:",
choices=choices,
style=custom_style
).ask()
if selected and selected != "Cancel":
if self.k8s_client.switch_context(selected):
# Reset namespace selection after context switch
self.current_namespace = None
console.print("[yellow]Note:[/yellow] Namespace selection reset. Please select a namespace.")
def _manage_favorites(self): def _manage_favorites(self):
"""Manage favorite namespaces.""" """Manage favorite namespaces."""
choices = [] choices = []