123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- package docker
- import (
- _"bytes"
- "encoding/json"
- "fmt"
- "github.com/gorilla/mux"
- "io/ioutil"
- "log"
- "net/http"
- "os"
- "runtime"
- "strconv"
- "strings"
- "time"
- )
- func ListenAndServe(addr string, rtime *Runtime) error {
- r := mux.NewRouter()
- log.Printf("Listening for HTTP on %s\n", addr)
- r.Path("/version").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- m := VersionOut{VERSION, GIT_COMMIT, NO_MEMORY_LIMIT}
- b, err := json.Marshal(m)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- } else {
- w.Write(b)
- }
- })
- r.Path("/containers/{name:.*}/kill").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
- if container := rtime.Get(name); container != nil {
- if err := container.Kill(); err != nil {
- http.Error(w, "Error restarting container "+name+": "+err.Error(), http.StatusInternalServerError)
- return
- }
- } else {
- http.Error(w, "No such container: "+name, http.StatusInternalServerError)
- return
- }
- w.WriteHeader(200)
- })
- r.Path("/images").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- All := r.Form.Get("all")
- NameFilter := r.Form.Get("filter")
- Quiet := r.Form.Get("quiet")
- var allImages map[string]*Image
- var err error
- if All == "true" {
- allImages, err = rtime.graph.Map()
- } else {
- allImages, err = rtime.graph.Heads()
- }
- if err != nil {
- w.WriteHeader(500)
- return
- }
- var outs []ImagesOut
- for name, repository := range rtime.repositories.Repositories {
- if NameFilter != "" && name != NameFilter {
- continue
- }
- for tag, id := range repository {
- var out ImagesOut
- image, err := rtime.graph.Get(id)
- if err != nil {
- log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
- continue
- }
- delete(allImages, id)
- if Quiet != "true" {
- out.Repository = name
- out.Tag = tag
- out.Id = TruncateId(id)
- out.Created = HumanDuration(time.Now().Sub(image.Created)) + " ago"
- } else {
- out.Id = image.ShortId()
- }
- outs = append(outs, out)
- }
- }
- // Display images which aren't part of a
- if NameFilter == "" {
- for id, image := range allImages {
- var out ImagesOut
- if Quiet != "true" {
- out.Repository = "<none>"
- out.Tag = "<none>"
- out.Id = TruncateId(id)
- out.Created = HumanDuration(time.Now().Sub(image.Created)) + " ago"
- } else {
- out.Id = image.ShortId()
- }
- outs = append(outs, out)
- }
- }
- b, err := json.Marshal(outs)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- } else {
- w.Write(b)
- }
- })
- r.Path("/info").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- images, _ := rtime.graph.All()
- var imgcount int
- if images == nil {
- imgcount = 0
- } else {
- imgcount = len(images)
- }
- var out InfoOut
- out.Containers = len(rtime.List())
- out.Version = VERSION
- out.Images = imgcount
- if os.Getenv("DEBUG") == "1" {
- out.Debug = true
- out.NFd = getTotalUsedFds()
- out.NGoroutines = runtime.NumGoroutine()
- }
- b, err := json.Marshal(out)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- } else {
- w.Write(b)
- }
- })
- r.Path("/images/{name:.*}/history").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
- image, err := rtime.repositories.LookupImage(name)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- var outs []HistoryOut
- err = image.WalkHistory(func(img *Image) error {
- var out HistoryOut
- out.Id = rtime.repositories.ImageName(img.ShortId())
- out.Created = HumanDuration(time.Now().Sub(img.Created)) + " ago"
- out.CreatedBy = strings.Join(img.ContainerConfig.Cmd, " ")
- return nil
- })
- b, err := json.Marshal(outs)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- } else {
- w.Write(b)
- }
- })
- r.Path("/containers/{name:.*}/logs").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
- if container := rtime.Get(name); container != nil {
- var out LogsOut
- logStdout, err := container.ReadLog("stdout")
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- logStderr, err := container.ReadLog("stderr")
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- stdout, errStdout := ioutil.ReadAll(logStdout)
- if errStdout != nil {
- http.Error(w, errStdout.Error(), http.StatusInternalServerError)
- return
- } else {
- out.Stdout = fmt.Sprintf("%s", stdout)
- }
- stderr, errStderr := ioutil.ReadAll(logStderr)
- if errStderr != nil {
- http.Error(w, errStderr.Error(), http.StatusInternalServerError)
- return
- } else {
- out.Stderr = fmt.Sprintf("%s", stderr)
- }
- b, err := json.Marshal(out)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- } else {
- w.Write(b)
- }
- } else {
- http.Error(w, "No such container: "+name, http.StatusInternalServerError)
- }
- })
- r.Path("/containers").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- All := r.Form.Get("all")
- NoTrunc := r.Form.Get("notrunc")
- Quiet := r.Form.Get("quiet")
- Last := r.Form.Get("n")
- n, err := strconv.Atoi(Last)
- if err != nil {
- n = -1
- }
- var outs []PsOut
- for i, container := range rtime.List() {
- if !container.State.Running && All != "true" && n == -1 {
- continue
- }
- if i == n {
- break
- }
- var out PsOut
- out.Id = container.ShortId()
- if Quiet != "true" {
- command := fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
- if NoTrunc != "true" {
- command = Trunc(command, 20)
- }
- out.Image = rtime.repositories.ImageName(container.Image)
- out.Command = command
- out.Created = HumanDuration(time.Now().Sub(container.Created)) + " ago"
- out.Status = container.State.String()
- }
- outs = append(outs, out)
- }
- b, err := json.Marshal(outs)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- } else {
- w.Write(b)
- }
- })
- r.Path("/pull").Methods("GET", "POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- var in PullIn
- //json.NewDecoder(r.Body).Decode(&in)
- in.Name = "base"
- hj, ok := w.(http.Hijacker)
- if !ok {
- http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
- return
- }
- conn, bufrw, err := hj.Hijack()
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- // Don't forget to close the connection:
- defer conn.Close()
- if rtime.graph.LookupRemoteImage(in.Name, rtime.authConfig) {
- if err := rtime.graph.PullImage(bufrw, in.Name, rtime.authConfig); err != nil {
- //http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- return
- }
- if err := rtime.graph.PullRepository(bufrw, in.Name, "", rtime.repositories, rtime.authConfig); err != nil {
- //http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- return
- })
- r.Path("/containers/{name:.*}/restart").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
- if container := rtime.Get(name); container != nil {
- if err := container.Restart(); err != nil {
- http.Error(w, "Error restarting container "+name+": "+err.Error(), http.StatusInternalServerError)
- return
- }
- } else {
- http.Error(w, "No such container: "+name, http.StatusInternalServerError)
- return
- }
- w.WriteHeader(200)
- })
- r.Path("/containers/{name:.*}").Methods("DELETE").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
- if container := rtime.Get(name); container != nil {
- if err := rtime.Destroy(container); err != nil {
- http.Error(w, "Error destroying container "+name+": "+err.Error(), http.StatusInternalServerError)
- return
- }
- } else {
- http.Error(w, "No such container: "+name, http.StatusInternalServerError)
- return
- }
- w.WriteHeader(200)
- })
- r.Path("/images/{name:.*}").Methods("DELETE").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
-
- img, err := rtime.repositories.LookupImage(name)
- if err != nil {
- http.Error(w, "No such image: "+name, http.StatusInternalServerError)
- return
- } else {
- if err := rtime.graph.Delete(img.Id); err != nil {
- http.Error(w, "Error deleting image "+name+": "+err.Error(), http.StatusInternalServerError)
- return
- }
- }
- w.WriteHeader(200)
- })
- r.Path("/containers/{name:.*}/start").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
- if container := rtime.Get(name); container != nil {
- if err := container.Start(); err != nil {
- http.Error(w, "Error starting container "+name+": "+err.Error(), http.StatusInternalServerError)
- return
- }
- } else {
- http.Error(w, "No such container: "+name, http.StatusInternalServerError)
- return
- }
- w.WriteHeader(200)
- })
- r.Path("/containers/{name:.*}/stop").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- log.Println(r.RequestURI)
- vars := mux.Vars(r)
- name := vars["name"]
- if container := rtime.Get(name); container != nil {
- if err := container.Stop(); err != nil {
- http.Error(w, "Error stopping container "+name+": "+err.Error(), http.StatusInternalServerError)
- return
- }
- } else {
- http.Error(w, "No such container: "+name, http.StatusInternalServerError)
- return
- }
- w.WriteHeader(200)
- })
- return http.ListenAndServe(addr, r)
- }
|