From c0d5d5969bb9c0bfe79e7a11977697e50cc185ae Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Thu, 18 Apr 2013 03:13:43 +0200 Subject: [PATCH] skeleton remote API, only version working (wip) --- api.go | 73 ++++++++++--------------------------- api_params.go | 7 ++++ commands.go | 15 -------- commands2.go | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ docker/docker.go | 14 ++++--- 5 files changed, 130 insertions(+), 74 deletions(-) create mode 100644 api_params.go create mode 100644 commands2.go diff --git a/api.go b/api.go index 853f7abbde..353a93288a 100644 --- a/api.go +++ b/api.go @@ -1,63 +1,30 @@ package docker import ( + "encoding/json" + "log" "github.com/gorilla/mux" "net/http" - _"encoding/json" ) +func ListenAndServe(addr string, runtime *Runtime) error { + r := mux.NewRouter() + log.Printf("Listening for HTTP on %s\n", addr) -type RestEndpoint struct { - *mux.Router - runtime *Runtime + r.Path("/version").Methods("GET", "POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + m := VersionOut{VERSION, GIT_COMMIT, NO_MEMORY_LIMIT} + b, err := json.Marshal(m) + if err != nil { + w.WriteHeader(500) + } else { + w.Write(b) + } + }) + + r.Path("/images").Methods("GET", "POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + //TODO use runtime + }) + + return http.ListenAndServe(addr, r) } -func NewRestEndpoint(runtime *Runtime) *RestEndpoint { - endpoint := &RestEndpoint{ - Router: mux.NewRouter(), - runtime: runtime, - } - endpoint.Path("/images").Methods("GET").HandlerFunc(endpoint.GetImages) - endpoint.Path("/images").Methods("POST").HandlerFunc(endpoint.PostImages) - endpoint.Path("/images/{id}").Methods("GET").HandlerFunc(endpoint.GetImage) - endpoint.Path("/images/{id}").Methods("DELETE").HandlerFunc(endpoint.DeleteImage) - endpoint.Path("/containers").Methods("GET").HandlerFunc(endpoint.GetContainers) - endpoint.Path("/containers").Methods("POST").HandlerFunc(endpoint.PostContainers) - endpoint.Path("/containers/{id}").Methods("GET").HandlerFunc(endpoint.GetContainer) - endpoint.Path("/containers/{id}").Methods("DELETE").HandlerFunc(endpoint.DeleteContainer) - return endpoint -} - -func (ep *RestEndpoint) GetImages(w http.ResponseWriter, r *http.Response) { - -} - -func (ep *RestEndpoint) PostImages(w http.ResponseWriter, r *http.Response) { - -} - -func (ep *RestEndpoint) GetImage(w http.ResponseWriter, r *http.Response) { - -} - -func (ep *RestEndpoint) DeleteImage(w http.ResponseWriter, r *http.Response) { - -} - -func (ep *RestEndpoint) GetContainers(w http.ResponseWriter, r *http.Response) { - -} - -func (ep *RestEndpoint) PostContainers(w http.ResponseWriter, r *http.Response) { - -} - -func (ep *RestEndpoint) GetContainer(w http.ResponseWriter, r *http.Response) { - -} - -func (ep *RestEndpoint) DeleteContainer(w http.ResponseWriter, r *http.Response) { - -} - - diff --git a/api_params.go b/api_params.go new file mode 100644 index 0000000000..277074964d --- /dev/null +++ b/api_params.go @@ -0,0 +1,7 @@ +package docker + +type VersionOut struct { + Version string + GitCommit string + MemoryLimitDisabled bool +} diff --git a/commands.go b/commands.go index 10890ad92c..b30f9690e4 100644 --- a/commands.go +++ b/commands.go @@ -976,22 +976,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s return nil } -func NewServer() (*Server, error) { - if runtime.GOARCH != "amd64" { - log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH) - } - runtime, err := NewRuntime() - if err != nil { - return nil, err - } - srv := &Server{ - runtime: runtime, - restEndpoint: NewRestEndpoint(runtime), - } - return srv, nil -} type Server struct { runtime *Runtime - restEndpoint *RestEndpoint } diff --git a/commands2.go b/commands2.go new file mode 100644 index 0000000000..014a4bbe62 --- /dev/null +++ b/commands2.go @@ -0,0 +1,95 @@ +package docker + +import ( + "fmt" + "io/ioutil" + "net/http" + "encoding/json" +) + +func ParseCommands(args []string) error { + + cmds := map[string]func(args []string) error { + "version":cmdVersion, + } + + if len(args) > 0 { + cmd, exists := cmds[args[0]] + if !exists { + //TODO display commend not found + return cmdHelp(args) + } + return cmd(args) + } + return cmdHelp(args) +} + +func cmdHelp(args []string) error { + help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n" + for _, cmd := range [][]string{ +// {"attach", "Attach to a running container"}, +// {"commit", "Create a new image from a container's changes"}, +// {"diff", "Inspect changes on a container's filesystem"}, +// {"export", "Stream the contents of a container as a tar archive"}, +// {"history", "Show the history of an image"}, +// {"images", "List images"}, +// {"import", "Create a new filesystem image from the contents of a tarball"}, +// {"info", "Display system-wide information"}, +// {"inspect", "Return low-level information on a container"}, +// {"kill", "Kill a running container"}, +// {"login", "Register or Login to the docker registry server"}, +// {"logs", "Fetch the logs of a container"}, +// {"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"}, +// {"ps", "List containers"}, +// {"pull", "Pull an image or a repository from the docker registry server"}, +// {"push", "Push an image or a repository to the docker registry server"}, +// {"restart", "Restart a running container"}, +// {"rm", "Remove a container"}, +// {"rmi", "Remove an image"}, +// {"run", "Run a command in a new container"}, +// {"start", "Start a stopped container"}, +// {"stop", "Stop a running container"}, +// {"tag", "Tag an image into a repository"}, + {"version", "Show the docker version information"}, +// {"wait", "Block until a container stops, then print its exit code"}, + } { + help += fmt.Sprintf(" %-10.10s%s\n", cmd[0], cmd[1]) + } + fmt.Println(help) + return nil +} + +func cmdVersion(args []string) error { + body, err := apiCall("version") + if err != nil { + return err + } + + var out VersionOut + err = json.Unmarshal(body, &out) + if err != nil { + return err + } + fmt.Println("Version:", out.Version) + fmt.Println("Git Commit:", out.GitCommit) + if out.MemoryLimitDisabled { + fmt.Println("Memory limit disabled") + } + + return nil +} + +func apiCall(path string) ([]byte, error) { + resp, err := http.Get("http://0.0.0.0:4243/" + path) + if err != nil { + return nil,err + } + //TODO check status code + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return body, nil + +} \ No newline at end of file diff --git a/docker/docker.go b/docker/docker.go index 693ddd72f8..4639921d52 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -10,6 +10,7 @@ import ( "log" "os" "os/signal" + "runtime" "syscall" ) @@ -52,7 +53,7 @@ func main() { log.Fatal(err) } } else { - if err := runCommand(flag.Args()); err != nil { + if err := docker.ParseCommands(flag.Args()); err != nil { log.Fatal(err) } } @@ -95,14 +96,15 @@ func daemon(pidfile string) error { os.Exit(0) }() - service, err := docker.NewServer() + if runtime.GOARCH != "amd64" { + log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH) + } + runtime, err := docker.NewRuntime() if err != nil { return err } - if err := http.ListenAndServe("0.0.0.0:4243", service.restEndpoint); err != nil { - return err - } - return rcli.ListenAndServe("tcp", "127.0.0.1:4242", service) + + return docker.ListenAndServe("0.0.0.0:4243", runtime) } func runCommand(args []string) error {