func execWithTimeout(timeout time.Duration, cmd string, args ...string) (output []byte, err error) { var buf safe.Buffer ch := make(chan []byte, 1) errCh := make(chan error, 1) command := osexec.Command(cmd, args...) command.Stdout = &Writer{&buf} command.Stderr = &Writer{&buf} if err = command.Start(); err != nil { return nil, err } go func() { if err := command.Wait(); err == nil { ch <- buf.Bytes() } else { errCh <- err ch <- buf.Bytes() } }() select { case output = <-ch: select { case err = <-errCh: case <-time.After(1e9): } case err = <-errCh: output = <-ch case <-time.After(timeout): argsStr := strings.Join(args, " ") err = fmt.Errorf("%q ran for more than %s.", cmd+" "+argsStr, timeout) command.Process.Kill() } return output, err }
func TestPullImage(t *testing.T) { server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Pulling from 1!")) })) defer server1.Close() server2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Pulling from 2!")) })) defer server2.Close() var buf safe.Buffer cluster, err := New(nil, Node{ID: "handler0", Address: server1.URL}, Node{ID: "handler1", Address: server2.URL}, ) if err != nil { t.Fatal(err) } err = cluster.PullImage(docker.PullImageOptions{Repository: "tsuru/python"}, &buf) if err != nil { t.Error(err) } alternatives := []string{ "Pulling from 1!Pulling from 2!", "Pulling from 2!Pulling from 1!", } if r := buf.String(); r != alternatives[0] && r != alternatives[1] { t.Errorf("Wrong output: Want %q. Got %q.", "Pulling from 1!Pulling from 2!", buf.String()) } }
func TestImportImage(t *testing.T) { server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("importing from 1")) })) defer server1.Close() server2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("importing from 2")) })) defer server2.Close() cluster, err := New(nil, Node{ID: "handler0", Address: server1.URL}, Node{ID: "handler1", Address: server2.URL}, ) if err != nil { t.Fatal(err) } var buf safe.Buffer err = cluster.ImportImage(docker.ImportImageOptions{Repository: "tsuru/python", Source: "http://url.to/tar"}, nil, &buf) if err != nil { t.Error(err) } re := regexp.MustCompile(`^importing from \d`) if !re.MatchString(buf.String()) { t.Errorf("Wrong output: Want %q. Got %q.", "importing from [12]", buf.String()) } }
// replicateImage replicates the given image through all nodes in the cluster. func replicateImage(name string) error { var buf safe.Buffer if _, err := config.GetString("docker:registry"); err == nil { pushOpts := docker.PushImageOptions{Name: name, OutputStream: &buf} for i := 0; i < maxTry; i++ { err = dockerCluster().PushImage(pushOpts, docker.AuthConfiguration{}) if err == nil { buf.Reset() break } log.Errorf("[docker] Failed to push image %q (%s): %s", name, err, buf.String()) buf.Reset() } if err != nil { return err } pullOpts := docker.PullImageOptions{Repository: name, OutputStream: &buf} for i := 0; i < maxTry; i++ { err = dockerCluster().PullImage(pullOpts) if err == nil { break } buf.Reset() } if err != nil { log.Errorf("[docker] Failed to replicate image %q through nodes (%s): %s", name, err, buf.String()) return err } } return nil }
// pushImage sends the given image to the registry server defined in the // configuration file. func pushImage(name string) error { if _, err := config.GetString("docker:registry"); err == nil { var buf safe.Buffer pushOpts := docker.PushImageOptions{Name: name, OutputStream: &buf} err = dockerCluster().PushImage(pushOpts, docker.AuthConfiguration{}) if err != nil { log.Errorf("[docker] Failed to push image %q (%s): %s", name, err, buf.String()) return err } } return nil }
func TestPushImage(t *testing.T) { server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Pushing to server 1!")) })) defer server1.Close() server2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Pushing to server 2!")) })) defer server2.Close() var buf safe.Buffer cluster, err := New(nil, Node{ID: "handler0", Address: server1.URL}, Node{ID: "handler1", Address: server2.URL}, ) if err != nil { t.Fatal(err) } var auth docker.AuthConfiguration err = cluster.PushImage(docker.PushImageOptions{Name: "tsuru/ruby"}, auth, &buf) re := regexp.MustCompile(`^Pushing to server \d`) if !re.MatchString(buf.String()) { t.Errorf("Wrong output: Want %q. Got %q.", "Pushing to server [12]", buf.String()) } }