// CreateApp creates a new app. // // Creating a new app is a process composed of the following steps: // // 1. Save the app in the database // 2. Create the git repository using the repository manager // 3. Provision the app using 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{} } platform, err := getPlatform(app.Platform) if err != nil { return err } if platform.Disabled && !user.IsAdmin() { return InvalidPlatformError{} } var plan *Plan if app.Plan.Name == "" { plan, err = DefaultPlan() } else { plan, err = findPlanByName(app.Plan.Name) } if err != nil { return err } if app.TeamOwner == "" { if len(teams) > 1 { return ManyTeamsError{} } app.TeamOwner = teams[0].Name } err = app.ValidateTeamOwner(user) if err != nil { return err } app.Plan = *plan err = app.SetPool() if err != nil { return err } app.Teams = []string{app.TeamOwner} app.Owner = user.Email err = app.validate() if err != nil { return err } actions := []*action.Action{ &reserveUserApp, &insertApp, &exportEnvironmentsAction, &createRepository, &provisionApp, &setAppIp, } pipeline := action.NewPipeline(actions...) err = pipeline.Execute(app, user) if err != nil { return &AppCreationError{app: app.Name, Err: err} } return nil }
func GetServiceInstancesByServicesAndTeams(services []Service, u *auth.User, appName string) ([]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() var teamNames []string if !u.IsAdmin() { teamNames = auth.GetTeamsNames(teams) } query := genericServiceInstancesFilter(services, teamNames) if appName != "" { query["apps"] = appName } err = conn.ServiceInstances().Find(query).All(&instances) return instances, err }
// List returns the list of apps that the given user has access to. // // If the user does not have access to any app, this function returns an empty // list and a nil error. // // The list can be filtered through the filter parameter. func List(u *auth.User, filter *Filter) ([]App, error) { var apps []App conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() query := filter.Query() if u == nil || u.IsAdmin() { if err = conn.Apps().Find(query).All(&apps); err != nil { return []App{}, err } return apps, nil } ts, err := u.Teams() if err != nil { return []App{}, err } teams := auth.GetTeamsNames(ts) query["teams"] = bson.M{"$in": teams} if err := conn.Apps().Find(query).All(&apps); err != nil { return []App{}, err } return apps, 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 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 }
func (app *App) ValidateTeamOwner(user *auth.User) error { if _, err := auth.GetTeam(app.TeamOwner); err == auth.ErrTeamNotFound { return err } if user.IsAdmin() { return nil } teams, err := user.Teams() if err != nil { return err } for _, t := range teams { if t.Name == app.TeamOwner { return nil } } errorMsg := fmt.Sprintf("You can not set %s team as app's owner. Please set one of your teams as app's owner.", app.TeamOwner) return stderr.New(errorMsg) }
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 }
// 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 CreateServiceInstance(instance ServiceInstance, service *Service, user *auth.User) error { err := validateServiceInstanceName(service.Name, instance.Name) if err != nil { return err } instance.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) } } if instance.TeamOwner == "" { if len(instance.Teams) > 1 { return ErrMultipleTeams } instance.TeamOwner = instance.Teams[0] } else { var found bool for _, team := range instance.Teams { if instance.TeamOwner == team { found = true break } } if !found { return auth.ErrTeamNotFound } } actions := []*action.Action{&createServiceInstance, &insertServiceInstance} pipeline := action.NewPipeline(actions...) return pipeline.Execute(*service, instance, user.Email) }
func CreateServiceInstance(name string, service *Service, planName string, user *auth.User) error { err := validateServiceInstanceName(name) if err != nil { return err } instance := ServiceInstance{ Name: name, ServiceName: service.Name, } instance.PlanName = planName 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) }
// 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 the git repository using gandalf // 4. 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 } } // app.Swap is empty, no custom swap passed from CLI if app.Swap < 1 { // get default swap limit from tsuru config configSwap, err := config.GetInt("docker:swap") if err != nil { // no default swap set in config (or error when reading), set it as unlimited (0) app.Swap = 0 } else { // default swap set in config, use that. app.Swap = configSwap } } // Swap size must always be the sum of memory plus swap if app.Swap > 0 { app.Swap = app.Memory + app.Swap } 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} } if app.equalAppNameAndPlatformName() { msg := "Invalid app name: platform name and app name " + "can not be the same" return &errors.ValidationError{Message: msg} } if app.equalToSomePlatformName() { msg := "Invalid app name: platform name already exists " + "with the same name" return &errors.ValidationError{Message: msg} } actions := []*action.Action{ &reserveUserApp, &insertApp, &exportEnvironmentsAction, &createRepository, &provisionApp, } pipeline := action.NewPipeline(actions...) err = pipeline.Execute(app, user) if err != nil { return &AppCreationError{app: app.Name, Err: err} } return nil }