""" Docker file generation service. """ from typing import Union from pathlib import Path from fastapi import HTTPException, status from jinja2 import Environment, Template from app.core.config import Settings from app.models.schemas import DockerfileConfig, DockerComposeConfig class DockerGenerator: """Service for generating Docker files and configurations.""" def __init__(self, template_env: Environment, settings: Settings, logger): self.template_env = template_env self.settings = settings self.logger = logger def generate_dockerfile(self, config: DockerfileConfig, file_id: str) -> str: """ Generate a Dockerfile based on stack type and configuration. """ stack = config.stackType.lower() # Map stack to template template_map = { "nodejs": "docker/dockerfile_nodejs.j2", "python": "docker/dockerfile_python.j2", "php": "docker/dockerfile_php.j2", "go": "docker/dockerfile_go.j2", "java": "docker/dockerfile_java.j2", "dotnet": "docker/dockerfile_dotnet.j2", "ruby": "docker/dockerfile_ruby.j2", } template_name = template_map.get(stack) if not template_name: raise ValueError(f"Unsupported stack type: {stack}") try: # Read template from disk template_path = self.settings.templates_dir / template_name with open(template_path, 'r', encoding='utf-8') as f: template_content = f.read() # Render using Jinja2 template = Template( template_content, trim_blocks=True, lstrip_blocks=True ) dockerfile_content = template.render(config=config, file_id=file_id) return dockerfile_content except Exception as e: self.logger.error(f"Failed to generate Dockerfile: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to generate Dockerfile: {str(e)}" ) def generate_docker_compose(self, config: DockerComposeConfig, file_id: str) -> str: """ Generate a docker-compose.yml based on configuration. """ template_name = "docker/docker-compose.yml.j2" try: # Read template from disk template_path = self.settings.templates_dir / template_name with open(template_path, 'r', encoding='utf-8') as f: template_content = f.read() # Render using Jinja2 template = Template( template_content, trim_blocks=True, lstrip_blocks=True ) compose_content = template.render(config=config, file_id=file_id) return compose_content except Exception as e: self.logger.error(f"Failed to generate docker-compose: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to generate docker-compose: {str(e)}" ) def generate_dockerignore(self, config: Union[DockerfileConfig, DockerComposeConfig], file_id: str) -> str: """ Generate a .dockerignore file. """ template_name = "docker/dockerignore.j2" try: # Read template from disk template_path = self.settings.templates_dir / template_name with open(template_path, 'r', encoding='utf-8') as f: template_content = f.read() # Render using Jinja2 template = Template( template_content, trim_blocks=True, lstrip_blocks=True ) dockerignore_content = template.render(config=config, file_id=file_id) return dockerignore_content except Exception as e: self.logger.error(f"Failed to generate .dockerignore: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to generate .dockerignore: {str(e)}" ) def generate_env_example(self, config: DockerComposeConfig, file_id: str) -> str: """ Generate a .env.example file for docker-compose. """ template_name = "docker/env.example.j2" try: # Read template from disk template_path = self.settings.templates_dir / template_name with open(template_path, 'r', encoding='utf-8') as f: template_content = f.read() # Render using Jinja2 template = Template( template_content, trim_blocks=True, lstrip_blocks=True ) env_content = template.render(config=config, file_id=file_id) return env_content except Exception as e: self.logger.error(f"Failed to generate .env.example: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to generate .env.example: {str(e)}" ) def generate_build_script(self, config: DockerComposeConfig, file_id: str) -> str: """ Generate a docker-build.sh helper script. """ template_name = "docker/docker-build.sh.j2" try: # Read template from disk template_path = self.settings.templates_dir / template_name with open(template_path, 'r', encoding='utf-8') as f: template_content = f.read() # Render using Jinja2 template = Template( template_content, trim_blocks=True, lstrip_blocks=True ) script_content = template.render(config=config, file_id=file_id) return script_content except Exception as e: self.logger.error(f"Failed to generate build script: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to generate build script: {str(e)}" )