buildargs.go 5.0 KB

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