namespaces favouites
This commit is contained in:
parent
b76941ec3a
commit
3cf37a3389
17
README.md
17
README.md
@ -5,11 +5,13 @@
|
||||
## Особенности
|
||||
|
||||
- 🎯 Интерактивное меню с навигацией стрелками
|
||||
- ⭐ Избранные namespaces для быстрого доступа
|
||||
- 🎨 Красивый вывод с использованием Rich
|
||||
- 📦 Управление namespaces, deployments, pods, ConfigMaps
|
||||
- 🔄 Быстрый рестарт и масштабирование deployments
|
||||
- 📝 Просмотр логов pods
|
||||
- 🔍 Просмотр содержимого ConfigMaps
|
||||
- 💾 Сохранение настроек в `~/.config/k8s-tool/k8s-tool.cfg`
|
||||
|
||||
## Требования
|
||||
|
||||
@ -58,6 +60,18 @@ poetry run k8s-tool
|
||||
#### Выбор Namespace
|
||||
Выберите namespace для работы. Все последующие операции будут выполняться в выбранном namespace.
|
||||
|
||||
Избранные namespaces отображаются в начале списка с пометкой ⭐ для быстрого доступа. Список избранных сохраняется между запусками приложения.
|
||||
|
||||
#### Управление избранными
|
||||
Добавляйте часто используемые namespaces в избранное для быстрого доступа:
|
||||
- Добавить/удалить текущий namespace в/из избранного
|
||||
- Просмотр всех избранных namespaces
|
||||
- Добавление любого namespace в избранное из полного списка
|
||||
- Удаление namespace из избранного
|
||||
- Очистка всех избранных
|
||||
|
||||
Конфигурация сохраняется в файле `~/.config/k8s-tool/k8s-tool.cfg`.
|
||||
|
||||
#### Список Deployments
|
||||
Отображает все deployments в текущем namespace с информацией о:
|
||||
- Имени deployment
|
||||
@ -92,9 +106,10 @@ poetry run k8s-tool
|
||||
|
||||
## Архитектура
|
||||
|
||||
Проект состоит из двух основных модулей:
|
||||
Проект состоит из трёх основных модулей:
|
||||
|
||||
- `k8s_client.py` - обёртка над Kubernetes Python API для работы с кластером
|
||||
- `config.py` - менеджер конфигурации для управления избранными namespaces
|
||||
- `main.py` - главное приложение с интерактивным меню
|
||||
|
||||
### Технологии
|
||||
|
||||
87
k8s_tool/config.py
Normal file
87
k8s_tool/config.py
Normal file
@ -0,0 +1,87 @@
|
||||
"""Configuration manager for k8s-tool."""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Any
|
||||
from rich.console import Console
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
"""Manage application configuration."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize configuration manager."""
|
||||
self.config_dir = Path.home() / ".config" / "k8s-tool"
|
||||
self.config_file = self.config_dir / "k8s-tool.cfg"
|
||||
self._ensure_config_dir()
|
||||
self.config = self._load_config()
|
||||
|
||||
def _ensure_config_dir(self):
|
||||
"""Ensure configuration directory exists."""
|
||||
try:
|
||||
self.config_dir.mkdir(parents=True, exist_ok=True)
|
||||
except Exception as e:
|
||||
console.print(f"[yellow]Warning:[/yellow] Could not create config directory: {e}")
|
||||
|
||||
def _load_config(self) -> Dict[str, Any]:
|
||||
"""Load configuration from file."""
|
||||
if not self.config_file.exists():
|
||||
return {"favorites": []}
|
||||
|
||||
try:
|
||||
with open(self.config_file, 'r') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
console.print(f"[yellow]Warning:[/yellow] Could not load config: {e}")
|
||||
return {"favorites": []}
|
||||
|
||||
def _save_config(self):
|
||||
"""Save configuration to file."""
|
||||
try:
|
||||
with open(self.config_file, 'w') as f:
|
||||
json.dump(self.config, f, indent=2)
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error:[/red] Could not save config: {e}")
|
||||
|
||||
def get_favorites(self) -> List[str]:
|
||||
"""Get list of favorite namespaces."""
|
||||
return self.config.get("favorites", [])
|
||||
|
||||
def add_favorite(self, namespace: str) -> bool:
|
||||
"""Add namespace to favorites."""
|
||||
favorites = self.config.get("favorites", [])
|
||||
if namespace not in favorites:
|
||||
favorites.append(namespace)
|
||||
self.config["favorites"] = sorted(favorites)
|
||||
self._save_config()
|
||||
console.print(f"[green]✓[/green] Added [cyan]{namespace}[/cyan] to favorites")
|
||||
return True
|
||||
else:
|
||||
console.print(f"[yellow]![/yellow] [cyan]{namespace}[/cyan] is already in favorites")
|
||||
return False
|
||||
|
||||
def remove_favorite(self, namespace: str) -> bool:
|
||||
"""Remove namespace from favorites."""
|
||||
favorites = self.config.get("favorites", [])
|
||||
if namespace in favorites:
|
||||
favorites.remove(namespace)
|
||||
self.config["favorites"] = favorites
|
||||
self._save_config()
|
||||
console.print(f"[green]✓[/green] Removed [cyan]{namespace}[/cyan] from favorites")
|
||||
return True
|
||||
else:
|
||||
console.print(f"[yellow]![/yellow] [cyan]{namespace}[/cyan] is not in favorites")
|
||||
return False
|
||||
|
||||
def is_favorite(self, namespace: str) -> bool:
|
||||
"""Check if namespace is in favorites."""
|
||||
return namespace in self.config.get("favorites", [])
|
||||
|
||||
def clear_favorites(self):
|
||||
"""Clear all favorites."""
|
||||
self.config["favorites"] = []
|
||||
self._save_config()
|
||||
console.print("[green]✓[/green] Cleared all favorites")
|
||||
141
k8s_tool/main.py
141
k8s_tool/main.py
@ -9,6 +9,7 @@ from rich.panel import Panel
|
||||
from rich.syntax import Syntax
|
||||
|
||||
from k8s_tool.k8s_client import K8sClient
|
||||
from k8s_tool.config import ConfigManager
|
||||
|
||||
console = Console()
|
||||
|
||||
@ -32,6 +33,7 @@ class K8sTool:
|
||||
def __init__(self):
|
||||
"""Initialize the application."""
|
||||
self.k8s_client = K8sClient()
|
||||
self.config = ConfigManager()
|
||||
self.current_namespace: Optional[str] = None
|
||||
|
||||
def run(self):
|
||||
@ -58,10 +60,13 @@ class K8sTool:
|
||||
def _main_menu(self):
|
||||
"""Display main menu."""
|
||||
namespace_info = f"[cyan]{self.current_namespace}[/cyan]" if self.current_namespace else "[dim]not selected[/dim]"
|
||||
console.print(f"\n[bold]Current namespace:[/bold] {namespace_info}")
|
||||
is_favorite = self.config.is_favorite(self.current_namespace) if self.current_namespace else False
|
||||
fav_indicator = " ⭐" if is_favorite else ""
|
||||
console.print(f"\n[bold]Current namespace:[/bold] {namespace_info}{fav_indicator}")
|
||||
|
||||
choices = [
|
||||
"Select Namespace",
|
||||
"Manage Favorites",
|
||||
"List Deployments",
|
||||
"Restart Deployment",
|
||||
"Scale Deployment",
|
||||
@ -78,6 +83,8 @@ class K8sTool:
|
||||
|
||||
if action == "Select Namespace":
|
||||
self._select_namespace()
|
||||
elif action == "Manage Favorites":
|
||||
self._manage_favorites()
|
||||
elif action == "List Deployments":
|
||||
self._list_deployments()
|
||||
elif action == "Restart Deployment":
|
||||
@ -101,15 +108,139 @@ class K8sTool:
|
||||
console.print("[red]No namespaces found[/red]")
|
||||
return
|
||||
|
||||
namespace = questionary.select(
|
||||
# Get favorites
|
||||
favorites = self.config.get_favorites()
|
||||
|
||||
# Separate favorites and non-favorites
|
||||
fav_namespaces = [ns for ns in namespaces if ns in favorites]
|
||||
other_namespaces = [ns for ns in namespaces if ns not in favorites]
|
||||
|
||||
# Create choices with stars for favorites
|
||||
choices = []
|
||||
if fav_namespaces:
|
||||
choices.extend([f"⭐ {ns}" for ns in fav_namespaces])
|
||||
if other_namespaces:
|
||||
choices.append(questionary.Separator("─" * 40))
|
||||
choices.extend(other_namespaces)
|
||||
|
||||
selected = questionary.select(
|
||||
"Select namespace:",
|
||||
choices=namespaces,
|
||||
choices=choices,
|
||||
style=custom_style
|
||||
).ask()
|
||||
|
||||
if selected:
|
||||
# Remove star prefix if present
|
||||
namespace = selected.replace("⭐ ", "")
|
||||
self.current_namespace = namespace
|
||||
is_fav = self.config.is_favorite(namespace)
|
||||
fav_text = " (favorite)" if is_fav else ""
|
||||
console.print(f"[green]✓[/green] Namespace set to: [cyan]{namespace}[/cyan]{fav_text}")
|
||||
|
||||
def _manage_favorites(self):
|
||||
"""Manage favorite namespaces."""
|
||||
choices = []
|
||||
|
||||
if self.current_namespace:
|
||||
if self.config.is_favorite(self.current_namespace):
|
||||
choices.append(f"Remove '{self.current_namespace}' from favorites")
|
||||
else:
|
||||
choices.append(f"Add '{self.current_namespace}' to favorites")
|
||||
|
||||
choices.extend([
|
||||
"View all favorites",
|
||||
"Add namespace to favorites",
|
||||
"Remove namespace from favorites",
|
||||
"Clear all favorites",
|
||||
"Back to main menu"
|
||||
])
|
||||
|
||||
action = questionary.select(
|
||||
"Favorites management:",
|
||||
choices=choices,
|
||||
style=custom_style
|
||||
).ask()
|
||||
|
||||
if not action or action == "Back to main menu":
|
||||
return
|
||||
|
||||
if action.startswith("Add '") and action.endswith("' to favorites"):
|
||||
# Add current namespace
|
||||
self.config.add_favorite(self.current_namespace)
|
||||
|
||||
elif action.startswith("Remove '") and action.endswith("' from favorites"):
|
||||
# Remove current namespace
|
||||
self.config.remove_favorite(self.current_namespace)
|
||||
|
||||
elif action == "View all favorites":
|
||||
self._view_favorites()
|
||||
|
||||
elif action == "Add namespace to favorites":
|
||||
self._add_namespace_to_favorites()
|
||||
|
||||
elif action == "Remove namespace from favorites":
|
||||
self._remove_namespace_from_favorites()
|
||||
|
||||
elif action == "Clear all favorites":
|
||||
if questionary.confirm("Are you sure you want to clear all favorites?", style=custom_style, default=False).ask():
|
||||
self.config.clear_favorites()
|
||||
|
||||
def _view_favorites(self):
|
||||
"""View all favorite namespaces."""
|
||||
favorites = self.config.get_favorites()
|
||||
|
||||
if not favorites:
|
||||
console.print("[yellow]No favorites yet[/yellow]")
|
||||
return
|
||||
|
||||
console.print("\n[bold]Favorite namespaces:[/bold]")
|
||||
for ns in favorites:
|
||||
indicator = " [dim](current)[/dim]" if ns == self.current_namespace else ""
|
||||
console.print(f" ⭐ [cyan]{ns}[/cyan]{indicator}")
|
||||
console.print()
|
||||
|
||||
def _add_namespace_to_favorites(self):
|
||||
"""Add a namespace to favorites."""
|
||||
console.print("[dim]Fetching namespaces...[/dim]")
|
||||
namespaces = self.k8s_client.get_namespaces()
|
||||
|
||||
if not namespaces:
|
||||
console.print("[red]No namespaces found[/red]")
|
||||
return
|
||||
|
||||
# Filter out already favorite namespaces
|
||||
favorites = self.config.get_favorites()
|
||||
available = [ns for ns in namespaces if ns not in favorites]
|
||||
|
||||
if not available:
|
||||
console.print("[yellow]All namespaces are already in favorites[/yellow]")
|
||||
return
|
||||
|
||||
namespace = questionary.select(
|
||||
"Select namespace to add to favorites:",
|
||||
choices=available,
|
||||
style=custom_style
|
||||
).ask()
|
||||
|
||||
if namespace:
|
||||
self.current_namespace = namespace
|
||||
console.print(f"[green]✓[/green] Namespace set to: [cyan]{namespace}[/cyan]")
|
||||
self.config.add_favorite(namespace)
|
||||
|
||||
def _remove_namespace_from_favorites(self):
|
||||
"""Remove a namespace from favorites."""
|
||||
favorites = self.config.get_favorites()
|
||||
|
||||
if not favorites:
|
||||
console.print("[yellow]No favorites to remove[/yellow]")
|
||||
return
|
||||
|
||||
namespace = questionary.select(
|
||||
"Select namespace to remove from favorites:",
|
||||
choices=favorites,
|
||||
style=custom_style
|
||||
).ask()
|
||||
|
||||
if namespace:
|
||||
self.config.remove_favorite(namespace)
|
||||
|
||||
def _ensure_namespace_selected(self) -> bool:
|
||||
"""Ensure namespace is selected."""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user