grafana
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import typer
|
import typer
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from .wrap_cli import wrap_app
|
from .wrap_cli import wrap_app
|
||||||
|
from .grafana_cli import grafana_app
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer()
|
||||||
console = Console()
|
console = Console()
|
||||||
@@ -8,5 +9,8 @@ console = Console()
|
|||||||
# Add the wrap subcommand to the main app
|
# Add the wrap subcommand to the main app
|
||||||
app.add_typer(wrap_app, name="wrap")
|
app.add_typer(wrap_app, name="wrap")
|
||||||
|
|
||||||
|
# Add the grafana subcommand to the main app
|
||||||
|
app.add_typer(grafana_app, name="grafana")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app()
|
app()
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
import typer
|
||||||
|
from rich.console import Console
|
||||||
|
import json
|
||||||
|
import pyperclip
|
||||||
|
from typing import Dict, Any, List, Optional
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
# Create the main grafana subcommand
|
||||||
|
grafana_app = typer.Typer()
|
||||||
|
|
||||||
|
def safe_get(data: Dict[str, Any], key: str, default: Any = None) -> Any:
|
||||||
|
"""Safely get a value from a dictionary."""
|
||||||
|
return data.get(key, default)
|
||||||
|
|
||||||
|
def mutate_panel(panel: Dict[str, Any]) -> None:
|
||||||
|
"""Mutate a single panel by setting repeat and repeatDirection fields."""
|
||||||
|
# Check if type is "row" and remove repeat key if it exists
|
||||||
|
if safe_get(panel, 'type') == 'row':
|
||||||
|
if 'repeat' in panel:
|
||||||
|
del panel['repeat']
|
||||||
|
else:
|
||||||
|
# For non-row panels, set repeat and repeatDirection
|
||||||
|
panel['repeat'] = 'instance'
|
||||||
|
panel['repeatDirection'] = 'h'
|
||||||
|
panel['maxPerRow'] = 12
|
||||||
|
|
||||||
|
def mutate_panels_recursive(panels: List[Dict[str, Any]]) -> None:
|
||||||
|
"""Recursively mutate panels, handling nested panels."""
|
||||||
|
for panel in panels:
|
||||||
|
if not isinstance(panel, dict):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Mutate current panel
|
||||||
|
mutate_panel(panel)
|
||||||
|
|
||||||
|
# Check for nested panels
|
||||||
|
nested_panels = safe_get(panel, 'panels', [])
|
||||||
|
if nested_panels and isinstance(nested_panels, list):
|
||||||
|
mutate_panels_recursive(nested_panels)
|
||||||
|
|
||||||
|
def mutate_grafana_json(data: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Mutate Grafana JSON by setting repeat and repeatDirection fields.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: The Grafana dashboard JSON data
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The mutated JSON data
|
||||||
|
"""
|
||||||
|
# Make a copy to avoid mutating the original
|
||||||
|
mutated_data = json.loads(json.dumps(data))
|
||||||
|
|
||||||
|
# Get panels safely
|
||||||
|
panels = safe_get(mutated_data, 'panels', [])
|
||||||
|
|
||||||
|
if panels and isinstance(panels, list):
|
||||||
|
mutate_panels_recursive(panels)
|
||||||
|
|
||||||
|
return mutated_data
|
||||||
|
|
||||||
|
@grafana_app.command("mutate", short_help="Mutate Grafana JSON to set repeat fields.")
|
||||||
|
def mutate_dashboard(
|
||||||
|
input_file: Optional[Path] = typer.Option(
|
||||||
|
None, "--input-file", "-i", help="Input JSON file path. If not provided, reads from clipboard."
|
||||||
|
),
|
||||||
|
output_file: Optional[Path] = typer.Option(
|
||||||
|
None, "--output-file", "-o", help="Output JSON file path. If not provided, outputs to clipboard."
|
||||||
|
)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Mutate Grafana JSON by setting repeat="instance" and repeatDirection="h".
|
||||||
|
|
||||||
|
This command processes Grafana dashboard JSON and modifies panels to:
|
||||||
|
- Set repeat field to "instance"
|
||||||
|
- Set repeatDirection field to "h"
|
||||||
|
- Set maxPerRow to 12
|
||||||
|
- Remove repeat field from row-type panels
|
||||||
|
"""
|
||||||
|
console.print("[blue]Processing Grafana dashboard JSON...[/blue]")
|
||||||
|
|
||||||
|
# Read input
|
||||||
|
try:
|
||||||
|
if input_file:
|
||||||
|
console.print(f"[blue]Reading from file: {input_file}[/blue]")
|
||||||
|
if not input_file.exists():
|
||||||
|
console.print(f"[red]Error: Input file '{input_file}' not found[/red]")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
|
||||||
|
json_content = input_file.read_text(encoding='utf-8')
|
||||||
|
else:
|
||||||
|
console.print("[blue]Reading from clipboard...[/blue]")
|
||||||
|
json_content = pyperclip.paste()
|
||||||
|
if not json_content.strip():
|
||||||
|
console.print("[red]Error: Clipboard is empty or contains no text.[/red]")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
except Exception as e:
|
||||||
|
console.print(f"[red]Error reading input: {e}[/red]")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
|
||||||
|
# Parse JSON
|
||||||
|
try:
|
||||||
|
data = json.loads(json_content)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
console.print(f"[red]Error parsing JSON: {e}[/red]")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
|
||||||
|
# Mutate the data
|
||||||
|
try:
|
||||||
|
mutated_data = mutate_grafana_json(data)
|
||||||
|
console.print("[green]Successfully mutated Grafana JSON![/green]")
|
||||||
|
except Exception as e:
|
||||||
|
console.print(f"[red]Error mutating JSON: {e}[/red]")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
|
||||||
|
# Output result
|
||||||
|
try:
|
||||||
|
output_json = json.dumps(mutated_data, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
if output_file:
|
||||||
|
console.print(f"[blue]Writing to file: {output_file}[/blue]")
|
||||||
|
output_file.write_text(output_json, encoding='utf-8')
|
||||||
|
console.print(f"[green]Output written to {output_file}[/green]")
|
||||||
|
else:
|
||||||
|
console.print("[blue]Copying to clipboard...[/blue]")
|
||||||
|
pyperclip.copy(output_json)
|
||||||
|
console.print("[green]Output copied to clipboard![/green]")
|
||||||
|
except Exception as e:
|
||||||
|
console.print(f"[red]Error writing output: {e}[/red]")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
Reference in New Issue
Block a user