mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Start moving the docker builder into the server
This commit is contained in:
parent
e6e13d6ade
commit
0f135ad7f3
4 changed files with 157 additions and 24 deletions
80
api.go
80
api.go
|
@ -1,6 +1,7 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/auth"
|
||||
|
@ -9,6 +10,7 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
@ -31,6 +33,13 @@ func parseForm(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func parseMultipartForm(r *http.Request) error {
|
||||
if err := r.ParseMultipartForm(4096); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func httpError(w http.ResponseWriter, err error) {
|
||||
if strings.HasPrefix(err.Error(), "No such") {
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
|
@ -329,9 +338,15 @@ func postImagesInsert(srv *Server, w http.ResponseWriter, r *http.Request, vars
|
|||
}
|
||||
name := vars["name"]
|
||||
|
||||
if err := srv.ImageInsert(name, url, path, w); err != nil {
|
||||
imgId, err := srv.ImageInsert(name, url, path, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := json.Marshal(&ApiId{Id: imgId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writeJson(w, b)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -585,6 +600,68 @@ func postImagesGetCache(srv *Server, w http.ResponseWriter, r *http.Request, var
|
|||
return nil
|
||||
}
|
||||
|
||||
func Upload(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
mr, err := req.MultipartReader()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
length := req.ContentLength
|
||||
for {
|
||||
|
||||
part, err := mr.NextPart()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
var read int64
|
||||
var p float32
|
||||
for {
|
||||
buffer := make([]byte, 100000)
|
||||
cBytes, err := part.Read(buffer)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
read = read + int64(cBytes)
|
||||
//fmt.Printf("read: %v \n",read )
|
||||
p = float32(read) / float32(length) * 100
|
||||
fmt.Printf("progress: %v \n", p)
|
||||
os.Stdout.Write(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func postBuild(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
|
||||
Upload(w, r)
|
||||
|
||||
// io.Copy(os.Stderr, r.Body)
|
||||
|
||||
if err := r.ParseMultipartForm(409699); err != nil {
|
||||
utils.Debugf("----- %s\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
mpr, err := r.MultipartReader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := mpr.NextPart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dockerfile := make([]byte, 4096)
|
||||
p.Read(dockerfile)
|
||||
|
||||
utils.Debugf("Dockerfile >>>%s<<<\n", dockerfile)
|
||||
b := NewBuildFile(srv, w)
|
||||
if _, err := b.Build(bytes.NewReader(dockerfile)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ListenAndServe(addr string, srv *Server, logging bool) error {
|
||||
r := mux.NewRouter()
|
||||
log.Printf("Listening for HTTP on %s\n", addr)
|
||||
|
@ -607,6 +684,7 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
|
|||
"POST": {
|
||||
"/auth": postAuth,
|
||||
"/commit": postCommit,
|
||||
"/build": postBuild,
|
||||
"/images/create": postImagesCreate,
|
||||
"/images/{name:.*}/insert": postImagesInsert,
|
||||
"/images/{name:.*}/push": postImagesPush,
|
||||
|
|
|
@ -12,12 +12,6 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type BuilderClient interface {
|
||||
Build(io.Reader) (string, error)
|
||||
CmdFrom(string) error
|
||||
CmdRun(string) error
|
||||
}
|
||||
|
||||
type builderClient struct {
|
||||
cli *DockerCli
|
||||
|
||||
|
@ -164,8 +158,23 @@ func (b *builderClient) CmdExpose(args string) error {
|
|||
}
|
||||
|
||||
func (b *builderClient) CmdInsert(args string) error {
|
||||
// FIXME: Reimplement this once the remove_hijack branch gets merged.
|
||||
// We need to retrieve the resulting Id
|
||||
// tmp := strings.SplitN(args, "\t ", 2)
|
||||
// sourceUrl, destPath := tmp[0], tmp[1]
|
||||
|
||||
// v := url.Values{}
|
||||
// v.Set("url", sourceUrl)
|
||||
// v.Set("path", destPath)
|
||||
// body, _, err := b.cli.call("POST", "/images/insert?"+v.Encode(), nil)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// apiId := &ApiId{}
|
||||
// if err := json.Unmarshal(body, apiId); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// FIXME: Reimplement this, we need to retrieve the resulting Id
|
||||
return fmt.Errorf("INSERT not implemented")
|
||||
}
|
||||
|
||||
|
@ -269,18 +278,18 @@ func (b *builderClient) Build(dockerfile io.Reader) (string, error) {
|
|||
instruction := strings.ToLower(strings.Trim(tmp[0], " "))
|
||||
arguments := strings.Trim(tmp[1], " ")
|
||||
|
||||
fmt.Printf("%s %s (%s)\n", strings.ToUpper(instruction), arguments, b.image)
|
||||
fmt.Fprintf(os.Stderr, "%s %s (%s)\n", strings.ToUpper(instruction), arguments, b.image)
|
||||
|
||||
method, exists := reflect.TypeOf(b).MethodByName("Cmd" + strings.ToUpper(instruction[:1]) + strings.ToLower(instruction[1:]))
|
||||
if !exists {
|
||||
fmt.Printf("Skipping unknown instruction %s\n", strings.ToUpper(instruction))
|
||||
fmt.Fprintf(os.Stderr, "Skipping unknown instruction %s\n", strings.ToUpper(instruction))
|
||||
}
|
||||
ret := method.Func.Call([]reflect.Value{reflect.ValueOf(b), reflect.ValueOf(arguments)})[0].Interface()
|
||||
if ret != nil {
|
||||
return "", ret.(error)
|
||||
}
|
||||
|
||||
fmt.Printf("===> %v\n", b.image)
|
||||
fmt.Fprintf(os.Stderr, "===> %v\n", b.image)
|
||||
}
|
||||
if b.needCommit {
|
||||
if err := b.commit(""); err != nil {
|
||||
|
@ -295,13 +304,13 @@ func (b *builderClient) Build(dockerfile io.Reader) (string, error) {
|
|||
for i := range b.tmpContainers {
|
||||
delete(b.tmpContainers, i)
|
||||
}
|
||||
fmt.Printf("Build finished. image id: %s\n", b.image)
|
||||
fmt.Fprintf(os.Stderr, "Build finished. image id: %s\n", b.image)
|
||||
return b.image, nil
|
||||
}
|
||||
return "", fmt.Errorf("An error occured during the build\n")
|
||||
}
|
||||
|
||||
func NewBuilderClient(addr string, port int) BuilderClient {
|
||||
func NewBuilderClient(addr string, port int) BuildFile {
|
||||
return &builderClient{
|
||||
cli: NewDockerCli(addr, port),
|
||||
config: &Config{},
|
||||
|
|
50
commands.go
50
commands.go
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/dotcloud/docker/utils"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
|
@ -104,14 +105,59 @@ func (cli *DockerCli) CmdInsert(args ...string) error {
|
|||
v.Set("url", cmd.Arg(1))
|
||||
v.Set("path", cmd.Arg(2))
|
||||
|
||||
err := cli.stream("POST", "/images/"+cmd.Arg(0)+"/insert?"+v.Encode(), nil, os.Stdout)
|
||||
if err != nil {
|
||||
if err := cli.stream("POST", "/images/"+cmd.Arg(0)+"/insert?"+v.Encode(), nil, os.Stdout); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *DockerCli) CmdBuild(args ...string) error {
|
||||
|
||||
buff := bytes.NewBuffer([]byte{})
|
||||
|
||||
w := multipart.NewWriter(buff)
|
||||
|
||||
dockerfile, err := w.CreateFormFile("Dockerfile", "Dockerfile")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.Open("Dockerfile")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dockerfile.Write([]byte(w.Boundary() + "\r\n"))
|
||||
if _, err := io.Copy(dockerfile, file); err != nil {
|
||||
return err
|
||||
}
|
||||
dockerfile.Write([]byte("\r\n" + w.Boundary()))
|
||||
|
||||
// req, err := http.NewRequest("POST", fmt.Sprintf("http://%s:%d%s", cli.host, cli.port, "/build"), buff)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// req.Header.Set("Content-Type", w.FormDataContentType())
|
||||
resp, err := http.Post(fmt.Sprintf("http://%s:%d%s", cli.host, cli.port, "/build"), w.FormDataContentType(), buff)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("error: %s", body)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(os.Stdout, resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *DockerCli) CmdBuildClient(args ...string) error {
|
||||
cmd := Subcmd("build", "-|Dockerfile", "Build an image from Dockerfile or via stdin")
|
||||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
|
|
16
server.go
16
server.go
|
@ -67,40 +67,40 @@ func (srv *Server) ImagesSearch(term string) ([]ApiSearch, error) {
|
|||
return outs, nil
|
||||
}
|
||||
|
||||
func (srv *Server) ImageInsert(name, url, path string, out io.Writer) error {
|
||||
func (srv *Server) ImageInsert(name, url, path string, out io.Writer) (string, error) {
|
||||
out = utils.NewWriteFlusher(out)
|
||||
img, err := srv.runtime.repositories.LookupImage(name)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
file, err := utils.Download(url, out)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
defer file.Body.Close()
|
||||
|
||||
config, _, err := ParseRun([]string{img.Id, "echo", "insert", url, path}, srv.runtime.capabilities)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
b := NewBuilder(srv.runtime)
|
||||
c, err := b.Create(config)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, "Downloading %v/%v (%v)"), path); err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
// FIXME: Handle custom repo, tag comment, author
|
||||
img, err = b.Commit(c, "", "", img.Comment, img.Author, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
fmt.Fprintf(out, "%s\n", img.Id)
|
||||
return nil
|
||||
return img.ShortId(), nil
|
||||
}
|
||||
|
||||
func (srv *Server) ImagesViz(out io.Writer) error {
|
||||
|
|
Loading…
Reference in a new issue