github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/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  func (b *buildArgs) Clone() *buildArgs {
    46  	result := newBuildArgs(b.argsFromOptions)
    47  	for k, v := range b.allowedBuildArgs {
    48  		result.allowedBuildArgs[k] = v
    49  	}
    50  	for k, v := range b.allowedMetaArgs {
    51  		result.allowedMetaArgs[k] = v
    52  	}
    53  	for k := range b.referencedArgs {
    54  		result.referencedArgs[k] = struct{}{}
    55  	}
    56  	return result
    57  }
    58  
    59  func (b *buildArgs) MergeReferencedArgs(other *buildArgs) {
    60  	for k := range other.referencedArgs {
    61  		b.referencedArgs[k] = struct{}{}
    62  	}
    63  }
    64  
    65  // WarnOnUnusedBuildArgs checks if there are any leftover build-args that were
    66  // passed but not consumed during build. Print a warning, if there are any.
    67  func (b *buildArgs) WarnOnUnusedBuildArgs(out io.Writer) {
    68  	leftoverArgs := []string{}
    69  	for arg := range b.argsFromOptions {
    70  		_, isReferenced := b.referencedArgs[arg]
    71  		_, isBuiltin := builtinAllowedBuildArgs[arg]
    72  		if !isBuiltin && !isReferenced {
    73  			leftoverArgs = append(leftoverArgs, arg)
    74  		}
    75  	}
    76  	if len(leftoverArgs) > 0 {
    77  		fmt.Fprintf(out, "[Warning] One or more build-args %v were not consumed\n", leftoverArgs)
    78  	}
    79  }
    80  
    81  // ResetAllowed clears the list of args that are allowed to be used by a
    82  // directive
    83  func (b *buildArgs) ResetAllowed() {
    84  	b.allowedBuildArgs = make(map[string]*string)
    85  }
    86  
    87  // AddMetaArg adds a new meta arg that can be used by FROM directives
    88  func (b *buildArgs) AddMetaArg(key string, value *string) {
    89  	b.allowedMetaArgs[key] = value
    90  }
    91  
    92  // AddArg adds a new arg that can be used by directives
    93  func (b *buildArgs) AddArg(key string, value *string) {
    94  	b.allowedBuildArgs[key] = value
    95  	b.referencedArgs[key] = struct{}{}
    96  }
    97  
    98  // IsReferencedOrNotBuiltin checks if the key is a built-in arg, or if it has been
    99  // referenced by the Dockerfile. Returns true if the arg is not a builtin or
   100  // if the builtin has been referenced in the Dockerfile.
   101  func (b *buildArgs) IsReferencedOrNotBuiltin(key string) bool {
   102  	_, isBuiltin := builtinAllowedBuildArgs[key]
   103  	_, isAllowed := b.allowedBuildArgs[key]
   104  	return isAllowed || !isBuiltin
   105  }
   106  
   107  // GetAllAllowed returns a mapping with all the allowed args
   108  func (b *buildArgs) GetAllAllowed() map[string]string {
   109  	return b.getAllFromMapping(b.allowedBuildArgs)
   110  }
   111  
   112  // GetAllMeta returns a mapping with all the meta meta args
   113  func (b *buildArgs) GetAllMeta() map[string]string {
   114  	return b.getAllFromMapping(b.allowedMetaArgs)
   115  }
   116  
   117  func (b *buildArgs) getAllFromMapping(source map[string]*string) map[string]string {
   118  	m := make(map[string]string)
   119  
   120  	keys := keysFromMaps(source, builtinAllowedBuildArgs)
   121  	for _, key := range keys {
   122  		v, ok := b.getBuildArg(key, source)
   123  		if ok {
   124  			m[key] = v
   125  		}
   126  	}
   127  	return m
   128  }
   129  
   130  // FilterAllowed returns all allowed args without the filtered args
   131  func (b *buildArgs) FilterAllowed(filter []string) []string {
   132  	envs := []string{}
   133  	configEnv := opts.ConvertKVStringsToMap(filter)
   134  
   135  	for key, val := range b.GetAllAllowed() {
   136  		if _, ok := configEnv[key]; !ok {
   137  			envs = append(envs, fmt.Sprintf("%s=%s", key, val))
   138  		}
   139  	}
   140  	return envs
   141  }
   142  
   143  func (b *buildArgs) getBuildArg(key string, mapping map[string]*string) (string, bool) {
   144  	defaultValue, exists := mapping[key]
   145  	// Return override from options if one is defined
   146  	if v, ok := b.argsFromOptions[key]; ok && v != nil {
   147  		return *v, ok
   148  	}
   149  
   150  	if defaultValue == nil {
   151  		if v, ok := b.allowedMetaArgs[key]; ok && v != nil {
   152  			return *v, ok
   153  		}
   154  		return "", false
   155  	}
   156  	return *defaultValue, exists
   157  }
   158  
   159  func keysFromMaps(source map[string]*string, builtin map[string]bool) []string {
   160  	keys := []string{}
   161  	for key := range source {
   162  		keys = append(keys, key)
   163  	}
   164  	for key := range builtin {
   165  		keys = append(keys, key)
   166  	}
   167  	return keys
   168  }