mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge remote-tracking branch 'dotcloud/master' into clean-reshuffle
This commit is contained in:
commit
097531d853
7 changed files with 509 additions and 455 deletions
10
README.md
10
README.md
|
@ -79,12 +79,12 @@ Here's a typical docker build process:
|
||||||
```bash
|
```bash
|
||||||
from ubuntu:12.10
|
from ubuntu:12.10
|
||||||
run apt-get update
|
run apt-get update
|
||||||
run apt-get install python
|
run DEBIAN_FRONTEND=noninteractive apt-get install -q -y python
|
||||||
run apt-get install python-pip
|
run DEBIAN_FRONTEND=noninteractive apt-get install -q -y python-pip
|
||||||
run pip install django
|
run pip install django
|
||||||
run apt-get install curl
|
run DEBIAN_FRONTEND=noninteractive apt-get install -q -y curl
|
||||||
run curl http://github.com/shykes/helloflask/helloflask/master.tar.gz | tar -zxv
|
run curl -L https://github.com/shykes/helloflask/archive/master.tar.gz | tar -xzv
|
||||||
run cd master && pip install -r requirements.txt
|
run cd helloflask-master && pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that Docker doesn't care *how* dependencies are built - as long as they can be built by running a unix command in a container.
|
Note that Docker doesn't care *how* dependencies are built - as long as they can be built by running a unix command in a container.
|
||||||
|
|
288
api.go
288
api.go
|
@ -39,22 +39,28 @@ func httpError(w http.ResponseWriter, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func writeJson(w http.ResponseWriter, b []byte) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
config := &auth.AuthConfig{
|
config := &auth.AuthConfig{
|
||||||
Username: srv.runtime.authConfig.Username,
|
Username: srv.runtime.authConfig.Username,
|
||||||
Email: srv.runtime.authConfig.Email,
|
Email: srv.runtime.authConfig.Email,
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(config)
|
b, err := json.Marshal(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
config := &auth.AuthConfig{}
|
config := &auth.AuthConfig{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Username == srv.runtime.authConfig.Username {
|
if config.Username == srv.runtime.authConfig.Username {
|
||||||
|
@ -64,7 +70,7 @@ func postAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[stri
|
||||||
newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root)
|
newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root)
|
||||||
status, err := auth.Login(newAuthConfig)
|
status, err := auth.Login(newAuthConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
} else {
|
} else {
|
||||||
srv.runtime.graph.getHttpClient().Jar = cookiejar.NewCookieJar()
|
srv.runtime.graph.getHttpClient().Jar = cookiejar.NewCookieJar()
|
||||||
srv.runtime.authConfig = newAuthConfig
|
srv.runtime.authConfig = newAuthConfig
|
||||||
|
@ -72,51 +78,53 @@ func postAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[stri
|
||||||
if status != "" {
|
if status != "" {
|
||||||
b, err := json.Marshal(&ApiAuth{Status: status})
|
b, err := json.Marshal(&ApiAuth{Status: status})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVersion(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getVersion(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
m := srv.DockerVersion()
|
m := srv.DockerVersion()
|
||||||
b, err := json.Marshal(m)
|
b, err := json.Marshal(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersKill(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postContainersKill(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
if err := srv.ContainerKill(name); err != nil {
|
if err := srv.ContainerKill(name); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersExport(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getContainersExport(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
if err := srv.ContainerExport(name, w); err != nil {
|
if err := srv.ContainerExport(name, w); err != nil {
|
||||||
Debugf("%s", err.Error())
|
Debugf("%s", err.Error())
|
||||||
//return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImagesJson(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getImagesJson(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
all := r.Form.Get("all") == "1"
|
all := r.Form.Get("all") == "1"
|
||||||
|
@ -125,66 +133,70 @@ func getImagesJson(srv *Server, w http.ResponseWriter, r *http.Request, vars map
|
||||||
|
|
||||||
outs, err := srv.Images(all, only_ids, filter)
|
outs, err := srv.Images(all, only_ids, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(outs)
|
b, err := json.Marshal(outs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImagesViz(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getImagesViz(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := srv.ImagesViz(w); err != nil {
|
if err := srv.ImagesViz(w); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInfo(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getInfo(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
out := srv.DockerInfo()
|
out := srv.DockerInfo()
|
||||||
b, err := json.Marshal(out)
|
b, err := json.Marshal(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImagesHistory(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getImagesHistory(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
outs, err := srv.ImageHistory(name)
|
outs, err := srv.ImageHistory(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(outs)
|
b, err := json.Marshal(outs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersChanges(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getContainersChanges(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
changesStr, err := srv.ContainerChanges(name)
|
changesStr, err := srv.ContainerChanges(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(changesStr)
|
b, err := json.Marshal(changesStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersPs(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getContainersPs(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
all := r.Form.Get("all") == "1"
|
all := r.Form.Get("all") == "1"
|
||||||
trunc_cmd := r.Form.Get("trunc_cmd") != "0"
|
trunc_cmd := r.Form.Get("trunc_cmd") != "0"
|
||||||
|
@ -199,36 +211,37 @@ func getContainersPs(srv *Server, w http.ResponseWriter, r *http.Request, vars m
|
||||||
outs := srv.Containers(all, trunc_cmd, only_ids, n, since, before)
|
outs := srv.Containers(all, trunc_cmd, only_ids, n, since, before)
|
||||||
b, err := json.Marshal(outs)
|
b, err := json.Marshal(outs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postImagesTag(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postImagesTag(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
repo := r.Form.Get("repo")
|
repo := r.Form.Get("repo")
|
||||||
tag := r.Form.Get("tag")
|
tag := r.Form.Get("tag")
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
force := r.Form.Get("force") == "1"
|
force := r.Form.Get("force") == "1"
|
||||||
|
|
||||||
if err := srv.ContainerTag(name, repo, tag, force); err != nil {
|
if err := srv.ContainerTag(name, repo, tag, force); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postCommit(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postCommit(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
var config Config
|
config := &Config{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&config); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
||||||
Debugf("%s", err.Error())
|
Debugf("%s", err.Error())
|
||||||
}
|
}
|
||||||
repo := r.Form.Get("repo")
|
repo := r.Form.Get("repo")
|
||||||
|
@ -236,22 +249,23 @@ func postCommit(srv *Server, w http.ResponseWriter, r *http.Request, vars map[st
|
||||||
container := r.Form.Get("container")
|
container := r.Form.Get("container")
|
||||||
author := r.Form.Get("author")
|
author := r.Form.Get("author")
|
||||||
comment := r.Form.Get("comment")
|
comment := r.Form.Get("comment")
|
||||||
id, err := srv.ContainerCommit(container, repo, tag, author, comment, &config)
|
id, err := srv.ContainerCommit(container, repo, tag, author, comment, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(ApiId{id})
|
b, err := json.Marshal(&ApiId{id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an image from Pull or from Import
|
// Creates an image from Pull or from Import
|
||||||
func postImagesCreate(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postImagesCreate(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
src := r.Form.Get("fromSrc")
|
src := r.Form.Get("fromSrc")
|
||||||
|
@ -261,7 +275,7 @@ func postImagesCreate(srv *Server, w http.ResponseWriter, r *http.Request, vars
|
||||||
|
|
||||||
in, out, err := hijackServer(w)
|
in, out, err := hijackServer(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
||||||
|
@ -275,95 +289,96 @@ func postImagesCreate(srv *Server, w http.ResponseWriter, r *http.Request, vars
|
||||||
fmt.Fprintf(out, "Error: %s\n", err)
|
fmt.Fprintf(out, "Error: %s\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImagesSearch(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getImagesSearch(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
term := r.Form.Get("term")
|
term := r.Form.Get("term")
|
||||||
outs, err := srv.ImagesSearch(term)
|
outs, err := srv.ImagesSearch(term)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(outs)
|
b, err := json.Marshal(outs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postImagesInsert(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postImagesInsert(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
url := r.Form.Get("url")
|
url := r.Form.Get("url")
|
||||||
path := r.Form.Get("path")
|
path := r.Form.Get("path")
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
in, out, err := hijackServer(w)
|
in, out, err := hijackServer(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
||||||
if err := srv.ImageInsert(name, url, path, out); err != nil {
|
if err := srv.ImageInsert(name, url, path, out); err != nil {
|
||||||
fmt.Fprintf(out, "Error: %s\n", err)
|
fmt.Fprintf(out, "Error: %s\n", err)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postImagesPush(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postImagesPush(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
registry := r.Form.Get("registry")
|
registry := r.Form.Get("registry")
|
||||||
|
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
in, out, err := hijackServer(w)
|
in, out, err := hijackServer(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
||||||
if err := srv.ImagePush(name, registry, out); err != nil {
|
if err := srv.ImagePush(name, registry, out); err != nil {
|
||||||
fmt.Fprintln(out, "Error: %s\n", err)
|
fmt.Fprintf(out, "Error: %s\n", err)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postBuild(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postBuild(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
in, out, err := hijackServer(w)
|
in, out, err := hijackServer(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
||||||
if err := srv.ImageCreateFromFile(in, out); err != nil {
|
if err := srv.ImageCreateFromFile(in, out); err != nil {
|
||||||
fmt.Fprintln(out, "Error: %s\n", err)
|
fmt.Fprintln(out, "Error: %s\n", err)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersCreate(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postContainersCreate(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
config := &Config{}
|
config := &Config{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
id, err := srv.ContainerCreate(config)
|
id, err := srv.ContainerCreate(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
out := &ApiRun{
|
out := &ApiRun{
|
||||||
|
@ -379,75 +394,76 @@ func postContainersCreate(srv *Server, w http.ResponseWriter, r *http.Request, v
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(out)
|
b, err := json.Marshal(out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersRestart(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postContainersRestart(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
t, err := strconv.Atoi(r.Form.Get("t"))
|
t, err := strconv.Atoi(r.Form.Get("t"))
|
||||||
if err != nil || t < 0 {
|
if err != nil || t < 0 {
|
||||||
t = 10
|
t = 10
|
||||||
}
|
}
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
if err := srv.ContainerRestart(name, t); err != nil {
|
if err := srv.ContainerRestart(name, t); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteContainers(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func deleteContainers(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
removeVolume := r.Form.Get("v") == "1"
|
removeVolume := r.Form.Get("v") == "1"
|
||||||
|
|
||||||
if err := srv.ContainerDestroy(name, removeVolume); err != nil {
|
if err := srv.ContainerDestroy(name, removeVolume); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteImages(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func deleteImages(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
if err := srv.ImageDelete(name); err != nil {
|
if err := srv.ImageDelete(name); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersStart(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postContainersStart(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
if err := srv.ContainerStart(name); err != nil {
|
if err := srv.ContainerStart(name); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersStop(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postContainersStop(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
t, err := strconv.Atoi(r.Form.Get("t"))
|
t, err := strconv.Atoi(r.Form.Get("t"))
|
||||||
if err != nil || t < 0 {
|
if err != nil || t < 0 {
|
||||||
|
@ -455,36 +471,37 @@ func postContainersStop(srv *Server, w http.ResponseWriter, r *http.Request, var
|
||||||
}
|
}
|
||||||
|
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
if err := srv.ContainerStop(name, t); err != nil {
|
if err := srv.ContainerStop(name, t); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersWait(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postContainersWait(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
status, err := srv.ContainerWait(name)
|
status, err := srv.ContainerWait(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(&ApiWait{StatusCode: status})
|
b, err := json.Marshal(&ApiWait{StatusCode: status})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postContainersAttach(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func postContainersAttach(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if err := parseForm(r); err != nil {
|
if err := parseForm(r); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
logs := r.Form.Get("logs") == "1"
|
logs := r.Form.Get("logs") == "1"
|
||||||
stream := r.Form.Get("stream") == "1"
|
stream := r.Form.Get("stream") == "1"
|
||||||
|
@ -492,13 +509,13 @@ func postContainersAttach(srv *Server, w http.ResponseWriter, r *http.Request, v
|
||||||
stdout := r.Form.Get("stdout") == "1"
|
stdout := r.Form.Get("stdout") == "1"
|
||||||
stderr := r.Form.Get("stderr") == "1"
|
stderr := r.Form.Get("stderr") == "1"
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
in, out, err := hijackServer(w)
|
in, out, err := hijackServer(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
|
|
||||||
|
@ -506,48 +523,50 @@ func postContainersAttach(srv *Server, w http.ResponseWriter, r *http.Request, v
|
||||||
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, in, out); err != nil {
|
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, in, out); err != nil {
|
||||||
fmt.Fprintf(out, "Error: %s\n", err)
|
fmt.Fprintf(out, "Error: %s\n", err)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainersByName(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getContainersByName(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
container, err := srv.ContainerInspect(name)
|
container, err := srv.ContainerInspect(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(container)
|
b, err := json.Marshal(container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImagesByName(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) {
|
func getImagesByName(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil, fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
image, err := srv.ImageInspect(name)
|
image, err := srv.ImageInspect(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(image)
|
b, err := json.Marshal(image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return b, nil
|
writeJson(w, b)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenAndServe(addr string, srv *Server, logging bool) error {
|
func ListenAndServe(addr string, srv *Server, logging bool) error {
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
log.Printf("Listening for HTTP on %s\n", addr)
|
log.Printf("Listening for HTTP on %s\n", addr)
|
||||||
|
|
||||||
m := map[string]map[string]func(*Server, http.ResponseWriter, *http.Request, map[string]string) ([]byte, error){
|
m := map[string]map[string]func(*Server, http.ResponseWriter, *http.Request, map[string]string) error{
|
||||||
"GET": {
|
"GET": {
|
||||||
"/auth": getAuth,
|
"/auth": getAuth,
|
||||||
"/version": getVersion,
|
"/version": getVersion,
|
||||||
|
@ -602,14 +621,9 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
|
||||||
Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION)
|
Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json, err := localFct(srv, w, r, mux.Vars(r))
|
if err := localFct(srv, w, r, mux.Vars(r)); err != nil {
|
||||||
if err != nil {
|
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
}
|
}
|
||||||
if json != nil {
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.Write(json)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
505
api_test.go
505
api_test.go
|
@ -1,6 +1,7 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/tar"
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -11,7 +12,6 @@ import (
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -43,13 +43,9 @@ func TestGetAuth(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := postAuth(srv, r, req, nil)
|
if err := postAuth(srv, r, req, nil); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body == nil {
|
|
||||||
t.Fatalf("No body received\n")
|
|
||||||
}
|
|
||||||
if r.Code != http.StatusOK && r.Code != 0 {
|
if r.Code != http.StatusOK && r.Code != 0 {
|
||||||
t.Fatalf("%d OK or 0 expected, received %d\n", http.StatusOK, r.Code)
|
t.Fatalf("%d OK or 0 expected, received %d\n", http.StatusOK, r.Code)
|
||||||
}
|
}
|
||||||
|
@ -70,15 +66,14 @@ func TestGetVersion(t *testing.T) {
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
body, err := getVersion(srv, nil, nil, nil)
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
|
||||||
|
if err := getVersion(srv, r, nil, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v := &ApiVersion{}
|
v := &ApiVersion{}
|
||||||
|
if err = json.Unmarshal(r.Body.Bytes(), v); err != nil {
|
||||||
err = json.Unmarshal(body, v)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if v.Version != VERSION {
|
if v.Version != VERSION {
|
||||||
|
@ -95,12 +90,14 @@ func TestGetInfo(t *testing.T) {
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
body, err := getInfo(srv, nil, nil, nil)
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
|
||||||
|
if err := getInfo(srv, r, nil, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
infos := &ApiInfo{}
|
infos := &ApiInfo{}
|
||||||
err = json.Unmarshal(body, infos)
|
err = json.Unmarshal(r.Body.Bytes(), infos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -124,14 +121,14 @@ func TestGetImagesJson(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := getImagesJson(srv, nil, req, nil)
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
|
||||||
|
if err := getImagesJson(srv, r, req, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
images := []ApiImages{}
|
images := []ApiImages{}
|
||||||
err = json.Unmarshal(body, &images)
|
if err := json.Unmarshal(r.Body.Bytes(), &images); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,24 +136,24 @@ func TestGetImagesJson(t *testing.T) {
|
||||||
t.Errorf("Excepted 1 image, %d found", len(images))
|
t.Errorf("Excepted 1 image, %d found", len(images))
|
||||||
}
|
}
|
||||||
|
|
||||||
if images[0].Repository != "docker-ut" {
|
if images[0].Repository != unitTestImageName {
|
||||||
t.Errorf("Excepted image docker-ut, %s found", images[0].Repository)
|
t.Errorf("Excepted image %s, %s found", unitTestImageName, images[0].Repository)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r2 := httptest.NewRecorder()
|
||||||
|
|
||||||
// only_ids=1&all=1
|
// only_ids=1&all=1
|
||||||
req2, err := http.NewRequest("GET", "/images/json?only_ids=1&all=1", nil)
|
req2, err := http.NewRequest("GET", "/images/json?only_ids=1&all=1", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body2, err := getImagesJson(srv, nil, req2, nil)
|
if err := getImagesJson(srv, r2, req2, nil); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
images2 := []ApiImages{}
|
images2 := []ApiImages{}
|
||||||
err = json.Unmarshal(body2, &images2)
|
if err := json.Unmarshal(r2.Body.Bytes(), &images2); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,24 +165,24 @@ func TestGetImagesJson(t *testing.T) {
|
||||||
t.Errorf("Excepted no image Repository, %s found", images2[0].Repository)
|
t.Errorf("Excepted no image Repository, %s found", images2[0].Repository)
|
||||||
}
|
}
|
||||||
|
|
||||||
if images2[0].Id == "" {
|
if images2[0].Id != GetTestImage(runtime).ShortId() {
|
||||||
t.Errorf("Excepted image Id, %s found", images2[0].Id)
|
t.Errorf("Retrieved image Id differs, expected %s, received %s", GetTestImage(runtime).ShortId(), images2[0].Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r3 := httptest.NewRecorder()
|
||||||
|
|
||||||
// filter=a
|
// filter=a
|
||||||
req3, err := http.NewRequest("GET", "/images/json?filter=a", nil)
|
req3, err := http.NewRequest("GET", "/images/json?filter=a", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body3, err := getImagesJson(srv, nil, req3, nil)
|
if err := getImagesJson(srv, r3, req3, nil); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
images3 := []ApiImages{}
|
images3 := []ApiImages{}
|
||||||
err = json.Unmarshal(body3, &images3)
|
if err := json.Unmarshal(r3.Body.Bytes(), &images3); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,9 +201,7 @@ func TestGetImagesViz(t *testing.T) {
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
r := httptest.NewRecorder()
|
||||||
|
if err := getImagesViz(srv, r, nil, nil); err != nil {
|
||||||
_, err = getImagesViz(srv, r, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,20 +228,19 @@ func TestGetImagesSearch(t *testing.T) {
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
|
r := httptest.NewRecorder()
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/images/search?term=redis", nil)
|
req, err := http.NewRequest("GET", "/images/search?term=redis", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := getImagesSearch(srv, nil, req, nil)
|
if err := getImagesSearch(srv, r, req, nil); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
results := []ApiSearch{}
|
results := []ApiSearch{}
|
||||||
|
if err := json.Unmarshal(r.Body.Bytes(), &results); err != nil {
|
||||||
err = json.Unmarshal(body, &results)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(results) < 2 {
|
if len(results) < 2 {
|
||||||
|
@ -263,15 +257,14 @@ func TestGetImagesHistory(t *testing.T) {
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
body, err := getImagesHistory(srv, nil, nil, map[string]string{"name": unitTestImageName})
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
|
||||||
|
if err := getImagesHistory(srv, r, nil, map[string]string{"name": unitTestImageName}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
history := []ApiHistory{}
|
history := []ApiHistory{}
|
||||||
|
if err := json.Unmarshal(r.Body.Bytes(), &history); err != nil {
|
||||||
err = json.Unmarshal(body, &history)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(history) != 1 {
|
if len(history) != 1 {
|
||||||
|
@ -288,18 +281,16 @@ func TestGetImagesByName(t *testing.T) {
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
body, err := getImagesByName(srv, nil, nil, map[string]string{"name": unitTestImageName})
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := getImagesByName(srv, r, nil, map[string]string{"name": unitTestImageName}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
img := &Image{}
|
img := &Image{}
|
||||||
|
if err := json.Unmarshal(r.Body.Bytes(), img); err != nil {
|
||||||
err = json.Unmarshal(body, img)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if img.Comment != "Imported from http://get.docker.io/images/busybox" {
|
if img.Id != GetTestImage(runtime).Id || img.Comment != "Imported from http://get.docker.io/images/busybox" {
|
||||||
t.Errorf("Error inspecting image")
|
t.Errorf("Error inspecting image")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,13 +318,12 @@ func TestGetContainersPs(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := getContainersPs(srv, nil, req, nil)
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := getContainersPs(srv, r, req, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
containers := []ApiContainers{}
|
containers := []ApiContainers{}
|
||||||
err = json.Unmarshal(body, &containers)
|
if err := json.Unmarshal(r.Body.Bytes(), &containers); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(containers) != 1 {
|
if len(containers) != 1 {
|
||||||
|
@ -359,7 +349,7 @@ func TestGetContainersExport(t *testing.T) {
|
||||||
container, err := builder.Create(
|
container, err := builder.Create(
|
||||||
&Config{
|
&Config{
|
||||||
Image: GetTestImage(runtime).Id,
|
Image: GetTestImage(runtime).Id,
|
||||||
Cmd: []string{"/bin/rm", "/etc/passwd"},
|
Cmd: []string{"touch", "/test"},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -372,9 +362,7 @@ func TestGetContainersExport(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
r := httptest.NewRecorder()
|
||||||
|
if err = getContainersExport(srv, r, nil, map[string]string{"name": container.Id}); err != nil {
|
||||||
_, err = getContainersExport(srv, r, nil, map[string]string{"name": container.Id})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,8 +370,22 @@ func TestGetContainersExport(t *testing.T) {
|
||||||
t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
|
t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Body == nil {
|
found := false
|
||||||
t.Fatalf("Body expected, found 0")
|
for tarReader := tar.NewReader(r.Body); ; {
|
||||||
|
h, err := tarReader.Next()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if h.Name == "./test" {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Fatalf("The created test file has not been found in the exported image")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,12 +416,12 @@ func TestGetContainersChanges(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := getContainersChanges(srv, nil, nil, map[string]string{"name": container.Id})
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := getContainersChanges(srv, r, nil, map[string]string{"name": container.Id}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
changes := []Change{}
|
changes := []Change{}
|
||||||
if err := json.Unmarshal(body, &changes); err != nil {
|
if err := json.Unmarshal(r.Body.Bytes(), &changes); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +452,7 @@ func TestGetContainersByName(t *testing.T) {
|
||||||
container, err := builder.Create(
|
container, err := builder.Create(
|
||||||
&Config{
|
&Config{
|
||||||
Image: GetTestImage(runtime).Id,
|
Image: GetTestImage(runtime).Id,
|
||||||
Cmd: []string{"/bin/rm", "/etc/passwd"},
|
Cmd: []string{"echo", "test"},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -458,14 +460,17 @@ func TestGetContainersByName(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer runtime.Destroy(container)
|
defer runtime.Destroy(container)
|
||||||
|
|
||||||
body, err := getContainersByName(srv, nil, nil, map[string]string{"name": container.Id})
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := getContainersByName(srv, r, nil, map[string]string{"name": container.Id}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
outContainer := Container{}
|
outContainer := &Container{}
|
||||||
if err := json.Unmarshal(body, &outContainer); err != nil {
|
if err := json.Unmarshal(r.Body.Bytes(), outContainer); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
if outContainer.Id != container.Id {
|
||||||
|
t.Fatalf("Wrong containers retrieved. Expected %s, recieved %s", container.Id, outContainer.Id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostAuth(t *testing.T) {
|
func TestPostAuth(t *testing.T) {
|
||||||
|
@ -483,14 +488,13 @@ func TestPostAuth(t *testing.T) {
|
||||||
}
|
}
|
||||||
runtime.authConfig = authConfigOrig
|
runtime.authConfig = authConfigOrig
|
||||||
|
|
||||||
body, err := getAuth(srv, nil, nil, nil)
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := getAuth(srv, r, nil, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
authConfig := &auth.AuthConfig{}
|
authConfig := &auth.AuthConfig{}
|
||||||
err = json.Unmarshal(body, authConfig)
|
if err := json.Unmarshal(r.Body.Bytes(), authConfig); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,15 +512,13 @@ func TestPostCommit(t *testing.T) {
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
|
||||||
|
|
||||||
builder := NewBuilder(runtime)
|
builder := NewBuilder(runtime)
|
||||||
|
|
||||||
// Create a container and remove a file
|
// Create a container and remove a file
|
||||||
container, err := builder.Create(
|
container, err := builder.Create(
|
||||||
&Config{
|
&Config{
|
||||||
Image: GetTestImage(runtime).Id,
|
Image: GetTestImage(runtime).Id,
|
||||||
Cmd: []string{"/bin/rm", "/etc/passwd"},
|
Cmd: []string{"touch", "/test"},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -533,17 +535,21 @@ func TestPostCommit(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := postCommit(srv, r, req, nil)
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := postCommit(srv, r, req, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if body == nil {
|
|
||||||
t.Fatalf("Body expected, received: 0\n")
|
|
||||||
}
|
|
||||||
if r.Code != http.StatusCreated {
|
if r.Code != http.StatusCreated {
|
||||||
t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
|
t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apiId := &ApiId{}
|
||||||
|
if err := json.Unmarshal(r.Body.Bytes(), apiId); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := runtime.graph.Get(apiId.Id); err != nil {
|
||||||
|
t.Fatalf("The image has not been commited")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostBuild(t *testing.T) {
|
func TestPostBuild(t *testing.T) {
|
||||||
|
@ -560,20 +566,16 @@ func TestPostBuild(t *testing.T) {
|
||||||
|
|
||||||
c1 := make(chan struct{})
|
c1 := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(c1)
|
||||||
r := &hijackTester{
|
r := &hijackTester{
|
||||||
ResponseRecorder: httptest.NewRecorder(),
|
ResponseRecorder: httptest.NewRecorder(),
|
||||||
in: stdin,
|
in: stdin,
|
||||||
out: stdoutPipe,
|
out: stdoutPipe,
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := postBuild(srv, r, nil, nil)
|
if err := postBuild(srv, r, nil, nil); err != nil {
|
||||||
close(c1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Acknowledge hijack
|
// Acknowledge hijack
|
||||||
|
@ -601,163 +603,169 @@ func TestPostBuild(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostImagesCreate(t *testing.T) {
|
func TestPostImagesCreate(t *testing.T) {
|
||||||
runtime, err := newTestRuntime()
|
// FIXME: Use the staging in order to perform tests
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer nuke(runtime)
|
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
// runtime, err := newTestRuntime()
|
||||||
|
// if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
// defer nuke(runtime)
|
||||||
|
|
||||||
stdin, stdinPipe := io.Pipe()
|
// srv := &Server{runtime: runtime}
|
||||||
stdout, stdoutPipe := io.Pipe()
|
|
||||||
|
|
||||||
c1 := make(chan struct{})
|
// stdin, stdinPipe := io.Pipe()
|
||||||
go func() {
|
// stdout, stdoutPipe := io.Pipe()
|
||||||
r := &hijackTester{
|
|
||||||
ResponseRecorder: httptest.NewRecorder(),
|
|
||||||
in: stdin,
|
|
||||||
out: stdoutPipe,
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/images/create?fromImage=docker-ut", bytes.NewReader([]byte{}))
|
// c1 := make(chan struct{})
|
||||||
if err != nil {
|
// go func() {
|
||||||
t.Fatal(err)
|
// defer close(c1)
|
||||||
}
|
|
||||||
|
|
||||||
body, err := postImagesCreate(srv, r, req, nil)
|
// r := &hijackTester{
|
||||||
close(c1)
|
// ResponseRecorder: httptest.NewRecorder(),
|
||||||
if err != nil {
|
// in: stdin,
|
||||||
t.Fatal(err)
|
// out: stdoutPipe,
|
||||||
}
|
// }
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Acknowledge hijack
|
// req, err := http.NewRequest("POST", "/images/create?fromImage="+unitTestImageName, bytes.NewReader([]byte{}))
|
||||||
setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
|
// if err != nil {
|
||||||
stdout.Read([]byte{})
|
// t.Fatal(err)
|
||||||
stdout.Read(make([]byte, 4096))
|
// }
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(t, "Waiting for imagesCreate output", 5*time.Second, func() {
|
// body, err := postImagesCreate(srv, r, req, nil)
|
||||||
reader := bufio.NewReader(stdout)
|
// if err != nil {
|
||||||
line, err := reader.ReadString('\n')
|
// t.Fatal(err)
|
||||||
if err != nil {
|
// }
|
||||||
t.Fatal(err)
|
// if body != nil {
|
||||||
}
|
// t.Fatalf("No body expected, received: %s\n", body)
|
||||||
if !strings.HasPrefix(line, "Pulling repository docker-ut from") {
|
// }
|
||||||
t.Fatalf("Expected Pulling repository docker-ut from..., found %s", line)
|
// }()
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Close pipes (client disconnects)
|
// // Acknowledge hijack
|
||||||
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
// setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
|
||||||
t.Fatal(err)
|
// stdout.Read([]byte{})
|
||||||
}
|
// stdout.Read(make([]byte, 4096))
|
||||||
|
// })
|
||||||
|
|
||||||
// Wait for imagesCreate to finish, the client disconnected, therefore, Create finished his job
|
// setTimeout(t, "Waiting for imagesCreate output", 5*time.Second, func() {
|
||||||
setTimeout(t, "Waiting for imagesCreate timed out", 10*time.Second, func() {
|
// reader := bufio.NewReader(stdout)
|
||||||
<-c1
|
// line, err := reader.ReadString('\n')
|
||||||
})
|
// if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
// if !strings.HasPrefix(line, "Pulling repository d from") {
|
||||||
|
// t.Fatalf("Expected Pulling repository docker-ut from..., found %s", line)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
// // Close pipes (client disconnects)
|
||||||
|
// if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Wait for imagesCreate to finish, the client disconnected, therefore, Create finished his job
|
||||||
|
// setTimeout(t, "Waiting for imagesCreate timed out", 10*time.Second, func() {
|
||||||
|
// <-c1
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostImagesInsert(t *testing.T) {
|
// func TestPostImagesInsert(t *testing.T) {
|
||||||
//FIXME: Implement this test (or remove this endpoint)
|
// //FIXME: Implement this test (or remove this endpoint)
|
||||||
t.Log("Test not implemented")
|
// t.Log("Test not implemented")
|
||||||
}
|
// }
|
||||||
|
|
||||||
func TestPostImagesPush(t *testing.T) {
|
func TestPostImagesPush(t *testing.T) {
|
||||||
runtime, err := newTestRuntime()
|
//FIXME: Use staging in order to perform tests
|
||||||
if err != nil {
|
// runtime, err := newTestRuntime()
|
||||||
t.Fatal(err)
|
// if err != nil {
|
||||||
}
|
// t.Fatal(err)
|
||||||
defer nuke(runtime)
|
// }
|
||||||
|
// defer nuke(runtime)
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
// srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
stdin, stdinPipe := io.Pipe()
|
// stdin, stdinPipe := io.Pipe()
|
||||||
stdout, stdoutPipe := io.Pipe()
|
// stdout, stdoutPipe := io.Pipe()
|
||||||
|
|
||||||
c1 := make(chan struct{})
|
// c1 := make(chan struct{})
|
||||||
go func() {
|
// go func() {
|
||||||
r := &hijackTester{
|
// r := &hijackTester{
|
||||||
ResponseRecorder: httptest.NewRecorder(),
|
// ResponseRecorder: httptest.NewRecorder(),
|
||||||
in: stdin,
|
// in: stdin,
|
||||||
out: stdoutPipe,
|
// out: stdoutPipe,
|
||||||
}
|
// }
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/images/docker-ut/push", bytes.NewReader([]byte{}))
|
// req, err := http.NewRequest("POST", "/images/docker-ut/push", bytes.NewReader([]byte{}))
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
t.Fatal(err)
|
// t.Fatal(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
body, err := postImagesPush(srv, r, req, map[string]string{"name": "docker-ut"})
|
// body, err := postImagesPush(srv, r, req, map[string]string{"name": "docker-ut"})
|
||||||
close(c1)
|
// close(c1)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
t.Fatal(err)
|
// t.Fatal(err)
|
||||||
}
|
// }
|
||||||
if body != nil {
|
// if body != nil {
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
// t.Fatalf("No body expected, received: %s\n", body)
|
||||||
}
|
// }
|
||||||
}()
|
// }()
|
||||||
|
|
||||||
// Acknowledge hijack
|
// // Acknowledge hijack
|
||||||
setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
|
// setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
|
||||||
stdout.Read([]byte{})
|
// stdout.Read([]byte{})
|
||||||
stdout.Read(make([]byte, 4096))
|
// stdout.Read(make([]byte, 4096))
|
||||||
})
|
// })
|
||||||
|
|
||||||
setTimeout(t, "Waiting for imagesCreate output", 5*time.Second, func() {
|
// setTimeout(t, "Waiting for imagesCreate output", 5*time.Second, func() {
|
||||||
reader := bufio.NewReader(stdout)
|
// reader := bufio.NewReader(stdout)
|
||||||
line, err := reader.ReadString('\n')
|
// line, err := reader.ReadString('\n')
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
t.Fatal(err)
|
// t.Fatal(err)
|
||||||
}
|
// }
|
||||||
if !strings.HasPrefix(line, "Processing checksum") {
|
// if !strings.HasPrefix(line, "Processing checksum") {
|
||||||
t.Fatalf("Processing checksum..., found %s", line)
|
// t.Fatalf("Processing checksum..., found %s", line)
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
// Close pipes (client disconnects)
|
// // Close pipes (client disconnects)
|
||||||
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
// if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
||||||
t.Fatal(err)
|
// t.Fatal(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Wait for imagesPush to finish, the client disconnected, therefore, Push finished his job
|
// // Wait for imagesPush to finish, the client disconnected, therefore, Push finished his job
|
||||||
setTimeout(t, "Waiting for imagesPush timed out", 10*time.Second, func() {
|
// setTimeout(t, "Waiting for imagesPush timed out", 10*time.Second, func() {
|
||||||
<-c1
|
// <-c1
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostImagesTag(t *testing.T) {
|
func TestPostImagesTag(t *testing.T) {
|
||||||
runtime, err := newTestRuntime()
|
// FIXME: Use staging in order to perform tests
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer nuke(runtime)
|
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
// runtime, err := newTestRuntime()
|
||||||
|
// if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
// defer nuke(runtime)
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
// srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/images/docker-ut/tag?repo=testrepo&tag=testtag", bytes.NewReader([]byte{}))
|
// r := httptest.NewRecorder()
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := postImagesTag(srv, r, req, map[string]string{"name": "docker-ut"})
|
// req, err := http.NewRequest("POST", "/images/docker-ut/tag?repo=testrepo&tag=testtag", bytes.NewReader([]byte{}))
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
t.Fatal(err)
|
// t.Fatal(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
if body != nil {
|
// body, err := postImagesTag(srv, r, req, map[string]string{"name": "docker-ut"})
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
// if err != nil {
|
||||||
}
|
// t.Fatal(err)
|
||||||
if r.Code != http.StatusCreated {
|
// }
|
||||||
t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
|
|
||||||
}
|
// if body != nil {
|
||||||
|
// t.Fatalf("No body expected, received: %s\n", body)
|
||||||
|
// }
|
||||||
|
// if r.Code != http.StatusCreated {
|
||||||
|
// t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPostContainersCreate(t *testing.T) {
|
func TestPostContainersCreate(t *testing.T) {
|
||||||
|
@ -769,8 +777,6 @@ func TestPostContainersCreate(t *testing.T) {
|
||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
|
||||||
|
|
||||||
configJson, err := json.Marshal(&Config{
|
configJson, err := json.Marshal(&Config{
|
||||||
Image: GetTestImage(runtime).Id,
|
Image: GetTestImage(runtime).Id,
|
||||||
Memory: 33554432,
|
Memory: 33554432,
|
||||||
|
@ -785,8 +791,8 @@ func TestPostContainersCreate(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := postContainersCreate(srv, r, req, nil)
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := postContainersCreate(srv, r, req, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if r.Code != http.StatusCreated {
|
if r.Code != http.StatusCreated {
|
||||||
|
@ -794,7 +800,7 @@ func TestPostContainersCreate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
apiRun := &ApiRun{}
|
apiRun := &ApiRun{}
|
||||||
if err := json.Unmarshal(body, apiRun); err != nil {
|
if err := json.Unmarshal(r.Body.Bytes(), apiRun); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,14 +855,9 @@ func TestPostContainersKill(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
r := httptest.NewRecorder()
|
||||||
|
if err := postContainersKill(srv, r, nil, map[string]string{"name": container.Id}); err != nil {
|
||||||
body, err := postContainersKill(srv, r, nil, map[string]string{"name": container.Id})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
if r.Code != http.StatusNoContent {
|
if r.Code != http.StatusNoContent {
|
||||||
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
||||||
}
|
}
|
||||||
|
@ -897,19 +898,14 @@ func TestPostContainersRestart(t *testing.T) {
|
||||||
t.Errorf("Container should be running")
|
t.Errorf("Container should be running")
|
||||||
}
|
}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/containers/"+container.Id+"/restart?t=1", bytes.NewReader([]byte{}))
|
req, err := http.NewRequest("POST", "/containers/"+container.Id+"/restart?t=1", bytes.NewReader([]byte{}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := postContainersRestart(srv, r, req, map[string]string{"name": container.Id})
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := postContainersRestart(srv, r, req, map[string]string{"name": container.Id}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
if r.Code != http.StatusNoContent {
|
if r.Code != http.StatusNoContent {
|
||||||
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
||||||
}
|
}
|
||||||
|
@ -948,14 +944,9 @@ func TestPostContainersStart(t *testing.T) {
|
||||||
defer runtime.Destroy(container)
|
defer runtime.Destroy(container)
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
r := httptest.NewRecorder()
|
||||||
|
if err := postContainersStart(srv, r, nil, map[string]string{"name": container.Id}); err != nil {
|
||||||
body, err := postContainersStart(srv, r, nil, map[string]string{"name": container.Id})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
if r.Code != http.StatusNoContent {
|
if r.Code != http.StatusNoContent {
|
||||||
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
||||||
}
|
}
|
||||||
|
@ -967,7 +958,8 @@ func TestPostContainersStart(t *testing.T) {
|
||||||
t.Errorf("Container should be running")
|
t.Errorf("Container should be running")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = postContainersStart(srv, r, nil, map[string]string{"name": container.Id}); err == nil {
|
r = httptest.NewRecorder()
|
||||||
|
if err = postContainersStart(srv, r, nil, map[string]string{"name": container.Id}); err == nil {
|
||||||
t.Fatalf("A running containter should be able to be started")
|
t.Fatalf("A running containter should be able to be started")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,20 +1000,15 @@ func TestPostContainersStop(t *testing.T) {
|
||||||
t.Errorf("Container should be running")
|
t.Errorf("Container should be running")
|
||||||
}
|
}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
|
||||||
|
|
||||||
// Note: as it is a POST request, it requires a body.
|
// Note: as it is a POST request, it requires a body.
|
||||||
req, err := http.NewRequest("POST", "/containers/"+container.Id+"/stop?t=1", bytes.NewReader([]byte{}))
|
req, err := http.NewRequest("POST", "/containers/"+container.Id+"/stop?t=1", bytes.NewReader([]byte{}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
body, err := postContainersStop(srv, r, req, map[string]string{"name": container.Id})
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := postContainersStop(srv, r, req, map[string]string{"name": container.Id}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
if r.Code != http.StatusNoContent {
|
if r.Code != http.StatusNoContent {
|
||||||
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
||||||
}
|
}
|
||||||
|
@ -1056,12 +1043,12 @@ func TestPostContainersWait(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(t, "Wait timed out", 3*time.Second, func() {
|
setTimeout(t, "Wait timed out", 3*time.Second, func() {
|
||||||
body, err := postContainersWait(srv, nil, nil, map[string]string{"name": container.Id})
|
r := httptest.NewRecorder()
|
||||||
if err != nil {
|
if err := postContainersWait(srv, r, nil, map[string]string{"name": container.Id}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
apiWait := &ApiWait{}
|
apiWait := &ApiWait{}
|
||||||
if err := json.Unmarshal(body, apiWait); err != nil {
|
if err := json.Unmarshal(r.Body.Bytes(), apiWait); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if apiWait.StatusCode != 0 {
|
if apiWait.StatusCode != 0 {
|
||||||
|
@ -1106,8 +1093,7 @@ func TestPostContainersAttach(t *testing.T) {
|
||||||
// Attach to it
|
// Attach to it
|
||||||
c1 := make(chan struct{})
|
c1 := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
// We're simulating a disconnect so the return value doesn't matter. What matters is the
|
defer close(c1)
|
||||||
// fact that CmdAttach returns.
|
|
||||||
|
|
||||||
r := &hijackTester{
|
r := &hijackTester{
|
||||||
ResponseRecorder: httptest.NewRecorder(),
|
ResponseRecorder: httptest.NewRecorder(),
|
||||||
|
@ -1120,14 +1106,9 @@ func TestPostContainersAttach(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := postContainersAttach(srv, r, req, map[string]string{"name": container.Id})
|
if err := postContainersAttach(srv, r, req, map[string]string{"name": container.Id}); err != nil {
|
||||||
close(c1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Acknowledge hijack
|
// Acknowledge hijack
|
||||||
|
@ -1165,7 +1146,7 @@ func TestPostContainersAttach(t *testing.T) {
|
||||||
container.Wait()
|
container.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Test deleting runnign container
|
// FIXME: Test deleting running container
|
||||||
// FIXME: Test deleting container with volume
|
// FIXME: Test deleting container with volume
|
||||||
// FIXME: Test deleting volume in use by other container
|
// FIXME: Test deleting volume in use by other container
|
||||||
func TestDeleteContainers(t *testing.T) {
|
func TestDeleteContainers(t *testing.T) {
|
||||||
|
@ -1190,20 +1171,14 @@ func TestDeleteContainers(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
|
||||||
|
|
||||||
req, err := http.NewRequest("DELETE", "/containers/"+container.Id, nil)
|
req, err := http.NewRequest("DELETE", "/containers/"+container.Id, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
r := httptest.NewRecorder()
|
||||||
body, err := deleteContainers(srv, r, req, map[string]string{"name": container.Id})
|
if err := deleteContainers(srv, r, req, map[string]string{"name": container.Id}); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if body != nil {
|
|
||||||
t.Fatalf("No body expected, received: %s\n", body)
|
|
||||||
}
|
|
||||||
if r.Code != http.StatusNoContent {
|
if r.Code != http.StatusNoContent {
|
||||||
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1196,6 +1196,14 @@ func stream(method, path string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
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 {
|
if _, err := io.Copy(os.Stdout, resp.Body); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,83 +4,120 @@ Docker Builder
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
.. contents:: Table of Contents
|
||||||
|
|
||||||
1. Format
|
Docker Builder specifes a simple DSL which allows you to automate the steps you
|
||||||
|
would normally manually take to create an image. Docker Build will run your
|
||||||
|
steps and commit them along the way, giving you a final image.
|
||||||
|
|
||||||
|
1. Usage
|
||||||
|
========
|
||||||
|
|
||||||
|
To use Docker Builder, assemble the steps into a text file (commonly referred to
|
||||||
|
as a Dockerfile) and supply this to `docker build` on STDIN, like so:
|
||||||
|
|
||||||
|
``docker build < Dockerfile``
|
||||||
|
|
||||||
|
Docker will run your steps one-by-one, committing the result if necessary,
|
||||||
|
before finally outputting the ID of your new image.
|
||||||
|
|
||||||
|
2. Format
|
||||||
=========
|
=========
|
||||||
|
|
||||||
The Docker builder format is quite simple:
|
The Dockerfile format is quite simple:
|
||||||
|
|
||||||
``instruction arguments``
|
``instruction arguments``
|
||||||
|
|
||||||
The first instruction must be `FROM`
|
The Instruction is not case-sensitive, however convention is for them to be
|
||||||
|
UPPERCASE in order to distinguish them from arguments more easily.
|
||||||
|
|
||||||
All instruction are to be placed in a file named `Dockerfile`
|
Dockerfiles are evaluated in order, therefore the first instruction must be
|
||||||
|
`FROM` in order to specify the base image from which you are building.
|
||||||
|
|
||||||
In order to place comments within a Dockerfile, simply prefix the line with "`#`"
|
Docker will ignore lines in Dockerfiles prefixed with "`#`", so you may add
|
||||||
|
comment lines. A comment marker in the rest of the line will be treated as an
|
||||||
|
argument.
|
||||||
|
|
||||||
2. Instructions
|
2. Instructions
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Docker builder comes with a set of instructions:
|
Docker builder comes with a set of instructions, described below.
|
||||||
|
|
||||||
1. FROM: Set from what image to build
|
|
||||||
2. RUN: Execute a command
|
|
||||||
3. INSERT: Insert a remote file (http) into the image
|
|
||||||
|
|
||||||
2.1 FROM
|
2.1 FROM
|
||||||
--------
|
--------
|
||||||
|
|
||||||
``FROM <image>``
|
``FROM <image>``
|
||||||
|
|
||||||
The `FROM` instruction must be the first one in order for Builder to know from where to run commands.
|
The `FROM` instruction sets the base image for subsequent instructions. As such,
|
||||||
|
a valid Dockerfile must have it as its first instruction.
|
||||||
|
|
||||||
`FROM` can also be used in order to build multiple images within a single Dockerfile
|
`FROM` can be included multiple times within a single Dockerfile in order to
|
||||||
|
create multiple images. Simply make a note of the last image id output by the
|
||||||
|
commit before each new `FROM` command.
|
||||||
|
|
||||||
2.2 MAINTAINER
|
2.2 MAINTAINER
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
``MAINTAINER <name>``
|
``MAINTAINER <name>``
|
||||||
|
|
||||||
The `MAINTAINER` instruction allow you to set the Author field of the generated images.
|
The `MAINTAINER` instruction allows you to set the Author field of the generated
|
||||||
This instruction is never automatically reset.
|
images.
|
||||||
|
|
||||||
2.3 RUN
|
2.3 RUN
|
||||||
-------
|
-------
|
||||||
|
|
||||||
``RUN <command>``
|
``RUN <command>``
|
||||||
|
|
||||||
The `RUN` instruction is the main one, it allows you to execute any commands on the `FROM` image and to save the results.
|
The `RUN` instruction will execute any commands on the current image and commit
|
||||||
You can use as many `RUN` as you want within a Dockerfile, the commands will be executed on the result of the previous command.
|
the results. The resulting committed image will be used for the next step in the
|
||||||
|
Dockerfile.
|
||||||
|
|
||||||
|
Layering `RUN` instructions and generating commits conforms to the
|
||||||
|
core concepts of Docker where commits are cheap and containers can be created
|
||||||
|
from any point in an image's history, much like source control.
|
||||||
|
|
||||||
2.4 CMD
|
2.4 CMD
|
||||||
-------
|
-------
|
||||||
|
|
||||||
``CMD <command>``
|
``CMD <command>``
|
||||||
|
|
||||||
The `CMD` instruction sets the command to be executed when running the image.
|
The `CMD` instruction sets the command to be executed when running the image.
|
||||||
It is equivalent to do `docker commit -run '{"Cmd": <command>}'` outside the builder.
|
This is functionally equivalent to running
|
||||||
|
`docker commit -run '{"Cmd": <command>}'` outside the builder.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Do not confuse `RUN` with `CMD`. `RUN` actually run a command and save the result, `CMD` does not execute anything.
|
Don't confuse `RUN` with `CMD`. `RUN` actually runs a command and commits
|
||||||
|
the result; `CMD` does not execute anything at build time, but specifies the
|
||||||
|
intended command for the image.
|
||||||
|
|
||||||
2.5 EXPOSE
|
2.5 EXPOSE
|
||||||
----------
|
----------
|
||||||
|
|
||||||
``EXPOSE <port> [<port>...]``
|
``EXPOSE <port> [<port>...]``
|
||||||
|
|
||||||
The `EXPOSE` instruction sets ports to be publicly exposed when running the image.
|
The `EXPOSE` instruction sets ports to be publicly exposed when running the
|
||||||
This is equivalent to do `docker commit -run '{"PortSpecs": ["<port>", "<port2>"]}'` outside the builder.
|
image. This is functionally equivalent to running
|
||||||
|
`docker commit -run '{"PortSpecs": ["<port>", "<port2>"]}'` outside the builder.
|
||||||
|
|
||||||
2.6 ENV
|
2.6 ENV
|
||||||
-------
|
-------
|
||||||
|
|
||||||
``ENV <key> <value>``
|
``ENV <key> <value>``
|
||||||
|
|
||||||
The `ENV` instruction set as environment variable `<key>` with the value `<value>`. This value will be passed to all future ``RUN`` instructions.
|
The `ENV` instruction sets the environment variable `<key>` to the value
|
||||||
|
`<value>`. This value will be passed to all future ``RUN`` instructions. This is
|
||||||
|
functionally equivalent to prefixing the command with `<key>=<value>`
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The environment variables are local to the Dockerfile, they will not be set as autorun.
|
The environment variables are local to the Dockerfile, they will not persist
|
||||||
|
when a container is run from the resulting image.
|
||||||
|
|
||||||
2.7 INSERT
|
2.7 INSERT
|
||||||
----------
|
----------
|
||||||
|
|
||||||
``INSERT <file url> <path>``
|
``INSERT <file url> <path>``
|
||||||
|
|
||||||
The `INSERT` instruction will download the file at the given url and place it within the image at the given path.
|
The `INSERT` instruction will download the file from the given url to the given
|
||||||
|
path within the image. It is similar to `RUN curl -o <path> <url>`, assuming
|
||||||
|
curl was installed within the image.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The path must include the file name.
|
The path must include the file name.
|
||||||
|
@ -89,42 +126,57 @@ The `INSERT` instruction will download the file at the given url and place it wi
|
||||||
3. Dockerfile Examples
|
3. Dockerfile Examples
|
||||||
======================
|
======================
|
||||||
|
|
||||||
::
|
.. code-block:: bash
|
||||||
|
|
||||||
# Nginx
|
# Nginx
|
||||||
#
|
#
|
||||||
# VERSION 0.0.1
|
# VERSION 0.0.1
|
||||||
# DOCKER-VERSION 0.2
|
|
||||||
|
|
||||||
from ubuntu
|
FROM ubuntu
|
||||||
maintainer Guillaume J. Charmes "guillaume@dotcloud.com"
|
MAINTAINER Guillaume J. Charmes "guillaume@dotcloud.com"
|
||||||
|
|
||||||
# make sure the package repository is up to date
|
# make sure the package repository is up to date
|
||||||
run echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
|
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
|
||||||
run apt-get update
|
RUN apt-get update
|
||||||
|
|
||||||
run apt-get install -y inotify-tools nginx apache2 openssh-server
|
RUN apt-get install -y inotify-tools nginx apache2 openssh-server
|
||||||
insert https://raw.github.com/creack/docker-vps/master/nginx-wrapper.sh /usr/sbin/nginx-wrapper
|
INSERT https://raw.github.com/creack/docker-vps/master/nginx-wrapper.sh /usr/sbin/nginx-wrapper
|
||||||
|
|
||||||
::
|
.. code-block:: bash
|
||||||
|
|
||||||
# Firefox over VNC
|
# Firefox over VNC
|
||||||
#
|
#
|
||||||
# VERSION 0.3
|
# VERSION 0.3
|
||||||
# DOCKER-VERSION 0.2
|
|
||||||
|
|
||||||
from ubuntu
|
FROM ubuntu
|
||||||
# make sure the package repository is up to date
|
# make sure the package repository is up to date
|
||||||
run echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
|
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
|
||||||
run apt-get update
|
RUN apt-get update
|
||||||
|
|
||||||
# Install vnc, xvfb in order to create a 'fake' display and firefox
|
# Install vnc, xvfb in order to create a 'fake' display and firefox
|
||||||
run apt-get install -y x11vnc xvfb firefox
|
RUN apt-get install -y x11vnc xvfb firefox
|
||||||
run mkdir /.vnc
|
RUN mkdir /.vnc
|
||||||
# Setup a password
|
# Setup a password
|
||||||
run x11vnc -storepasswd 1234 ~/.vnc/passwd
|
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
|
||||||
# Autostart firefox (might not be the best way to do it, but it does the trick)
|
# Autostart firefox (might not be the best way, but it does the trick)
|
||||||
run bash -c 'echo "firefox" >> /.bashrc'
|
RUN bash -c 'echo "firefox" >> /.bashrc'
|
||||||
|
|
||||||
expose 5900
|
EXPOSE 5900
|
||||||
cmd ["x11vnc", "-forever", "-usepw", "-create"]
|
CMD ["x11vnc", "-forever", "-usepw", "-create"]
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Multiple images example
|
||||||
|
#
|
||||||
|
# VERSION 0.1
|
||||||
|
|
||||||
|
FROM ubuntu
|
||||||
|
RUN echo foo > bar
|
||||||
|
# Will output something like ===> 907ad6c2736f
|
||||||
|
|
||||||
|
FROM ubuntu
|
||||||
|
RUN echo moo > oink
|
||||||
|
# Will output something like ===> 695d7793cbe4
|
||||||
|
|
||||||
|
# You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
|
||||||
|
# /oink.
|
|
@ -316,7 +316,7 @@ func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, re
|
||||||
err = func() error {
|
err = func() error {
|
||||||
localChecksums := make(map[string]string)
|
localChecksums := make(map[string]string)
|
||||||
remoteChecksums := []ImgListJson{}
|
remoteChecksums := []ImgListJson{}
|
||||||
checksumDictPth := path.Join(graph.Root, "..", "checksums")
|
checksumDictPth := path.Join(graph.Root, "checksums")
|
||||||
|
|
||||||
if err := json.Unmarshal(checksumsJson, &remoteChecksums); err != nil {
|
if err := json.Unmarshal(checksumsJson, &remoteChecksums); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -262,8 +262,13 @@ func (srv *Server) Containers(all, trunc_cmd, only_ids bool, n int, since, befor
|
||||||
displayed++
|
displayed++
|
||||||
|
|
||||||
c := ApiContainers{
|
c := ApiContainers{
|
||||||
|
Id: container.Id,
|
||||||
|
}
|
||||||
|
if trunc_cmd {
|
||||||
|
c = ApiContainers{
|
||||||
Id: container.ShortId(),
|
Id: container.ShortId(),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !only_ids {
|
if !only_ids {
|
||||||
command := fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
|
command := fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
|
||||||
|
|
Loading…
Add table
Reference in a new issue