// NewRockerfile reads parses Rockerfile from an io.Reader func NewRockerfile(name string, in io.Reader, vars template.Vars, funs template.Funs) (r *Rockerfile, err error) { r = &Rockerfile{ Name: name, Vars: vars, Funs: funs, } var ( source []byte content *bytes.Buffer ) if source, err = ioutil.ReadAll(in); err != nil { return nil, fmt.Errorf("Failed to read Rockerfile %s, error: %s", name, err) } r.Source = string(source) if content, err = template.Process(name, bytes.NewReader(source), vars, funs); err != nil { return nil, err } r.Content = content.String() // TODO: update parser from Docker if r.rootNode, err = parser.Parse(content); err != nil { return nil, err } return r, nil }
// Build runs the build of given Rockerfile and returns image id func (builder *Builder) Build() (imageID string, err error) { // Do initial cleanup, you know, just to be sure // Previous builds could be ended up abnormally if err := builder.cleanup(); err != nil { return "", err } // Initialize auth configuration if builder.Auth == nil { builder.Auth = &docker.AuthConfiguration{} } // Initialize in/out file descriptors if builder.InStream != nil { fd, isTerminal := term.GetFdInfo(builder.InStream) builder.fdIn = fd builder.isTerminalIn = isTerminal } if builder.OutStream != nil { fd, isTerminal := term.GetFdInfo(builder.OutStream) builder.fdOut = fd builder.isTerminalOut = isTerminal } // Wrap this into function to have deferred functions run before // we do final checks run := func() (err error) { fd, err := os.Open(builder.Rockerfile) if err != nil { return fmt.Errorf("Failed to open file %s, error: %s", builder.Rockerfile, err) } defer fd.Close() data, err := template.Process(builder.Rockerfile, fd, builder.Vars.ToMapOfInterface(), map[string]interface{}{}) if err != nil { return err } builder.RockerfileContent = data.String() if builder.Print { fmt.Print(builder.RockerfileContent) os.Exit(0) } if builder.ContextDir == "" { builder.ContextDir = filepath.Dir(builder.Rockerfile) } if _, err := os.Stat(builder.ContextDir); err != nil { return err } if err := builder.checkDockerignore(); err != nil { return err } rootNode, err := parser.Parse(strings.NewReader(builder.RockerfileContent)) if err != nil { return err } builder.rootNode = rootNode builder.dockerfile = &parser.Node{} defer func() { if err2 := builder.cleanup(); err2 != nil && err == nil { err = err2 } }() for builder.i = 0; builder.i < len(builder.rootNode.Children); builder.i++ { oldImageID := builder.imageID if err := builder.dispatch(builder.i, builder.rootNode.Children[builder.i]); err != nil { return err } if builder.imageID != oldImageID && builder.imageID != "" { fmt.Fprintf(builder.OutStream, "[Rocker] ---> %.12s\n", builder.imageID) } } if err := builder.runDockerfile(); err != nil { return err } return nil } if err := run(); err != nil { return "", err } if builder.imageID == "" { return "", fmt.Errorf("No image was generated. Is your Rockerfile empty?") } fmt.Fprintf(builder.OutStream, "[Rocker] Successfully built %.12s\n", builder.imageID) return builder.imageID, nil }