mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
added kill and images(wip)
This commit is contained in:
parent
c0d5d5969b
commit
79e9105806
4 changed files with 274 additions and 57 deletions
100
api.go
100
api.go
|
@ -2,9 +2,11 @@ package docker
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
_ "fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ListenAndServe(addr string, runtime *Runtime) error {
|
||||
|
@ -21,10 +23,102 @@ func ListenAndServe(addr string, runtime *Runtime) error {
|
|||
}
|
||||
})
|
||||
|
||||
r.Path("/kill").Methods("GET", "POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var ids []string
|
||||
if err := json.NewDecoder(r.Body).Decode(&ids); err != nil {
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
|
||||
var ret SimpleMessage
|
||||
for _, name := range ids {
|
||||
container := runtime.Get(name)
|
||||
if container == nil {
|
||||
ret.Message = "No such container: " + name + "\n"
|
||||
break
|
||||
}
|
||||
if err := container.Kill(); err != nil {
|
||||
ret.Message = ret.Message + "Error killing container " + name + ": " + err.Error() + "\n"
|
||||
}
|
||||
}
|
||||
if ret.Message == "" {
|
||||
w.WriteHeader(200)
|
||||
} else {
|
||||
w.WriteHeader(500)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(ret)
|
||||
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
|
||||
var in ImagesIn
|
||||
json.NewDecoder(r.Body).Decode(&in)
|
||||
|
||||
var allImages map[string]*Image
|
||||
var err error
|
||||
if in.All {
|
||||
allImages, err = runtime.graph.Map()
|
||||
} else {
|
||||
allImages, err = runtime.graph.Heads()
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
var outs []ImagesOut
|
||||
for name, repository := range runtime.repositories.Repositories {
|
||||
if in.NameFilter != "" && name != in.NameFilter {
|
||||
continue
|
||||
}
|
||||
for tag, id := range repository {
|
||||
var out ImagesOut
|
||||
image, err := runtime.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 !in.Quiet {
|
||||
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 in.NameFilter == "" {
|
||||
for id, image := range allImages {
|
||||
var out ImagesOut
|
||||
if !in.Quiet {
|
||||
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 {
|
||||
w.WriteHeader(500)
|
||||
} else {
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return http.ListenAndServe(addr, r)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
package docker
|
||||
|
||||
type VersionOut struct {
|
||||
Version string
|
||||
GitCommit string
|
||||
MemoryLimitDisabled bool
|
||||
type SimpleMessage struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type ImagesIn struct {
|
||||
NameFilter string
|
||||
Quiet bool
|
||||
All bool
|
||||
}
|
||||
|
||||
type ImagesOut struct {
|
||||
Repository string `json:",omitempty"`
|
||||
Tag string `json:",omitempty"`
|
||||
Id string
|
||||
Created string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type VersionOut struct {
|
||||
Version string
|
||||
GitCommit string
|
||||
MemoryLimitDisabled bool
|
||||
}
|
||||
|
|
|
@ -976,7 +976,6 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
|
|||
return nil
|
||||
}
|
||||
|
||||
|
||||
type Server struct {
|
||||
runtime *Runtime
|
||||
}
|
||||
|
|
205
commands2.go
205
commands2.go
|
@ -1,25 +1,31 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
func ParseCommands(args []string) error {
|
||||
|
||||
cmds := map[string]func(args []string) error {
|
||||
"version":cmdVersion,
|
||||
|
||||
cmds := map[string]func(args []string) error{
|
||||
"images": cmdImages,
|
||||
"kill": cmdKill,
|
||||
"version": cmdVersion,
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
cmd, exists := cmds[args[0]]
|
||||
cmd, exists := cmds[args[0]]
|
||||
if !exists {
|
||||
//TODO display commend not found
|
||||
return cmdHelp(args)
|
||||
}
|
||||
return cmd(args)
|
||||
return cmd(args[1:])
|
||||
}
|
||||
return cmdHelp(args)
|
||||
}
|
||||
|
@ -27,31 +33,31 @@ func ParseCommands(args []string) error {
|
|||
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"},
|
||||
// {"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"},
|
||||
// {"wait", "Block until a container stops, then print its exit code"},
|
||||
} {
|
||||
help += fmt.Sprintf(" %-10.10s%s\n", cmd[0], cmd[1])
|
||||
}
|
||||
|
@ -59,8 +65,80 @@ func cmdHelp(args []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func cmdVersion(args []string) error {
|
||||
body, err := apiCall("version")
|
||||
func cmdImages(args []string) error {
|
||||
cmd := subcmd("images", "[OPTIONS] [NAME]", "List images")
|
||||
quiet := cmd.Bool("q", false, "only show numeric IDs")
|
||||
flAll := cmd.Bool("a", false, "show all images")
|
||||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
}
|
||||
if cmd.NArg() > 1 {
|
||||
cmd.Usage()
|
||||
return nil
|
||||
}
|
||||
var nameFilter string
|
||||
if cmd.NArg() == 1 {
|
||||
nameFilter = cmd.Arg(0)
|
||||
}
|
||||
|
||||
in := ImagesIn{nameFilter, *quiet, *flAll}
|
||||
|
||||
body, err := apiPost("images", in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var outs []ImagesOut
|
||||
err = json.Unmarshal(body, &outs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
|
||||
if !*quiet {
|
||||
fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED")
|
||||
}
|
||||
|
||||
for _, out := range outs {
|
||||
if !*quiet {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", out.Repository, out.Tag, out.Id, out.Created)
|
||||
} else {
|
||||
fmt.Fprintln(w, out.Id)
|
||||
}
|
||||
}
|
||||
|
||||
if !*quiet {
|
||||
w.Flush()
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func cmdKill(args []string) error {
|
||||
cmd := subcmd("kill", "CONTAINER [CONTAINER...]", "Kill a running container")
|
||||
if err := cmd.Parse(args); err != nil {
|
||||
return nil
|
||||
}
|
||||
if cmd.NArg() < 1 {
|
||||
cmd.Usage()
|
||||
return nil
|
||||
}
|
||||
|
||||
body, err := apiPost("kill", args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var out SimpleMessage
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Print(out.Message)
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdVersion(_ []string) error {
|
||||
body, err := apiGet("version")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -68,28 +146,57 @@ func cmdVersion(args []string) error {
|
|||
var out VersionOut
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
fmt.Println("Version:", out.Version)
|
||||
fmt.Println("Git Commit:", out.GitCommit)
|
||||
if out.MemoryLimitDisabled {
|
||||
fmt.Println("Memory limit disabled")
|
||||
}
|
||||
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
|
||||
}
|
||||
func apiGet(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
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func apiPost(path string, data interface{}) ([]byte, error) {
|
||||
buf, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataBuf := bytes.NewBuffer(buf)
|
||||
resp, err := http.Post("http://0.0.0.0:4243/"+path, "application/json", dataBuf)
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
func subcmd(name, signature, description string) *flag.FlagSet {
|
||||
flags := flag.NewFlagSet(name, flag.ContinueOnError)
|
||||
flags.Usage = func() {
|
||||
fmt.Printf("\nUsage: docker %s %s\n\n%s\n\n", name, signature, description)
|
||||
flags.PrintDefaults()
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue