func ListTeams(w http.ResponseWriter, r *http.Request, u *auth.User) error { teams, err := u.Teams() if err != nil { return err } if len(teams) > 0 { var result []map[string]string for _, team := range teams { result = append(result, map[string]string{"name": team.Name}) } b, err := json.Marshal(result) if err != nil { return err } n, err := w.Write(b) if err != nil { return err } if n != len(b) { return &errors.Http{Code: http.StatusInternalServerError, Message: "Failed to write response body."} } } else { w.WriteHeader(http.StatusNoContent) } return nil }
func CreateServiceInstance(name string, service *Service, plan *Plan, user *auth.User) error { err := validateServiceInstanceName(name) if err != nil { return err } instance := ServiceInstance{ Name: name, ServiceName: service.Name, } if plan != nil { instance.PlanName = plan.Name } teams, err := user.Teams() if err != nil { return err } instance.Teams = make([]string, 0, len(teams)) for _, team := range teams { if service.HasTeam(&team) || !service.IsRestricted { instance.Teams = append(instance.Teams, team.Name) } } actions := []*action.Action{&createServiceInstance, &insertServiceInstance} pipeline := action.NewPipeline(actions...) return pipeline.Execute(*service, instance) }
func ServiceInfoHandler(w http.ResponseWriter, r *http.Request, u *auth.User) error { serviceName := r.URL.Query().Get(":name") _, err := getServiceOrError(serviceName, u) if err != nil { return err } instances := []service.ServiceInstance{} teams, err := u.Teams() if err != nil { return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() teamsNames := auth.GetTeamsNames(teams) q := bson.M{"service_name": serviceName, "teams": bson.M{"$in": teamsNames}} err = conn.ServiceInstances().Find(q).All(&instances) if err != nil { return err } b, err := json.Marshal(instances) if err != nil { return nil } w.Write(b) return nil }
// CreateApp creates a new app. // // Creating a new app is a process composed of four steps: // // 1. Save the app in the database // 2. Create IAM credentials for the app // 3. Create S3 bucket for the app (if the bucket support is enabled) // 4. Create the git repository using gandalf // 5. Provision units within the provisioner func CreateApp(app *App, user *auth.User) error { teams, err := user.Teams() if err != nil { return err } if len(teams) == 0 { return NoTeamsError{} } if _, err := getPlatform(app.Platform); err != nil { return err } app.SetTeams(teams) app.Owner = user.Email if !app.isValid() { msg := "Invalid app name, your app should have at most 63 " + "characters, containing only lower case letters, numbers or dashes, " + "starting with a letter." return &errors.ValidationError{Message: msg} } actions := []*action.Action{&reserveUserApp, &createAppQuota, &insertApp} useS3, _ := config.GetBool("bucket-support") if useS3 { actions = append(actions, &createIAMUserAction, &createIAMAccessKeyAction, &createBucketAction, &createUserPolicyAction) } actions = append(actions, &exportEnvironmentsAction, &createRepository, &provisionApp) pipeline := action.NewPipeline(actions...) err = pipeline.Execute(app, user) if err != nil { return &AppCreationError{app: app.Name, Err: err} } return nil }
func getTeamNames(u *auth.User) ([]string, error) { var ( teams []auth.Team err error ) if teams, err = u.Teams(); err != nil { return nil, err } return auth.GetTeamsNames(teams), nil }
// CreateApp creates a new app. // // Creating a new app is a process composed of four steps: // // 1. Save the app in the database // 2. Create IAM credentials for the app // 3. Create S3 bucket for the app (if the bucket support is enabled) // 4. Create the git repository using gandalf // 5. Provision units within the provisioner func CreateApp(app *App, user *auth.User) error { teams, err := user.Teams() if err != nil { return err } if len(teams) == 0 { return NoTeamsError{} } if _, err := getPlatform(app.Platform); err != nil { return err } // app.Memory is empty, no custom memory passed from CLI if app.Memory < 1 { // get default memory limit from tsuru config configMemory, err := config.GetInt("docker:memory") if err != nil { // no default memory set in config (or error when reading), set it as unlimited (0) app.Memory = 0 } else { // default memory set in config, use that. app.Memory = configMemory } } if err := app.setTeamOwner(teams); err != nil { return err } app.SetTeams(teams) app.Owner = user.Email if !app.isValid() { msg := "Invalid app name, your app should have at most 63 " + "characters, containing only lower case letters, numbers or dashes, " + "starting with a letter." return &errors.ValidationError{Message: msg} } actions := []*action.Action{&reserveUserApp, &insertApp} useS3, _ := config.GetBool("bucket-support") if useS3 { actions = append(actions, &createIAMUserAction, &createIAMAccessKeyAction, &createBucketAction, &createUserPolicyAction) } actions = append(actions, &exportEnvironmentsAction, &createRepository, &provisionApp) pipeline := action.NewPipeline(actions...) err = pipeline.Execute(app, user) if err != nil { return &AppCreationError{app: app.Name, Err: err} } return nil }
func CreateInstanceHandler(w http.ResponseWriter, r *http.Request, u *auth.User) error { log.Print("Receiving request to create a service instance") b, err := ioutil.ReadAll(r.Body) if err != nil { log.Print("Got error while reading request body:") log.Print(err.Error()) return &errors.Http{Code: http.StatusInternalServerError, Message: err.Error()} } var sJson map[string]string err = json.Unmarshal(b, &sJson) if err != nil { log.Print("Got a problem while unmarshalling request's json:") log.Print(err.Error()) return &errors.Http{Code: http.StatusInternalServerError, Message: err.Error()} } var s service.Service err = validateInstanceForCreation(&s, sJson, u) if err != nil { log.Print("Got error while validation:") log.Print(err.Error()) return err } var teamNames []string teams, err := u.Teams() if err != nil { return err } for _, t := range teams { if s.HasTeam(&t) || !s.IsRestricted { teamNames = append(teamNames, t.Name) } } si := service.ServiceInstance{ Name: sJson["name"], ServiceName: sJson["service_name"], Teams: teamNames, } if err = s.ProductionEndpoint().Create(&si); err != nil { log.Print("Error while calling create action from service api.") log.Print(err.Error()) return err } err = si.Create() if err != nil { return err } fmt.Fprint(w, "success") return nil }
func GetServicesByOwnerTeams(teamKind string, u *auth.User) ([]Service, error) { teams, err := u.Teams() if err != nil { return nil, err } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() teamsNames := auth.GetTeamsNames(teams) q := bson.M{teamKind: bson.M{"$in": teamsNames}} var services []Service err = conn.Services().Find(q).All(&services) return services, err }
func CreateAppHandler(w http.ResponseWriter, r *http.Request, u *auth.User) error { var a app.App var japp jsonApp defer r.Body.Close() body, err := ioutil.ReadAll(r.Body) if err != nil { return err } if err = json.Unmarshal(body, &japp); err != nil { return err } a.Name = japp.Name a.Framework = japp.Framework if japp.Units == 0 { japp.Units = 1 } teams, err := u.Teams() if err != nil { return err } if len(teams) < 1 { msg := "In order to create an app, you should be member of at least one team" return &errors.Http{Code: http.StatusForbidden, Message: msg} } err = app.CreateApp(&a, japp.Units, teams) if err != nil { log.Printf("Got error while creating app: %s", err) if e, ok := err.(*errors.ValidationError); ok { return &errors.Http{Code: http.StatusPreconditionFailed, Message: e.Message} } if strings.Contains(err.Error(), "key error") { msg := fmt.Sprintf(`There is already an app named "%s".`, a.Name) return &errors.Http{Code: http.StatusConflict, Message: msg} } return err } msg := map[string]string{ "status": "success", "repository_url": repository.GetUrl(a.Name), } jsonMsg, err := json.Marshal(msg) if err != nil { return err } fmt.Fprintf(w, "%s", jsonMsg) return nil }
func GetServiceInstancesByServicesAndTeams(services []Service, u *auth.User) ([]ServiceInstance, error) { var instances []ServiceInstance teams, err := u.Teams() if err != nil { return nil, err } if len(teams) == 0 { return nil, nil } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() q, f := genericServiceInstancesFilter(services, auth.GetTeamsNames(teams)) err = conn.ServiceInstances().Find(q).Select(f).All(&instances) return instances, err }
// RemoveUser removes the user from the database and from gandalf server // // In order to successfuly remove a user, it's need that he/she is not the only // one in a team, otherwise the function will return an error. func RemoveUser(w http.ResponseWriter, r *http.Request, u *auth.User) error { gUrl := repository.GitServerUri() c := gandalf.Client{Endpoint: gUrl} alwdApps, err := u.AllowedApps() if err != nil { return err } if err := c.RevokeAccess(alwdApps, []string{u.Email}); err != nil { log.Printf("Failed to revoke access in Gandalf: %s", err) return fmt.Errorf("Failed to revoke acess from git repositories: %s", err) } teams, err := u.Teams() if err != nil { return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() for _, team := range teams { if len(team.Users) < 2 { msg := fmt.Sprintf(`This user is the last member of the team "%s", so it cannot be removed. Please remove the team, them remove the user.`, team.Name) return &errors.Http{Code: http.StatusForbidden, Message: msg} } err = team.RemoveUser(u) if err != nil { return err } // this can be done without the loop err = conn.Teams().Update(bson.M{"_id": team.Name}, team) if err != nil { return err } } if err := c.RemoveUser(u.Email); err != nil { log.Printf("Failed to remove user from gandalf: %s", err) return fmt.Errorf("Failed to remove the user from the git server: %s", err) } return conn.Users().Remove(bson.M{"email": u.Email}) }
func GetServicesByTeamKindAndNoRestriction(teamKind string, u *auth.User) ([]Service, error) { teams, err := u.Teams() if err != nil { return nil, err } conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() teamsNames := auth.GetTeamsNames(teams) q := bson.M{"$or": []bson.M{ {teamKind: bson.M{"$in": teamsNames}}, {"is_restricted": false}, }} var services []Service err = conn.Services().Find(q).Select(bson.M{"name": 1}).All(&services) return services, err }
func CreateServiceInstance(name string, service *Service, user *auth.User) error { if !instanceNameRegexp.MatchString(name) { return ErrInvalidInstanceName } instance := ServiceInstance{ Name: name, ServiceName: service.Name, } teams, err := user.Teams() if err != nil { return err } instance.Teams = make([]string, 0, len(teams)) for _, team := range teams { if service.HasTeam(&team) || !service.IsRestricted { instance.Teams = append(instance.Teams, team.Name) } } endpoint, err := service.getClient("production") if err != nil { return err } err = endpoint.Create(&instance) if err != nil { return err } conn, err := db.Conn() if err != nil { endpoint.Destroy(&instance) return err } defer conn.Close() err = conn.ServiceInstances().Insert(instance) if err != nil { endpoint.Destroy(&instance) return err } return nil }
// List returns the list of apps that the given user has access to. // // If the user does not have acces to any app, this function returns an empty // list and a nil error. func List(u *auth.User) ([]App, error) { var apps []App conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() if u.IsAdmin() { if err := conn.Apps().Find(nil).All(&apps); err != nil { return []App{}, err } return apps, nil } ts, err := u.Teams() if err != nil { return []App{}, err } teams := auth.GetTeamsNames(ts) if err := conn.Apps().Find(bson.M{"teams": bson.M{"$in": teams}}).All(&apps); err != nil { return []App{}, err } return apps, nil }
func CreateInstanceHandler(w http.ResponseWriter, r *http.Request, u *auth.User) error { b, err := ioutil.ReadAll(r.Body) if err != nil { return err } var sJson map[string]string err = json.Unmarshal(b, &sJson) if err != nil { return err } var s service.Service err = validateInstanceForCreation(&s, sJson, u) if err != nil { return err } var teamNames []string teams, err := u.Teams() if err != nil { return err } for _, t := range teams { if s.HasTeam(&t) || !s.IsRestricted { teamNames = append(teamNames, t.Name) } } si := service.ServiceInstance{ Name: sJson["name"], ServiceName: sJson["service_name"], Teams: teamNames, } err = service.CreateInstance(&si) if err != nil { return err } fmt.Fprint(w, "success") return nil }