func (s *S) TestResetPassword(c *check.C) { scheme := NativeScheme{} defer s.server.Reset() u := auth.User{Email: "*****@*****.**"} err := u.Create() c.Assert(err, check.IsNil) defer u.Delete() p := u.Password err = scheme.StartPasswordReset(&u) c.Assert(err, check.IsNil) err = tsurutest.WaitCondition(time.Second, func() bool { s.server.RLock() defer s.server.RUnlock() return len(s.server.MailBox) == 1 }) c.Assert(err, check.IsNil) var token passwordToken err = s.conn.PasswordTokens().Find(bson.M{"useremail": u.Email}).One(&token) c.Assert(err, check.IsNil) err = scheme.ResetPassword(&u, token.Token) c.Assert(err, check.IsNil) u2, _ := auth.GetUserByEmail(u.Email) c.Assert(u2.Password, check.Not(check.Equals), p) var m authtest.Mail err = tsurutest.WaitCondition(time.Second, func() bool { s.server.RLock() defer s.server.RUnlock() if len(s.server.MailBox) != 2 { return false } m = s.server.MailBox[1] return true }) c.Assert(err, check.IsNil) c.Assert(m.From, check.Equals, "root") c.Assert(m.To, check.DeepEquals, []string{u.Email}) var buf bytes.Buffer template, err := getEmailResetPasswordSucessfullyTemplate() c.Assert(err, check.IsNil) err = template.Execute(&buf, map[string]string{"email": u.Email, "password": ""}) c.Assert(err, check.IsNil) expected := strings.Replace(buf.String(), "\n", "\r\n", -1) + "\r\n" lines := strings.Split(string(m.Data), "\r\n") lines[len(lines)-4] = "" c.Assert(strings.Join(lines, "\r\n"), check.Equals, expected) err = s.conn.PasswordTokens().Find(bson.M{"useremail": u.Email}).One(&token) c.Assert(err, check.IsNil) c.Assert(token.Used, check.Equals, true) }
func (s *BindSuite) TestUnbindCallsTheUnbindMethodFromAPI(c *check.C) { var called int32 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "DELETE" && r.URL.Path == "/resources/my-mysql/bind" { atomic.StoreInt32(&called, 1) } })) defer ts.Close() srvc := Service{Name: "mysql", Endpoint: map[string]string{"production": ts.URL}} err := srvc.Create() c.Assert(err, check.IsNil) defer s.conn.Services().Remove(bson.M{"_id": "mysql"}) app := provisiontest.NewFakeApp("painkiller", "python", 1) app.AddInstance("mysql", bind.ServiceInstance{Name: "my-mysql"}, ioutil.Discard) units, err := app.GetUnits() c.Assert(err, check.IsNil) instance := ServiceInstance{ Name: "my-mysql", ServiceName: "mysql", Teams: []string{s.team.Name}, Apps: []string{app.GetName()}, Units: []string{units[0].GetID()}, } err = instance.Create() c.Assert(err, check.IsNil) defer s.conn.ServiceInstances().Remove(bson.M{"name": "my-mysql"}) err = instance.UnbindApp(app, nil) c.Assert(err, check.IsNil) err = tsurutest.WaitCondition(1e9, func() bool { return atomic.LoadInt32(&called) > 0 }) c.Assert(err, check.IsNil) }
func (s *S) TestStartPasswordReset(c *check.C) { scheme := NativeScheme{} conn, err := db.Conn() c.Assert(err, check.IsNil) defer conn.Close() defer s.server.Reset() u := auth.User{Email: "*****@*****.**"} err = scheme.StartPasswordReset(&u) c.Assert(err, check.IsNil) var token passwordToken err = conn.PasswordTokens().Find(bson.M{"useremail": u.Email}).One(&token) c.Assert(err, check.IsNil) var m authtest.Mail err = tsurutest.WaitCondition(time.Second, func() bool { s.server.Lock() defer s.server.Unlock() if len(s.server.MailBox) != 1 { return false } m = s.server.MailBox[0] return true }) c.Assert(err, check.IsNil) c.Assert(m.From, check.Equals, "root") c.Assert(m.To, check.DeepEquals, []string{u.Email}) var buf bytes.Buffer template, err := getEmailResetPasswordTemplate() c.Assert(err, check.IsNil) err = template.Execute(&buf, token) c.Assert(err, check.IsNil) expected := strings.Replace(buf.String(), "\n", "\r\n", -1) + "\r\n" c.Assert(string(m.Data), check.Equals, expected) }
func (s *BindSuite) TestBindAppMultiUnits(c *check.C) { var calls int32 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"DATABASE_USER":"******","DATABASE_PASSWORD":"******"}`)) atomic.AddInt32(&calls, 1) })) defer ts.Close() srvc := Service{Name: "mysql", Endpoint: map[string]string{"production": ts.URL}} err := srvc.Create() c.Assert(err, check.IsNil) defer s.conn.Services().Remove(bson.M{"_id": "mysql"}) instance := ServiceInstance{ Name: "my-mysql", ServiceName: "mysql", Teams: []string{s.team.Name}, } err = instance.Create() c.Assert(err, check.IsNil) defer s.conn.ServiceInstances().Remove(bson.M{"name": "my-mysql"}) app := provisiontest.NewFakeApp("painkiller", "python", 2) err = instance.BindApp(app, true, nil) c.Assert(err, check.IsNil) err = tsurutest.WaitCondition(2e9, func() bool { return atomic.LoadInt32(&calls) == 3 }) c.Assert(err, check.IsNil) }
func (s *BindSuite) TestUnbindMultiUnits(c *check.C) { var calls int32 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { atomic.AddInt32(&calls, 1) w.WriteHeader(http.StatusNoContent) })) defer ts.Close() srvc := Service{Name: "mysql", Endpoint: map[string]string{"production": ts.URL}} err := srvc.Create() c.Assert(err, check.IsNil) defer s.conn.Services().Remove(bson.M{"_id": "mysql"}) app := provisiontest.NewFakeApp("painkiller", "python", 2) app.AddInstance("mysql", bind.ServiceInstance{Name: "my-mysql"}, ioutil.Discard) units, err := app.GetUnits() c.Assert(err, check.IsNil) instance := ServiceInstance{ Name: "my-mysql", ServiceName: "mysql", Teams: []string{s.team.Name}, Apps: []string{app.GetName()}, Units: []string{units[0].GetID(), units[1].GetID()}, } instance.Create() defer s.conn.ServiceInstances().Remove(bson.M{"name": "my-mysql"}) err = instance.UnbindApp(app, nil) c.Assert(err, check.IsNil) err = tsurutest.WaitCondition(1e9, func() bool { return atomic.LoadInt32(&calls) > 1 }) c.Assert(err, check.IsNil) c.Assert(app.GetInstances("mysql"), check.HasLen, 0) }
func (s *S) TestAppShellGenericError(c *check.C) { m := RunServer(true) server := httptest.NewServer(m) defer server.Close() testServerURL, err := url.Parse(server.URL) c.Assert(err, check.IsNil) url := fmt.Sprintf("ws://%s/apps/someapp/shell?width=140&height=38&term=xterm", testServerURL.Host) config, err := websocket.NewConfig(url, "ws://localhost/") c.Assert(err, check.IsNil) config.Header.Set("Authorization", "bearer "+s.token.GetValue()) wsConn, err := websocket.DialConfig(config) c.Assert(err, check.IsNil) defer wsConn.Close() _, err = wsConn.Write([]byte("echo test")) c.Assert(err, check.IsNil) var result string err = tsurutest.WaitCondition(5*time.Second, func() bool { part, readErr := ioutil.ReadAll(wsConn) if readErr != nil { c.Log(readErr) return false } result += string(part) return result == "Error: App someapp not found.\n" }) c.Assert(err, check.IsNil) }
func (s *S) TestAppShellUnauthorizedError(c *check.C) { a := app.App{ Name: "someapp", Platform: "zend", TeamOwner: s.team.Name, } err := app.CreateApp(&a, s.user) c.Assert(err, check.IsNil) err = s.provisioner.AddUnits(&a, 1, "web", nil) c.Assert(err, check.IsNil) m := RunServer(true) server := httptest.NewServer(m) defer server.Close() testServerURL, err := url.Parse(server.URL) c.Assert(err, check.IsNil) url := fmt.Sprintf("ws://%s/apps/%s/shell?width=140&height=38&term=xterm", testServerURL.Host, a.Name) config, err := websocket.NewConfig(url, "ws://localhost/") c.Assert(err, check.IsNil) wsConn, err := websocket.DialConfig(config) c.Assert(err, check.IsNil) defer wsConn.Close() _, err = wsConn.Write([]byte("echo test")) c.Assert(err, check.IsNil) var result string err = tsurutest.WaitCondition(5*time.Second, func() bool { part, readErr := ioutil.ReadAll(wsConn) if readErr != nil { return false } result += string(part) return result == "Error: no token provided or session expired, please login again\n" }) c.Assert(err, check.IsNil) }
func (s *S) TestHealthCheckFailure(c *check.C) { s.vulcandServer.Close() err := tsurutest.WaitCondition(time.Second, func() bool { _, err := http.Get(s.vulcandServer.URL) return err != nil }) c.Assert(err, check.IsNil) got, err := router.Get("vulcand") c.Assert(err, check.IsNil) hcRouter, ok := got.(router.HealthChecker) c.Assert(ok, check.Equals, true) c.Assert(hcRouter.HealthCheck(), check.ErrorMatches, ".* connection refused") }
func (s *S) TestAppShellSpecifyUnit(c *check.C) { a := app.App{ Name: "someapp", Platform: "zend", Teams: []string{s.team.Name}, } err := s.conn.Apps().Insert(a) c.Assert(err, check.IsNil) defer s.conn.Apps().Remove(bson.M{"name": a.Name}) defer s.logConn.Logs(a.Name).DropCollection() err = s.provisioner.Provision(&a) c.Assert(err, check.IsNil) defer s.provisioner.Destroy(&a) s.provisioner.AddUnits(&a, 5, "web", nil) units, err := s.provisioner.Units(&a) c.Assert(err, check.IsNil) unit := units[3] m := RunServer(true) server := httptest.NewServer(m) defer server.Close() testServerURL, err := url.Parse(server.URL) c.Assert(err, check.IsNil) url := fmt.Sprintf("ws://%s/apps/%s/shell?width=140&height=38&term=xterm&unit=%s", testServerURL.Host, a.Name, unit.ID) config, err := websocket.NewConfig(url, "ws://localhost/") c.Assert(err, check.IsNil) config.Header.Set("Authorization", "bearer "+s.token.GetValue()) wsConn, err := websocket.DialConfig(config) c.Assert(err, check.IsNil) defer wsConn.Close() _, err = wsConn.Write([]byte("echo test")) c.Assert(err, check.IsNil) var shells []provision.ShellOptions err = tsurutest.WaitCondition(5*time.Second, func() bool { shells = s.provisioner.Shells(unit.ID) return len(shells) == 1 }) c.Assert(err, check.IsNil) c.Assert(shells, check.HasLen, 1) c.Assert(shells[0].App.GetName(), check.Equals, a.Name) c.Assert(shells[0].Width, check.Equals, 140) c.Assert(shells[0].Height, check.Equals, 38) c.Assert(shells[0].Term, check.Equals, "xterm") c.Assert(shells[0].Unit, check.Equals, unit.ID) units, err = s.provisioner.Units(&a) c.Assert(err, check.IsNil) for _, u := range units { if u.ID != unit.ID { c.Check(s.provisioner.Shells(u.ID), check.HasLen, 0) } } }
func (s *S) TestAppShellWithAppNameInvalidPermission(c *check.C) { a := app.App{ Name: "someapp", Platform: "zend", TeamOwner: s.team.Name, } err := app.CreateApp(&a, s.user) c.Assert(err, check.IsNil) err = s.provisioner.AddUnits(&a, 1, "web", nil) c.Assert(err, check.IsNil) m := RunServer(true) server := httptest.NewServer(m) defer server.Close() testServerURL, err := url.Parse(server.URL) c.Assert(err, check.IsNil) token := userWithPermission(c, permission.Permission{ Scheme: permission.PermAppRead, Context: permission.Context(permission.CtxApp, a.Name), }) url := fmt.Sprintf("ws://%s/apps/%s/shell?width=140&height=38&term=xterm", testServerURL.Host, a.Name) config, err := websocket.NewConfig(url, "ws://localhost/") c.Assert(err, check.IsNil) config.Header.Set("Authorization", "bearer "+token.GetValue()) wsConn, err := websocket.DialConfig(config) c.Assert(err, check.IsNil) defer wsConn.Close() _, err = wsConn.Write([]byte("echo test")) c.Assert(err, check.IsNil) var result string err = tsurutest.WaitCondition(5*time.Second, func() bool { part, readErr := ioutil.ReadAll(wsConn) if readErr != nil { return false } result += string(part) return result == "Error: You don't have permission to do this action\n" }) c.Assert(err, check.IsNil) }
func (s *S) TestAppShellWithAppName(c *check.C) { a := app.App{ Name: "someapp", Platform: "zend", TeamOwner: s.team.Name, } err := app.CreateApp(&a, s.user) c.Assert(err, check.IsNil) err = s.provisioner.AddUnits(&a, 1, "web", nil) c.Assert(err, check.IsNil) m := RunServer(true) server := httptest.NewServer(m) defer server.Close() testServerURL, err := url.Parse(server.URL) c.Assert(err, check.IsNil) url := fmt.Sprintf("ws://%s/apps/%s/shell?width=140&height=38&term=xterm", testServerURL.Host, a.Name) config, err := websocket.NewConfig(url, "ws://localhost/") c.Assert(err, check.IsNil) config.Header.Set("Authorization", "bearer "+s.token.GetValue()) wsConn, err := websocket.DialConfig(config) c.Assert(err, check.IsNil) defer wsConn.Close() _, err = wsConn.Write([]byte("echo test")) c.Assert(err, check.IsNil) var shells []provision.ShellOptions err = tsurutest.WaitCondition(5*time.Second, func() bool { units, unitsErr := s.provisioner.Units(&a) c.Assert(unitsErr, check.IsNil) unit := units[0] shells = s.provisioner.Shells(unit.ID) return len(shells) == 1 }) c.Assert(err, check.IsNil) c.Assert(shells[0].App.GetName(), check.Equals, a.Name) c.Assert(shells[0].Width, check.Equals, 140) c.Assert(shells[0].Height, check.Equals, 38) c.Assert(shells[0].Term, check.Equals, "xterm") c.Assert(shells[0].Unit, check.Equals, "") }
func (s *S) TestAppShellGenericError(c *check.C) { a := app.App{ Name: "someapp", Platform: "zend", Teams: []string{s.team.Name}, } err := s.provisioner.Provision(&a) c.Assert(err, check.IsNil) defer s.provisioner.Destroy(&a) s.provisioner.AddUnits(&a, 1, "web", nil) m := RunServer(true) server := httptest.NewServer(m) defer server.Close() testServerURL, err := url.Parse(server.URL) c.Assert(err, check.IsNil) url := fmt.Sprintf("ws://%s/apps/%s/shell?width=140&height=38&term=xterm", testServerURL.Host, a.Name) config, err := websocket.NewConfig(url, "ws://localhost/") c.Assert(err, check.IsNil) config.Header.Set("Authorization", "bearer "+s.token.GetValue()) wsConn, err := websocket.DialConfig(config) c.Assert(err, check.IsNil) defer wsConn.Close() _, err = wsConn.Write([]byte("echo test")) c.Assert(err, check.IsNil) var result string err = tsurutest.WaitCondition(5*time.Second, func() bool { part, err := ioutil.ReadAll(wsConn) if err != nil { c.Log(err) return false } result += string(part) return result == "Error: App someapp not found.\n" }) c.Assert(err, check.IsNil) }
func (s *S) TestHealerHealNode(c *check.C) { factory, iaasInst := dockertest.NewHealerIaaSConstructorWithInst("127.0.0.1") iaas.RegisterIaasProvider("my-healer-iaas", factory) _, err := iaas.CreateMachineForIaaS("my-healer-iaas", map[string]string{}) c.Assert(err, check.IsNil) iaasInst.Addr = "localhost" node1, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) node2, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) config.Set("iaas:node-protocol", "http") config.Set("iaas:node-port", dockertest.URLPort(node2.URL())) defer config.Unset("iaas:node-protocol") defer config.Unset("iaas:node-port") p, err := s.newFakeDockerProvisioner(node1.URL()) c.Assert(err, check.IsNil) defer p.Destroy() app := provisiontest.NewFakeApp("myapp", "python", 0) _, err = p.StartContainers(dockertest.StartContainersArgs{ Endpoint: node1.URL(), App: app, Amount: map[string]int{"web": 1}, Image: "tsuru/python", PullImage: true, }) c.Assert(err, check.IsNil) healer := NewNodeHealer(NodeHealerArgs{ Provisioner: p, FailuresBeforeHealing: 1, WaitTimeNewMachine: time.Minute, }) nodes, err := p.Cluster().UnfilteredNodes() c.Assert(err, check.IsNil) c.Assert(nodes, check.HasLen, 1) c.Assert(dockertest.URLPort(nodes[0].Address), check.Equals, dockertest.URLPort(node1.URL())) c.Assert(net.URLToHost(nodes[0].Address), check.Equals, "127.0.0.1") containers := p.AllContainers() c.Assert(err, check.IsNil) c.Assert(containers, check.HasLen, 1) c.Assert(containers[0].HostAddr, check.Equals, "127.0.0.1") machines, err := iaas.ListMachines() c.Assert(err, check.IsNil) c.Assert(machines, check.HasLen, 1) c.Assert(machines[0].Address, check.Equals, "127.0.0.1") nodes[0].Metadata["iaas"] = "my-healer-iaas" created, err := healer.healNode(&nodes[0]) c.Assert(err, check.IsNil) c.Assert(created.Address, check.Equals, fmt.Sprintf("http://localhost:%d", dockertest.URLPort(node2.URL()))) nodes, err = p.Cluster().UnfilteredNodes() c.Assert(err, check.IsNil) c.Assert(nodes, check.HasLen, 1) c.Assert(dockertest.URLPort(nodes[0].Address), check.Equals, dockertest.URLPort(node2.URL())) c.Assert(net.URLToHost(nodes[0].Address), check.Equals, "localhost") machines, err = iaas.ListMachines() c.Assert(err, check.IsNil) c.Assert(machines, check.HasLen, 1) c.Assert(machines[0].Address, check.Equals, "localhost") err = tsurutest.WaitCondition(5*time.Second, func() bool { containers := p.AllContainers() return len(containers) == 1 && containers[0].HostAddr == "localhost" }) c.Assert(err, check.IsNil) }