github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/builder/dockerfile/buildargs.go (about)

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