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