Merge pull request #3119 from shykes/engine-version
Port 'docker version' to the engine API
This commit is contained in:
commit
09d2c2351c
7 changed files with 105 additions and 54 deletions
3
api.go
3
api.go
|
@ -140,7 +140,8 @@ func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Reque
|
|||
}
|
||||
|
||||
func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
return writeJSON(w, http.StatusOK, srv.DockerVersion())
|
||||
srv.Eng.ServeHTTP(w, r)
|
||||
return nil
|
||||
}
|
||||
|
||||
func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
|
|
|
@ -95,12 +95,6 @@ type (
|
|||
IP string
|
||||
}
|
||||
|
||||
APIVersion struct {
|
||||
Version string
|
||||
GitCommit string `json:",omitempty"`
|
||||
GoVersion string `json:",omitempty"`
|
||||
}
|
||||
|
||||
APIWait struct {
|
||||
StatusCode int
|
||||
}
|
||||
|
|
25
commands.go
25
commands.go
|
@ -11,6 +11,7 @@ import (
|
|||
"fmt"
|
||||
"github.com/dotcloud/docker/archive"
|
||||
"github.com/dotcloud/docker/auth"
|
||||
"github.com/dotcloud/docker/engine"
|
||||
"github.com/dotcloud/docker/registry"
|
||||
"github.com/dotcloud/docker/term"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
|
@ -391,26 +392,24 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
var out APIVersion
|
||||
err = json.Unmarshal(body, &out)
|
||||
out := engine.NewOutput()
|
||||
remoteVersion, err := out.AddEnv()
|
||||
if err != nil {
|
||||
utils.Errorf("Error unmarshal: body: %s, err: %s\n", body, err)
|
||||
utils.Errorf("Error reading remote version: %s\n", err)
|
||||
return err
|
||||
}
|
||||
if out.Version != "" {
|
||||
fmt.Fprintf(cli.out, "Server version: %s\n", out.Version)
|
||||
if _, err := out.Write(body); err != nil {
|
||||
utils.Errorf("Error reading remote version: %s\n", err)
|
||||
return err
|
||||
}
|
||||
if out.GitCommit != "" {
|
||||
fmt.Fprintf(cli.out, "Git commit (server): %s\n", out.GitCommit)
|
||||
}
|
||||
if out.GoVersion != "" {
|
||||
fmt.Fprintf(cli.out, "Go version (server): %s\n", out.GoVersion)
|
||||
}
|
||||
|
||||
out.Close()
|
||||
fmt.Fprintf(cli.out, "Server version: %s\n", remoteVersion.Get("Version"))
|
||||
fmt.Fprintf(cli.out, "Git commit (server): %s\n", remoteVersion.Get("GitCommit"))
|
||||
fmt.Fprintf(cli.out, "Go version (server): %s\n", remoteVersion.Get("GoVersion"))
|
||||
release := utils.GetReleaseVersion()
|
||||
if release != "" {
|
||||
fmt.Fprintf(cli.out, "Last stable version: %s", release)
|
||||
if (VERSION != "" || out.Version != "") && (strings.Trim(VERSION, "-dev") != release || strings.Trim(out.Version, "-dev") != release) {
|
||||
if (VERSION != "" || remoteVersion.Exists("Version")) && (strings.Trim(VERSION, "-dev") != release || strings.Trim(remoteVersion.Get("Version"), "-dev") != release) {
|
||||
fmt.Fprintf(cli.out, ", please update docker")
|
||||
}
|
||||
fmt.Fprintf(cli.out, "\n")
|
||||
|
|
40
engine/http.go
Normal file
40
engine/http.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"path"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ServeHTTP executes a job as specified by the http request `r`, and sends the
|
||||
// result as an http response.
|
||||
// This method allows an Engine instance to be passed as a standard http.Handler interface.
|
||||
//
|
||||
// Note that the protocol used in this methid is a convenience wrapper and is not the canonical
|
||||
// implementation of remote job execution. This is because HTTP/1 does not handle stream multiplexing,
|
||||
// and so cannot differentiate stdout from stderr. Additionally, headers cannot be added to a response
|
||||
// once data has been written to the body, which makes it inconvenient to return metadata such
|
||||
// as the exit status.
|
||||
//
|
||||
func (eng *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
jobName := path.Base(r.URL.Path)
|
||||
jobArgs, exists := r.URL.Query()["a"]
|
||||
if !exists {
|
||||
jobArgs = []string{}
|
||||
}
|
||||
w.Header().Set("Job-Name", jobName)
|
||||
for _, arg := range(jobArgs) {
|
||||
w.Header().Add("Job-Args", arg)
|
||||
}
|
||||
job := eng.Job(jobName, jobArgs...)
|
||||
job.Stdout.Add(w)
|
||||
job.Stderr.Add(w)
|
||||
// FIXME: distinguish job status from engine error in Run()
|
||||
// The former should be passed as a special header, the former
|
||||
// should cause a 500 status
|
||||
w.WriteHeader(http.StatusOK)
|
||||
// The exit status cannot be sent reliably with HTTP1, because headers
|
||||
// can only be sent before the body.
|
||||
// (we could possibly use http footers via chunked encoding, but I couldn't find
|
||||
// how to use them in net/http)
|
||||
job.Run()
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker"
|
||||
"github.com/dotcloud/docker/engine"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -35,12 +36,18 @@ func TestGetVersion(t *testing.T) {
|
|||
}
|
||||
assertHttpNotError(r, t)
|
||||
|
||||
v := &docker.APIVersion{}
|
||||
if err = json.Unmarshal(r.Body.Bytes(), v); err != nil {
|
||||
out := engine.NewOutput()
|
||||
v, err := out.AddEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v.Version != docker.VERSION {
|
||||
t.Errorf("Expected version %s, %s found", docker.VERSION, v.Version)
|
||||
if _, err := io.Copy(out, r.Body); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out.Close()
|
||||
expected := docker.VERSION
|
||||
if result := v.Get("Version"); result != expected {
|
||||
t.Errorf("Expected version %s, %s found", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
37
server.go
37
server.go
|
@ -122,14 +122,6 @@ func (srv *Server) ListenAndServe(job *engine.Job) engine.Status {
|
|||
return engine.StatusOK
|
||||
}
|
||||
|
||||
func (srv *Server) DockerVersion() APIVersion {
|
||||
return APIVersion{
|
||||
Version: VERSION,
|
||||
GitCommit: GITCOMMIT,
|
||||
GoVersion: runtime.Version(),
|
||||
}
|
||||
}
|
||||
|
||||
// simpleVersionInfo is a simple implementation of
|
||||
// the interface VersionInfo, which is used
|
||||
// to provide version information for some product,
|
||||
|
@ -148,27 +140,6 @@ func (v *simpleVersionInfo) Version() string {
|
|||
return v.version
|
||||
}
|
||||
|
||||
// versionCheckers() returns version informations of:
|
||||
// docker, go, git-commit (of the docker) and the host's kernel.
|
||||
//
|
||||
// Such information will be used on call to NewRegistry().
|
||||
func (srv *Server) versionInfos() []utils.VersionInfo {
|
||||
v := srv.DockerVersion()
|
||||
ret := append(make([]utils.VersionInfo, 0, 4), &simpleVersionInfo{"docker", v.Version})
|
||||
|
||||
if len(v.GoVersion) > 0 {
|
||||
ret = append(ret, &simpleVersionInfo{"go", v.GoVersion})
|
||||
}
|
||||
if len(v.GitCommit) > 0 {
|
||||
ret = append(ret, &simpleVersionInfo{"git-commit", v.GitCommit})
|
||||
}
|
||||
if kernelVersion, err := utils.GetKernelVersion(); err == nil {
|
||||
ret = append(ret, &simpleVersionInfo{"kernel", kernelVersion.String()})
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// ContainerKill send signal to the container
|
||||
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
||||
// for the container to exit.
|
||||
|
@ -1886,7 +1857,13 @@ func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) {
|
|||
func (srv *Server) HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFactory {
|
||||
srv.Lock()
|
||||
defer srv.Unlock()
|
||||
ud := utils.NewHTTPUserAgentDecorator(srv.versionInfos()...)
|
||||
v := dockerVersion()
|
||||
httpVersion := make([]utils.VersionInfo, 0, 4)
|
||||
httpVersion = append(httpVersion, &simpleVersionInfo{"docker", v.Get("Version")})
|
||||
httpVersion = append(httpVersion, &simpleVersionInfo{"go", v.Get("GoVersion")})
|
||||
httpVersion = append(httpVersion, &simpleVersionInfo{"git-commit", v.Get("GitCommit")})
|
||||
httpVersion = append(httpVersion, &simpleVersionInfo{"kernel", v.Get("KernelVersion")})
|
||||
ud := utils.NewHTTPUserAgentDecorator(httpVersion...)
|
||||
md := &utils.HTTPMetaHeadersDecorator{
|
||||
Headers: metaHeaders,
|
||||
}
|
||||
|
|
33
version.go
Normal file
33
version.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/engine"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.Register("version", jobVersion)
|
||||
}
|
||||
|
||||
func jobVersion(job *engine.Job) engine.Status {
|
||||
if _, err := dockerVersion().WriteTo(job.Stdout); err != nil {
|
||||
job.Errorf("%s", err)
|
||||
return engine.StatusErr
|
||||
}
|
||||
return engine.StatusOK
|
||||
}
|
||||
|
||||
// dockerVersion returns detailed version information in the form of a queriable
|
||||
// environment.
|
||||
func dockerVersion() *engine.Env {
|
||||
v := &engine.Env{}
|
||||
v.Set("Version", VERSION)
|
||||
v.Set("GitCommit", GITCOMMIT)
|
||||
v.Set("GoVersion", runtime.Version())
|
||||
// FIXME:utils.GetKernelVersion should only be needed here
|
||||
if kernelVersion, err := utils.GetKernelVersion(); err == nil {
|
||||
v.Set("KernelVersion", kernelVersion.String())
|
||||
}
|
||||
return v
|
||||
}
|
Loading…
Add table
Reference in a new issue