This commit is contained in:
Solomon Hykes 2013-11-13 19:25:55 +00:00
parent 8e71391572
commit b00d5f0185
8 changed files with 66 additions and 68 deletions

View File

@ -30,10 +30,10 @@ func Register(name string, handler Handler) error {
// It acts as a store for *containers*, and allows manipulation of these // It acts as a store for *containers*, and allows manipulation of these
// containers by executing *jobs*. // containers by executing *jobs*.
type Engine struct { type Engine struct {
root string root string
handlers map[string]Handler handlers map[string]Handler
hack Hack // data for temporary hackery (see hack.go) hack Hack // data for temporary hackery (see hack.go)
id string id string
} }
func (eng *Engine) Root() string { func (eng *Engine) Root() string {
@ -50,7 +50,6 @@ func (eng *Engine) Register(name string, handler Handler) error {
return nil return nil
} }
// New initializes a new engine managing the directory specified at `root`. // New initializes a new engine managing the directory specified at `root`.
// `root` is used to store containers and any other state private to the engine. // `root` is used to store containers and any other state private to the engine.
// Changing the contents of the root without executing a job will cause unspecified // Changing the contents of the root without executing a job will cause unspecified
@ -78,9 +77,9 @@ func New(root string) (*Engine, error) {
return nil, err return nil, err
} }
eng := &Engine{ eng := &Engine{
root: root, root: root,
handlers: make(map[string]Handler), handlers: make(map[string]Handler),
id: utils.RandomString(), id: utils.RandomString(),
} }
// Copy existing global handlers // Copy existing global handlers
for k, v := range globalHandlers { for k, v := range globalHandlers {
@ -97,12 +96,12 @@ func (eng *Engine) String() string {
// This function mimics `Command` from the standard os/exec package. // This function mimics `Command` from the standard os/exec package.
func (eng *Engine) Job(name string, args ...string) *Job { func (eng *Engine) Job(name string, args ...string) *Job {
job := &Job{ job := &Job{
Eng: eng, Eng: eng,
Name: name, Name: name,
Args: args, Args: args,
Stdin: os.Stdin, Stdin: os.Stdin,
Stdout: os.Stdout, Stdout: os.Stdout,
Stderr: os.Stderr, Stderr: os.Stderr,
} }
handler, exists := eng.handlers[name] handler, exists := eng.handlers[name]
if exists { if exists {

View File

@ -1,9 +1,7 @@
package engine package engine
type Hack map[string]interface{} type Hack map[string]interface{}
func (eng *Engine) Hack_GetGlobalVar(key string) interface{} { func (eng *Engine) Hack_GetGlobalVar(key string) interface{} {
if eng.hack == nil { if eng.hack == nil {
return nil return nil

View File

@ -3,14 +3,14 @@ package engine
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"encoding/json"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os"
"strconv" "strconv"
"strings" "strings"
"fmt"
"sync" "sync"
"encoding/json"
"os"
) )
// A job is the fundamental unit of work in the docker engine. // A job is the fundamental unit of work in the docker engine.
@ -27,16 +27,16 @@ import (
// This allows for richer error reporting. // This allows for richer error reporting.
// //
type Job struct { type Job struct {
Eng *Engine Eng *Engine
Name string Name string
Args []string Args []string
env []string env []string
Stdin io.Reader Stdin io.Reader
Stdout io.Writer Stdout io.Writer
Stderr io.Writer Stderr io.Writer
handler func(*Job) string handler func(*Job) string
status string status string
onExit []func() onExit []func()
} }
// Run executes the job and blocks until the job completes. // Run executes the job and blocks until the job completes.
@ -106,30 +106,33 @@ func (job *Job) parseLines(src io.Reader, dst *[]string, limit int) {
func (job *Job) StdoutParseString(dst *string) { func (job *Job) StdoutParseString(dst *string) {
lines := make([]string, 0, 1) lines := make([]string, 0, 1)
job.StdoutParseLines(&lines, 1) job.StdoutParseLines(&lines, 1)
job.onExit = append(job.onExit, func() { if len(lines) >= 1 { *dst = lines[0] }}) job.onExit = append(job.onExit, func() {
if len(lines) >= 1 {
*dst = lines[0]
}
})
} }
func (job *Job) StderrParseString(dst *string) { func (job *Job) StderrParseString(dst *string) {
lines := make([]string, 0, 1) lines := make([]string, 0, 1)
job.StderrParseLines(&lines, 1) job.StderrParseLines(&lines, 1)
job.onExit = append(job.onExit, func() { *dst = lines[0]; }) job.onExit = append(job.onExit, func() { *dst = lines[0] })
} }
func (job *Job) StdoutPipe() io.ReadCloser { func (job *Job) StdoutPipe() io.ReadCloser {
r, w := io.Pipe() r, w := io.Pipe()
job.Stdout = w job.Stdout = w
job.onExit = append(job.onExit, func(){ w.Close() }) job.onExit = append(job.onExit, func() { w.Close() })
return r return r
} }
func (job *Job) StderrPipe() io.ReadCloser { func (job *Job) StderrPipe() io.ReadCloser {
r, w := io.Pipe() r, w := io.Pipe()
job.Stderr = w job.Stderr = w
job.onExit = append(job.onExit, func(){ w.Close() }) job.onExit = append(job.onExit, func() { w.Close() })
return r return r
} }
func (job *Job) CallString() string { func (job *Job) CallString() string {
return fmt.Sprintf("%s(%s)", job.Name, strings.Join(job.Args, ", ")) return fmt.Sprintf("%s(%s)", job.Name, strings.Join(job.Args, ", "))
} }
@ -242,7 +245,7 @@ func (job *Job) DecodeEnv(src io.Reader) error {
job.SetenvInt(k, int64(fval)) job.SetenvInt(k, int64(fval))
} else if sval, ok := v.(string); ok { } else if sval, ok := v.(string); ok {
job.Setenv(k, sval) job.Setenv(k, sval)
} else if val, err := json.Marshal(v); err == nil { } else if val, err := json.Marshal(v); err == nil {
job.Setenv(k, string(val)) job.Setenv(k, string(val))
} else { } else {
job.Setenv(k, fmt.Sprintf("%v", v)) job.Setenv(k, fmt.Sprintf("%v", v))

View File

@ -9,6 +9,7 @@ import (
"io" "io"
"log" "log"
"net" "net"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -18,7 +19,6 @@ import (
"syscall" "syscall"
"testing" "testing"
"time" "time"
"net/url"
) )
const ( const (
@ -158,8 +158,8 @@ func spawnGlobalDaemon() {
go func() { go func() {
utils.Debugf("Spawning global daemon for integration tests") utils.Debugf("Spawning global daemon for integration tests")
listenURL := &url.URL{ listenURL := &url.URL{
Scheme: testDaemonProto, Scheme: testDaemonProto,
Host: testDaemonAddr, Host: testDaemonAddr,
} }
job := eng.Job("serveapi", listenURL.String()) job := eng.Job("serveapi", listenURL.String())
job.SetenvBool("Logging", os.Getenv("DEBUG") != "") job.SetenvBool("Logging", os.Getenv("DEBUG") != "")

View File

@ -74,7 +74,6 @@ func jobInitApi(job *engine.Job) string {
return "0" return "0"
} }
func (srv *Server) ListenAndServe(job *engine.Job) string { func (srv *Server) ListenAndServe(job *engine.Job) string {
protoAddrs := job.Args protoAddrs := job.Args
chErrors := make(chan error, len(protoAddrs)) chErrors := make(chan error, len(protoAddrs))
@ -1388,25 +1387,25 @@ func (srv *Server) ContainerStart(job *engine.Job) string {
return err.Error() return err.Error()
} }
// Validate the HostConfig binds. Make sure that: // Validate the HostConfig binds. Make sure that:
// 1) the source of a bind mount isn't / // 1) the source of a bind mount isn't /
// The bind mount "/:/foo" isn't allowed. // The bind mount "/:/foo" isn't allowed.
// 2) Check that the source exists // 2) Check that the source exists
// The source to be bind mounted must exist. // The source to be bind mounted must exist.
for _, bind := range hostConfig.Binds { for _, bind := range hostConfig.Binds {
splitBind := strings.Split(bind, ":") splitBind := strings.Split(bind, ":")
source := splitBind[0] source := splitBind[0]
// refuse to bind mount "/" to the container // refuse to bind mount "/" to the container
if source == "/" { if source == "/" {
return fmt.Sprintf("Invalid bind mount '%s' : source can't be '/'", bind) return fmt.Sprintf("Invalid bind mount '%s' : source can't be '/'", bind)
} }
// ensure the source exists on the host // ensure the source exists on the host
_, err := os.Stat(source) _, err := os.Stat(source)
if err != nil && os.IsNotExist(err) { if err != nil && os.IsNotExist(err) {
return fmt.Sprintf("Invalid bind mount '%s' : source doesn't exist", bind) return fmt.Sprintf("Invalid bind mount '%s' : source doesn't exist", bind)
} }
} }
// Register any links from the host config before starting the container // Register any links from the host config before starting the container
// FIXME: we could just pass the container here, no need to lookup by name again. // FIXME: we could just pass the container here, no need to lookup by name again.
if err := srv.RegisterLinks(name, &hostConfig); err != nil { if err := srv.RegisterLinks(name, &hostConfig); err != nil {

View File

@ -2,8 +2,8 @@ package docker
import ( import (
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
"strings"
"io/ioutil" "io/ioutil"
"strings"
"testing" "testing"
"time" "time"
) )

View File

@ -266,23 +266,23 @@ func TestHumanSize(t *testing.T) {
} }
func TestRAMInBytes(t *testing.T) { func TestRAMInBytes(t *testing.T) {
assertRAMInBytes(t, "32", false, 32) assertRAMInBytes(t, "32", false, 32)
assertRAMInBytes(t, "32b", false, 32) assertRAMInBytes(t, "32b", false, 32)
assertRAMInBytes(t, "32B", false, 32) assertRAMInBytes(t, "32B", false, 32)
assertRAMInBytes(t, "32k", false, 32*1024) assertRAMInBytes(t, "32k", false, 32*1024)
assertRAMInBytes(t, "32K", false, 32*1024) assertRAMInBytes(t, "32K", false, 32*1024)
assertRAMInBytes(t, "32kb", false, 32*1024) assertRAMInBytes(t, "32kb", false, 32*1024)
assertRAMInBytes(t, "32Kb", false, 32*1024) assertRAMInBytes(t, "32Kb", false, 32*1024)
assertRAMInBytes(t, "32Mb", false, 32*1024*1024) assertRAMInBytes(t, "32Mb", false, 32*1024*1024)
assertRAMInBytes(t, "32Gb", false, 32*1024*1024*1024) assertRAMInBytes(t, "32Gb", false, 32*1024*1024*1024)
assertRAMInBytes(t, "", true, -1) assertRAMInBytes(t, "", true, -1)
assertRAMInBytes(t, "hello", true, -1) assertRAMInBytes(t, "hello", true, -1)
assertRAMInBytes(t, "-32", true, -1) assertRAMInBytes(t, "-32", true, -1)
assertRAMInBytes(t, " 32 ", true, -1) assertRAMInBytes(t, " 32 ", true, -1)
assertRAMInBytes(t, "32 mb", true, -1) assertRAMInBytes(t, "32 mb", true, -1)
assertRAMInBytes(t, "32m b", true, -1) assertRAMInBytes(t, "32m b", true, -1)
assertRAMInBytes(t, "32bm", true, -1) assertRAMInBytes(t, "32bm", true, -1)
} }
func assertRAMInBytes(t *testing.T, size string, expectError bool, expectedBytes int64) { func assertRAMInBytes(t *testing.T, size string, expectError bool, expectedBytes int64) {

View File

@ -27,7 +27,7 @@ func mkRuntime(f utils.Fataler) *Runtime {
f.Fatal(err) f.Fatal(err)
} }
config := &DaemonConfig{ config := &DaemonConfig{
Root: root, Root: root,
AutoRestart: false, AutoRestart: false,
} }
r, err := NewRuntimeFromDirectory(config) r, err := NewRuntimeFromDirectory(config)
@ -66,7 +66,6 @@ func mkServerFromEngine(eng *engine.Engine, t utils.Fataler) *Server {
return srv return srv
} }
func NewTestEngine(t utils.Fataler) *engine.Engine { func NewTestEngine(t utils.Fataler) *engine.Engine {
root, err := newTestDirectory(unitTestStoreBase) root, err := newTestDirectory(unitTestStoreBase)
if err != nil { if err != nil {