editing deployment

This commit is contained in:
vy.boyko 2025-10-26 13:45:12 +03:00
parent 1374935d2d
commit cc43885279
2 changed files with 143 additions and 5 deletions

View File

@ -339,6 +339,59 @@ class K8sClient:
console.print(f"[red]Error scaling deployment:[/red] {e}")
return False
def get_deployment_yaml(self, namespace: str, name: str) -> Optional[str]:
"""Get deployment as YAML string."""
try:
from kubernetes import utils
deployment = self.apps_v1.read_namespaced_deployment(name, namespace)
# Convert to dict and remove managed fields and status
deployment_dict = deployment.to_dict()
# Remove fields that shouldn't be edited
if 'metadata' in deployment_dict:
deployment_dict['metadata'].pop('managed_fields', None)
deployment_dict['metadata'].pop('resource_version', None)
deployment_dict['metadata'].pop('uid', None)
deployment_dict['metadata'].pop('self_link', None)
deployment_dict['metadata'].pop('creation_timestamp', None)
deployment_dict['metadata'].pop('generation', None)
# Remove status
deployment_dict.pop('status', None)
# Convert to YAML
import yaml
yaml_str = yaml.dump(deployment_dict, default_flow_style=False, sort_keys=False)
return yaml_str
except ApiException as e:
console.print(f"[red]Error reading deployment:[/red] {e}")
return None
def update_deployment_yaml(self, namespace: str, name: str, yaml_str: str) -> bool:
"""Update deployment from YAML string."""
try:
import yaml
# Parse YAML
deployment_dict = yaml.safe_load(yaml_str)
# Update deployment
self.apps_v1.patch_namespaced_deployment(
name=name,
namespace=namespace,
body=deployment_dict
)
console.print(f"[green]✓[/green] Deployment {name} updated successfully")
return True
except ApiException as e:
console.print(f"[red]Error updating deployment:[/red] {e}")
return False
except yaml.YAMLError as e:
console.print(f"[red]Error parsing YAML:[/red] {e}")
return False
def get_pod_logs(self, namespace: str, pod_name: str, container: Optional[str] = None,
tail_lines: int = 100) -> Optional[str]:
"""Get logs from pod."""

View File

@ -80,6 +80,7 @@ class K8sTool:
"List Deployments",
"Restart Deployment",
"Scale Deployment",
"Edit Deployment",
"View ConfigMaps",
"Edit ConfigMap",
"View Pod Logs",
@ -104,6 +105,8 @@ class K8sTool:
self._restart_deployment()
elif action == "Scale Deployment":
self._scale_deployment()
elif action == "Edit Deployment":
self._edit_deployment()
elif action == "View ConfigMaps":
self._view_configmaps()
elif action == "Edit ConfigMap":
@ -134,14 +137,14 @@ class K8sTool:
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:",
# Use autocomplete for filtering
selected = questionary.autocomplete(
"Select namespace (type to filter):",
choices=choices,
style=custom_style
style=custom_style,
match_middle=True
).ask()
if selected:
@ -554,6 +557,88 @@ class K8sTool:
if replicas:
self.k8s_client.scale_deployment(self.current_namespace, dep_name, int(replicas))
def _edit_deployment(self):
"""Edit a deployment."""
if not self._ensure_namespace_selected():
return
console.print(f"[dim]Fetching deployments in {self.current_namespace}...[/dim]")
deployments = self.k8s_client.get_deployments(self.current_namespace)
if not deployments:
console.print("[yellow]No deployments found[/yellow]")
return
dep_names = [dep['name'] for dep in deployments]
dep_name = questionary.select(
"Select deployment to edit:",
choices=dep_names,
style=custom_style
).ask()
if not dep_name:
return
# Get deployment YAML
deployment_yaml = self.k8s_client.get_deployment_yaml(self.current_namespace, dep_name)
if deployment_yaml:
self._edit_deployment_yaml(dep_name, deployment_yaml)
def _edit_deployment_yaml(self, dep_name: str, current_yaml: str):
"""Edit deployment YAML in text editor."""
# Get editor from environment or use default
editor = os.environ.get('EDITOR', os.environ.get('VISUAL', 'vi'))
# Create temporary file with deployment YAML
with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as tf:
temp_file = tf.name
tf.write(current_yaml)
try:
# Get modification time before editing
mtime_before = os.path.getmtime(temp_file)
# Open editor
subprocess.call([editor, temp_file])
# Check if file was modified
mtime_after = os.path.getmtime(temp_file)
if mtime_after == mtime_before:
console.print("[yellow]No changes made[/yellow]")
return
# Read edited data
with open(temp_file, 'r') as f:
try:
new_yaml = f.read()
# Validate YAML
yaml.safe_load(new_yaml)
except yaml.YAMLError as e:
console.print(f"[red]Error parsing YAML:[/red] {e}")
if questionary.confirm("Retry editing?", style=custom_style, default=False).ask():
self._edit_deployment_yaml(dep_name, current_yaml)
return
# Show confirmation
console.print("\n[bold]Deployment YAML has been modified[/bold]")
console.print("[yellow]Warning:[/yellow] Editing deployment directly can be risky.")
# Confirm update
if questionary.confirm(
f"Apply changes to deployment '{dep_name}'?",
style=custom_style,
default=False
).ask():
self.k8s_client.update_deployment_yaml(self.current_namespace, dep_name, new_yaml)
finally:
# Clean up temp file
try:
os.unlink(temp_file)
except Exception:
pass
def _view_configmaps(self):
"""View ConfigMaps."""
if not self._ensure_namespace_selected():