зеркало из https://github.com/microsoft/docker.git
builder: Refactors according to @tiborvass's comments
Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)
This commit is contained in:
Родитель
305f735080
Коммит
2ef1dec7e8
|
@ -1,15 +0,0 @@
|
|||
package builder
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/runconfig"
|
||||
)
|
||||
|
||||
// Create a new builder. See
|
||||
func NewBuilder(opts *BuildOpts) *BuildFile {
|
||||
return &BuildFile{
|
||||
Dockerfile: nil,
|
||||
Config: &runconfig.Config{},
|
||||
Options: opts,
|
||||
TmpContainers: map[string]struct{}{},
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ import (
|
|||
)
|
||||
|
||||
// dispatch with no layer / parsing. This is effectively not a command.
|
||||
func nullDispatch(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func nullDispatch(b *Builder, args []string, attributes map[string]bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ func nullDispatch(b *BuildFile, args []string, attributes map[string]bool) error
|
|||
// Sets the environment variable foo to bar, also makes interpolation
|
||||
// in the dockerfile available from the next statement on via ${foo}.
|
||||
//
|
||||
func env(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func env(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 2 {
|
||||
return fmt.Errorf("ENV accepts two arguments")
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ func env(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// MAINTAINER some text <maybe@an.email.address>
|
||||
//
|
||||
// Sets the maintainer metadata.
|
||||
func maintainer(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func maintainer(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("MAINTAINER requires only one argument")
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func maintainer(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// Add the file 'foo' to '/path'. Tarball and Remote URL (git, http) handling
|
||||
// exist here. If you do not wish to have this automatic handling, use COPY.
|
||||
//
|
||||
func add(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func add(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 2 {
|
||||
return fmt.Errorf("ADD requires two arguments")
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ func add(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
//
|
||||
// Same as 'ADD' but without the tar and remote url handling.
|
||||
//
|
||||
func dispatchCopy(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func dispatchCopy(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 2 {
|
||||
return fmt.Errorf("COPY requires two arguments")
|
||||
}
|
||||
|
@ -86,16 +86,16 @@ func dispatchCopy(b *BuildFile, args []string, attributes map[string]bool) error
|
|||
//
|
||||
// This sets the image the dockerfile will build on top of.
|
||||
//
|
||||
func from(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func from(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("FROM requires one argument")
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
|
||||
image, err := b.Options.Daemon.Repositories().LookupImage(name)
|
||||
image, err := b.Daemon.Repositories().LookupImage(name)
|
||||
if err != nil {
|
||||
if b.Options.Daemon.Graph().IsNotExist(err) {
|
||||
if b.Daemon.Graph().IsNotExist(err) {
|
||||
image, err = b.pullImage(name)
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ func from(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// special cases. search for 'OnBuild' in internals.go for additional special
|
||||
// cases.
|
||||
//
|
||||
func onbuild(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func onbuild(b *Builder, args []string, attributes map[string]bool) error {
|
||||
triggerInstruction := strings.ToUpper(strings.TrimSpace(args[0]))
|
||||
switch triggerInstruction {
|
||||
case "ONBUILD":
|
||||
|
@ -137,7 +137,7 @@ func onbuild(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
//
|
||||
// Set the working directory for future RUN/CMD/etc statements.
|
||||
//
|
||||
func workdir(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func workdir(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("WORKDIR requires exactly one argument")
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ func workdir(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// RUN echo hi # sh -c echo hi
|
||||
// RUN [ "echo", "hi" ] # echo hi
|
||||
//
|
||||
func run(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func run(b *Builder, args []string, attributes map[string]bool) error {
|
||||
args = handleJsonArgs(args, attributes)
|
||||
|
||||
if b.image == "" {
|
||||
|
@ -220,7 +220,7 @@ func run(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// Set the default command to run in the container (which may be empty).
|
||||
// Argument handling is the same as RUN.
|
||||
//
|
||||
func cmd(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func cmd(b *Builder, args []string, attributes map[string]bool) error {
|
||||
b.Config.Cmd = handleJsonArgs(args, attributes)
|
||||
|
||||
if err := b.commit("", b.Config.Cmd, fmt.Sprintf("CMD %v", cmd)); err != nil {
|
||||
|
@ -239,7 +239,7 @@ func cmd(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// Handles command processing similar to CMD and RUN, only b.Config.Entrypoint
|
||||
// is initialized at NewBuilder time instead of through argument parsing.
|
||||
//
|
||||
func entrypoint(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func entrypoint(b *Builder, args []string, attributes map[string]bool) error {
|
||||
b.Config.Entrypoint = handleJsonArgs(args, attributes)
|
||||
|
||||
// if there is no cmd in current Dockerfile - cleanup cmd
|
||||
|
@ -258,7 +258,7 @@ func entrypoint(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// Expose ports for links and port mappings. This all ends up in
|
||||
// b.Config.ExposedPorts for runconfig.
|
||||
//
|
||||
func expose(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func expose(b *Builder, args []string, attributes map[string]bool) error {
|
||||
portsTab := args
|
||||
|
||||
if b.Config.ExposedPorts == nil {
|
||||
|
@ -285,7 +285,7 @@ func expose(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// Set the user to 'foo' for future commands and when running the
|
||||
// ENTRYPOINT/CMD at container run time.
|
||||
//
|
||||
func user(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func user(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("USER requires exactly one argument")
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ func user(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
// Expose the volume /foo for use. Will also accept the JSON form, but either
|
||||
// way requires exactly one argument.
|
||||
//
|
||||
func volume(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func volume(b *Builder, args []string, attributes map[string]bool) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("Volume cannot be empty")
|
||||
}
|
||||
|
@ -319,6 +319,6 @@ func volume(b *BuildFile, args []string, attributes map[string]bool) error {
|
|||
}
|
||||
|
||||
// INSERT is no longer accepted, but we still parse it.
|
||||
func insert(b *BuildFile, args []string, attributes map[string]bool) error {
|
||||
func insert(b *Builder, args []string, attributes map[string]bool) error {
|
||||
return fmt.Errorf("INSERT has been deprecated. Please use ADD instead")
|
||||
}
|
||||
|
|
|
@ -20,11 +20,9 @@
|
|||
package builder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
@ -42,10 +40,10 @@ var (
|
|||
ErrDockerfileEmpty = errors.New("Dockerfile cannot be empty")
|
||||
)
|
||||
|
||||
var evaluateTable map[string]func(*BuildFile, []string, map[string]bool) error
|
||||
var evaluateTable map[string]func(*Builder, []string, map[string]bool) error
|
||||
|
||||
func init() {
|
||||
evaluateTable = map[string]func(*BuildFile, []string, map[string]bool) error{
|
||||
evaluateTable = map[string]func(*Builder, []string, map[string]bool) error{
|
||||
"env": env,
|
||||
"maintainer": maintainer,
|
||||
"add": add,
|
||||
|
@ -66,23 +64,7 @@ func init() {
|
|||
|
||||
// internal struct, used to maintain configuration of the Dockerfile's
|
||||
// processing as it evaluates the parsing result.
|
||||
type BuildFile struct {
|
||||
Dockerfile *parser.Node // the syntax tree of the dockerfile
|
||||
Config *runconfig.Config // runconfig for cmd, run, entrypoint etc.
|
||||
Options *BuildOpts // see below
|
||||
|
||||
// both of these are controlled by the Remove and ForceRemove options in BuildOpts
|
||||
TmpContainers map[string]struct{} // a map of containers used for removes
|
||||
|
||||
image string // image name for commit processing
|
||||
maintainer string // maintainer name. could probably be removed.
|
||||
cmdSet bool // indicates is CMD was set in current Dockerfile
|
||||
context *tarsum.TarSum // the context is a tarball that is uploaded by the client
|
||||
contextPath string // the path of the temporary directory the local context is unpacked to (server side)
|
||||
|
||||
}
|
||||
|
||||
type BuildOpts struct {
|
||||
type Builder struct {
|
||||
Daemon *daemon.Daemon
|
||||
Engine *engine.Engine
|
||||
|
||||
|
@ -104,6 +86,19 @@ type BuildOpts struct {
|
|||
// Deprecated, original writer used for ImagePull. To be removed.
|
||||
OutOld io.Writer
|
||||
StreamFormatter *utils.StreamFormatter
|
||||
|
||||
Config *runconfig.Config // runconfig for cmd, run, entrypoint etc.
|
||||
|
||||
// both of these are controlled by the Remove and ForceRemove options in BuildOpts
|
||||
TmpContainers map[string]struct{} // a map of containers used for removes
|
||||
|
||||
dockerfile *parser.Node // the syntax tree of the dockerfile
|
||||
image string // image name for commit processing
|
||||
maintainer string // maintainer name. could probably be removed.
|
||||
cmdSet bool // indicates is CMD was set in current Dockerfile
|
||||
context *tarsum.TarSum // the context is a tarball that is uploaded by the client
|
||||
contextPath string // the path of the temporary directory the local context is unpacked to (server side)
|
||||
|
||||
}
|
||||
|
||||
// Run the builder with the context. This is the lynchpin of this package. This
|
||||
|
@ -118,38 +113,48 @@ type BuildOpts struct {
|
|||
// processing.
|
||||
// * Print a happy message and return the image ID.
|
||||
//
|
||||
func (b *BuildFile) Run(context io.Reader) (string, error) {
|
||||
func (b *Builder) Run(context io.Reader) (string, error) {
|
||||
if err := b.readContext(context); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
filename := path.Join(b.contextPath, "Dockerfile")
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
|
||||
fi, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("Cannot build a directory without a Dockerfile")
|
||||
}
|
||||
fileBytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(fileBytes) == 0 {
|
||||
if fi.Size() == 0 {
|
||||
return "", ErrDockerfileEmpty
|
||||
}
|
||||
ast, err := parser.Parse(bytes.NewReader(fileBytes))
|
||||
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
b.Dockerfile = ast
|
||||
defer f.Close()
|
||||
|
||||
for i, n := range b.Dockerfile.Children {
|
||||
ast, err := parser.Parse(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
b.dockerfile = ast
|
||||
|
||||
// some initializations that would not have been supplied by the caller.
|
||||
b.Config = &runconfig.Config{}
|
||||
b.TmpContainers = map[string]struct{}{}
|
||||
|
||||
for i, n := range b.dockerfile.Children {
|
||||
if err := b.dispatch(i, n); err != nil {
|
||||
if b.Options.ForceRemove {
|
||||
if b.ForceRemove {
|
||||
b.clearTmp()
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
fmt.Fprintf(b.Options.OutStream, " ---> %s\n", utils.TruncateID(b.image))
|
||||
if b.Options.Remove {
|
||||
fmt.Fprintf(b.OutStream, " ---> %s\n", utils.TruncateID(b.image))
|
||||
if b.Remove {
|
||||
b.clearTmp()
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +163,7 @@ func (b *BuildFile) Run(context io.Reader) (string, error) {
|
|||
return "", fmt.Errorf("No image was generated. Is your Dockerfile empty?\n")
|
||||
}
|
||||
|
||||
fmt.Fprintf(b.Options.OutStream, "Successfully built %s\n", utils.TruncateID(b.image))
|
||||
fmt.Fprintf(b.OutStream, "Successfully built %s\n", utils.TruncateID(b.image))
|
||||
return b.image, nil
|
||||
}
|
||||
|
||||
|
@ -168,7 +173,7 @@ func (b *BuildFile) Run(context io.Reader) (string, error) {
|
|||
// Child[Node, Node, Node] where Child is from parser.Node.Children and each
|
||||
// node comes from parser.Node.Next. This forms a "line" with a statement and
|
||||
// arguments and we process them in this normalized form by hitting
|
||||
// evaluateTable with the leaf nodes of the command and the BuildFile object.
|
||||
// evaluateTable with the leaf nodes of the command and the Builder object.
|
||||
//
|
||||
// ONBUILD is a special case; in this case the parser will emit:
|
||||
// Child[Node, Child[Node, Node...]] where the first node is the literal
|
||||
|
@ -176,14 +181,13 @@ func (b *BuildFile) Run(context io.Reader) (string, error) {
|
|||
// such as `RUN` in ONBUILD RUN foo. There is special case logic in here to
|
||||
// deal with that, at least until it becomes more of a general concern with new
|
||||
// features.
|
||||
func (b *BuildFile) dispatch(stepN int, ast *parser.Node) error {
|
||||
func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
|
||||
cmd := ast.Value
|
||||
attrs := ast.Attributes
|
||||
strs := []string{}
|
||||
msg := fmt.Sprintf("Step %d : %s", stepN, strings.ToUpper(cmd))
|
||||
|
||||
if cmd == "onbuild" {
|
||||
fmt.Fprintf(b.Options.OutStream, "%#v\n", ast.Next.Children[0].Value)
|
||||
ast = ast.Next.Children[0]
|
||||
strs = append(strs, b.replaceEnv(ast.Value))
|
||||
msg += " " + ast.Value
|
||||
|
@ -195,7 +199,7 @@ func (b *BuildFile) dispatch(stepN int, ast *parser.Node) error {
|
|||
msg += " " + ast.Value
|
||||
}
|
||||
|
||||
fmt.Fprintf(b.Options.OutStream, "%s\n", msg)
|
||||
fmt.Fprintln(b.OutStream, msg)
|
||||
|
||||
// XXX yes, we skip any cmds that are not valid; the parser should have
|
||||
// picked these out already.
|
||||
|
@ -203,7 +207,7 @@ func (b *BuildFile) dispatch(stepN int, ast *parser.Node) error {
|
|||
return f(b, strs, attrs)
|
||||
}
|
||||
|
||||
fmt.Fprintf(b.Options.ErrStream, "# Skipping unknown instruction %s\n", strings.ToUpper(cmd))
|
||||
fmt.Fprintf(b.ErrStream, "# Skipping unknown instruction %s\n", strings.ToUpper(cmd))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
"github.com/docker/docker/utils"
|
||||
)
|
||||
|
||||
func (b *BuildFile) readContext(context io.Reader) error {
|
||||
func (b *Builder) readContext(context io.Reader) error {
|
||||
tmpdirPath, err := ioutil.TempDir("", "docker-build")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -50,7 +50,7 @@ func (b *BuildFile) readContext(context io.Reader) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) commit(id string, autoCmd []string, comment string) error {
|
||||
func (b *Builder) commit(id string, autoCmd []string, comment string) error {
|
||||
if b.image == "" {
|
||||
return fmt.Errorf("Please provide a source image with `from` prior to commit")
|
||||
}
|
||||
|
@ -68,15 +68,15 @@ func (b *BuildFile) commit(id string, autoCmd []string, comment string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
container, warnings, err := b.Options.Daemon.Create(b.Config, "")
|
||||
container, warnings, err := b.Daemon.Create(b.Config, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, warning := range warnings {
|
||||
fmt.Fprintf(b.Options.OutStream, " ---> [Warning] %s\n", warning)
|
||||
fmt.Fprintf(b.OutStream, " ---> [Warning] %s\n", warning)
|
||||
}
|
||||
b.TmpContainers[container.ID] = struct{}{}
|
||||
fmt.Fprintf(b.Options.OutStream, " ---> Running in %s\n", utils.TruncateID(container.ID))
|
||||
fmt.Fprintf(b.OutStream, " ---> Running in %s\n", utils.TruncateID(container.ID))
|
||||
id = container.ID
|
||||
|
||||
if err := container.Mount(); err != nil {
|
||||
|
@ -84,7 +84,7 @@ func (b *BuildFile) commit(id string, autoCmd []string, comment string) error {
|
|||
}
|
||||
defer container.Unmount()
|
||||
}
|
||||
container := b.Options.Daemon.Get(id)
|
||||
container := b.Daemon.Get(id)
|
||||
if container == nil {
|
||||
return fmt.Errorf("An error occured while creating the container")
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ func (b *BuildFile) commit(id string, autoCmd []string, comment string) error {
|
|||
autoConfig := *b.Config
|
||||
autoConfig.Cmd = autoCmd
|
||||
// Commit the container
|
||||
image, err := b.Options.Daemon.Commit(container, "", "", "", b.maintainer, true, &autoConfig)
|
||||
image, err := b.Daemon.Commit(container, "", "", "", b.maintainer, true, &autoConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ func (b *BuildFile) commit(id string, autoCmd []string, comment string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) runContextCommand(args []string, allowRemote bool, allowDecompression bool, cmdName string) error {
|
||||
func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecompression bool, cmdName string) error {
|
||||
if b.context == nil {
|
||||
return fmt.Errorf("No context given. Impossible to use %s", cmdName)
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func (b *BuildFile) runContextCommand(args []string, allowRemote bool, allowDeco
|
|||
}
|
||||
|
||||
// Hash path and check the cache
|
||||
if b.Options.UtilizeCache {
|
||||
if b.UtilizeCache {
|
||||
var (
|
||||
hash string
|
||||
sums = b.context.GetSums()
|
||||
|
@ -244,7 +244,7 @@ func (b *BuildFile) runContextCommand(args []string, allowRemote bool, allowDeco
|
|||
}
|
||||
|
||||
// Create the container
|
||||
container, _, err := b.Options.Daemon.Create(b.Config, "")
|
||||
container, _, err := b.Daemon.Create(b.Config, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -268,27 +268,27 @@ func (b *BuildFile) runContextCommand(args []string, allowRemote bool, allowDeco
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) pullImage(name string) (*imagepkg.Image, error) {
|
||||
func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
|
||||
remote, tag := parsers.ParseRepositoryTag(name)
|
||||
pullRegistryAuth := b.Options.AuthConfig
|
||||
if len(b.Options.AuthConfigFile.Configs) > 0 {
|
||||
pullRegistryAuth := b.AuthConfig
|
||||
if len(b.AuthConfigFile.Configs) > 0 {
|
||||
// The request came with a full auth config file, we prefer to use that
|
||||
endpoint, _, err := registry.ResolveRepositoryName(remote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resolvedAuth := b.Options.AuthConfigFile.ResolveAuthConfig(endpoint)
|
||||
resolvedAuth := b.AuthConfigFile.ResolveAuthConfig(endpoint)
|
||||
pullRegistryAuth = &resolvedAuth
|
||||
}
|
||||
job := b.Options.Engine.Job("pull", remote, tag)
|
||||
job.SetenvBool("json", b.Options.StreamFormatter.Json())
|
||||
job := b.Engine.Job("pull", remote, tag)
|
||||
job.SetenvBool("json", b.StreamFormatter.Json())
|
||||
job.SetenvBool("parallel", true)
|
||||
job.SetenvJson("authConfig", pullRegistryAuth)
|
||||
job.Stdout.Add(b.Options.OutOld)
|
||||
job.Stdout.Add(b.OutOld)
|
||||
if err := job.Run(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
image, err := b.Options.Daemon.Repositories().LookupImage(name)
|
||||
image, err := b.Daemon.Repositories().LookupImage(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ func (b *BuildFile) pullImage(name string) (*imagepkg.Image, error) {
|
|||
return image, nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) processImageFrom(img *imagepkg.Image) error {
|
||||
func (b *Builder) processImageFrom(img *imagepkg.Image) error {
|
||||
b.image = img.ID
|
||||
|
||||
if img.Config != nil {
|
||||
|
@ -309,7 +309,7 @@ func (b *BuildFile) processImageFrom(img *imagepkg.Image) error {
|
|||
|
||||
// Process ONBUILD triggers if they exist
|
||||
if nTriggers := len(b.Config.OnBuild); nTriggers != 0 {
|
||||
fmt.Fprintf(b.Options.ErrStream, "# Executing %d build triggers\n", nTriggers)
|
||||
fmt.Fprintf(b.ErrStream, "# Executing %d build triggers\n", nTriggers)
|
||||
}
|
||||
|
||||
// Copy the ONBUILD triggers, and remove them from the config, since the config will be commited.
|
||||
|
@ -330,7 +330,8 @@ func (b *BuildFile) processImageFrom(img *imagepkg.Image) error {
|
|||
}
|
||||
|
||||
// FIXME we have to run the evaluator manually here. This does not belong
|
||||
// in this function.
|
||||
// in this function. Once removed, the init() in evaluator.go should no
|
||||
// longer be necessary.
|
||||
|
||||
if f, ok := evaluateTable[strings.ToLower(stepInstruction)]; ok {
|
||||
if err := f(b, splitStep[1:], nil); err != nil {
|
||||
|
@ -344,17 +345,17 @@ func (b *BuildFile) processImageFrom(img *imagepkg.Image) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// probeCache checks to see if image-caching is enabled (`b.Options.UtilizeCache`)
|
||||
// probeCache checks to see if image-caching is enabled (`b.UtilizeCache`)
|
||||
// and if so attempts to look up the current `b.image` and `b.Config` pair
|
||||
// in the current server `b.Options.Daemon`. If an image is found, probeCache returns
|
||||
// in the current server `b.Daemon`. If an image is found, probeCache returns
|
||||
// `(true, nil)`. If no image is found, it returns `(false, nil)`. If there
|
||||
// is any error, it returns `(false, err)`.
|
||||
func (b *BuildFile) probeCache() (bool, error) {
|
||||
if b.Options.UtilizeCache {
|
||||
if cache, err := b.Options.Daemon.ImageGetCached(b.image, b.Config); err != nil {
|
||||
func (b *Builder) probeCache() (bool, error) {
|
||||
if b.UtilizeCache {
|
||||
if cache, err := b.Daemon.ImageGetCached(b.image, b.Config); err != nil {
|
||||
return false, err
|
||||
} else if cache != nil {
|
||||
fmt.Fprintf(b.Options.OutStream, " ---> Using cache\n")
|
||||
fmt.Fprintf(b.OutStream, " ---> Using cache\n")
|
||||
log.Debugf("[BUILDER] Use cached version")
|
||||
b.image = cache.ID
|
||||
return true, nil
|
||||
|
@ -365,19 +366,20 @@ func (b *BuildFile) probeCache() (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) create() (*daemon.Container, error) {
|
||||
func (b *Builder) create() (*daemon.Container, error) {
|
||||
if b.image == "" {
|
||||
return nil, fmt.Errorf("Please provide a source image with `from` prior to run")
|
||||
}
|
||||
b.Config.Image = b.image
|
||||
|
||||
// Create the container
|
||||
c, _, err := b.Options.Daemon.Create(b.Config, "")
|
||||
c, _, err := b.Daemon.Create(b.Config, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.TmpContainers[c.ID] = struct{}{}
|
||||
fmt.Fprintf(b.Options.OutStream, " ---> Running in %s\n", utils.TruncateID(c.ID))
|
||||
fmt.Fprintf(b.OutStream, " ---> Running in %s\n", utils.TruncateID(c.ID))
|
||||
|
||||
// override the entry point that may have been picked up from the base image
|
||||
c.Path = b.Config.Cmd[0]
|
||||
|
@ -386,16 +388,16 @@ func (b *BuildFile) create() (*daemon.Container, error) {
|
|||
return c, nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) run(c *daemon.Container) error {
|
||||
func (b *Builder) run(c *daemon.Container) error {
|
||||
var errCh chan error
|
||||
if b.Options.Verbose {
|
||||
if b.Verbose {
|
||||
errCh = utils.Go(func() error {
|
||||
// FIXME: call the 'attach' job so that daemon.Attach can be made private
|
||||
//
|
||||
// FIXME (LK4D4): Also, maybe makes sense to call "logs" job, it is like attach
|
||||
// but without hijacking for stdin. Also, with attach there can be race
|
||||
// condition because of some output already was printed before it.
|
||||
return <-b.Options.Daemon.Attach(c, nil, nil, b.Options.OutStream, b.Options.ErrStream)
|
||||
return <-b.Daemon.Attach(c, nil, nil, b.OutStream, b.ErrStream)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -422,7 +424,7 @@ func (b *BuildFile) run(c *daemon.Container) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) checkPathForAddition(orig string) error {
|
||||
func (b *Builder) checkPathForAddition(orig string) error {
|
||||
origPath := path.Join(b.contextPath, orig)
|
||||
origPath, err := filepath.EvalSymlinks(origPath)
|
||||
if err != nil {
|
||||
|
@ -443,7 +445,7 @@ func (b *BuildFile) checkPathForAddition(orig string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *BuildFile) addContext(container *daemon.Container, orig, dest string, decompress bool) error {
|
||||
func (b *Builder) addContext(container *daemon.Container, orig, dest string, decompress bool) error {
|
||||
var (
|
||||
err error
|
||||
destExists = true
|
||||
|
@ -548,14 +550,14 @@ func fixPermissions(destination string, uid, gid int) error {
|
|||
})
|
||||
}
|
||||
|
||||
func (b *BuildFile) clearTmp() {
|
||||
func (b *Builder) clearTmp() {
|
||||
for c := range b.TmpContainers {
|
||||
tmp := b.Options.Daemon.Get(c)
|
||||
if err := b.Options.Daemon.Destroy(tmp); err != nil {
|
||||
fmt.Fprintf(b.Options.OutStream, "Error removing intermediate container %s: %s\n", utils.TruncateID(c), err.Error())
|
||||
tmp := b.Daemon.Get(c)
|
||||
if err := b.Daemon.Destroy(tmp); err != nil {
|
||||
fmt.Fprintf(b.OutStream, "Error removing intermediate container %s: %s\n", utils.TruncateID(c), err.Error())
|
||||
} else {
|
||||
delete(b.TmpContainers, c)
|
||||
fmt.Fprintf(b.Options.OutStream, "Removing intermediate container %s\n", utils.TruncateID(c))
|
||||
fmt.Fprintf(b.OutStream, "Removing intermediate container %s\n", utils.TruncateID(c))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) engine.Status {
|
|||
|
||||
sf := utils.NewStreamFormatter(job.GetenvBool("json"))
|
||||
|
||||
opts := &BuildOpts{
|
||||
builder := &Builder{
|
||||
Daemon: b.Daemon,
|
||||
Engine: b.Engine,
|
||||
OutStream: &utils.StdoutFormater{
|
||||
|
@ -106,7 +106,7 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) engine.Status {
|
|||
AuthConfigFile: configFile,
|
||||
}
|
||||
|
||||
id, err := NewBuilder(opts).Run(context)
|
||||
id, err := builder.Run(context)
|
||||
if err != nil {
|
||||
return job.Error(err)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ var (
|
|||
)
|
||||
|
||||
// handle environment replacement. Used in dispatcher.
|
||||
func (b *BuildFile) replaceEnv(str string) string {
|
||||
func (b *Builder) replaceEnv(str string) string {
|
||||
for _, match := range TOKEN_ENV_INTERPOLATION.FindAllString(str, -1) {
|
||||
match = match[strings.Index(match, "$"):]
|
||||
matchKey := strings.Trim(match, "${}")
|
||||
|
|
Загрузка…
Ссылка в новой задаче