package deploy import ( "os" "strings" "git.solsynth.dev/goatworks/turbine/pkg/launchpad/config" "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" ) // --- Docker Compose Structures for YAML Marshalling --- type ComposeFile struct { Version string `yaml:"version"` Services map[string]ComposeService `yaml:"services"` Networks map[string]interface{} `yaml:"networks,omitempty"` } type ComposeService struct { Image string `yaml:"image,omitempty"` Build *ComposeBuild `yaml:"build,omitempty"` Command interface{} `yaml:"command,omitempty"` Ports []string `yaml:"ports,omitempty"` Expose []string `yaml:"expose,omitempty"` Environment map[string]string `yaml:"environment,omitempty"` Volumes []string `yaml:"volumes,omitempty"` DependsOn map[string]config.Dependency `yaml:"depends_on,omitempty"` Networks []string `yaml:"networks,omitempty"` Healthcheck *config.Healthcheck `yaml:"healthcheck,omitempty"` } type ComposeBuild struct { Context string `yaml:"context,omitempty"` Dockerfile string `yaml:"dockerfile,omitempty"` } // GenerateDockerCompose creates a docker-compose.yml file from the launchpad config. func GenerateDockerCompose(cfg config.LaunchpadConfig) { compose := ComposeFile{ Version: "3.8", Services: make(map[string]ComposeService), Networks: cfg.Networks, } for _, s := range cfg.Services { subst := func(val string) string { return os.ExpandEnv(val) } composeService := ComposeService{ Image: subst(s.Prod.Image), Command: s.Prod.Command, Ports: s.Prod.Ports, Expose: s.Prod.Expose, Volumes: s.Prod.Volumes, DependsOn: s.Prod.DependsOn, Networks: s.Prod.Networks, } // Add healthcheck if defined if len(s.Prod.Healthcheck.Test) > 0 { composeService.Healthcheck = &s.Prod.Healthcheck } if s.Prod.Dockerfile != "" { context := "." if s.Prod.BuildContext != "" { context = s.Prod.BuildContext } composeService.Build = &ComposeBuild{ Context: context, Dockerfile: s.Prod.Dockerfile, } } if len(s.Prod.Environment) > 0 { envMap := make(map[string]string) for _, env := range s.Prod.Environment { parts := strings.SplitN(subst(env), "=", 2) if len(parts) == 2 { envMap[parts[0]] = parts[1] } } composeService.Environment = envMap } compose.Services[s.Name] = composeService } yamlData, err := yaml.Marshal(&compose) if err != nil { log.Fatal().Err(err).Msg("Failed to generate YAML for docker-compose") } outFile := "docker-compose.yml" if err := os.WriteFile(outFile, yamlData, 0o644); err != nil { log.Fatal().Err(err).Msgf("Failed to write %s", outFile) } log.Info().Msgf("Successfully generated %s", outFile) }