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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
_ "fmt"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ListenAndServe(addr string, runtime *Runtime) error {
|
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) {
|
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)
|
return http.ListenAndServe(addr, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,24 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
type VersionOut struct {
|
type SimpleMessage struct {
|
||||||
Version string
|
Message string
|
||||||
GitCommit string
|
}
|
||||||
MemoryLimitDisabled bool
|
|
||||||
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
runtime *Runtime
|
runtime *Runtime
|
||||||
}
|
}
|
||||||
|
|
205
commands2.go
205
commands2.go
|
@ -1,25 +1,31 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"encoding/json"
|
"os"
|
||||||
|
"text/tabwriter"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseCommands(args []string) error {
|
func ParseCommands(args []string) error {
|
||||||
|
|
||||||
cmds := map[string]func(args []string) error {
|
cmds := map[string]func(args []string) error{
|
||||||
"version":cmdVersion,
|
"images": cmdImages,
|
||||||
|
"kill": cmdKill,
|
||||||
|
"version": cmdVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
cmd, exists := cmds[args[0]]
|
cmd, exists := cmds[args[0]]
|
||||||
if !exists {
|
if !exists {
|
||||||
//TODO display commend not found
|
//TODO display commend not found
|
||||||
return cmdHelp(args)
|
return cmdHelp(args)
|
||||||
}
|
}
|
||||||
return cmd(args)
|
return cmd(args[1:])
|
||||||
}
|
}
|
||||||
return cmdHelp(args)
|
return cmdHelp(args)
|
||||||
}
|
}
|
||||||
|
@ -27,31 +33,31 @@ func ParseCommands(args []string) error {
|
||||||
func cmdHelp(args []string) error {
|
func cmdHelp(args []string) error {
|
||||||
help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n"
|
help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n"
|
||||||
for _, cmd := range [][]string{
|
for _, cmd := range [][]string{
|
||||||
// {"attach", "Attach to a running container"},
|
// {"attach", "Attach to a running container"},
|
||||||
// {"commit", "Create a new image from a container's changes"},
|
// {"commit", "Create a new image from a container's changes"},
|
||||||
// {"diff", "Inspect changes on a container's filesystem"},
|
// {"diff", "Inspect changes on a container's filesystem"},
|
||||||
// {"export", "Stream the contents of a container as a tar archive"},
|
// {"export", "Stream the contents of a container as a tar archive"},
|
||||||
// {"history", "Show the history of an image"},
|
// {"history", "Show the history of an image"},
|
||||||
// {"images", "List images"},
|
{"images", "List images"},
|
||||||
// {"import", "Create a new filesystem image from the contents of a tarball"},
|
// {"import", "Create a new filesystem image from the contents of a tarball"},
|
||||||
// {"info", "Display system-wide information"},
|
// {"info", "Display system-wide information"},
|
||||||
// {"inspect", "Return low-level information on a container"},
|
// {"inspect", "Return low-level information on a container"},
|
||||||
// {"kill", "Kill a running container"},
|
{"kill", "Kill a running container"},
|
||||||
// {"login", "Register or Login to the docker registry server"},
|
// {"login", "Register or Login to the docker registry server"},
|
||||||
// {"logs", "Fetch the logs of a container"},
|
// {"logs", "Fetch the logs of a container"},
|
||||||
// {"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"},
|
// {"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"},
|
||||||
// {"ps", "List containers"},
|
// {"ps", "List containers"},
|
||||||
// {"pull", "Pull an image or a repository from the docker registry server"},
|
// {"pull", "Pull an image or a repository from the docker registry server"},
|
||||||
// {"push", "Push an image or a repository to the docker registry server"},
|
// {"push", "Push an image or a repository to the docker registry server"},
|
||||||
// {"restart", "Restart a running container"},
|
// {"restart", "Restart a running container"},
|
||||||
// {"rm", "Remove a container"},
|
// {"rm", "Remove a container"},
|
||||||
// {"rmi", "Remove an image"},
|
// {"rmi", "Remove an image"},
|
||||||
// {"run", "Run a command in a new container"},
|
// {"run", "Run a command in a new container"},
|
||||||
// {"start", "Start a stopped container"},
|
// {"start", "Start a stopped container"},
|
||||||
// {"stop", "Stop a running container"},
|
// {"stop", "Stop a running container"},
|
||||||
// {"tag", "Tag an image into a repository"},
|
// {"tag", "Tag an image into a repository"},
|
||||||
{"version", "Show the docker version information"},
|
{"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])
|
help += fmt.Sprintf(" %-10.10s%s\n", cmd[0], cmd[1])
|
||||||
}
|
}
|
||||||
|
@ -59,8 +65,80 @@ func cmdHelp(args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdVersion(args []string) error {
|
func cmdImages(args []string) error {
|
||||||
body, err := apiCall("version")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -68,28 +146,57 @@ func cmdVersion(args []string) error {
|
||||||
var out VersionOut
|
var out VersionOut
|
||||||
err = json.Unmarshal(body, &out)
|
err = json.Unmarshal(body, &out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("Version:", out.Version)
|
fmt.Println("Version:", out.Version)
|
||||||
fmt.Println("Git Commit:", out.GitCommit)
|
fmt.Println("Git Commit:", out.GitCommit)
|
||||||
if out.MemoryLimitDisabled {
|
if out.MemoryLimitDisabled {
|
||||||
fmt.Println("Memory limit disabled")
|
fmt.Println("Memory limit disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiCall(path string) ([]byte, error) {
|
func apiGet(path string) ([]byte, error) {
|
||||||
resp, err := http.Get("http://0.0.0.0:4243/" + path)
|
resp, err := http.Get("http://0.0.0.0:4243/" + path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil,err
|
return nil, err
|
||||||
}
|
}
|
||||||
//TODO check status code
|
//TODO check status code
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return body, nil
|
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…
Add table
Add a link
Reference in a new issue