github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/builder/dockerfile/buildargs.go (about)

     1  package dockerfile // import "github.com/docker/docker/builder/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  	"ALL_PROXY":   true,
    23  	"all_proxy":   true,
    24  }
    25  
    26  // BuildArgs manages arguments used by the builder
    27  type BuildArgs struct {
    28  	// args that are allowed for expansion/substitution and passing to commands in 'run'.
    29  	allowedBuildArgs map[string]*string
    30  	// args defined before the first `FROM` in a Dockerfile
    31  	allowedMetaArgs map[string]*string
    32  	// args referenced by the Dockerfile
    33  	referencedArgs map[string]struct{}
    34  	// args provided by the user on the command line
    35  	argsFromOptions map[string]*string
    36  }
    37  
    38  // NewBuildArgs creates a new BuildArgs type
    39  func NewBuildArgs(argsFromOptions map[string]*string) *BuildArgs {
    40  	return &BuildArgs{
    41  		allowedBuildArgs: make(map[string]*string),
    42  		allowedMetaArgs:  make(map[string]*string),
    43  		referencedArgs:   make(map[string]struct{}),
    44  		argsFromOptions:  argsFromOptions,
    45  	}
    46  }
    47  
    48  // Clone returns a copy of the BuildArgs type
    49  func (b *BuildArgs) Clone() *BuildArgs {
    50  	result := NewBuildArgs(b.argsFromOptions)
    51  	for k, v := range b.allowedBuildArgs {
    52  		result.allowedBuildArgs[k] = v
    53  	}
    54  	for k, v := range b.allowedMetaArgs {
    55  		result.allowedMetaArgs[k] = v
    56  	}
    57  	for k := range b.referencedArgs {
    58  		result.referencedArgs[k] = struct{}{}
    59  	}
    60  	return result
    61  }
    62  
    63  // MergeReferencedArgs merges referenced args from another BuildArgs
    64  // object into the current one
    65  func (b *BuildArgs) MergeReferencedArgs(other *BuildArgs) {
    66  	for k := range other.referencedArgs {
    67  		b.referencedArgs[k] = struct{}{}
    68  	}
    69  }
    70  
    71  // WarnOnUnusedBuildArgs checks if there are any leftover build-args that were
    72  // passed but not consumed during build. Print a warning, if there are any.
    73  func (b *BuildArgs) WarnOnUnusedBuildArgs(out io.Writer) {
    74  	var leftoverArgs []string
    75  	for arg := range b.argsFromOptions {
    76  		_, isReferenced := b.referencedArgs[arg]
    77  		_, isBuiltin := builtinAllowedBuildArgs[arg]
    78  		if !isBuiltin && !isReferenced {
    79  			leftoverArgs = append(leftoverArgs, arg)
    80  		}
    81  	}
    82  	if len(leftoverArgs) > 0 {
    83  		fmt.Fprintf(out, "[Warning] One or more build-args %v were not consumed\n", leftoverArgs)
    84  	}
    85  }
    86  
    87  // ResetAllowed clears the list of args that are allowed to be used by a
    88  // directive
    89  func (b *BuildArgs) ResetAllowed() {
    90  	b.allowedBuildArgs = make(map[string]*string)
    91  }
    92  
    93  // AddMetaArg adds a new meta arg that can be used by FROM directives
    94  func (b *BuildArgs) AddMetaArg(key string, value *string) {
    95  	b.allowedMetaArgs[key] = value
    96  }
    97  
    98  // AddArg adds a new arg that can be used by directives
    99  func (b *BuildArgs) AddArg(key string, value *string) {
   100  	b.allowedBuildArgs[key] = value
   101  	b.referencedArgs[key] = struct{}{}
   102  }
   103  
   104  // IsReferencedOrNotBuiltin checks if the key is a built-in arg, or if it has been
   105  // referenced by the Dockerfile. Returns true if the arg is not a builtin or
   106  // if the builtin has been referenced in the Dockerfile.
   107  func (b *BuildArgs) IsReferencedOrNotBuiltin(key string) bool {
   108  	_, isBuiltin := builtinAllowedBuildArgs[key]
   109  	_, isAllowed := b.allowedBuildArgs[key]
   110  	return isAllowed || !isBuiltin
   111  }
   112  
   113  // GetAllAllowed returns a mapping with all the allowed args
   114  func (b *BuildArgs) GetAllAllowed() map[string]string {
   115  	return b.getAllFromMapping(b.allowedBuildArgs)
   116  }
   117  
   118  // GetAllMeta returns a mapping with all the meta args
   119  func (b *BuildArgs) GetAllMeta() map[string]string {
   120  	return b.getAllFromMapping(b.allowedMetaArgs)
   121  }
   122  
   123  func (b *BuildArgs) getAllFromMapping(source map[string]*string) map[string]string {
   124  	m := make(map[string]string)
   125  
   126  	keys := keysFromMaps(source, builtinAllowedBuildArgs)
   127  	for _, key := range keys {
   128  		v, ok := b.getBuildArg(key, source)
   129  		if ok {
   130  			m[key] = v
   131  		}
   132  	}
   133  	return m
   134  }
   135  
   136  // FilterAllowed returns all allowed args without the filtered args
   137  func (b *BuildArgs) FilterAllowed(filter []string) []string {
   138  	envs := []string{}
   139  	configEnv := opts.ConvertKVStringsToMap(filter)
   140  
   141  	for key, val := range b.GetAllAllowed() {
   142  		if _, ok := configEnv[key]; !ok {
   143  			envs = append(envs, fmt.Sprintf("%s=%s", key, val))
   144  		}
   145  	}
   146  	return envs
   147  }
   148  
   149  func (b *BuildArgs) getBuildArg(key string, mapping map[string]*string) (string, bool) {
   150  	defaultValue, exists := mapping[key]
   151  	// Return override from options if one is defined
   152  	if v, ok := b.argsFromOptions[key]; ok && v != nil {
   153  		return *v, ok
   154  	}
   155  
   156  	if defaultValue == nil {
   157  		if v, ok := b.allowedMetaArgs[key]; ok && v != nil {
   158  			return *v, ok
   159  		}
   160  		return "", false
   161  	}
   162  	return *defaultValue, exists
   163  }
   164  
   165  func keysFromMaps(source map[string]*string, builtin map[string]bool) []string {
   166  	keys := []string{}
   167  	for key := range source {
   168  		keys = append(keys, key)
   169  	}
   170  	for key := range builtin {
   171  		keys = append(keys, key)
   172  	}
   173  	return keys
   174  }