// Package docker implements a compiler for turning Blubber configuration into // a valid single- or multi-stage Dockerfile. // package docker import ( "bytes" "gerrit.wikimedia.org/r/blubber/build" "gerrit.wikimedia.org/r/blubber/config" "gerrit.wikimedia.org/r/blubber/meta" ) // Compile takes a parsed config.Config and a configured variant name and // returns the bytes of a resulting Dockerfile. In the case where artifacts // are defined or the shorthand "copies" configured is set, a multi-stage // Dockerfile will be returned. // func Compile(cfg *config.Config, variant string) (*bytes.Buffer, error) { buffer := new(bytes.Buffer) vcfg, err := config.ExpandVariant(cfg, variant) if err != nil { return nil, err } // omit the main stage name unless multi-stage is required below mainStage := "" // write multi-stage sections for each variant dependency for _, stage := range vcfg.VariantDependencies() { dependency, err := config.ExpandVariant(cfg, stage) if err != nil { return nil, err } compileStage(buffer, stage, dependency) mainStage = variant } compileStage(buffer, mainStage, vcfg) // add meta-data labels to the final stage compileInstructions(buffer, build.Label{map[string]string{ "blubber.variant": variant, "blubber.version": meta.FullVersion(), }}) return buffer, nil } func compileStage(buffer *bytes.Buffer, stage string, vcfg *config.VariantConfig) { baseAndStage := vcfg.Base if stage != "" { baseAndStage += " AS " + stage } writeln(buffer, "FROM ", baseAndStage) for _, phase := range build.Phases() { compilePhase(buffer, vcfg, phase) } } func compileInstructions(buffer *bytes.Buffer, instructions ...build.Instruction) { for _, instruction := range instructions { dockerInstruction, _ := NewInstruction(instruction) write(buffer, dockerInstruction.Compile()) } } func compilePhase(buffer *bytes.Buffer, vcfg *config.VariantConfig, phase build.Phase) { compileInstructions(buffer, vcfg.InstructionsForPhase(phase)...) } func write(buffer *bytes.Buffer, strings ...string) { for _, str := range strings { buffer.WriteString(str) } } func writeln(buffer *bytes.Buffer, strings ...string) { write(buffer, strings...) buffer.WriteString("\n") }