2018-02-05 16:05:59 -05:00
|
|
|
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
2017-04-06 17:38:02 -04:00
|
|
|
|
2017-04-26 17:45:16 -04:00
|
|
|
import (
|
|
|
|
"fmt"
|
2017-05-09 11:25:33 -04:00
|
|
|
"io"
|
2017-04-13 18:44:36 -04:00
|
|
|
|
|
|
|
"github.com/docker/docker/runconfig/opts"
|
2017-04-26 17:45:16 -04:00
|
|
|
)
|
|
|
|
|
2017-04-06 17:38:02 -04:00
|
|
|
// builtinAllowedBuildArgs is list of built-in allowed build args
|
|
|
|
// these args are considered transparent and are excluded from the image history.
|
|
|
|
// Filtering from history is implemented in dispatchers.go
|
|
|
|
var builtinAllowedBuildArgs = map[string]bool{
|
|
|
|
"HTTP_PROXY": true,
|
|
|
|
"http_proxy": true,
|
|
|
|
"HTTPS_PROXY": true,
|
|
|
|
"https_proxy": true,
|
|
|
|
"FTP_PROXY": true,
|
|
|
|
"ftp_proxy": true,
|
|
|
|
"NO_PROXY": true,
|
|
|
|
"no_proxy": true,
|
|
|
|
}
|
|
|
|
|
2018-05-07 13:49:13 -04:00
|
|
|
// BuildArgs manages arguments used by the builder
|
|
|
|
type BuildArgs struct {
|
2017-04-06 17:38:02 -04:00
|
|
|
// args that are allowed for expansion/substitution and passing to commands in 'run'.
|
|
|
|
allowedBuildArgs map[string]*string
|
|
|
|
// args defined before the first `FROM` in a Dockerfile
|
|
|
|
allowedMetaArgs map[string]*string
|
|
|
|
// args referenced by the Dockerfile
|
|
|
|
referencedArgs map[string]struct{}
|
|
|
|
// args provided by the user on the command line
|
|
|
|
argsFromOptions map[string]*string
|
|
|
|
}
|
|
|
|
|
2018-05-07 13:49:13 -04:00
|
|
|
// NewBuildArgs creates a new BuildArgs type
|
|
|
|
func NewBuildArgs(argsFromOptions map[string]*string) *BuildArgs {
|
|
|
|
return &BuildArgs{
|
2017-04-06 17:38:02 -04:00
|
|
|
allowedBuildArgs: make(map[string]*string),
|
|
|
|
allowedMetaArgs: make(map[string]*string),
|
|
|
|
referencedArgs: make(map[string]struct{}),
|
|
|
|
argsFromOptions: argsFromOptions,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-07 13:49:13 -04:00
|
|
|
// Clone returns a copy of the BuildArgs type
|
|
|
|
func (b *BuildArgs) Clone() *BuildArgs {
|
|
|
|
result := NewBuildArgs(b.argsFromOptions)
|
2017-05-22 11:21:17 -04:00
|
|
|
for k, v := range b.allowedBuildArgs {
|
|
|
|
result.allowedBuildArgs[k] = v
|
|
|
|
}
|
|
|
|
for k, v := range b.allowedMetaArgs {
|
|
|
|
result.allowedMetaArgs[k] = v
|
|
|
|
}
|
|
|
|
for k := range b.referencedArgs {
|
|
|
|
result.referencedArgs[k] = struct{}{}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2018-05-07 13:49:13 -04:00
|
|
|
// MergeReferencedArgs merges referenced args from another BuildArgs
|
|
|
|
// object into the current one
|
|
|
|
func (b *BuildArgs) MergeReferencedArgs(other *BuildArgs) {
|
2017-05-22 11:21:17 -04:00
|
|
|
for k := range other.referencedArgs {
|
|
|
|
b.referencedArgs[k] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-09 11:25:33 -04:00
|
|
|
// WarnOnUnusedBuildArgs checks if there are any leftover build-args that were
|
|
|
|
// passed but not consumed during build. Print a warning, if there are any.
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) WarnOnUnusedBuildArgs(out io.Writer) {
|
2018-05-19 07:38:54 -04:00
|
|
|
var leftoverArgs []string
|
2017-04-06 17:38:02 -04:00
|
|
|
for arg := range b.argsFromOptions {
|
2017-05-09 11:25:33 -04:00
|
|
|
_, isReferenced := b.referencedArgs[arg]
|
|
|
|
_, isBuiltin := builtinAllowedBuildArgs[arg]
|
|
|
|
if !isBuiltin && !isReferenced {
|
2017-04-06 17:38:02 -04:00
|
|
|
leftoverArgs = append(leftoverArgs, arg)
|
|
|
|
}
|
|
|
|
}
|
2017-05-09 11:25:33 -04:00
|
|
|
if len(leftoverArgs) > 0 {
|
|
|
|
fmt.Fprintf(out, "[Warning] One or more build-args %v were not consumed\n", leftoverArgs)
|
|
|
|
}
|
2017-04-06 17:38:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// ResetAllowed clears the list of args that are allowed to be used by a
|
|
|
|
// directive
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) ResetAllowed() {
|
2017-04-06 17:38:02 -04:00
|
|
|
b.allowedBuildArgs = make(map[string]*string)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddMetaArg adds a new meta arg that can be used by FROM directives
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) AddMetaArg(key string, value *string) {
|
2017-04-06 17:38:02 -04:00
|
|
|
b.allowedMetaArgs[key] = value
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddArg adds a new arg that can be used by directives
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) AddArg(key string, value *string) {
|
2017-04-06 17:38:02 -04:00
|
|
|
b.allowedBuildArgs[key] = value
|
|
|
|
b.referencedArgs[key] = struct{}{}
|
|
|
|
}
|
|
|
|
|
2017-05-09 11:25:33 -04:00
|
|
|
// IsReferencedOrNotBuiltin checks if the key is a built-in arg, or if it has been
|
|
|
|
// referenced by the Dockerfile. Returns true if the arg is not a builtin or
|
|
|
|
// if the builtin has been referenced in the Dockerfile.
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) IsReferencedOrNotBuiltin(key string) bool {
|
2017-04-06 17:38:02 -04:00
|
|
|
_, isBuiltin := builtinAllowedBuildArgs[key]
|
|
|
|
_, isAllowed := b.allowedBuildArgs[key]
|
2017-05-09 11:25:33 -04:00
|
|
|
return isAllowed || !isBuiltin
|
2017-04-06 17:38:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetAllAllowed returns a mapping with all the allowed args
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) GetAllAllowed() map[string]string {
|
2017-04-06 17:38:02 -04:00
|
|
|
return b.getAllFromMapping(b.allowedBuildArgs)
|
|
|
|
}
|
|
|
|
|
2018-08-31 11:27:02 -04:00
|
|
|
// GetAllMeta returns a mapping with all the meta args
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) GetAllMeta() map[string]string {
|
2017-04-06 17:38:02 -04:00
|
|
|
return b.getAllFromMapping(b.allowedMetaArgs)
|
|
|
|
}
|
|
|
|
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) getAllFromMapping(source map[string]*string) map[string]string {
|
2017-04-06 17:38:02 -04:00
|
|
|
m := make(map[string]string)
|
|
|
|
|
|
|
|
keys := keysFromMaps(source, builtinAllowedBuildArgs)
|
|
|
|
for _, key := range keys {
|
|
|
|
v, ok := b.getBuildArg(key, source)
|
|
|
|
if ok {
|
|
|
|
m[key] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
2017-04-26 17:45:16 -04:00
|
|
|
// FilterAllowed returns all allowed args without the filtered args
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) FilterAllowed(filter []string) []string {
|
2017-04-26 17:45:16 -04:00
|
|
|
envs := []string{}
|
|
|
|
configEnv := opts.ConvertKVStringsToMap(filter)
|
|
|
|
|
|
|
|
for key, val := range b.GetAllAllowed() {
|
|
|
|
if _, ok := configEnv[key]; !ok {
|
|
|
|
envs = append(envs, fmt.Sprintf("%s=%s", key, val))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return envs
|
|
|
|
}
|
|
|
|
|
2018-05-07 13:49:13 -04:00
|
|
|
func (b *BuildArgs) getBuildArg(key string, mapping map[string]*string) (string, bool) {
|
2017-04-06 17:38:02 -04:00
|
|
|
defaultValue, exists := mapping[key]
|
|
|
|
// Return override from options if one is defined
|
|
|
|
if v, ok := b.argsFromOptions[key]; ok && v != nil {
|
|
|
|
return *v, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
if defaultValue == nil {
|
|
|
|
if v, ok := b.allowedMetaArgs[key]; ok && v != nil {
|
|
|
|
return *v, ok
|
|
|
|
}
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
return *defaultValue, exists
|
|
|
|
}
|
|
|
|
|
|
|
|
func keysFromMaps(source map[string]*string, builtin map[string]bool) []string {
|
|
|
|
keys := []string{}
|
|
|
|
for key := range source {
|
|
|
|
keys = append(keys, key)
|
|
|
|
}
|
|
|
|
for key := range builtin {
|
|
|
|
keys = append(keys, key)
|
|
|
|
}
|
|
|
|
return keys
|
|
|
|
}
|