Use ImageBuildOptions in builder.
dockerfile.Config is almost redundant with ImageBuildOptions. Unify the two so that the latter can be removed. This also helps build's API endpoint code to be less dependent on package dockerfile. Signed-off-by: Anusha Ragunathan <anusha@docker.com> Upstream-commit: 5190794f1d85d5406611eb69c270df62ac1cdc7f Component: engine
This commit is contained in:
@ -10,11 +10,11 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/builder"
|
||||
"github.com/docker/docker/builder/dockerfile/parser"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
||||
var validCommitCommands = map[string]bool{
|
||||
@ -41,38 +41,10 @@ var BuiltinAllowedBuildArgs = map[string]bool{
|
||||
"no_proxy": true,
|
||||
}
|
||||
|
||||
// Config constitutes the configuration for a Dockerfile builder.
|
||||
type Config struct {
|
||||
// only used if Dockerfile has to be extracted from Context
|
||||
DockerfileName string
|
||||
|
||||
Verbose bool
|
||||
UseCache bool
|
||||
Remove bool
|
||||
ForceRemove bool
|
||||
Pull bool
|
||||
BuildArgs map[string]string // build-time args received in build context for expansion/substitution and commands in 'run'.
|
||||
Isolation container.IsolationLevel
|
||||
|
||||
// resource constraints
|
||||
// TODO: factor out to be reused with Run ?
|
||||
|
||||
Memory int64
|
||||
MemorySwap int64
|
||||
ShmSize *int64
|
||||
CPUShares int64
|
||||
CPUPeriod int64
|
||||
CPUQuota int64
|
||||
CPUSetCpus string
|
||||
CPUSetMems string
|
||||
CgroupParent string
|
||||
Ulimits []*units.Ulimit
|
||||
}
|
||||
|
||||
// Builder is a Dockerfile builder
|
||||
// It implements the builder.Backend interface.
|
||||
type Builder struct {
|
||||
*Config
|
||||
options *types.ImageBuildOptions
|
||||
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
@ -101,18 +73,18 @@ type Builder struct {
|
||||
// NewBuilder creates a new Dockerfile builder from an optional dockerfile and a Config.
|
||||
// If dockerfile is nil, the Dockerfile specified by Config.DockerfileName,
|
||||
// will be read from the Context passed to Build().
|
||||
func NewBuilder(config *Config, docker builder.Backend, context builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) {
|
||||
func NewBuilder(config *types.ImageBuildOptions, backend builder.Backend, context builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) {
|
||||
if config == nil {
|
||||
config = new(Config)
|
||||
config = new(types.ImageBuildOptions)
|
||||
}
|
||||
if config.BuildArgs == nil {
|
||||
config.BuildArgs = make(map[string]string)
|
||||
}
|
||||
b = &Builder{
|
||||
Config: config,
|
||||
options: config,
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stderr,
|
||||
docker: docker,
|
||||
docker: backend,
|
||||
context: context,
|
||||
runConfig: new(container.Config),
|
||||
tmpContainers: map[string]struct{}{},
|
||||
@ -162,14 +134,14 @@ func (b *Builder) Build() (string, error) {
|
||||
// Not cancelled yet, keep going...
|
||||
}
|
||||
if err := b.dispatch(i, n); err != nil {
|
||||
if b.ForceRemove {
|
||||
if b.options.ForceRemove {
|
||||
b.clearTmp()
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
shortImgID = stringid.TruncateID(b.image)
|
||||
fmt.Fprintf(b.Stdout, " ---> %s\n", shortImgID)
|
||||
if b.Remove {
|
||||
if b.options.Remove {
|
||||
b.clearTmp()
|
||||
}
|
||||
}
|
||||
@ -177,7 +149,7 @@ func (b *Builder) Build() (string, error) {
|
||||
// check if there are any leftover build-args that were passed but not
|
||||
// consumed during build. Return an error, if there are any.
|
||||
leftoverArgs := []string{}
|
||||
for arg := range b.BuildArgs {
|
||||
for arg := range b.options.BuildArgs {
|
||||
if !b.isBuildArgAllowed(arg) {
|
||||
leftoverArgs = append(leftoverArgs, arg)
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
|
||||
err error
|
||||
)
|
||||
// TODO: don't use `name`, instead resolve it to a digest
|
||||
if !b.Pull {
|
||||
if !b.options.PullParent {
|
||||
image, err = b.docker.GetImage(name)
|
||||
// TODO: shouldn't we error out if error is different from "not found" ?
|
||||
}
|
||||
@ -339,7 +339,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
|
||||
// lookup for same image built with same build time environment.
|
||||
cmdBuildEnv := []string{}
|
||||
configEnv := runconfigopts.ConvertKVStringsToMap(b.runConfig.Env)
|
||||
for key, val := range b.BuildArgs {
|
||||
for key, val := range b.options.BuildArgs {
|
||||
if !b.isBuildArgAllowed(key) {
|
||||
// skip build-args that are not in allowed list, meaning they have
|
||||
// not been defined by an "ARG" Dockerfile command yet.
|
||||
@ -622,8 +622,8 @@ func arg(b *Builder, args []string, attributes map[string]bool, original string)
|
||||
// If there is a default value associated with this arg then add it to the
|
||||
// b.buildArgs if one is not already passed to the builder. The args passed
|
||||
// to builder override the default value of 'arg'.
|
||||
if _, ok := b.BuildArgs[name]; !ok && hasDefault {
|
||||
b.BuildArgs[name] = value
|
||||
if _, ok := b.options.BuildArgs[name]; !ok && hasDefault {
|
||||
b.options.BuildArgs[name] = value
|
||||
}
|
||||
|
||||
return b.commit("", b.runConfig.Cmd, fmt.Sprintf("ARG %s", arg))
|
||||
|
||||
@ -148,7 +148,7 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
|
||||
// a subsequent one. So, putting the buildArgs list after the Config.Env
|
||||
// list, in 'envs', is safe.
|
||||
envs := b.runConfig.Env
|
||||
for key, val := range b.BuildArgs {
|
||||
for key, val := range b.options.BuildArgs {
|
||||
if !b.isBuildArgAllowed(key) {
|
||||
// skip build-args that are not in allowed list, meaning they have
|
||||
// not been defined by an "ARG" Dockerfile command yet.
|
||||
|
||||
@ -450,7 +450,7 @@ func (b *Builder) processImageFrom(img builder.Image) error {
|
||||
// If there is any error, it returns `(false, err)`.
|
||||
func (b *Builder) probeCache() (bool, error) {
|
||||
c, ok := b.docker.(builder.ImageCache)
|
||||
if !ok || !b.UseCache || b.cacheBusted {
|
||||
if !ok || b.options.NoCache || b.cacheBusted {
|
||||
return false, nil
|
||||
}
|
||||
cache, err := c.GetCachedImage(b.image, b.runConfig)
|
||||
@ -477,21 +477,21 @@ func (b *Builder) create() (string, error) {
|
||||
b.runConfig.Image = b.image
|
||||
|
||||
resources := container.Resources{
|
||||
CgroupParent: b.CgroupParent,
|
||||
CPUShares: b.CPUShares,
|
||||
CPUPeriod: b.CPUPeriod,
|
||||
CPUQuota: b.CPUQuota,
|
||||
CpusetCpus: b.CPUSetCpus,
|
||||
CpusetMems: b.CPUSetMems,
|
||||
Memory: b.Memory,
|
||||
MemorySwap: b.MemorySwap,
|
||||
Ulimits: b.Ulimits,
|
||||
CgroupParent: b.options.CgroupParent,
|
||||
CPUShares: b.options.CPUShares,
|
||||
CPUPeriod: b.options.CPUPeriod,
|
||||
CPUQuota: b.options.CPUQuota,
|
||||
CpusetCpus: b.options.CPUSetCPUs,
|
||||
CpusetMems: b.options.CPUSetMems,
|
||||
Memory: b.options.Memory,
|
||||
MemorySwap: b.options.MemorySwap,
|
||||
Ulimits: b.options.Ulimits,
|
||||
}
|
||||
|
||||
// TODO: why not embed a hostconfig in builder?
|
||||
hostConfig := &container.HostConfig{
|
||||
Isolation: b.Isolation,
|
||||
ShmSize: b.ShmSize,
|
||||
Isolation: b.options.IsolationLevel,
|
||||
ShmSize: b.options.ShmSize,
|
||||
Resources: resources,
|
||||
}
|
||||
|
||||
@ -587,20 +587,20 @@ func (b *Builder) readDockerfile() error {
|
||||
// If no -f was specified then look for 'Dockerfile'. If we can't find
|
||||
// that then look for 'dockerfile'. If neither are found then default
|
||||
// back to 'Dockerfile' and use that in the error message.
|
||||
if b.DockerfileName == "" {
|
||||
b.DockerfileName = api.DefaultDockerfileName
|
||||
if _, _, err := b.context.Stat(b.DockerfileName); os.IsNotExist(err) {
|
||||
lowercase := strings.ToLower(b.DockerfileName)
|
||||
if b.options.Dockerfile == "" {
|
||||
b.options.Dockerfile = api.DefaultDockerfileName
|
||||
if _, _, err := b.context.Stat(b.options.Dockerfile); os.IsNotExist(err) {
|
||||
lowercase := strings.ToLower(b.options.Dockerfile)
|
||||
if _, _, err := b.context.Stat(lowercase); err == nil {
|
||||
b.DockerfileName = lowercase
|
||||
b.options.Dockerfile = lowercase
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f, err := b.context.Open(b.DockerfileName)
|
||||
f, err := b.context.Open(b.options.Dockerfile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("Cannot locate specified Dockerfile: %s", b.DockerfileName)
|
||||
return fmt.Errorf("Cannot locate specified Dockerfile: %s", b.options.Dockerfile)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@ -611,7 +611,7 @@ func (b *Builder) readDockerfile() error {
|
||||
return fmt.Errorf("Unexpected error reading Dockerfile: %v", err)
|
||||
}
|
||||
if fi.Size() == 0 {
|
||||
return fmt.Errorf("The Dockerfile (%s) cannot be empty", b.DockerfileName)
|
||||
return fmt.Errorf("The Dockerfile (%s) cannot be empty", b.options.Dockerfile)
|
||||
}
|
||||
}
|
||||
b.dockerfile, err = parser.Parse(f)
|
||||
@ -629,7 +629,7 @@ func (b *Builder) readDockerfile() error {
|
||||
// Note that this assumes the Dockerfile has been read into memory and
|
||||
// is now safe to be removed.
|
||||
if dockerIgnore, ok := b.context.(builder.DockerIgnoreContext); ok {
|
||||
dockerIgnore.Process([]string{b.DockerfileName})
|
||||
dockerIgnore.Process([]string{b.options.Dockerfile})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user