| ... | ... |
@@ -122,17 +122,17 @@ func postAuth(eng *engine.Engine, version version.Version, w http.ResponseWriter |
| 122 | 122 |
var ( |
| 123 | 123 |
authConfig, err = ioutil.ReadAll(r.Body) |
| 124 | 124 |
job = eng.Job("auth")
|
| 125 |
- status string |
|
| 125 |
+ stdoutBuffer = bytes.NewBuffer(nil) |
|
| 126 | 126 |
) |
| 127 | 127 |
if err != nil {
|
| 128 | 128 |
return err |
| 129 | 129 |
} |
| 130 | 130 |
job.Setenv("authConfig", string(authConfig))
|
| 131 |
- job.Stdout.AddString(&status) |
|
| 131 |
+ job.Stdout.Add(stdoutBuffer) |
|
| 132 | 132 |
if err = job.Run(); err != nil {
|
| 133 | 133 |
return err |
| 134 | 134 |
} |
| 135 |
- if status != "" {
|
|
| 135 |
+ if status := engine.Tail(stdoutBuffer, 1); status != "" {
|
|
| 136 | 136 |
var env engine.Env |
| 137 | 137 |
env.Set("Status", status)
|
| 138 | 138 |
return writeJSON(w, http.StatusOK, env) |
| ... | ... |
@@ -393,9 +393,10 @@ func postCommit(eng *engine.Engine, version version.Version, w http.ResponseWrit |
| 393 | 393 |
return err |
| 394 | 394 |
} |
| 395 | 395 |
var ( |
| 396 |
- config engine.Env |
|
| 397 |
- env engine.Env |
|
| 398 |
- job = eng.Job("commit", r.Form.Get("container"))
|
|
| 396 |
+ config engine.Env |
|
| 397 |
+ env engine.Env |
|
| 398 |
+ job = eng.Job("commit", r.Form.Get("container"))
|
|
| 399 |
+ stdoutBuffer = bytes.NewBuffer(nil) |
|
| 399 | 400 |
) |
| 400 | 401 |
if err := config.Decode(r.Body); err != nil {
|
| 401 | 402 |
utils.Errorf("%s", err)
|
| ... | ... |
@@ -407,12 +408,11 @@ func postCommit(eng *engine.Engine, version version.Version, w http.ResponseWrit |
| 407 | 407 |
job.Setenv("comment", r.Form.Get("comment"))
|
| 408 | 408 |
job.SetenvSubEnv("config", &config)
|
| 409 | 409 |
|
| 410 |
- var id string |
|
| 411 |
- job.Stdout.AddString(&id) |
|
| 410 |
+ job.Stdout.Add(stdoutBuffer) |
|
| 412 | 411 |
if err := job.Run(); err != nil {
|
| 413 | 412 |
return err |
| 414 | 413 |
} |
| 415 |
- env.Set("Id", id)
|
|
| 414 |
+ env.Set("Id", engine.Tail(stdoutBuffer, 1))
|
|
| 416 | 415 |
return writeJSON(w, http.StatusCreated, env) |
| 417 | 416 |
} |
| 418 | 417 |
|
| ... | ... |
@@ -603,17 +603,17 @@ func postContainersCreate(eng *engine.Engine, version version.Version, w http.Re |
| 603 | 603 |
return nil |
| 604 | 604 |
} |
| 605 | 605 |
var ( |
| 606 |
- out engine.Env |
|
| 607 |
- job = eng.Job("create", r.Form.Get("name"))
|
|
| 608 |
- outWarnings []string |
|
| 609 |
- outId string |
|
| 610 |
- warnings = bytes.NewBuffer(nil) |
|
| 606 |
+ out engine.Env |
|
| 607 |
+ job = eng.Job("create", r.Form.Get("name"))
|
|
| 608 |
+ outWarnings []string |
|
| 609 |
+ stdoutBuffer = bytes.NewBuffer(nil) |
|
| 610 |
+ warnings = bytes.NewBuffer(nil) |
|
| 611 | 611 |
) |
| 612 | 612 |
if err := job.DecodeEnv(r.Body); err != nil {
|
| 613 | 613 |
return err |
| 614 | 614 |
} |
| 615 | 615 |
// Read container ID from the first line of stdout |
| 616 |
- job.Stdout.AddString(&outId) |
|
| 616 |
+ job.Stdout.Add(stdoutBuffer) |
|
| 617 | 617 |
// Read warnings from stderr |
| 618 | 618 |
job.Stderr.Add(warnings) |
| 619 | 619 |
if err := job.Run(); err != nil {
|
| ... | ... |
@@ -624,7 +624,7 @@ func postContainersCreate(eng *engine.Engine, version version.Version, w http.Re |
| 624 | 624 |
for scanner.Scan() {
|
| 625 | 625 |
outWarnings = append(outWarnings, scanner.Text()) |
| 626 | 626 |
} |
| 627 |
- out.Set("Id", outId)
|
|
| 627 |
+ out.Set("Id", engine.Tail(stdoutBuffer, 1))
|
|
| 628 | 628 |
out.SetList("Warnings", outWarnings)
|
| 629 | 629 |
return writeJSON(w, http.StatusCreated, out) |
| 630 | 630 |
} |
| ... | ... |
@@ -720,20 +720,16 @@ func postContainersWait(eng *engine.Engine, version version.Version, w http.Resp |
| 720 | 720 |
return fmt.Errorf("Missing parameter")
|
| 721 | 721 |
} |
| 722 | 722 |
var ( |
| 723 |
- env engine.Env |
|
| 724 |
- status string |
|
| 725 |
- job = eng.Job("wait", vars["name"])
|
|
| 723 |
+ env engine.Env |
|
| 724 |
+ stdoutBuffer = bytes.NewBuffer(nil) |
|
| 725 |
+ job = eng.Job("wait", vars["name"])
|
|
| 726 | 726 |
) |
| 727 |
- job.Stdout.AddString(&status) |
|
| 727 |
+ job.Stdout.Add(stdoutBuffer) |
|
| 728 | 728 |
if err := job.Run(); err != nil {
|
| 729 | 729 |
return err |
| 730 | 730 |
} |
| 731 |
- // Parse a 16-bit encoded integer to map typical unix exit status. |
|
| 732 |
- _, err := strconv.ParseInt(status, 10, 16) |
|
| 733 |
- if err != nil {
|
|
| 734 |
- return err |
|
| 735 |
- } |
|
| 736 |
- env.Set("StatusCode", status)
|
|
| 731 |
+ |
|
| 732 |
+ env.Set("StatusCode", engine.Tail(stdoutBuffer, 1))
|
|
| 737 | 733 |
return writeJSON(w, http.StatusOK, env) |
| 738 | 734 |
} |
| 739 | 735 |
|
| ... | ... |
@@ -3,11 +3,12 @@ package engine |
| 3 | 3 |
import ( |
| 4 | 4 |
"bufio" |
| 5 | 5 |
"fmt" |
| 6 |
- "github.com/dotcloud/docker/utils" |
|
| 7 | 6 |
"io" |
| 8 | 7 |
"os" |
| 9 | 8 |
"sort" |
| 10 | 9 |
"strings" |
| 10 |
+ |
|
| 11 |
+ "github.com/dotcloud/docker/utils" |
|
| 11 | 12 |
) |
| 12 | 13 |
|
| 13 | 14 |
// Installer is a standard interface for objects which can "install" themselves |
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package engine |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "bytes" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"io" |
| 6 | 7 |
"strings" |
| ... | ... |
@@ -56,8 +57,8 @@ func (job *Job) Run() error {
|
| 56 | 56 |
defer func() {
|
| 57 | 57 |
job.Eng.Logf("-job %s%s", job.CallString(), job.StatusString())
|
| 58 | 58 |
}() |
| 59 |
- var errorMessage string |
|
| 60 |
- job.Stderr.AddString(&errorMessage) |
|
| 59 |
+ var errorMessage = bytes.NewBuffer(nil) |
|
| 60 |
+ job.Stderr.Add(errorMessage) |
|
| 61 | 61 |
if job.handler == nil {
|
| 62 | 62 |
job.Errorf("%s: command not found", job.Name)
|
| 63 | 63 |
job.status = 127 |
| ... | ... |
@@ -76,7 +77,7 @@ func (job *Job) Run() error {
|
| 76 | 76 |
return err |
| 77 | 77 |
} |
| 78 | 78 |
if job.status != 0 {
|
| 79 |
- return fmt.Errorf("%s", errorMessage)
|
|
| 79 |
+ return fmt.Errorf("%s", Tail(errorMessage, 1))
|
|
| 80 | 80 |
} |
| 81 | 81 |
return nil |
| 82 | 82 |
} |
| ... | ... |
@@ -1,6 +1,8 @@ |
| 1 | 1 |
package engine |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "bytes" |
|
| 5 |
+ "fmt" |
|
| 4 | 6 |
"testing" |
| 5 | 7 |
) |
| 6 | 8 |
|
| ... | ... |
@@ -40,13 +42,13 @@ func TestJobStdoutString(t *testing.T) {
|
| 40 | 40 |
}) |
| 41 | 41 |
|
| 42 | 42 |
job := eng.Job("say_something_in_stdout")
|
| 43 |
- var output string |
|
| 44 |
- if err := job.Stdout.AddString(&output); err != nil {
|
|
| 45 |
- t.Fatal(err) |
|
| 46 |
- } |
|
| 43 |
+ var outputBuffer = bytes.NewBuffer(nil) |
|
| 44 |
+ job.Stdout.Add(outputBuffer) |
|
| 47 | 45 |
if err := job.Run(); err != nil {
|
| 48 | 46 |
t.Fatal(err) |
| 49 | 47 |
} |
| 48 |
+ fmt.Println(outputBuffer) |
|
| 49 |
+ var output = Tail(outputBuffer, 1) |
|
| 50 | 50 |
if expectedOutput := "Hello world"; output != expectedOutput {
|
| 51 | 51 |
t.Fatalf("Stdout last line:\nExpected: %v\nReceived: %v", expectedOutput, output)
|
| 52 | 52 |
} |
| ... | ... |
@@ -61,13 +63,12 @@ func TestJobStderrString(t *testing.T) {
|
| 61 | 61 |
}) |
| 62 | 62 |
|
| 63 | 63 |
job := eng.Job("say_something_in_stderr")
|
| 64 |
- var output string |
|
| 65 |
- if err := job.Stderr.AddString(&output); err != nil {
|
|
| 66 |
- t.Fatal(err) |
|
| 67 |
- } |
|
| 64 |
+ var outputBuffer = bytes.NewBuffer(nil) |
|
| 65 |
+ job.Stderr.Add(outputBuffer) |
|
| 68 | 66 |
if err := job.Run(); err != nil {
|
| 69 | 67 |
t.Fatal(err) |
| 70 | 68 |
} |
| 69 |
+ var output = Tail(outputBuffer, 1) |
|
| 71 | 70 |
if expectedOutput := "Something happened"; output != expectedOutput {
|
| 72 | 71 |
t.Fatalf("Stderr last line:\nExpected: %v\nReceived: %v", expectedOutput, output)
|
| 73 | 72 |
} |
| ... | ... |
@@ -1,8 +1,7 @@ |
| 1 | 1 |
package engine |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "bufio" |
|
| 5 |
- "container/ring" |
|
| 4 |
+ "bytes" |
|
| 6 | 5 |
"fmt" |
| 7 | 6 |
"io" |
| 8 | 7 |
"io/ioutil" |
| ... | ... |
@@ -16,6 +15,28 @@ type Output struct {
|
| 16 | 16 |
used bool |
| 17 | 17 |
} |
| 18 | 18 |
|
| 19 |
+// Tail returns the n last lines of a buffer |
|
| 20 |
+// stripped out of the last \n, if any |
|
| 21 |
+// if n <= 0, returns an empty string |
|
| 22 |
+func Tail(buffer *bytes.Buffer, n int) string {
|
|
| 23 |
+ if n <= 0 {
|
|
| 24 |
+ return "" |
|
| 25 |
+ } |
|
| 26 |
+ bytes := buffer.Bytes() |
|
| 27 |
+ if len(bytes) > 0 && bytes[len(bytes)-1] == '\n' {
|
|
| 28 |
+ bytes = bytes[:len(bytes)-1] |
|
| 29 |
+ } |
|
| 30 |
+ for i := buffer.Len() - 2; i >= 0; i-- {
|
|
| 31 |
+ if bytes[i] == '\n' {
|
|
| 32 |
+ n-- |
|
| 33 |
+ if n == 0 {
|
|
| 34 |
+ return string(bytes[i+1:]) |
|
| 35 |
+ } |
|
| 36 |
+ } |
|
| 37 |
+ } |
|
| 38 |
+ return string(bytes) |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 19 | 41 |
// NewOutput returns a new Output object with no destinations attached. |
| 20 | 42 |
// Writing to an empty Output will cause the written data to be discarded. |
| 21 | 43 |
func NewOutput() *Output {
|
| ... | ... |
@@ -58,42 +79,6 @@ func (o *Output) AddPipe() (io.Reader, error) {
|
| 58 | 58 |
return r, nil |
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 |
-// AddTail starts a new goroutine which will read all subsequent data written to the output, |
|
| 62 |
-// line by line, and append the last `n` lines to `dst`. |
|
| 63 |
-func (o *Output) AddTail(dst *[]string, n int) error {
|
|
| 64 |
- src, err := o.AddPipe() |
|
| 65 |
- if err != nil {
|
|
| 66 |
- return err |
|
| 67 |
- } |
|
| 68 |
- o.tasks.Add(1) |
|
| 69 |
- go func() {
|
|
| 70 |
- defer o.tasks.Done() |
|
| 71 |
- Tail(src, n, dst) |
|
| 72 |
- }() |
|
| 73 |
- return nil |
|
| 74 |
-} |
|
| 75 |
- |
|
| 76 |
-// AddString starts a new goroutine which will read all subsequent data written to the output, |
|
| 77 |
-// line by line, and store the last line into `dst`. |
|
| 78 |
-func (o *Output) AddString(dst *string) error {
|
|
| 79 |
- src, err := o.AddPipe() |
|
| 80 |
- if err != nil {
|
|
| 81 |
- return err |
|
| 82 |
- } |
|
| 83 |
- o.tasks.Add(1) |
|
| 84 |
- go func() {
|
|
| 85 |
- defer o.tasks.Done() |
|
| 86 |
- lines := make([]string, 0, 1) |
|
| 87 |
- Tail(src, 1, &lines) |
|
| 88 |
- if len(lines) == 0 {
|
|
| 89 |
- *dst = "" |
|
| 90 |
- } else {
|
|
| 91 |
- *dst = lines[0] |
|
| 92 |
- } |
|
| 93 |
- }() |
|
| 94 |
- return nil |
|
| 95 |
-} |
|
| 96 |
- |
|
| 97 | 61 |
// Write writes the same data to all registered destinations. |
| 98 | 62 |
// This method is thread-safe. |
| 99 | 63 |
func (o *Output) Write(p []byte) (n int, err error) {
|
| ... | ... |
@@ -174,26 +159,6 @@ func (i *Input) Add(src io.Reader) error {
|
| 174 | 174 |
return nil |
| 175 | 175 |
} |
| 176 | 176 |
|
| 177 |
-// Tail reads from `src` line per line, and returns the last `n` lines as an array. |
|
| 178 |
-// A ring buffer is used to only store `n` lines at any time. |
|
| 179 |
-func Tail(src io.Reader, n int, dst *[]string) {
|
|
| 180 |
- scanner := bufio.NewScanner(src) |
|
| 181 |
- r := ring.New(n) |
|
| 182 |
- for scanner.Scan() {
|
|
| 183 |
- if n == 0 {
|
|
| 184 |
- continue |
|
| 185 |
- } |
|
| 186 |
- r.Value = scanner.Text() |
|
| 187 |
- r = r.Next() |
|
| 188 |
- } |
|
| 189 |
- r.Do(func(v interface{}) {
|
|
| 190 |
- if v == nil {
|
|
| 191 |
- return |
|
| 192 |
- } |
|
| 193 |
- *dst = append(*dst, v.(string)) |
|
| 194 |
- }) |
|
| 195 |
-} |
|
| 196 |
- |
|
| 197 | 177 |
// AddEnv starts a new goroutine which will decode all subsequent data |
| 198 | 178 |
// as a stream of json-encoded objects, and point `dst` to the last |
| 199 | 179 |
// decoded object. |
| ... | ... |
@@ -10,53 +10,6 @@ import ( |
| 10 | 10 |
"testing" |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 |
-func TestOutputAddString(t *testing.T) {
|
|
| 14 |
- var testInputs = [][2]string{
|
|
| 15 |
- {
|
|
| 16 |
- "hello, world!", |
|
| 17 |
- "hello, world!", |
|
| 18 |
- }, |
|
| 19 |
- |
|
| 20 |
- {
|
|
| 21 |
- "One\nTwo\nThree", |
|
| 22 |
- "Three", |
|
| 23 |
- }, |
|
| 24 |
- |
|
| 25 |
- {
|
|
| 26 |
- "", |
|
| 27 |
- "", |
|
| 28 |
- }, |
|
| 29 |
- |
|
| 30 |
- {
|
|
| 31 |
- "A line\nThen another nl-terminated line\n", |
|
| 32 |
- "Then another nl-terminated line", |
|
| 33 |
- }, |
|
| 34 |
- |
|
| 35 |
- {
|
|
| 36 |
- "A line followed by an empty line\n\n", |
|
| 37 |
- "", |
|
| 38 |
- }, |
|
| 39 |
- } |
|
| 40 |
- for _, testData := range testInputs {
|
|
| 41 |
- input := testData[0] |
|
| 42 |
- expectedOutput := testData[1] |
|
| 43 |
- o := NewOutput() |
|
| 44 |
- var output string |
|
| 45 |
- if err := o.AddString(&output); err != nil {
|
|
| 46 |
- t.Error(err) |
|
| 47 |
- } |
|
| 48 |
- if n, err := o.Write([]byte(input)); err != nil {
|
|
| 49 |
- t.Error(err) |
|
| 50 |
- } else if n != len(input) {
|
|
| 51 |
- t.Errorf("Expected %d, got %d", len(input), n)
|
|
| 52 |
- } |
|
| 53 |
- o.Close() |
|
| 54 |
- if output != expectedOutput {
|
|
| 55 |
- t.Errorf("Last line is not stored as return string.\nInput: '%s'\nExpected: '%s'\nGot: '%s'", input, expectedOutput, output)
|
|
| 56 |
- } |
|
| 57 |
- } |
|
| 58 |
-} |
|
| 59 |
- |
|
| 60 | 13 |
type sentinelWriteCloser struct {
|
| 61 | 14 |
calledWrite bool |
| 62 | 15 |
calledClose bool |
| ... | ... |
@@ -145,59 +98,24 @@ func TestOutputAddPipe(t *testing.T) {
|
| 145 | 145 |
} |
| 146 | 146 |
|
| 147 | 147 |
func TestTail(t *testing.T) {
|
| 148 |
- var tests = make(map[string][][]string) |
|
| 149 |
- tests["hello, world!"] = [][]string{
|
|
| 150 |
- {},
|
|
| 151 |
- {"hello, world!"},
|
|
| 152 |
- {"hello, world!"},
|
|
| 153 |
- {"hello, world!"},
|
|
| 154 |
- } |
|
| 155 |
- tests["One\nTwo\nThree"] = [][]string{
|
|
| 156 |
- {},
|
|
| 157 |
- {"Three"},
|
|
| 158 |
- {"Two", "Three"},
|
|
| 159 |
- {"One", "Two", "Three"},
|
|
| 160 |
- } |
|
| 161 |
- for input, outputs := range tests {
|
|
| 162 |
- for n, expectedOutput := range outputs {
|
|
| 163 |
- var output []string |
|
| 164 |
- Tail(strings.NewReader(input), n, &output) |
|
| 165 |
- if fmt.Sprintf("%v", output) != fmt.Sprintf("%v", expectedOutput) {
|
|
| 166 |
- t.Errorf("Tail n=%d returned wrong result.\nExpected: '%s'\nGot : '%s'", expectedOutput, output)
|
|
| 167 |
- } |
|
| 168 |
- } |
|
| 169 |
- } |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-func TestOutputAddTail(t *testing.T) {
|
|
| 173 |
- var tests = make(map[string][][]string) |
|
| 174 |
- tests["hello, world!"] = [][]string{
|
|
| 175 |
- {},
|
|
| 176 |
- {"hello, world!"},
|
|
| 177 |
- {"hello, world!"},
|
|
| 178 |
- {"hello, world!"},
|
|
| 148 |
+ var tests = make(map[string][]string) |
|
| 149 |
+ tests["hello, world!"] = []string{
|
|
| 150 |
+ "", |
|
| 151 |
+ "hello, world!", |
|
| 152 |
+ "hello, world!", |
|
| 153 |
+ "hello, world!", |
|
| 179 | 154 |
} |
| 180 |
- tests["One\nTwo\nThree"] = [][]string{
|
|
| 181 |
- {},
|
|
| 182 |
- {"Three"},
|
|
| 183 |
- {"Two", "Three"},
|
|
| 184 |
- {"One", "Two", "Three"},
|
|
| 155 |
+ tests["One\nTwo\nThree"] = []string{
|
|
| 156 |
+ "", |
|
| 157 |
+ "Three", |
|
| 158 |
+ "Two\nThree", |
|
| 159 |
+ "One\nTwo\nThree", |
|
| 185 | 160 |
} |
| 186 | 161 |
for input, outputs := range tests {
|
| 187 | 162 |
for n, expectedOutput := range outputs {
|
| 188 |
- o := NewOutput() |
|
| 189 |
- var output []string |
|
| 190 |
- if err := o.AddTail(&output, n); err != nil {
|
|
| 191 |
- t.Error(err) |
|
| 192 |
- } |
|
| 193 |
- if n, err := o.Write([]byte(input)); err != nil {
|
|
| 194 |
- t.Error(err) |
|
| 195 |
- } else if n != len(input) {
|
|
| 196 |
- t.Errorf("Expected %d, got %d", len(input), n)
|
|
| 197 |
- } |
|
| 198 |
- o.Close() |
|
| 199 |
- if fmt.Sprintf("%v", output) != fmt.Sprintf("%v", expectedOutput) {
|
|
| 200 |
- t.Errorf("Tail(%d) returned wrong result.\nExpected: %v\nGot: %v", n, expectedOutput, output)
|
|
| 163 |
+ output := Tail(bytes.NewBufferString(input), n) |
|
| 164 |
+ if output != expectedOutput {
|
|
| 165 |
+ t.Errorf("Tail n=%d returned wrong result.\nExpected: '%s'\nGot : '%s'", n, expectedOutput, output)
|
|
| 201 | 166 |
} |
| 202 | 167 |
} |
| 203 | 168 |
} |
| ... | ... |
@@ -3,13 +3,6 @@ package docker |
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"fmt" |
| 6 |
- "github.com/dotcloud/docker/daemon" |
|
| 7 |
- "github.com/dotcloud/docker/engine" |
|
| 8 |
- "github.com/dotcloud/docker/image" |
|
| 9 |
- "github.com/dotcloud/docker/nat" |
|
| 10 |
- "github.com/dotcloud/docker/runconfig" |
|
| 11 |
- "github.com/dotcloud/docker/sysinit" |
|
| 12 |
- "github.com/dotcloud/docker/utils" |
|
| 13 | 6 |
"io" |
| 14 | 7 |
"log" |
| 15 | 8 |
"net" |
| ... | ... |
@@ -22,6 +15,14 @@ import ( |
| 22 | 22 |
"syscall" |
| 23 | 23 |
"testing" |
| 24 | 24 |
"time" |
| 25 |
+ |
|
| 26 |
+ "github.com/dotcloud/docker/daemon" |
|
| 27 |
+ "github.com/dotcloud/docker/engine" |
|
| 28 |
+ "github.com/dotcloud/docker/image" |
|
| 29 |
+ "github.com/dotcloud/docker/nat" |
|
| 30 |
+ "github.com/dotcloud/docker/runconfig" |
|
| 31 |
+ "github.com/dotcloud/docker/sysinit" |
|
| 32 |
+ "github.com/dotcloud/docker/utils" |
|
| 25 | 33 |
) |
| 26 | 34 |
|
| 27 | 35 |
const ( |
| ... | ... |
@@ -421,13 +422,14 @@ func TestGet(t *testing.T) {
|
| 421 | 421 |
|
| 422 | 422 |
func startEchoServerContainer(t *testing.T, proto string) (*daemon.Daemon, *daemon.Container, string) {
|
| 423 | 423 |
var ( |
| 424 |
- err error |
|
| 425 |
- id string |
|
| 426 |
- strPort string |
|
| 427 |
- eng = NewTestEngine(t) |
|
| 428 |
- daemon = mkDaemonFromEngine(eng, t) |
|
| 429 |
- port = 5554 |
|
| 430 |
- p nat.Port |
|
| 424 |
+ err error |
|
| 425 |
+ id string |
|
| 426 |
+ outputBuffer = bytes.NewBuffer(nil) |
|
| 427 |
+ strPort string |
|
| 428 |
+ eng = NewTestEngine(t) |
|
| 429 |
+ daemon = mkDaemonFromEngine(eng, t) |
|
| 430 |
+ port = 5554 |
|
| 431 |
+ p nat.Port |
|
| 431 | 432 |
) |
| 432 | 433 |
defer func() {
|
| 433 | 434 |
if err != nil {
|
| ... | ... |
@@ -455,10 +457,11 @@ func startEchoServerContainer(t *testing.T, proto string) (*daemon.Daemon, *daem |
| 455 | 455 |
jobCreate.SetenvList("Cmd", []string{"sh", "-c", cmd})
|
| 456 | 456 |
jobCreate.SetenvList("PortSpecs", []string{fmt.Sprintf("%s/%s", strPort, proto)})
|
| 457 | 457 |
jobCreate.SetenvJson("ExposedPorts", ep)
|
| 458 |
- jobCreate.Stdout.AddString(&id) |
|
| 458 |
+ jobCreate.Stdout.Add(outputBuffer) |
|
| 459 | 459 |
if err := jobCreate.Run(); err != nil {
|
| 460 | 460 |
t.Fatal(err) |
| 461 | 461 |
} |
| 462 |
+ id = engine.Tail(outputBuffer, 1) |
|
| 462 | 463 |
// FIXME: this relies on the undocumented behavior of daemon.Create |
| 463 | 464 |
// which will return a nil error AND container if the exposed ports |
| 464 | 465 |
// are invalid. That behavior should be fixed! |
| ... | ... |
@@ -720,12 +723,12 @@ func TestContainerNameValidation(t *testing.T) {
|
| 720 | 720 |
t.Fatal(err) |
| 721 | 721 |
} |
| 722 | 722 |
|
| 723 |
- var shortID string |
|
| 723 |
+ var outputBuffer = bytes.NewBuffer(nil) |
|
| 724 | 724 |
job := eng.Job("create", test.Name)
|
| 725 | 725 |
if err := job.ImportEnv(config); err != nil {
|
| 726 | 726 |
t.Fatal(err) |
| 727 | 727 |
} |
| 728 |
- job.Stdout.AddString(&shortID) |
|
| 728 |
+ job.Stdout.Add(outputBuffer) |
|
| 729 | 729 |
if err := job.Run(); err != nil {
|
| 730 | 730 |
if !test.Valid {
|
| 731 | 731 |
continue |
| ... | ... |
@@ -733,7 +736,7 @@ func TestContainerNameValidation(t *testing.T) {
|
| 733 | 733 |
t.Fatal(err) |
| 734 | 734 |
} |
| 735 | 735 |
|
| 736 |
- container := daemon.Get(shortID) |
|
| 736 |
+ container := daemon.Get(engine.Tail(outputBuffer, 1)) |
|
| 737 | 737 |
|
| 738 | 738 |
if container.Name != "/"+test.Name {
|
| 739 | 739 |
t.Fatalf("Expect /%s got %s", test.Name, container.Name)
|
| ... | ... |
@@ -1,12 +1,14 @@ |
| 1 | 1 |
package docker |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "github.com/dotcloud/docker/engine" |
|
| 5 |
- "github.com/dotcloud/docker/runconfig" |
|
| 6 |
- "github.com/dotcloud/docker/server" |
|
| 4 |
+ "bytes" |
|
| 7 | 5 |
"strings" |
| 8 | 6 |
"testing" |
| 9 | 7 |
"time" |
| 8 |
+ |
|
| 9 |
+ "github.com/dotcloud/docker/engine" |
|
| 10 |
+ "github.com/dotcloud/docker/runconfig" |
|
| 11 |
+ "github.com/dotcloud/docker/server" |
|
| 10 | 12 |
) |
| 11 | 13 |
|
| 12 | 14 |
func TestCreateNumberHostname(t *testing.T) {
|
| ... | ... |
@@ -70,13 +72,13 @@ func TestMergeConfigOnCommit(t *testing.T) {
|
| 70 | 70 |
job.Setenv("repo", "testrepo")
|
| 71 | 71 |
job.Setenv("tag", "testtag")
|
| 72 | 72 |
job.SetenvJson("config", config)
|
| 73 |
- var newId string |
|
| 74 |
- job.Stdout.AddString(&newId) |
|
| 73 |
+ var outputBuffer = bytes.NewBuffer(nil) |
|
| 74 |
+ job.Stdout.Add(outputBuffer) |
|
| 75 | 75 |
if err := job.Run(); err != nil {
|
| 76 | 76 |
t.Error(err) |
| 77 | 77 |
} |
| 78 | 78 |
|
| 79 |
- container2, _, _ := mkContainer(runtime, []string{newId}, t)
|
|
| 79 |
+ container2, _, _ := mkContainer(runtime, []string{engine.Tail(outputBuffer, 1)}, t)
|
|
| 80 | 80 |
defer runtime.Destroy(container2) |
| 81 | 81 |
|
| 82 | 82 |
job = eng.Job("inspect", container1.Name, "container")
|
| ... | ... |
@@ -168,8 +170,6 @@ func TestRestartKillWait(t *testing.T) {
|
| 168 | 168 |
|
| 169 | 169 |
setTimeout(t, "Waiting on stopped container timedout", 5*time.Second, func() {
|
| 170 | 170 |
job = srv.Eng.Job("wait", outs.Data[0].Get("Id"))
|
| 171 |
- var statusStr string |
|
| 172 |
- job.Stdout.AddString(&statusStr) |
|
| 173 | 171 |
if err := job.Run(); err != nil {
|
| 174 | 172 |
t.Fatal(err) |
| 175 | 173 |
} |
| ... | ... |
@@ -266,8 +266,6 @@ func TestRunWithTooLowMemoryLimit(t *testing.T) {
|
| 266 | 266 |
job.Setenv("Memory", "524287")
|
| 267 | 267 |
job.Setenv("CpuShares", "1000")
|
| 268 | 268 |
job.SetenvList("Cmd", []string{"/bin/cat"})
|
| 269 |
- var id string |
|
| 270 |
- job.Stdout.AddString(&id) |
|
| 271 | 269 |
if err := job.Run(); err == nil {
|
| 272 | 270 |
t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
|
| 273 | 271 |
} |
| ... | ... |
@@ -302,13 +300,13 @@ func TestRmi(t *testing.T) {
|
| 302 | 302 |
|
| 303 | 303 |
job = eng.Job("commit", containerID)
|
| 304 | 304 |
job.Setenv("repo", "test")
|
| 305 |
- var imageID string |
|
| 306 |
- job.Stdout.AddString(&imageID) |
|
| 305 |
+ var outputBuffer = bytes.NewBuffer(nil) |
|
| 306 |
+ job.Stdout.Add(outputBuffer) |
|
| 307 | 307 |
if err := job.Run(); err != nil {
|
| 308 | 308 |
t.Fatal(err) |
| 309 | 309 |
} |
| 310 | 310 |
|
| 311 |
- if err := eng.Job("tag", imageID, "test", "0.1").Run(); err != nil {
|
|
| 311 |
+ if err := eng.Job("tag", engine.Tail(outputBuffer, 1), "test", "0.1").Run(); err != nil {
|
|
| 312 | 312 |
t.Fatal(err) |
| 313 | 313 |
} |
| 314 | 314 |
|
| ... | ... |
@@ -339,7 +337,7 @@ func TestRmi(t *testing.T) {
|
| 339 | 339 |
t.Fatalf("Expected 2 new images, found %d.", images.Len()-initialImages.Len())
|
| 340 | 340 |
} |
| 341 | 341 |
|
| 342 |
- if err = srv.DeleteImage(imageID, engine.NewTable("", 0), true, false, false); err != nil {
|
|
| 342 |
+ if err = srv.DeleteImage(engine.Tail(outputBuffer, 1), engine.NewTable("", 0), true, false, false); err != nil {
|
|
| 343 | 343 |
t.Fatal(err) |
| 344 | 344 |
} |
| 345 | 345 |
|
| ... | ... |
@@ -3,7 +3,6 @@ package docker |
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"fmt" |
| 6 |
- "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" |
|
| 7 | 6 |
"io" |
| 8 | 7 |
"io/ioutil" |
| 9 | 8 |
"net/http" |
| ... | ... |
@@ -14,6 +13,8 @@ import ( |
| 14 | 14 |
"testing" |
| 15 | 15 |
"time" |
| 16 | 16 |
|
| 17 |
+ "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" |
|
| 18 |
+ |
|
| 17 | 19 |
"github.com/dotcloud/docker/builtins" |
| 18 | 20 |
"github.com/dotcloud/docker/daemon" |
| 19 | 21 |
"github.com/dotcloud/docker/engine" |
| ... | ... |
@@ -42,11 +43,12 @@ func createNamedTestContainer(eng *engine.Engine, config *runconfig.Config, f ut |
| 42 | 42 |
if err := job.ImportEnv(config); err != nil {
|
| 43 | 43 |
f.Fatal(err) |
| 44 | 44 |
} |
| 45 |
- job.Stdout.AddString(&shortId) |
|
| 45 |
+ var outputBuffer = bytes.NewBuffer(nil) |
|
| 46 |
+ job.Stdout.Add(outputBuffer) |
|
| 46 | 47 |
if err := job.Run(); err != nil {
|
| 47 | 48 |
f.Fatal(err) |
| 48 | 49 |
} |
| 49 |
- return |
|
| 50 |
+ return engine.Tail(outputBuffer, 1) |
|
| 50 | 51 |
} |
| 51 | 52 |
|
| 52 | 53 |
func createTestContainer(eng *engine.Engine, config *runconfig.Config, f utils.Fataler) (shortId string) {
|