evaluator.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package evaluator
  2. import (
  3. "fmt"
  4. "io"
  5. "regexp"
  6. "strings"
  7. "github.com/erikh/buildfile/parser"
  8. "github.com/docker/docker/daemon"
  9. "github.com/docker/docker/engine"
  10. "github.com/docker/docker/nat"
  11. "github.com/docker/docker/registry"
  12. "github.com/docker/docker/runconfig"
  13. "github.com/docker/docker/utils"
  14. )
  15. var (
  16. evaluateTable = map[string]func(*buildFile, ...string) error{
  17. "env": env,
  18. "maintainer": maintainer,
  19. "add": add,
  20. "copy": dispatchCopy, // copy() is a go builtin
  21. //"onbuild": parseMaybeJSON,
  22. //"workdir": parseString,
  23. //"docker-version": parseString,
  24. //"run": parseMaybeJSON,
  25. //"cmd": parseMaybeJSON,
  26. //"entrypoint": parseMaybeJSON,
  27. //"expose": parseMaybeJSON,
  28. //"volume": parseMaybeJSON,
  29. }
  30. )
  31. type buildFile struct {
  32. dockerfile *parser.Node
  33. env envMap
  34. image string
  35. config *runconfig.Config
  36. options *BuildOpts
  37. maintainer string
  38. }
  39. type BuildOpts struct {
  40. Daemon *daemon.Daemon
  41. Engine *engine.Engine
  42. OutStream io.Writer
  43. ErrStream io.Writer
  44. Verbose bool
  45. UtilizeCache bool
  46. Remove bool
  47. ForceRm bool
  48. OutOld io.Writer
  49. StreamFormatter *utils.StreamFormatter
  50. Auth *registry.AuthConfig
  51. AuthConfigFile *registry.ConfigFile
  52. }
  53. func (opts *BuildOpts) NewBuildFile(file io.ReadWriteCloser) (*buildFile, error) {
  54. ast, err := parser.Parse(file)
  55. if err != nil {
  56. return nil, err
  57. }
  58. return &buildFile{
  59. dockerfile: ast,
  60. env: envMap{},
  61. config: initRunConfig(),
  62. options: opts,
  63. }, nil
  64. }
  65. func (b *buildFile) Run() error {
  66. node := b.dockerfile
  67. for i, n := range node.Children {
  68. if err := b.dispatch(i, n); err != nil {
  69. return err
  70. }
  71. }
  72. return nil
  73. }
  74. func initRunConfig() *runconfig.Config {
  75. return &runconfig.Config{
  76. PortSpecs: []string{},
  77. // FIXME(erikh) this should be a type that lives in runconfig
  78. ExposedPorts: map[nat.Port]struct{}{},
  79. Env: []string{},
  80. Cmd: []string{},
  81. // FIXME(erikh) this should also be a type in runconfig
  82. Volumes: map[string]struct{}{},
  83. Entrypoint: []string{},
  84. OnBuild: []string{},
  85. }
  86. }
  87. func (b *buildFile) dispatch(stepN int, ast *parser.Node) error {
  88. cmd := ast.Value
  89. strs := []string{}
  90. for ast.Next != nil {
  91. ast = ast.Next
  92. strs = append(strs, replaceEnv(b, stripQuotes(ast.Value)))
  93. }
  94. fmt.Fprintf(b.outStream, "Step %d : %s\n", i, cmd, expression)
  95. // XXX yes, we skip any cmds that are not valid; the parser should have
  96. // picked these out already.
  97. if f, ok := evaluateTable[cmd]; ok {
  98. return f(b, strs...)
  99. }
  100. return nil
  101. }