func (s *appSuite) initApp(t *c.C, app string) { s.appDir = filepath.Join(t.MkDir(), "app") t.Assert(run(exec.Command("cp", "-r", filepath.Join("apps", app), s.appDir)), Succeeds) t.Assert(s.Git("init"), Succeeds) t.Assert(s.Git("add", "."), Succeeds) t.Assert(s.Git("commit", "-am", "init"), Succeeds) }
func initApp(t *c.C, app string) string { dir := filepath.Join(t.MkDir(), "app") t.Assert(run(exec.Command("cp", "-r", filepath.Join("apps", app), dir)), Succeeds) t.Assert(git(dir, "init"), Succeeds) t.Assert(git(dir, "add", "."), Succeeds) t.Assert(git(dir, "commit", "-am", "init"), Succeeds) return dir }
func waitForJobEvents(t *c.C, events chan *ct.JobEvent, diff map[string]int) error { actual := make(map[string]int) for { select { case event := <-events: switch event.State { case "up": actual[event.Type] += 1 case "down": actual[event.Type] -= 1 } if processesEqual(diff, actual) { return nil } case <-time.After(5 * time.Second): t.Fatal("timed out waiting for job events") } } }
func (s *SchedulerSuite) SetUpSuite(t *c.C) { conf, err := config.ReadFile(flynnrc) t.Assert(err, c.IsNil) cluster := conf.Clusters[0] pin, err := base64.StdEncoding.DecodeString(cluster.TLSPin) t.Assert(err, c.IsNil) client, err := controller.NewClientWithPin(cluster.URL, cluster.Key, pin) t.Assert(err, c.IsNil) s.client = client }
func (s *BasicSuite) TestBasic(t *c.C) { name := random.String(30) t.Assert(s.Flynn("create", name), Outputs, fmt.Sprintf("Created %s\n", name)) push := s.Git("push", "flynn", "master") t.Assert(push, OutputContains, "Node.js app detected") t.Assert(push, OutputContains, "Downloading and installing node") t.Assert(push, OutputContains, "Installing dependencies") t.Assert(push, OutputContains, "Procfile declares types -> web") t.Assert(push, OutputContains, "Creating release") t.Assert(push, OutputContains, "Application deployed") t.Assert(push, OutputContains, "* [new branch] master -> master") t.Assert(s.Flynn("scale", "web=3"), Succeeds) route := random.String(32) + ".dev" newRoute := s.Flynn("route", "add", "-t", "http", route) t.Assert(newRoute, Succeeds) t.Assert(s.Flynn("route"), OutputContains, strings.TrimSpace(newRoute.Output)) // use Attempts to give the processes time to start if err := Attempts.Run(func() error { ps := s.Flynn("ps") if ps.Err != nil { return ps.Err } psLines := strings.Split(strings.TrimSpace(ps.Output), "\n") if len(psLines) != 4 { return fmt.Errorf("Expected 4 ps lines, got %d", len(psLines)) } for _, l := range psLines[1:] { idType := regexp.MustCompile(`\s+`).Split(l, 2) if idType[1] != "web" { return fmt.Errorf("Expected web type, got %s", idType[1]) } log := s.Flynn("log", idType[0]) if !strings.Contains(log.Output, "Listening on ") { return fmt.Errorf("Expected \"%s\" to contain \"Listening on \"", log.Output) } } return nil }); err != nil { t.Error(err) } // Make HTTP requests client := &http.Client{} req, err := http.NewRequest("GET", "http://"+routerIP, nil) if err != nil { t.Error(err) } req.Host = route res, err := client.Do(req) if err != nil { t.Error(err) } defer res.Body.Close() contents, err := ioutil.ReadAll(res.Body) if err != nil { t.Error(err) } t.Assert(res.StatusCode, c.Equals, 200) t.Assert(string(contents), Matches, `Hello to Yahoo from Flynn on port \d+`) }
func (s *SchedulerSuite) TestScale(t *c.C) { app := &ct.App{} t.Assert(s.client.CreateApp(app), c.IsNil) artifact := &ct.Artifact{Type: "docker", URI: "https://registry.hub.docker.com/flynn/busybox?id=" + busyboxID} t.Assert(s.client.CreateArtifact(artifact), c.IsNil) release := &ct.Release{ ArtifactID: artifact.ID, Processes: map[string]ct.ProcessType{ "date": {Cmd: []string{"sh", "-c", "while true; do date; sleep 1; done"}}, "work": {Cmd: []string{"sh", "-c", "while true; do echo work; sleep 1; done"}}, }, } t.Assert(s.client.CreateRelease(release), c.IsNil) t.Assert(s.client.SetAppRelease(app.ID, release.ID), c.IsNil) stream, err := s.client.StreamJobEvents(app.ID) t.Assert(err, c.IsNil) defer stream.Close() formation := &ct.Formation{ AppID: app.ID, ReleaseID: release.ID, Processes: make(map[string]int), } current := make(map[string]int) updates := []map[string]int{ {"date": 2}, {"date": 3, "work": 1}, {"date": 1}, } for _, procs := range updates { formation.Processes = procs t.Assert(s.client.PutFormation(formation), c.IsNil) diff := make(map[string]int) for t, n := range procs { diff[t] = n - current[t] } for t, n := range current { if _, ok := procs[t]; !ok { diff[t] = -n } } waitForJobEvents(t, stream.Events, diff) current = procs } }
func (s *BasicSuite) TestBasic(t *c.C) { name := util.RandomString(30) t.Assert(s.Flynn("create", name), Outputs, fmt.Sprintf("Created %s\n", name)) push := s.Git("push", "flynn", "master") t.Assert(push, OutputContains, "Node.js app detected") t.Assert(push, OutputContains, "Downloading and installing node") t.Assert(push, OutputContains, "Installing dependencies") t.Assert(push, OutputContains, "Procfile declares types -> web") t.Assert(push, OutputContains, "Creating release") t.Assert(push, OutputContains, "Application deployed") t.Assert(push, OutputContains, "* [new branch] master -> master") t.Assert(s.Flynn("scale", "web=3"), Succeeds) newRoute := s.Flynn("route-add-http", util.RandomString(32)+".dev") t.Assert(newRoute, Succeeds) t.Assert(s.Flynn("routes"), OutputContains, strings.TrimSpace(newRoute.Output)) // use Attempts to give the processes time to start if err := Attempts.Run(func() error { ps := s.Flynn("ps") if ps.Err != nil { return ps.Err } psLines := strings.Split(strings.TrimSpace(ps.Output), "\n") if len(psLines) != 4 { return fmt.Errorf("Expected 4 ps lines, got %d", len(psLines)) } for _, l := range psLines[1:] { idType := regexp.MustCompile(`\s+`).Split(l, 2) if idType[1] != "web" { return fmt.Errorf("Expected web type, got %s", idType[1]) } log := s.Flynn("log", idType[0]) if !strings.Contains(log.Output, "Listening on ") { return fmt.Errorf("Expected \"%s\" to contain \"Listening on \"", log.Output) } } return nil }); err != nil { t.Error(err) } // Make HTTP requests }
func (s *SchedulerSuite) TestTCPApp(t *c.C) { r, err := s.client.GetAppRelease("gitreceive") t.Assert(err, c.IsNil) imageID := r.Processes["app"].Env["SLUGRUNNER_IMAGE_ID"] app := &ct.App{} t.Assert(s.client.CreateApp(app), c.IsNil) artifact := &ct.Artifact{Type: "docker", URI: "https://registry.hub.docker.com/flynn/slugrunner?id=" + imageID} t.Assert(s.client.CreateArtifact(artifact), c.IsNil) release := &ct.Release{ ArtifactID: artifact.ID, Processes: map[string]ct.ProcessType{ "echo": { Ports: []ct.Port{{Proto: "tcp"}}, Cmd: []string{"sdutil exec -s echo-service:$PORT socat -v tcp-l:$PORT,fork exec:/bin/cat"}, Entrypoint: []string{"sh", "-c"}, }, }, } t.Assert(s.client.CreateRelease(release), c.IsNil) t.Assert(s.client.SetAppRelease(app.ID, release.ID), c.IsNil) stream, err := s.client.StreamJobEvents(app.ID) defer stream.Close() if err != nil { t.Error(err) } t.Assert(flynn("/", "-a", app.Name, "scale", "echo=1"), Succeeds) newRoute := flynn("/", "-a", app.Name, "route", "add", "tcp", "-s", "echo-service") t.Assert(newRoute, Succeeds) t.Assert(newRoute.Output, Matches, `.+ on port \d+`) str := strings.Split(strings.TrimSpace(string(newRoute.Output)), " ") port := str[len(str)-1] waitForJobEvents(t, stream.Events, map[string]int{"echo": 1}) // use Attempts to give the processes time to start if err := Attempts.Run(func() error { servAddr := routerIP + ":" + port conn, err := net.Dial("tcp", servAddr) defer conn.Close() if err != nil { return err } echo := random.Bytes(16) _, err = conn.Write(echo) if err != nil { return err } reply := make([]byte, 16) _, err = conn.Read(reply) if err != nil { return err } t.Assert(reply, c.DeepEquals, echo) return nil }); err != nil { t.Error(err) } }