func generateAppToken(w http.ResponseWriter, r *http.Request, t *auth.Token) error { var body jToken defer r.Body.Close() err := json.NewDecoder(r.Body).Decode(&body) if err != nil { return err } if body.Client == "" { return &errors.HTTP{ Code: http.StatusBadRequest, Message: "Missing client name in JSON body", } } token, err := auth.CreateApplicationToken(body.Client) if err != nil { return err } if body.Export { a := app.App{Name: body.Client} if err := a.Get(); err == nil { envs := []bind.EnvVar{ { Name: "TSURU_APP_TOKEN", Value: token.Token, Public: false, }, } a.SetEnvs(envs, false) } } return json.NewEncoder(w).Encode(token) }
func (s *ELBSuite) TestELBInstanceHealerInstallingUnit(c *gocheck.C) { lb := "elbtest" instance := s.server.NewInstance() defer s.server.RemoveInstance(instance) s.server.NewLoadBalancer(lb) defer s.server.RemoveLoadBalancer(lb) s.server.RegisterInstance(instance, lb) defer s.server.DeregisterInstance(instance, lb) a := app.App{ Name: "elbtest", Units: []app.Unit{{InstanceId: instance, State: "installing", Name: "elbtest/0"}}, } storage, err := db.Conn() c.Assert(err, gocheck.IsNil) err = storage.Apps().Insert(a) c.Assert(err, gocheck.IsNil) defer storage.Apps().Remove(bson.M{"name": a.Name}) s.provisioner.Provision(&a) defer s.provisioner.Destroy(&a) state := elb.InstanceState{ Description: "Instance has failed at least the UnhealthyThreshold number of health checks consecutively.", State: "OutOfService", ReasonCode: "Instance", InstanceId: instance, } s.server.ChangeInstanceState(lb, state) healer := elbInstanceHealer{} err = healer.Heal() c.Assert(err, gocheck.IsNil) err = a.Get() c.Assert(err, gocheck.IsNil) c.Assert(a.Units, gocheck.HasLen, 1) c.Assert(a.Units[0].InstanceId, gocheck.Equals, instance) }
func (s *S) TestUnbindRemovesEnvironmentVariableFromApp(c *gocheck.C) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) })) defer ts.Close() srvc := service.Service{Name: "mysql", Endpoint: map[string]string{"production": ts.URL}} err := srvc.Create() c.Assert(err, gocheck.IsNil) defer s.conn.Services().Remove(bson.M{"_id": "mysql"}) instance := service.ServiceInstance{ Name: "my-mysql", ServiceName: "mysql", Teams: []string{s.team.Name}, Apps: []string{"painkiller"}, } err = instance.Create() c.Assert(err, gocheck.IsNil) defer s.conn.ServiceInstances().Remove(bson.M{"_id": "my-mysql"}) a := app.App{ Name: "painkiller", Teams: []string{s.team.Name}, Env: map[string]bind.EnvVar{ "DATABASE_HOST": { Name: "DATABASE_HOST", Value: "arrea", Public: false, InstanceName: instance.Name, }, "MY_VAR": { Name: "MY_VAR", Value: "123", }, }, Units: []app.Unit{ { Ip: "10.10.10.10", }, }, } err = s.conn.Apps().Insert(&a) c.Assert(err, gocheck.IsNil) defer s.conn.Apps().Remove(bson.M{"name": a.Name}) err = instance.UnbindApp(&a) c.Assert(err, gocheck.IsNil) newApp := app.App{Name: a.Name} err = newApp.Get() c.Assert(err, gocheck.IsNil) expected := map[string]bind.EnvVar{ "MY_VAR": { Name: "MY_VAR", Value: "123", }, } c.Assert(a.Env, gocheck.DeepEquals, expected) }
func (s segregatedScheduler) Schedule(cfg *docker.Config) (string, *docker.Container, error) { image := cfg.Image namespace, err := config.GetString("docker:repository-namespace") if err != nil { return "", nil, err } conn, err := db.Conn() if err != nil { return "", nil, err } defer conn.Close() appname := strings.Replace(image, namespace+"/", "", -1) app := app.App{Name: appname} err = app.Get() if err != nil { return s.fallback(cfg) } if len(app.Teams) == 1 { var nodes []node err = conn.Collection(schedulerCollection).Find(bson.M{"team": app.Teams[0]}).All(&nodes) if err != nil || len(nodes) < 1 { return s.fallback(cfg) } return s.handle(cfg, nodes) } return s.fallback(cfg) }
func (s *S) TestSaveUnitsForward(c *gocheck.C) { app := app.App{ Name: "otherapp", Platform: "zend", } conn, err := db.Conn() c.Assert(err, gocheck.IsNil) defer conn.Close() err = conn.Apps().Insert(app) c.Assert(err, gocheck.IsNil) defer conn.Apps().Remove(bson.M{"name": app.Name}) container := container{ ID: "id", Type: "python", HostAddr: "", AppName: app.Name, } coll := collection() c.Assert(err, gocheck.IsNil) coll.Insert(&container) context := action.FWContext{Params: []interface{}{&app}} _, err = saveUnits.Forward(context) c.Assert(err, gocheck.IsNil) err = app.Get() c.Assert(err, gocheck.IsNil) c.Assert(app.Units[0].Name, gocheck.Equals, "id") }
func (s segregatedScheduler) Schedule(opts dcli.CreateContainerOptions, cfg *docker.Config) (string, *docker.Container, error) { conn, err := db.Conn() if err != nil { return "", nil, err } defer conn.Close() var cont container coll := collection() defer coll.Close() err = coll.Find(bson.M{"name": opts.Name}).One(&cont) if err != nil { return "", nil, err } app := app.App{Name: cont.AppName} err = app.Get() if err != nil { return s.fallback(opts, cfg) } var nodes []node query := bson.M{"teams": bson.M{"$in": app.Teams}} err = conn.Collection(schedulerCollection).Find(query).All(&nodes) if err != nil || len(nodes) < 1 { return s.fallback(opts, cfg) } return s.handle(opts, cfg, nodes) }
func addLog(w http.ResponseWriter, r *http.Request, t *auth.Token) error { queryValues := r.URL.Query() app := app.App{Name: queryValues.Get(":app")} err := app.Get() if err != nil { return err } defer r.Body.Close() body, err := ioutil.ReadAll(r.Body) if err != nil { return err } var logs []string err = json.Unmarshal(body, &logs) source := queryValues.Get("source") if len(source) == 0 { source = "app" } for _, log := range logs { err := app.Log(log, source) if err != nil { return err } } w.WriteHeader(http.StatusOK) return nil }
func (s *S) TestUpdateWithMultipleApps(c *gocheck.C) { appDicts := []map[string]string{ { "name": "andrewzito3", "ip": "10.10.10.163", }, { "name": "flaviapp", "ip": "10.10.10.208", }, { "name": "mysqlapi", "ip": "10.10.10.131", }, { "name": "teste_api_semantica", "ip": "10.10.10.189", }, { "name": "xikin", "ip": "10.10.10.168", }, } apps := make([]app.App, len(appDicts)) units := make([]provision.Unit, len(appDicts)) for i, appDict := range appDicts { a := app.App{Name: appDict["name"]} err := s.conn.Apps().Insert(&a) c.Assert(err, gocheck.IsNil) apps[i] = a units[i] = provision.Unit{ Name: "i-00000", AppName: appDict["name"], Machine: i + 1, Type: "python", Ip: appDict["ip"], Status: provision.StatusInstalling, } } update(units) for _, appDict := range appDicts { a := app.App{Name: appDict["name"]} err := a.Get() c.Assert(err, gocheck.IsNil) c.Assert(a.Units[0].Ip, gocheck.Equals, appDict["ip"]) } }
func (s *S) TestUpdateWithDownMachine(c *gocheck.C) { a := app.App{Name: "barduscoapp"} err := s.conn.Apps().Insert(&a) c.Assert(err, gocheck.IsNil) units := []provision.Unit{ { Name: "i-00000zz8", AppName: "barduscoapp", Type: "python", Machine: 2, Ip: "", Status: provision.StatusPending, }, } update(units) err = a.Get() c.Assert(err, gocheck.IsNil) }
func (s *S) TestUpdateWithDownMachine(c *C) { a := app.App{Name: "barduscoapp"} err := db.Session.Apps().Insert(&a) c.Assert(err, IsNil) units := []provision.Unit{ { Name: "i-00000zz8", AppName: "barduscoapp", Type: "python", Machine: 2, Ip: "", Status: provision.StatusPending, }, } update(units) err = a.Get() c.Assert(err, IsNil) c.Assert(a.State, Equals, string(provision.StatusPending)) }
func getAppOrError(name string, u *auth.User) (app.App, error) { app := app.App{Name: name} err := app.Get() if err != nil { return app, &errors.Http{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", name)} } if !auth.CheckUserAccess(app.Teams, u) { return app, &errors.Http{Code: http.StatusForbidden, Message: "User does not have access to this app"} } return app, nil }
func (s *S) TestBindCallTheServiceAPIAndSetsEnvironmentVariableReturnedFromTheCall(c *gocheck.C) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"DATABASE_USER":"******","DATABASE_PASSWORD":"******"}`)) })) defer ts.Close() srvc := service.Service{Name: "mysql", Endpoint: map[string]string{"production": ts.URL}} err := srvc.Create() c.Assert(err, gocheck.IsNil) defer s.conn.Services().Remove(bson.M{"_id": "mysql"}) instance := service.ServiceInstance{ Name: "my-mysql", ServiceName: "mysql", Teams: []string{s.team.Name}, } err = instance.Create() c.Assert(err, gocheck.IsNil) defer s.conn.ServiceInstances().Remove(bson.M{"_id": "my-mysql"}) a, err := createTestApp(s.conn, "painkiller", "", []string{s.team.Name}, []app.Unit{{Ip: "127.0.0.1"}}) c.Assert(err, gocheck.IsNil) defer s.conn.Apps().Remove(bson.M{"name": a.Name}) err = instance.BindApp(&a) c.Assert(err, gocheck.IsNil) newApp := app.App{Name: a.Name} err = newApp.Get() c.Assert(err, gocheck.IsNil) expectedEnv := map[string]bind.EnvVar{ "DATABASE_USER": { Name: "DATABASE_USER", Value: "root", Public: false, InstanceName: instance.Name, }, "DATABASE_PASSWORD": { Name: "DATABASE_PASSWORD", Value: "s3cr3t", Public: false, InstanceName: instance.Name, }, } c.Assert(a.Env, gocheck.DeepEquals, expectedEnv) }
func appIsAvailable(w http.ResponseWriter, r *http.Request, t *auth.Token) error { app := app.App{Name: r.URL.Query().Get(":appname")} err := app.Get() if err != nil { return err } if !app.Available() { return fmt.Errorf("App must be available to receive pushs.") } w.WriteHeader(http.StatusOK) return nil }
// AppIsAvaliableHandler verify if the app.Unit().State() is // started. If is started it returns 200 else returns 500 for // status code. func AppIsAvaliableHandler(w http.ResponseWriter, r *http.Request) error { app := app.App{Name: r.URL.Query().Get(":name")} err := app.Get() if err != nil { return err } if app.State != "started" { return fmt.Errorf("App must be started to receive pushs, but it is %q.", app.State) } w.WriteHeader(http.StatusOK) return nil }
func CloneRepositoryHandler(w http.ResponseWriter, r *http.Request) error { w.Header().Set("Content-Type", "text") instance := app.App{Name: r.URL.Query().Get(":name")} err := instance.Get() logWriter := LogWriter{&instance, w} if err != nil { return &errors.Http{Code: http.StatusNotFound, Message: fmt.Sprintf("App %s not found.", instance.Name)} } err = write(&logWriter, []byte("\n ---> Tsuru receiving push\n")) if err != nil { return err } err = write(&logWriter, []byte("\n ---> Replicating the application repository across units\n")) if err != nil { return err } out, err := repository.CloneOrPull(&instance) // should iterate over the machines if err != nil { return &errors.Http{Code: http.StatusInternalServerError, Message: string(out)} } err = write(&logWriter, out) if err != nil { return err } err = write(&logWriter, []byte("\n ---> Installing dependencies\n")) if err != nil { return err } err = instance.InstallDeps(&logWriter) if err != nil { return err } err = instance.Restart(&logWriter) if err != nil { return err } return write(&logWriter, []byte("\n ---> Deploy done!\n\n")) }
func ensureAppIsStarted(msg *queue.Message) (app.App, error) { a := app.App{Name: msg.Args[0]} err := a.Get() if err != nil { return a, fmt.Errorf("Error handling %q: app %q does not exist.", msg.Action, a.Name) } units := getUnits(&a, msg.Args[1:]) if a.State != "started" || !units.Started() { format := "Error handling %q for the app %q:" switch a.State { case "error": format += " the app is in %q state." queue.Delete(msg) case "down": format += " the app is %s." queue.Delete(msg) default: format += ` The status of the app and all units should be "started" (the app is %q).` } return a, fmt.Errorf(format, msg.Action, a.Name, a.State) } return a, nil }
func (h *MessageHandler) ensureAppIsStarted(msg queue.Message) (app.App, error) { a := app.App{Name: msg.Args[0]} err := a.Get() if err != nil { return a, fmt.Errorf("Error handling %q: app %q does not exist.", msg.Action, a.Name) } units := h.getUnits(&a, msg.Args[1:]) if a.State != "started" || !units.Started() { format := "Error handling %q for the app %q:" switch a.State { case "error": format += " the app is in %q state." case "down": format += " the app is %s." default: format += ` The status of the app and all units should be "started" (the app is %q).` time.Sleep(time.Duration(msg.Visits+1) * time.Second) h.server.PutBack(msg) } return a, fmt.Errorf(format, msg.Action, a.Name, a.State) } return a, nil }
func AddLogHandler(w http.ResponseWriter, r *http.Request) error { app := app.App{Name: r.URL.Query().Get(":name")} err := app.Get() if err != nil { return err } defer r.Body.Close() body, err := ioutil.ReadAll(r.Body) if err != nil { return err } var logs []string err = json.Unmarshal(body, &logs) for _, log := range logs { err := app.Log(log, "app") if err != nil { return err } } w.WriteHeader(http.StatusOK) return nil }