buildargs.go 4.7 KB

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