1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
// Package docker implements a compiler for turning Blubber configuration into
// a valid single- or multi-stage Dockerfile.
//
package docker
import (
"bytes"
"phabricator.wikimedia.org/source/blubber/build"
"phabricator.wikimedia.org/source/blubber/config"
"phabricator.wikimedia.org/source/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")
}
|