summaryrefslogtreecommitdiff
path: root/docker
diff options
context:
space:
mode:
authorDan Duvall <dduvall@wikimedia.org>2017-08-30 09:47:41 -0700
committerDan Duvall <dduvall@wikimedia.org>2017-09-07 10:01:34 -0700
commit410085e1f5be759b6a2bfbe08a51dca84aa18e3c (patch)
tree9c0b1e24953082cfe96e84b0924ba0ac90c67100 /docker
parent2a19f04679b042567dd7ed9c0208eacbb63b8d26 (diff)
downloadblubber-410085e1f5be759b6a2bfbe08a51dca84aa18e3c.tar.gz
Support `copies` config entry for multi-stage builds
Summary: Support a `copies` variant config entry that will result in a multi-stage build, copying both shared library files and application directory from a previously defined variant. This is essentially a shorthand for two `artifacts` entries that are likely to be idiomatic to multi-stage build/prod configurations. Defined a new abstract `build.CopyFrom` instruction and corresponding `docker.DockerCopyFrom` instruction and refactored the writing of these Dockerfile lines to be accomplished using an `InstructionsForPhase` method on `config.ArtifactsConfig`. Implemented new support for `copies` configuration in `config.VariantConfig` and an `InstructionsForPhase` method that returns `build.CopyFrom` instructions for both the shared library and application directories. Fixes T174622 Depends on D759 Test Plan: Run `go test ./...`. Run `blubber blubber.example.yaml production` and ensure the right `COPY --from` lines are included for the final stage. Reviewers: thcipriani, mobrovac, hashar, mmodell, #release-engineering-team Reviewed By: thcipriani, #release-engineering-team Tags: #release-engineering-team Maniphest Tasks: T174622 Differential Revision: https://phabricator.wikimedia.org/D768
Diffstat (limited to 'docker')
-rw-r--r--docker/compiler.go29
-rw-r--r--docker/instructions.go24
-rw-r--r--docker/instructions_test.go12
3 files changed, 36 insertions, 29 deletions
diff --git a/docker/compiler.go b/docker/compiler.go
index e77691f..2891140 100644
--- a/docker/compiler.go
+++ b/docker/compiler.go
@@ -17,25 +17,13 @@ func Compile(cfg *config.Config, variant string) *bytes.Buffer {
// omit the main stage name unless multi-stage is required below
mainStage := ""
- // get unique set of artifact/variant dependencies
- existing := map[string]bool{}
- stages := []string{}
-
- for _, artifact := range vcfg.Artifacts {
- if stage := artifact.From; stage != "" && !existing[stage] {
- existing[stage] = true
- stages = append(stages, stage)
-
- mainStage = variant
- }
- }
-
- // write multi-stage sections for each artifact/variant dependency
- for _, stage := range stages {
+ // write multi-stage sections for each variant dependency
+ for _, stage := range vcfg.VariantDependencies() {
dependency, err := config.ExpandVariant(cfg, stage)
if err == nil {
CompileStage(buffer, stage, dependency)
+ mainStage = variant
}
}
@@ -76,17 +64,6 @@ func CompileStage(buffer *bytes.Buffer, stage string, vcfg *config.VariantConfig
Writeln(buffer, "COPY . .")
}
- // Artifact copying
- for _, artifact := range vcfg.Artifacts {
- Write(buffer, "COPY ")
-
- if artifact.From != "" {
- Write(buffer, "--from=", artifact.From, " ")
- }
-
- Writeln(buffer, "[\"", artifact.Source, "\", \"", artifact.Destination, "\"]")
- }
-
CompilePhase(buffer, vcfg, build.PhasePostInstall)
if len(vcfg.EntryPoint) > 0 {
diff --git a/docker/instructions.go b/docker/instructions.go
index a93ad11..2b00c1b 100644
--- a/docker/instructions.go
+++ b/docker/instructions.go
@@ -18,11 +18,16 @@ func NewDockerInstruction(instruction build.Instruction) (DockerInstruction, err
var dockerInstruction DockerCopy
dockerInstruction.arguments = instruction.Compile()
return dockerInstruction, nil
+ case build.CopyFrom:
+ var dockerInstruction DockerCopyFrom
+ dockerInstruction.arguments = instruction.Compile()
+ return dockerInstruction, nil
case build.Env:
var dockerInstruction DockerEnv
dockerInstruction.arguments = instruction.Compile()
return dockerInstruction, nil
}
+
return nil, errors.New("Unable to create DockerInstruction")
}
@@ -44,7 +49,7 @@ type DockerRun struct{ abstractDockerInstruction }
func (dr DockerRun) Compile() string {
return fmt.Sprintf(
"RUN %s\n",
- removeNewlines(strings.Join(dr.arguments, "")))
+ join(dr.arguments, ""))
}
type DockerCopy struct{ abstractDockerInstruction }
@@ -52,7 +57,16 @@ type DockerCopy struct{ abstractDockerInstruction }
func (dc DockerCopy) Compile() string {
return fmt.Sprintf(
"COPY [%s]\n",
- removeNewlines(strings.Join(dc.arguments, ", ")))
+ join(dc.arguments, ", "))
+}
+
+type DockerCopyFrom struct{ abstractDockerInstruction }
+
+func (dcf DockerCopyFrom) Compile() string {
+ return fmt.Sprintf(
+ "COPY --from=%s [%s]\n",
+ dcf.arguments[0],
+ join(dcf.arguments[1:], ", "))
}
type DockerEnv struct{ abstractDockerInstruction }
@@ -60,7 +74,11 @@ type DockerEnv struct{ abstractDockerInstruction }
func (de DockerEnv) Compile() string {
return fmt.Sprintf(
"ENV %s\n",
- removeNewlines(strings.Join(de.arguments, " ")))
+ join(de.arguments, " "))
+}
+
+func join(arguments []string, delimiter string) string {
+ return removeNewlines(strings.Join(arguments, delimiter))
}
func removeNewlines(instructions string) string {
diff --git a/docker/instructions_test.go b/docker/instructions_test.go
index c03d48b..fb9116b 100644
--- a/docker/instructions_test.go
+++ b/docker/instructions_test.go
@@ -46,6 +46,18 @@ func TestCopy(t *testing.T) {
assert.Equal(t, "COPY [\"foo1\", \"foo2\", \"bar\"]\n", di.Compile())
}
+func TestCopyFrom(t *testing.T) {
+ i := build.CopyFrom{"foo", build.Copy{[]string{"foo1", "foo2"}, "bar"}}
+
+ di, err := docker.NewDockerInstruction(i)
+
+ var dockerCopyFrom docker.DockerCopyFrom
+
+ assert.Nil(t, err)
+ assert.IsType(t, dockerCopyFrom, di)
+ assert.Equal(t, "COPY --from=foo [\"foo1\", \"foo2\", \"bar\"]\n", di.Compile())
+}
+
func TestEnv(t *testing.T) {
i := build.Env{map[string]string{"foo": "bar", "bar": "foo"}}