scripts/gendockerfile.go (93 lines of code) (raw):
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//go:build ignore
// +build ignore
package main
import (
"bytes"
"flag"
"io"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"sort"
"strings"
"text/template"
)
var (
baseFlag = flag.String("base", ".", "base directory of the repo, relative to the working directory")
outFlag = flag.String("o", "Dockerfile-testing", "output file, relative to this directory")
diffFlag = flag.Bool("d", false, "diff file against output file instead of writing")
)
func relPath(p string) string {
if *baseFlag == "." {
return "./" + p
}
rel, err := filepath.Rel(*baseFlag, p)
if err != nil {
panic(err)
}
return rel
}
var dockerfileTemplateFuncs = template.FuncMap{
"join": path.Join,
}
// This generates a Dockerfile that copies all of the go.mod and go.sum
// files found and then runs "go mod download" for each module, before
// copying across the rest of the source code.
var dockerfileTemplate = template.Must(template.New("Dockerfile").Funcs(dockerfileTemplateFuncs).Parse(`
# Code generated by gendockerfile. DO NOT EDIT.
FROM golang:latest
ENV GO111MODULE=on
{{range .Dirs}}
COPY {{join . "go.mod"}} {{join . "go.sum"}} {{join "/go/src/go.elastic.co/apm" .}}/{{end}}
{{range .Dirs}}RUN cd {{join "/go/src/go.elastic.co/apm" .}} && go mod download
{{end}}
WORKDIR /go/src/go.elastic.co/apm
ADD . /go/src/go.elastic.co/apm
`[1:]))
func main() {
flag.Parse()
// Locate all go.mod files.
var moduleDirs []string
if err := filepath.Walk(*baseFlag, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
if info.Name() == "go.mod" {
moduleDirs = append(moduleDirs, relPath(filepath.Dir(path)))
}
return nil
}
name := info.Name()
if name != *baseFlag && (name == "vendor" || name == "tools" || strings.HasPrefix(name, ".")) {
return filepath.SkipDir
}
return nil
}); err != nil {
log.Fatal(err)
}
sort.Strings(moduleDirs)
var buf bytes.Buffer
var out io.Writer = &buf
outFile := filepath.Join(*baseFlag, "scripts", *outFlag)
if !*diffFlag {
f, err := os.Create(outFile)
if err != nil {
log.Fatal(err)
}
defer f.Close()
out = f
}
var data struct {
Dirs []string
}
data.Dirs = moduleDirs
if err := dockerfileTemplate.Execute(out, &data); err != nil {
log.Fatal(err)
}
if *diffFlag {
cmd := exec.Command("diff", "-c", outFile, "-")
cmd.Stdin = &buf
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
}