buildargs.go 4.3 KB

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