Remove builtins

Signed-off-by: Antonio Murdaca <me@runcom.ninja>
This commit is contained in:
Antonio Murdaca 2015-04-16 21:48:04 +02:00
parent 5e40de9286
commit a0bf80fe03
12 changed files with 122 additions and 160 deletions

View file

@ -3,6 +3,7 @@ package server
import (
"bufio"
"bytes"
"runtime"
"time"
"encoding/base64"
@ -21,6 +22,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/autogen/dockerversion"
"github.com/docker/docker/daemon"
"github.com/docker/docker/daemon/networkdriver/bridge"
"github.com/docker/docker/engine"
@ -28,6 +30,7 @@ import (
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/parsers/filters"
"github.com/docker/docker/pkg/parsers/kernel"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/stdcopy"
"github.com/docker/docker/pkg/streamformatter"
@ -41,6 +44,19 @@ var (
activationLock = make(chan struct{})
)
type ServerConfig struct {
Logging bool
EnableCors bool
CorsHeaders string
Version string
SocketGroup string
Tls bool
TlsVerify bool
TlsCa string
TlsCert string
TlsKey string
}
type HttpServer struct {
srv *http.Server
l net.Listener
@ -187,8 +203,20 @@ func postAuth(eng *engine.Engine, version version.Version, w http.ResponseWriter
func getVersion(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
w.Header().Set("Content-Type", "application/json")
eng.ServeHTTP(w, r)
return nil
v := &types.Version{
Version: dockerversion.VERSION,
ApiVersion: api.APIVERSION,
GitCommit: dockerversion.GITCOMMIT,
GoVersion: runtime.Version(),
Os: runtime.GOOS,
Arch: runtime.GOARCH,
}
if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
v.KernelVersion = kernelVersion.String()
}
return writeJSON(w, http.StatusOK, v)
}
func postContainersKill(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@ -1588,28 +1616,22 @@ type Server interface {
// ServeApi loops through all of the protocols sent in to docker and spawns
// off a go routine to setup a serving http.Server for each.
func ServeApi(job *engine.Job) error {
if len(job.Args) == 0 {
return fmt.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", job.Name)
}
var (
protoAddrs = job.Args
chErrors = make(chan error, len(protoAddrs))
)
func ServeApi(protoAddrs []string, conf *ServerConfig, eng *engine.Engine) error {
var chErrors = make(chan error, len(protoAddrs))
for _, protoAddr := range protoAddrs {
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
if len(protoAddrParts) != 2 {
return fmt.Errorf("usage: %s PROTO://ADDR [PROTO://ADDR ...]", job.Name)
return fmt.Errorf("bad format, expected PROTO://ADDR")
}
go func() {
logrus.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
srv, err := NewServer(protoAddrParts[0], protoAddrParts[1], job)
srv, err := NewServer(protoAddrParts[0], protoAddrParts[1], conf, eng)
if err != nil {
chErrors <- err
return
}
job.Eng.OnShutdown(func() {
eng.OnShutdown(func() {
if err := srv.Close(); err != nil {
logrus.Error(err)
}

View file

@ -13,16 +13,16 @@ import (
)
// NewServer sets up the required Server and does protocol specific checking.
func NewServer(proto, addr string, job *engine.Job) (Server, error) {
func NewServer(proto, addr string, conf *ServerConfig, eng *engine.Engine) (Server, error) {
var (
err error
l net.Listener
r = createRouter(
job.Eng,
job.GetenvBool("Logging"),
job.GetenvBool("EnableCors"),
job.Getenv("CorsHeaders"),
job.Getenv("Version"),
eng,
conf.Logging,
conf.EnableCors,
conf.CorsHeaders,
conf.Version,
)
)
switch proto {
@ -52,17 +52,17 @@ func NewServer(proto, addr string, job *engine.Job) (Server, error) {
}
return nil, nil
case "tcp":
if !job.GetenvBool("TlsVerify") {
if !conf.TlsVerify {
logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
}
if l, err = NewTcpSocket(addr, tlsConfigFromJob(job)); err != nil {
if l, err = NewTcpSocket(addr, tlsConfigFromServerConfig(conf)); err != nil {
return nil, err
}
if err := allocateDaemonPort(addr); err != nil {
return nil, err
}
case "unix":
if l, err = NewUnixSocket(addr, job.Getenv("SocketGroup")); err != nil {
if l, err = NewUnixSocket(addr, conf.SocketGroup); err != nil {
return nil, err
}
default:
@ -77,8 +77,7 @@ func NewServer(proto, addr string, job *engine.Job) (Server, error) {
}, nil
}
// Called through eng.Job("acceptconnections")
func AcceptConnections(job *engine.Job) error {
func AcceptConnections() {
// Tell the init daemon we are accepting requests
go systemd.SdNotify("READY=1")
// close the lock so the listeners start accepting connections
@ -87,5 +86,4 @@ func AcceptConnections(job *engine.Job) error {
default:
close(activationLock)
}
return nil
}

View file

@ -34,35 +34,6 @@ func TesthttpError(t *testing.T) {
}
}
func TestGetVersion(t *testing.T) {
eng := engine.New()
var called bool
eng.Register("version", func(job *engine.Job) error {
called = true
v := &engine.Env{}
v.SetJson("Version", "42.1")
v.Set("ApiVersion", "1.1.1.1.1")
v.Set("GoVersion", "2.42")
v.Set("Os", "Linux")
v.Set("Arch", "x86_64")
if _, err := v.WriteTo(job.Stdout); err != nil {
return err
}
return nil
})
r := serveRequest("GET", "/version", nil, eng, t)
if !called {
t.Fatalf("handler was not called")
}
v := readEnv(r.Body, t)
if v.Get("Version") != "42.1" {
t.Fatalf("%#v\n", v)
}
if r.HeaderMap.Get("Content-Type") != "application/json" {
t.Fatalf("%#v\n", r)
}
}
func TestGetInfo(t *testing.T) {
eng := engine.New()
var called bool

View file

@ -39,13 +39,11 @@ func NewServer(proto, addr string, job *engine.Job) (Server, error) {
}
}
// Called through eng.Job("acceptconnections")
func AcceptConnections(job *engine.Job) error {
func AcceptConnections() {
// close the lock so the listeners start accepting connections
select {
case <-activationLock:
default:
close(activationLock)
}
return nil
}

View file

@ -8,7 +8,6 @@ import (
"net"
"os"
"github.com/docker/docker/engine"
"github.com/docker/docker/pkg/listenbuffer"
)
@ -19,16 +18,16 @@ type tlsConfig struct {
Verify bool
}
func tlsConfigFromJob(job *engine.Job) *tlsConfig {
verify := job.GetenvBool("TlsVerify")
if !job.GetenvBool("Tls") && !verify {
func tlsConfigFromServerConfig(conf *ServerConfig) *tlsConfig {
verify := conf.TlsVerify
if !conf.Tls && !conf.TlsVerify {
return nil
}
return &tlsConfig{
Verify: verify,
Certificate: job.Getenv("TlsCert"),
Key: job.Getenv("TlsKey"),
CA: job.Getenv("TlsCa"),
Certificate: conf.TlsCert,
Key: conf.TlsKey,
CA: conf.TlsCa,
}
}

View file

@ -1,5 +1,7 @@
package types
import "github.com/docker/docker/pkg/version"
// ContainerCreateResponse contains the information returned to a client on the
// creation of a new container.
type ContainerCreateResponse struct {
@ -110,3 +112,13 @@ type ContainerProcessList struct {
Processes [][]string
Titles []string
}
type Version struct {
Version string
ApiVersion version.Version
GitCommit string
GoVersion string
Os string
Arch string
KernelVersion string `json:",omitempty"`
}

View file

@ -1,48 +0,0 @@
package builtins
import (
"runtime"
"github.com/docker/docker/api"
apiserver "github.com/docker/docker/api/server"
"github.com/docker/docker/autogen/dockerversion"
"github.com/docker/docker/engine"
"github.com/docker/docker/pkg/parsers/kernel"
)
func Register(eng *engine.Engine) error {
if err := remote(eng); err != nil {
return err
}
if err := eng.Register("version", dockerVersion); err != nil {
return err
}
return nil
}
// remote: a RESTful api for cross-docker communication
func remote(eng *engine.Engine) error {
if err := eng.Register("serveapi", apiserver.ServeApi); err != nil {
return err
}
return eng.Register("acceptconnections", apiserver.AcceptConnections)
}
// builtins jobs independent of any subsystem
func dockerVersion(job *engine.Job) error {
v := &engine.Env{}
v.SetJson("Version", dockerversion.VERSION)
v.SetJson("ApiVersion", api.APIVERSION)
v.SetJson("GitCommit", dockerversion.GITCOMMIT)
v.Set("GoVersion", runtime.Version())
v.Set("Os", runtime.GOOS)
v.Set("Arch", runtime.GOARCH)
if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
v.Set("KernelVersion", kernelVersion.String())
}
if _, err := v.WriteTo(job.Stdout); err != nil {
return err
}
return nil
}

View file

@ -10,9 +10,9 @@ import (
"strings"
"github.com/Sirupsen/logrus"
apiserver "github.com/docker/docker/api/server"
"github.com/docker/docker/autogen/dockerversion"
"github.com/docker/docker/builder"
"github.com/docker/docker/builtins"
"github.com/docker/docker/daemon"
_ "github.com/docker/docker/daemon/execdriver/lxc"
_ "github.com/docker/docker/daemon/execdriver/native"
@ -93,11 +93,6 @@ func mainDaemon() {
}
daemonCfg.TrustKeyPath = *flTrustKey
// Load builtins
if err := builtins.Register(eng); err != nil {
logrus.Fatal(err)
}
registryService := registry.NewService(registryCfg)
// load the daemon in the background so we can immediately start
// the http api so that connections don't fail while the daemon
@ -127,33 +122,30 @@ func mainDaemon() {
// after the daemon is done setting up we can tell the api to start
// accepting connections
if err := eng.Job("acceptconnections").Run(); err != nil {
daemonInitWait <- err
return
}
apiserver.AcceptConnections()
daemonInitWait <- nil
}()
// Serve api
job := eng.Job("serveapi", flHosts...)
job.SetenvBool("Logging", true)
job.SetenvBool("EnableCors", daemonCfg.EnableCors)
job.Setenv("CorsHeaders", daemonCfg.CorsHeaders)
job.Setenv("Version", dockerversion.VERSION)
job.Setenv("SocketGroup", daemonCfg.SocketGroup)
serverConfig := &apiserver.ServerConfig{
Logging: true,
EnableCors: daemonCfg.EnableCors,
CorsHeaders: daemonCfg.CorsHeaders,
Version: dockerversion.VERSION,
SocketGroup: daemonCfg.SocketGroup,
Tls: *flTls,
TlsVerify: *flTlsVerify,
TlsCa: *flCa,
TlsCert: *flCert,
TlsKey: *flKey,
}
job.SetenvBool("Tls", *flTls)
job.SetenvBool("TlsVerify", *flTlsVerify)
job.Setenv("TlsCa", *flCa)
job.Setenv("TlsCert", *flCert)
job.Setenv("TlsKey", *flKey)
// The serve API job never exits unless an error occurs
// The serve API routine never exits unless an error occurs
// We need to start it as a goroutine and wait on it so
// daemon doesn't exit
serveAPIWait := make(chan error)
go func() {
if err := job.Run(); err != nil {
if err := apiserver.ServeApi(flHosts, serverConfig, eng); err != nil {
logrus.Errorf("ServeAPI error: %v", err)
serveAPIWait <- err
return

View file

@ -0,0 +1,24 @@
package main
import (
"encoding/json"
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/autogen/dockerversion"
)
func TestGetVersion(t *testing.T) {
_, body, err := sockRequest("GET", "/version", nil)
if err != nil {
t.Fatal(err)
}
var v types.Version
if err := json.Unmarshal(body, &v); err != nil {
t.Fatal(err)
}
if v.Version != dockerversion.VERSION {
t.Fatal("Version mismatch")
}
}

View file

@ -3363,7 +3363,7 @@ func TestRunRestartMaxRetries(t *testing.T) {
t.Fatal(string(out), err)
}
id := strings.TrimSpace(string(out))
if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5); err != nil {
if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 10); err != nil {
t.Fatal(err)
}
count, err := inspectField(id, "RestartCount")

View file

@ -17,6 +17,7 @@ import (
"time"
"github.com/Sirupsen/logrus"
apiserver "github.com/docker/docker/api/server"
"github.com/docker/docker/daemon"
"github.com/docker/docker/daemon/execdriver"
"github.com/docker/docker/engine"
@ -157,9 +158,9 @@ func spawnGlobalDaemon() {
Scheme: testDaemonProto,
Host: testDaemonAddr,
}
job := eng.Job("serveapi", listenURL.String())
job.SetenvBool("Logging", true)
if err := job.Run(); err != nil {
serverConfig := &apiserver.ServerConfig{Logging: true}
if err := apiserver.ServeApi([]string{listenURL.String()}, serverConfig, eng); err != nil {
logrus.Fatalf("Unable to spawn the test daemon: %s", err)
}
}()
@ -168,9 +169,7 @@ func spawnGlobalDaemon() {
// FIXME: use inmem transports instead of tcp
time.Sleep(time.Second)
if err := eng.Job("acceptconnections").Run(); err != nil {
logrus.Fatalf("Unable to accept connections for test api: %s", err)
}
apiserver.AcceptConnections()
}
func spawnLegitHttpsDaemon() {
@ -207,14 +206,15 @@ func spawnHttpsDaemon(addr, cacert, cert, key string) *engine.Engine {
Scheme: testDaemonHttpsProto,
Host: addr,
}
job := eng.Job("serveapi", listenURL.String())
job.SetenvBool("Logging", true)
job.SetenvBool("Tls", true)
job.SetenvBool("TlsVerify", true)
job.Setenv("TlsCa", cacert)
job.Setenv("TlsCert", cert)
job.Setenv("TlsKey", key)
if err := job.Run(); err != nil {
serverConfig := &apiserver.ServerConfig{
Logging: true,
Tls: true,
TlsVerify: true,
TlsCa: cacert,
TlsCert: cert,
TlsKey: key,
}
if err := apiserver.ServeApi([]string{listenURL.String()}, serverConfig, eng); err != nil {
logrus.Fatalf("Unable to spawn the test daemon: %s", err)
}
}()
@ -222,9 +222,8 @@ func spawnHttpsDaemon(addr, cacert, cert, key string) *engine.Engine {
// Give some time to ListenAndServer to actually start
time.Sleep(time.Second)
if err := eng.Job("acceptconnections").Run(); err != nil {
logrus.Fatalf("Unable to accept connections for test api: %s", err)
}
apiserver.AcceptConnections()
return eng
}

View file

@ -17,7 +17,6 @@ import (
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"github.com/docker/docker/api/types"
"github.com/docker/docker/builtins"
"github.com/docker/docker/daemon"
"github.com/docker/docker/daemon/networkdriver/bridge"
"github.com/docker/docker/engine"
@ -170,10 +169,6 @@ func newTestEngine(t Fataler, autorestart bool, root string) *engine.Engine {
eng := engine.New()
eng.Logging = false
// Load default plugins
if err := builtins.Register(eng); err != nil {
t.Fatal(err)
}
// (This is manually copied and modified from main() until we have a more generic plugin system)
cfg := &daemon.Config{