github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/builder/dockerfile/buildargs.go (about)

     1  package dockerfile
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/docker/docker/runconfig/opts"
     8  )
     9  
    10  // builtinAllowedBuildArgs is list of built-in allowed build args
    11  // these args are considered transparent and are excluded from the image history.
    12  // Filtering from history is implemented in dispatchers.go
    13  var builtinAllowedBuildArgs = map[string]bool{
    14  	"HTTP_PROXY":  true,
    15  	"http_proxy":  true,
    16  	"HTTPS_PROXY": true,
    17  	"https_proxy": true,
    18  	"FTP_PROXY":   true,
    19  	"ftp_proxy":   true,
    20  	"NO_PROXY":    true,
    21  	"no_proxy":    true,
    22  }
    23  
    24  // buildArgs manages arguments used by the builder
    25  type buildArgs struct {
    26  	// args that are allowed for expansion/substitution and passing to commands in 'run'.
    27  	allowedBuildArgs map[string]*string
    28  	// args defined before the first `FROM` in a Dockerfile
    29  	allowedMetaArgs map[string]*string
    30  	// args referenced by the Dockerfile
    31  	referencedArgs map[string]struct{}
    32  	// args provided by the user on the command line
    33  	argsFromOptions map[string]*string
    34  }
    35  
    36  func newBuildArgs(argsFromOptions map[string]*string) *buildArgs {
    37  	return &buildArgs{
    38  		allowedBuildArgs: make(map[string]*string),
    39  		allowedMetaArgs:  make(map[string]*string),
    40  		referencedArgs:   make(map[string]struct{}),
    41  		argsFromOptions:  argsFromOptions,
    42  	}
    43  }
    44  
    45  // WarnOnUnusedBuildArgs checks if there are any leftover build-args that were
    46  // passed but not consumed during build. Print a warning, if there are any.
    47  func (b *buildArgs) WarnOnUnusedBuildArgs(out io.Writer) {
    48  	leftoverArgs := []string{}
    49  	for arg := range b.argsFromOptions {
    50  		_, isReferenced := b.referencedArgs[arg]
    51  		_, isBuiltin := builtinAllowedBuildArgs[arg]
    52  		if !isBuiltin && !isReferenced {
    53  			leftoverArgs = append(leftoverArgs, arg)
    54  		}
    55  	}
    56  	if len(leftoverArgs) > 0 {
    57  		fmt.Fprintf(out, "[Warning] One or more build-args %v were not consumed\n", leftoverArgs)
    58  	}
    59  }
    60  
    61  // ResetAllowed clears the list of args that are allowed to be used by a
    62  // directive
    63  func (b *buildArgs) ResetAllowed() {
    64  	b.allowedBuildArgs = make(map[string]*string)
    65  }
    66  
    67  // AddMetaArg adds a new meta arg that can be used by FROM directives
    68  func (b *buildArgs) AddMetaArg(key string, value *string) {
    69  	b.allowedMetaArgs[key] = value
    70  }
    71  
    72  // AddArg adds a new arg that can be used by directives
    73  func (b *buildArgs) AddArg(key string, value *string) {
    74  	b.allowedBuildArgs[key] = value
    75  	b.referencedArgs[key] = struct{}{}
    76  }
    77  
    78  // IsReferencedOrNotBuiltin checks if the key is a built-in arg, or if it has been
    79  // referenced by the Dockerfile. Returns true if the arg is not a builtin or
    80  // if the builtin has been referenced in the Dockerfile.
    81  func (b *buildArgs) IsReferencedOrNotBuiltin(key string) bool {
    82  	_, isBuiltin := builtinAllowedBuildArgs[key]
    83  	_, isAllowed := b.allowedBuildArgs[key]
    84  	return isAllowed || !isBuiltin
    85  }
    86  
    87  // GetAllAllowed returns a mapping with all the allowed args
    88  func (b *buildArgs) GetAllAllowed() map[string]string {
    89  	return b.getAllFromMapping(b.allowedBuildArgs)
    90  }
    91  
    92  // GetAllMeta returns a mapping with all the meta meta args
    93  func (b *buildArgs) GetAllMeta() map[string]string {
    94  	return b.getAllFromMapping(b.allowedMetaArgs)
    95  }
    96  
    97  func (b *buildArgs) getAllFromMapping(source map[string]*string) map[string]string {
    98  	m := make(map[string]string)
    99  
   100  	keys := keysFromMaps(source, builtinAllowedBuildArgs)
   101  	for _, key := range keys {
   102  		v, ok := b.getBuildArg(key, source)
   103  		if ok {
   104  			m[key] = v
   105  		}
   106  	}
   107  	return m
   108  }
   109  
   110  // FilterAllowed returns all allowed args without the filtered args
   111  func (b *buildArgs) FilterAllowed(filter []string) []string {
   112  	envs := []string{}
   113  	configEnv := opts.ConvertKVStringsToMap(filter)
   114  
   115  	for key, val := range b.GetAllAllowed() {
   116  		if _, ok := configEnv[key]; !ok {
   117  			envs = append(envs, fmt.Sprintf("%s=%s", key, val))
   118  		}
   119  	}
   120  	return envs
   121  }
   122  
   123  func (b *buildArgs) getBuildArg(key string, mapping map[string]*string) (string, bool) {
   124  	defaultValue, exists := mapping[key]
   125  	// Return override from options if one is defined
   126  	if v, ok := b.argsFromOptions[key]; ok && v != nil {
   127  		return *v, ok
   128  	}
   129  
   130  	if defaultValue == nil {
   131  		if v, ok := b.allowedMetaArgs[key]; ok && v != nil {
   132  			return *v, ok
   133  		}
   134  		return "", false
   135  	}
   136  	return *defaultValue, exists
   137  }
   138  
   139  func keysFromMaps(source map[string]*string, builtin map[string]bool) []string {
   140  	keys := []string{}
   141  	for key := range source {
   142  		keys = append(keys, key)
   143  	}
   144  	for key := range builtin {
   145  		keys = append(keys, key)
   146  	}
   147  	return keys
   148  }