import secrets from pathlib import Path import typer import yaml from src.commands.utils import CONSOLE from src.config import GENERATED_STACK_PREFIX, Config, InfraConfig, S3Config app = typer.Typer() @app.command() def init( output: str = typer.Option("config.yaml", help="Destination path for the config file"), force: bool = typer.Option(False, "--force", "-f", help="Overwrite an existing config file"), ) -> None: """Write a starter config.yaml to the current directory.""" dest = Path(output) if dest.exists() and not force: CONSOLE.print(f"[yellow]{dest} already exists.[/yellow] Use --force to overwrite.") raise typer.Exit(1) config = _new_isolated_config() dest.parent.mkdir(parents=True, exist_ok=True) config_data = config.model_dump(mode="json") config_data["sagemaker"].pop("role_name", None) with open(dest, "w") as f: yaml.safe_dump(config_data, f, sort_keys=False) CONSOLE.print(f"[green]✓[/green] Config written to [bold]{dest}[/bold]") CONSOLE.print("Edit [cyan]sagemaker.training.image_uri[/cyan] before running training commands.") def _new_isolated_config() -> Config: suffix = secrets.token_hex(6) namespace = f"{GENERATED_STACK_PREFIX}{suffix}" config = Config(infra=InfraConfig(stack_name=namespace)) config.s3 = S3Config(bucket=f"{namespace}-data") return config