Add Load for container and Task with Attach

This adds both container and task loading of running tasks as well as
reattaching to the IO of the task after load.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby
2017-05-31 16:29:41 -07:00
parent 1db752bca8
commit 43fb19e01c
7 changed files with 228 additions and 47 deletions

View File

@@ -4,14 +4,17 @@ import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"os"
"sync"
"syscall"
"testing"
)
func empty() IOCreation {
return BufferedIO(bytes.NewBuffer(nil), bytes.NewBuffer(nil), bytes.NewBuffer(nil))
null := ioutil.Discard
return NewIO(bytes.NewBuffer(nil), null, null)
}
func TestContainerList(t *testing.T) {
@@ -170,7 +173,7 @@ func TestContainerOutput(t *testing.T) {
defer container.Delete(ctx)
stdout := bytes.NewBuffer(nil)
task, err := container.NewTask(ctx, BufferedIO(bytes.NewBuffer(nil), stdout, bytes.NewBuffer(nil)))
task, err := container.NewTask(ctx, NewIO(bytes.NewBuffer(nil), stdout, bytes.NewBuffer(nil)))
if err != nil {
t.Error(err)
return
@@ -445,3 +448,132 @@ func TestContainerCloseStdin(t *testing.T) {
t.Errorf("expected output %q but received %q", expected, output)
}
}
func TestContainerAttach(t *testing.T) {
if testing.Short() {
t.Skip()
}
client, err := New(address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
ctx = context.Background()
id = "ContainerAttach"
)
image, err := client.GetImage(ctx, testImage)
if err != nil {
t.Error(err)
return
}
spec, err := GenerateSpec(WithImageConfig(ctx, image), WithProcessArgs("cat"))
if err != nil {
t.Error(err)
return
}
container, err := client.NewContainer(ctx, id, spec, WithImage(image), WithNewRootFS(id, image))
if err != nil {
t.Error(err)
return
}
defer container.Delete(ctx)
expected := "hello\n"
stdout := bytes.NewBuffer(nil)
r, w, err := os.Pipe()
if err != nil {
t.Error(err)
return
}
or, ow, err := os.Pipe()
if err != nil {
t.Error(err)
return
}
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
io.Copy(stdout, or)
wg.Done()
}()
// TODO: return fifo information from shim based on task/process
dir, err := ioutil.TempDir("", "attach")
if err != nil {
t.Error(err)
return
}
task, err := container.NewTask(ctx, WithIO(r, ow, ioutil.Discard, dir))
if err != nil {
t.Error(err)
return
}
defer task.Delete(ctx)
originalIO := task.IO()
statusC := make(chan uint32, 1)
go func() {
status, err := task.Wait(ctx)
if err != nil {
t.Error(err)
}
statusC <- status
}()
if err := task.Start(ctx); err != nil {
t.Error(err)
return
}
if _, err := fmt.Fprint(w, expected); err != nil {
t.Error(err)
}
w.Close()
// load the container and re-load the task
if container, err = client.LoadContainer(ctx, id); err != nil {
t.Error(err)
return
}
// create new IO for the loaded task
if r, w, err = os.Pipe(); err != nil {
t.Error(err)
return
}
if task, err = container.LoadTask(ctx, WithIO(r, ow, ioutil.Discard, dir)); err != nil {
t.Error(err)
return
}
if _, err := fmt.Fprint(w, expected); err != nil {
t.Error(err)
}
w.Close()
if err := task.CloseStdin(ctx); err != nil {
t.Error(err)
}
<-statusC
originalIO.Close()
if _, err := task.Delete(ctx); err != nil {
t.Error(err)
}
ow.Close()
wg.Wait()
output := stdout.String()
// we wrote the same thing after attach
expected = expected + expected
if output != expected {
t.Errorf("expected output %q but received %q", expected, output)
}
}