func addUserToTeam(email, teamName string, u *auth.User) error { conn, err := db.Conn() if err != nil { return err } defer conn.Close() team, user := new(auth.Team), new(auth.User) selector := bson.M{"_id": teamName} if err := conn.Teams().Find(selector).One(team); err != nil { return &errors.Http{Code: http.StatusNotFound, Message: "Team not found"} } if !team.ContainsUser(u) { msg := fmt.Sprintf("You are not authorized to add new users to the team %s", team.Name) return &errors.Http{Code: http.StatusUnauthorized, Message: msg} } if err := conn.Users().Find(bson.M{"email": email}).One(user); err != nil { return &errors.Http{Code: http.StatusNotFound, Message: "User not found"} } actions := []*action.Action{ &addUserToTeamInGandalfAction, &addUserToTeamInDatabaseAction, } pipeline := action.NewPipeline(actions...) return pipeline.Execute(user.Email, u, team) }
// 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 }
// 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, units uint, teams []auth.Team) error { if units == 0 { return &errors.ValidationError{Message: "Cannot create app with 0 units."} } if len(teams) == 0 { return NoTeamsError{} } app.SetTeams(teams) if !app.isValid() { msg := "Invalid app name, your app should have at most 63 " + "characters, containing only lower case letters or numbers, " + "starting with a letter." return &errors.ValidationError{Message: msg} } actions := []*action.Action{&insertApp} useS3, _ := config.GetBool("bucket-support") if useS3 { actions = append(actions, &createIAMUserAction, &createIAMAccessKeyAction, &createBucketAction, &createUserPolicyAction) } actions = append(actions, &exportEnvironmentsAction, &createRepository, &provisionApp, &provisionAddUnits) pipeline := action.NewPipeline(actions...) err := pipeline.Execute(app, units) if err != nil { return &appCreationError{app: app.Name, err: err} } 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 addUserToTeam(w http.ResponseWriter, r *http.Request, t *auth.Token) error { teamName := r.URL.Query().Get(":team") email := r.URL.Query().Get(":user") u, err := t.User() if err != nil { return err } rec.Log(u.Email, "add-user-to-team", "team="+teamName, "user="******"Team not found"} } if !team.ContainsUser(u) { msg := fmt.Sprintf("You are not authorized to add new users to the team %s", team.Name) return &errors.HTTP{Code: http.StatusUnauthorized, Message: msg} } user, err := auth.GetUserByEmail(email) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: "User not found"} } actions := []*action.Action{ &addUserToTeamInGandalfAction, &addUserToTeamInDatabaseAction, } pipeline := action.NewPipeline(actions...) return pipeline.Execute(user.Email, u, team) }
func deploy(app provision.App, version string, w io.Writer) (string, error) { commands, err := deployCmds(app, version) if err != nil { return "", err } imageId := getImage(app) actions := []*action.Action{&createContainer, &startContainer, &insertContainer} pipeline := action.NewPipeline(actions...) err = pipeline.Execute(app, imageId, commands) if err != nil { log.Errorf("error on execute deploy pipeline for app %s - %s", app.GetName(), err) return "", err } c := pipeline.Result().(container) err = c.logs(w) if err != nil { log.Errorf("error on get logs for container %s - %s", c.ID, err) return "", err } _, err = dockerCluster().WaitContainer(c.ID) if err != nil { log.Errorf("Process failed for container %q: %s", c.ID, err) return "", err } imageId, err = c.commit() if err != nil { log.Errorf("error on commit container %s - %s", c.ID, err) return "", err } c.remove() return imageId, nil }
// BindApp makes the bind between the service instance and an app. func (si *ServiceInstance) BindApp(app bind.App) error { actions := []*action.Action{ &addAppToServiceInstance, &setEnvironVariablesToApp, } pipeline := action.NewPipeline(actions...) return pipeline.Execute(app, *si) }
// DeployApp calls the Provisioner.Deploy func DeployApp(app *App, version string, writer io.Writer) error { pipeline := Provisioner.DeployPipeline() if pipeline == nil { actions := []*action.Action{&ProvisionerDeploy, &IncrementDeploy} pipeline = action.NewPipeline(actions...) } logWriter := LogWriter{App: app, Writer: writer} return pipeline.Execute(app, version, &logWriter) }
// AddUnits creates n new units within the provisioner, saves new units in the // database and enqueues the apprc serialization. func (app *App) AddUnits(n uint) error { if n == 0 { return stderr.New("Cannot add zero units.") } return action.NewPipeline( &reserveUnitsToAdd, &provisionAddUnits, &saveNewUnitsInDatabase, ).Execute(app, n) }
func (p *dockerProvisioner) DeployPipeline() *action.Pipeline { actions := []*action.Action{ &app.ProvisionerDeploy, &app.IncrementDeploy, &saveUnits, &injectEnvirons, &bindService, } pipeline := action.NewPipeline(actions...) return pipeline }
// 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 }
// DeployApp calls the Provisioner.Deploy func DeployApp(app *App, version, commit string, writer io.Writer) error { start := time.Now() pipeline := Provisioner.DeployPipeline() if pipeline == nil { actions := []*action.Action{&ProvisionerDeploy, &IncrementDeploy} pipeline = action.NewPipeline(actions...) } logWriter := LogWriter{App: app, Writer: writer} err := pipeline.Execute(app, version, &logWriter) if err != nil { return err } elapsed := time.Since(start) return saveDeployData(app.Name, commit, elapsed) }
// addKeyToUser adds a key to a user in mongodb and send the key to the git server // in order to allow ssh-ing into git server. func addKeyToUser(content string, u *auth.User) error { key := auth.Key{Content: content} if u.HasKey(key) { return &errors.Http{Code: http.StatusConflict, Message: "User already has this key"} } actions := []*action.Action{ &addKeyInGandalfAction, &addKeyInDatabaseAction, } pipeline := action.NewPipeline(actions...) err := pipeline.Execute(&key, u) if err != nil { return err } return nil }
func (p *FakeProvisioner) DeployPipeline() *action.Pipeline { if p.CustomPipeline { act := action.Action{ Name: "change-executed-pipeline", Forward: func(ctx action.FWContext) (action.Result, error) { p.executedPipeline = true return nil, nil }, Backward: func(ctx action.BWContext) { }, } actions := []*action.Action{&act} pipeline := action.NewPipeline(actions...) return pipeline } return nil }
// AddKeyToUser adds a key to a user. // // This function is just an http wrapper around addKeyToUser. The latter function // exists to be used in other places in the package without the http stuff (request and // response). func addKeyToUser(w http.ResponseWriter, r *http.Request, t *auth.Token) error { content, err := getKeyFromBody(r.Body) if err != nil { return err } u, err := t.User() if err != nil { return err } rec.Log(u.Email, "add-key", content) key := auth.Key{Content: content} if u.HasKey(key) { return &errors.HTTP{Code: http.StatusConflict, Message: "User already has this key"} } actions := []*action.Action{ &addKeyInGandalfAction, &addKeyInDatabaseAction, } pipeline := action.NewPipeline(actions...) return pipeline.Execute(&key, u) }
func deploy(app provision.App, version string, w io.Writer) (string, error) { commands, err := deployCmds(app, version) if err != nil { return "", err } imageId := getImage(app) actions := []*action.Action{&createContainer, &startContainer, &insertContainer} pipeline := action.NewPipeline(actions...) err = pipeline.Execute(app, imageId, commands) if err != nil { log.Printf("error on execute deploy pipeline for app %s - %s", app.GetName(), err.Error()) return "", err } c := pipeline.Result().(container) for { result, err := c.stopped() if err != nil { log.Printf("error on stopped for container %s - %s", c.ID, err.Error()) return "", err } if result { break } } err = c.logs(w) if err != nil { log.Printf("error on get logs for container %s - %s", c.ID, err.Error()) return "", err } imageId, err = c.commit() if err != nil { log.Printf("error on commit container %s - %s", c.ID, err.Error()) return "", err } c.remove() // if err != nil { // return "", err // } return imageId, nil }
func start(app provision.App, imageId string, w io.Writer) (*container, error) { commands, err := runCmds() if err != nil { return nil, err } actions := []*action.Action{&createContainer, &startContainer, &setNetworkInfo, &insertContainer, &addRoute} pipeline := action.NewPipeline(actions...) err = pipeline.Execute(app, imageId, commands) if err != nil { return nil, err } c := pipeline.Result().(container) err = c.setImage(imageId) if err != nil { return nil, err } err = c.setStatus("running") if err != nil { return nil, err } return &c, nil }