func (app *App) RemoveCName(cnames ...string) error { var err error var cnamesDone []string for _, cname := range cnames { count := 0 for _, appCname := range app.CName { if cname == appCname { count += 1 } } if count == 0 { err = stderr.New("cname not exists!") break } if s, ok := Provisioner.(provision.CNameManager); ok { err = s.UnsetCName(app, cname) if err != nil { break } } var conn *db.Storage conn, err = db.Conn() if err != nil { break } defer conn.Close() err = conn.Apps().Update( bson.M{"name": app.Name}, bson.M{"$pull": bson.M{"cname": cname}}, ) if err != nil { break } cnamesDone = append(cnamesDone, cname) } if err != nil { var rollback rollbackFunc if s, ok := Provisioner.(provision.CNameManager); ok { rollback = s.SetCName } app.rollbackCNames(rollback, cnamesDone, "$push") return err } return nil }
// AddCName adds a CName to app. It updates the attribute, // calls the SetCName function on the provisioner and saves // the app in the database, returning an error when it cannot save the change // in the database or add the CName on the provisioner. func (app *App) AddCName(cnames ...string) error { var cnamesDone []string var err error for _, cname := range cnames { if !cnameRegexp.MatchString(cname) { err = stderr.New("Invalid cname") break } if cnameExists(cname) { err = stderr.New("cname already exists!") break } if s, ok := Provisioner.(provision.CNameManager); ok { err = s.SetCName(app, cname) if err != nil { break } } var conn *db.Storage conn, err = db.Conn() if err != nil { break } defer conn.Close() err = conn.Apps().Update( bson.M{"name": app.Name}, bson.M{"$push": bson.M{"cname": cname}}, ) if err != nil { break } cnamesDone = append(cnamesDone, cname) } if err != nil { var rollback rollbackFunc if s, ok := Provisioner.(provision.CNameManager); ok { rollback = s.UnsetCName } app.rollbackCNames(rollback, cnamesDone, "$pull") return err } app.CName = append(app.CName, cnamesDone...) return nil }
func (app *App) RebuildRoutes() (*RebuildRoutesResult, error) { routerName, err := app.GetRouter() if err != nil { return nil, err } r, err := router.Get(routerName) if err != nil { return nil, err } err = r.AddBackend(app.Name) if err != nil && err != router.ErrBackendExists { return nil, err } var newAddr string if newAddr, err = r.Addr(app.GetName()); err == nil && newAddr != app.Ip { var conn *db.Storage conn, err = db.Conn() if err != nil { return nil, err } defer conn.Close() err = conn.Apps().Update(bson.M{"name": app.Name}, bson.M{"$set": bson.M{"ip": newAddr}}) if err != nil { return nil, err } } for _, cname := range app.CName { err := r.SetCName(cname, app.Name) if err != nil && err != router.ErrCNameExists { return nil, err } } oldRoutes, err := r.Routes(app.GetName()) if err != nil { return nil, err } expectedMap := make(map[string]*url.URL) units, err := Provisioner.RoutableUnits(app) if err != nil { return nil, err } for _, unit := range units { expectedMap[unit.Address.String()] = unit.Address } var toRemove []*url.URL for _, url := range oldRoutes { if _, isPresent := expectedMap[url.String()]; isPresent { delete(expectedMap, url.String()) } else { toRemove = append(toRemove, url) } } var result RebuildRoutesResult for _, toAddUrl := range expectedMap { err := r.AddRoute(app.GetName(), toAddUrl) if err != nil { return nil, err } result.Added = append(result.Added, toAddUrl.String()) } for _, toRemoveUrl := range toRemove { err := r.RemoveRoute(app.GetName(), toRemoveUrl) if err != nil { return nil, err } result.Removed = append(result.Removed, toRemoveUrl.String()) } return &result, nil }
func (p *FakeProvisioner) Restart(app provision.App, process string, w io.Writer) error { if err := p.getError("Restart"); err != nil { return err } p.mut.Lock() defer p.mut.Unlock() pApp, ok := p.apps[app.GetName()] if !ok { return errNotProvisioned } pApp.restarts[process]++ p.apps[app.GetName()] = pApp if w != nil { fmt.Fprintf(w, "restarting app") } r := routertest.FakeRouter err := r.AddBackend(app.GetName()) if err != nil && err != router.ErrBackendExists { return err } var newAddr string if newAddr, err = r.Addr(app.GetName()); err == nil && newAddr != app.GetIp() { var conn *db.Storage conn, err = db.Conn() if err != nil { return err } defer conn.Close() err = conn.Apps().Update(bson.M{"name": app.GetName()}, bson.M{"$set": bson.M{"ip": newAddr}}) if err != nil { return err } } for _, cname := range app.GetCname() { err = r.SetCName(cname, app.GetName()) if err != nil && err != router.ErrCNameExists { return err } } oldRoutes, err := r.Routes(app.GetName()) if err != nil { return err } expectedMap := make(map[string]*url.URL) units := p.apps[app.GetName()].units if err != nil { return err } for _, unit := range units { expectedMap[unit.Address.String()] = unit.Address } var toRemove []*url.URL for _, url := range oldRoutes { if _, isPresent := expectedMap[url.String()]; isPresent { delete(expectedMap, url.String()) } else { toRemove = append(toRemove, url) } } for _, toAddUrl := range expectedMap { err := r.AddRoute(app.GetName(), toAddUrl) if err != nil { return err } } for _, toRemoveUrl := range toRemove { err := r.RemoveRoute(app.GetName(), toRemoveUrl) if err != nil { return err } } return nil }
} } }, } var saveCNames = action.Action{ Name: "add-cname-save-in-database", Forward: func(ctx action.FWContext) (action.Result, error) { app := ctx.Params[0].(*App) cnames := ctx.Params[1].([]string) var conn *db.Storage conn, err := db.Conn() if err != nil { return nil, err } defer conn.Close() var cnamesDone []string for _, cname := range cnames { err = conn.Apps().Update( bson.M{"name": app.Name}, bson.M{"$push": bson.M{"cname": cname}}, ) if err != nil { for _, c := range cnamesDone { conn.Apps().Update( bson.M{"name": app.Name}, bson.M{"$pull": bson.M{"cname": c}}, ) } return nil, err }