Remove package daemonbuilder.
Currently, daemonbuilder package (part of daemon) implemented the builder backend. However, it was a very thin wrapper around daemon methods and caused an implementation dependency for api/server build endpoint. api/server buildrouter should only know about the backend implementing the /build API endpoint. Removing daemonbuilder involved moving build specific methods to respective files in the daemon, where they fit naturally. Signed-off-by: Anusha Ragunathan <anusha@docker.com> Upstream-commit: 9c332b164f1aefa2407706adf59d50495d6e02cb Component: engine
This commit is contained in:
@ -2,6 +2,7 @@ package dockerfile
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -13,6 +14,7 @@ import (
|
||||
"github.com/docker/docker/builder"
|
||||
"github.com/docker/docker/builder/dockerfile/parser"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/reference"
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/docker/engine-api/types/container"
|
||||
)
|
||||
@ -48,6 +50,7 @@ type Builder struct {
|
||||
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
Output io.Writer
|
||||
|
||||
docker builder.Backend
|
||||
context builder.Context
|
||||
@ -67,8 +70,17 @@ type Builder struct {
|
||||
allowedBuildArgs map[string]bool // list of build-time args that are allowed for expansion/substitution and passing to commands in 'run'.
|
||||
|
||||
// TODO: remove once docker.Commit can receive a tag
|
||||
id string
|
||||
Output io.Writer
|
||||
id string
|
||||
}
|
||||
|
||||
// BuildManager implements builder.Backend and is shared across all Builder objects.
|
||||
type BuildManager struct {
|
||||
backend builder.Backend
|
||||
}
|
||||
|
||||
// NewBuildManager creates a BuildManager.
|
||||
func NewBuildManager(b builder.Backend) (bm *BuildManager) {
|
||||
return &BuildManager{backend: b}
|
||||
}
|
||||
|
||||
// NewBuilder creates a new Dockerfile builder from an optional dockerfile and a Config.
|
||||
@ -103,7 +115,57 @@ func NewBuilder(config *types.ImageBuildOptions, backend builder.Backend, contex
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Build runs the Dockerfile builder from a context and a docker object that allows to make calls
|
||||
// sanitizeRepoAndTags parses the raw "t" parameter received from the client
|
||||
// to a slice of repoAndTag.
|
||||
// It also validates each repoName and tag.
|
||||
func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
|
||||
var (
|
||||
repoAndTags []reference.Named
|
||||
// This map is used for deduplicating the "-t" parameter.
|
||||
uniqNames = make(map[string]struct{})
|
||||
)
|
||||
for _, repo := range names {
|
||||
if repo == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
ref, err := reference.ParseNamed(repo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ref = reference.WithDefaultTag(ref)
|
||||
|
||||
if _, isCanonical := ref.(reference.Canonical); isCanonical {
|
||||
return nil, errors.New("build tag cannot contain a digest")
|
||||
}
|
||||
|
||||
if _, isTagged := ref.(reference.NamedTagged); !isTagged {
|
||||
ref, err = reference.WithTag(ref, reference.DefaultTag)
|
||||
}
|
||||
|
||||
nameWithTag := ref.String()
|
||||
|
||||
if _, exists := uniqNames[nameWithTag]; !exists {
|
||||
uniqNames[nameWithTag] = struct{}{}
|
||||
repoAndTags = append(repoAndTags, ref)
|
||||
}
|
||||
}
|
||||
return repoAndTags, nil
|
||||
}
|
||||
|
||||
// Build creates a NewBuilder, which builds the image.
|
||||
func (bm *BuildManager) Build(config *types.ImageBuildOptions, context builder.Context, stdout io.Writer, stderr io.Writer, out io.Writer, clientGone <-chan bool) (string, error) {
|
||||
b, err := NewBuilder(config, bm.backend, context, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
img, err := b.build(config, context, stdout, stderr, out, clientGone)
|
||||
return img, err
|
||||
|
||||
}
|
||||
|
||||
// build runs the Dockerfile builder from a context and a docker object that allows to make calls
|
||||
// to Docker.
|
||||
//
|
||||
// This will (barring errors):
|
||||
@ -113,10 +175,16 @@ func NewBuilder(config *types.ImageBuildOptions, backend builder.Backend, contex
|
||||
// * walk the AST and execute it by dispatching to handlers. If Remove
|
||||
// or ForceRemove is set, additional cleanup around containers happens after
|
||||
// processing.
|
||||
// * Tag image, if applicable.
|
||||
// * Print a happy message and return the image ID.
|
||||
// * NOT tag the image, that is responsibility of the caller.
|
||||
//
|
||||
func (b *Builder) Build() (string, error) {
|
||||
func (b *Builder) build(config *types.ImageBuildOptions, context builder.Context, stdout io.Writer, stderr io.Writer, out io.Writer, clientGone <-chan bool) (string, error) {
|
||||
b.options = config
|
||||
b.context = context
|
||||
b.Stdout = stdout
|
||||
b.Stderr = stderr
|
||||
b.Output = out
|
||||
|
||||
// If Dockerfile was not parsed yet, extract it from the Context
|
||||
if b.dockerfile == nil {
|
||||
if err := b.readDockerfile(); err != nil {
|
||||
@ -124,6 +192,24 @@ func (b *Builder) Build() (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
finished := make(chan struct{})
|
||||
defer close(finished)
|
||||
go func() {
|
||||
select {
|
||||
case <-finished:
|
||||
case <-clientGone:
|
||||
b.cancelOnce.Do(func() {
|
||||
close(b.cancelled)
|
||||
})
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
repoAndTags, err := sanitizeRepoAndTags(config.Tags)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var shortImgID string
|
||||
for i, n := range b.dockerfile.Children {
|
||||
select {
|
||||
@ -163,6 +249,12 @@ func (b *Builder) Build() (string, error) {
|
||||
return "", fmt.Errorf("No image was generated. Is your Dockerfile empty?")
|
||||
}
|
||||
|
||||
for _, rt := range repoAndTags {
|
||||
if err := b.docker.TagImage(rt, b.image); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(b.Stdout, "Successfully built %s\n", shortImgID)
|
||||
return b.image, nil
|
||||
}
|
||||
|
||||
@ -208,11 +208,11 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
|
||||
} else {
|
||||
// TODO: don't use `name`, instead resolve it to a digest
|
||||
if !b.options.PullParent {
|
||||
image, err = b.docker.GetImage(name)
|
||||
image, err = b.docker.GetImageOnBuild(name)
|
||||
// TODO: shouldn't we error out if error is different from "not found" ?
|
||||
}
|
||||
if image == nil {
|
||||
image, err = b.docker.Pull(name, b.options.AuthConfigs, b.Output)
|
||||
image, err = b.docker.PullOnBuild(name, b.options.AuthConfigs, b.Output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -205,7 +205,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
if err := b.docker.BuilderCopy(container.ID, dest, info.FileInfo, info.decompress); err != nil {
|
||||
if err := b.docker.CopyOnBuild(container.ID, dest, info.FileInfo, info.decompress); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -396,10 +396,10 @@ func containsWildcards(name string) bool {
|
||||
|
||||
func (b *Builder) processImageFrom(img builder.Image) error {
|
||||
if img != nil {
|
||||
b.image = img.ID()
|
||||
b.image = img.ImageID()
|
||||
|
||||
if img.Config() != nil {
|
||||
b.runConfig = img.Config()
|
||||
if img.RunConfig() != nil {
|
||||
b.runConfig = img.RunConfig()
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,7 +469,7 @@ func (b *Builder) probeCache() (bool, error) {
|
||||
if !ok || b.options.NoCache || b.cacheBusted {
|
||||
return false, nil
|
||||
}
|
||||
cache, err := c.GetCachedImage(b.image, b.runConfig)
|
||||
cache, err := c.GetCachedImageOnBuild(b.image, b.runConfig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -530,7 +530,7 @@ func (b *Builder) create() (string, error) {
|
||||
|
||||
if config.Cmd.Len() > 0 {
|
||||
// override the entry point that may have been picked up from the base image
|
||||
if err := b.docker.ContainerUpdateCmd(c.ID, config.Cmd.Slice()); err != nil {
|
||||
if err := b.docker.ContainerUpdateCmdOnBuild(c.ID, config.Cmd.Slice()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
@ -541,7 +541,7 @@ func (b *Builder) create() (string, error) {
|
||||
func (b *Builder) run(cID string) (err error) {
|
||||
errCh := make(chan error)
|
||||
go func() {
|
||||
errCh <- b.docker.ContainerAttach(cID, nil, b.Stdout, b.Stderr, true)
|
||||
errCh <- b.docker.ContainerAttachOnBuild(cID, nil, b.Stdout, b.Stderr, true)
|
||||
}()
|
||||
|
||||
finished := make(chan struct{})
|
||||
|
||||
Reference in New Issue
Block a user