buildargs.go 5.0 KB

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