func (r *AppRepo) Add(data interface{}) error { app := data.(*ct.App) tx, err := r.db.Begin() if err != nil { return err } if app.Name == "" { var nameID uint32 if err := tx.QueryRow("SELECT nextval('name_ids')").Scan(&nameID); err != nil { tx.Rollback() return err } app.Name = name.Get(nameID) } if len(app.Name) > 100 || !utils.AppNamePattern.MatchString(app.Name) { return ct.ValidationError{Field: "name", Message: "is invalid"} } if app.ID == "" { app.ID = random.UUID() } if app.Strategy == "" { app.Strategy = "all-at-once" } meta, err := json.Marshal(app.Meta) if err != nil { return err } if err := tx.QueryRow("INSERT INTO apps (app_id, name, meta, strategy) VALUES ($1, $2, $3, $4) RETURNING created_at, updated_at", app.ID, app.Name, meta, app.Strategy).Scan(&app.CreatedAt, &app.UpdatedAt); err != nil { tx.Rollback() if postgres.IsUniquenessError(err, "apps_name_idx") { return httphelper.ObjectExistsErr(fmt.Sprintf("application %q already exists", app.Name)) } return err } if err := createEvent(tx.Exec, &ct.Event{ AppID: app.ID, ObjectID: app.ID, ObjectType: ct.EventTypeApp, }, app); err != nil { tx.Rollback() return err } if err := tx.Commit(); err != nil { return err } if !app.System() && r.defaultDomain != "" { route := (&router.HTTPRoute{ Domain: fmt.Sprintf("%s.%s", app.Name, r.defaultDomain), Service: app.Name + "-web", }).ToRoute() if err := createRoute(r.db, r.router, app.ID, route); err != nil { log.Printf("Error creating default route for %s: %s", app.Name, err) } } return nil }
func (r *AppRepo) Add(data interface{}) error { app := data.(*ct.App) tx, err := r.db.Begin() if err != nil { return err } if app.Name == "" { var nameID int64 if err := tx.QueryRow("app_next_name_id").Scan(&nameID); err != nil { tx.Rollback() return err } // Safe cast because name_ids is limited to 32 bit size in schema app.Name = name.Get(uint32(nameID)) } if len(app.Name) > 100 || !utils.AppNamePattern.MatchString(app.Name) { return ct.ValidationError{Field: "name", Message: "is invalid"} } if app.ID == "" { app.ID = random.UUID() } if app.Strategy == "" { app.Strategy = "all-at-once" } if app.DeployTimeout == 0 { app.DeployTimeout = ct.DefaultDeployTimeout } if err := tx.QueryRow("app_insert", app.ID, app.Name, app.Meta, app.Strategy, app.DeployTimeout).Scan(&app.CreatedAt, &app.UpdatedAt); err != nil { tx.Rollback() if postgres.IsUniquenessError(err, "apps_name_idx") { return httphelper.ObjectExistsErr(fmt.Sprintf("application %q already exists", app.Name)) } return err } if err := createEvent(tx.Exec, &ct.Event{ AppID: app.ID, ObjectID: app.ID, ObjectType: ct.EventTypeApp, }, app); err != nil { tx.Rollback() return err } if err := tx.Commit(); err != nil { return err } if !app.System() && r.defaultDomain != "" { route := (&router.HTTPRoute{ Domain: fmt.Sprintf("%s.%s", app.Name, r.defaultDomain), Service: app.Name + "-web", }).ToRoute() if err := createRoute(r.db, r.router, app.ID, route); err != nil { log.Printf("Error creating default route for %s: %s", app.Name, err) } } return nil }
func (r *AppRepo) Add(data interface{}) error { app := data.(*ct.App) if app.Name == "" { var nameID uint32 if err := r.db.QueryRow("SELECT nextval('name_ids')").Scan(&nameID); err != nil { return err } app.Name = name.Get(nameID) } if len(app.Name) > 100 || !appNamePattern.MatchString(app.Name) { return ct.ValidationError{Field: "name", Message: "is invalid"} } if app.ID == "" { app.ID = random.UUID() } if app.Strategy == "" { app.Strategy = "all-at-once" } meta := metaToHstore(app.Meta) if err := r.db.QueryRow("INSERT INTO apps (app_id, name, meta, strategy) VALUES ($1, $2, $3, $4) RETURNING created_at, updated_at", app.ID, app.Name, meta, app.Strategy).Scan(&app.CreatedAt, &app.UpdatedAt); err != nil { if postgres.IsUniquenessError(err, "apps_name_idx") { return httphelper.ObjectExistsErr(fmt.Sprintf("application %q already exists", app.Name)) } return err } app.ID = postgres.CleanUUID(app.ID) if !app.System() && r.defaultDomain != "" { route := (&router.HTTPRoute{ Domain: fmt.Sprintf("%s.%s", app.Name, r.defaultDomain), Service: app.Name + "-web", }).ToRoute() route.ParentRef = routeParentRef(app.ID) if err := r.router.CreateRoute(route); err != nil { log.Printf("Error creating default route for %s: %s", app.Name, err) } } return nil }
func (r *AppRepo) Add(data interface{}) error { app := data.(*ct.App) if app.Name == "" { var nameID uint32 if err := r.db.QueryRow("SELECT nextval('name_ids')").Scan(&nameID); err != nil { return err } app.Name = name.Get(nameID) } if len(app.Name) > 100 || !appNamePattern.MatchString(app.Name) { return ct.ValidationError{Field: "name", Message: "is invalid"} } if app.ID == "" { app.ID = random.UUID() } var meta hstore.Hstore if len(app.Meta) > 0 { meta.Map = make(map[string]sql.NullString, len(app.Meta)) for k, v := range app.Meta { meta.Map[k] = sql.NullString{String: v, Valid: true} } } err := r.db.QueryRow("INSERT INTO apps (app_id, name, protected, meta) VALUES ($1, $2, $3, $4) RETURNING created_at, updated_at", app.ID, app.Name, app.Protected, meta).Scan(&app.CreatedAt, &app.UpdatedAt) app.ID = cleanUUID(app.ID) if !app.Protected && r.defaultDomain != "" { route := (&router.HTTPRoute{ Domain: fmt.Sprintf("%s.%s", app.Name, r.defaultDomain), Service: app.Name + "-web", }).ToRoute() route.ParentRef = routeParentRef(app) if err := r.router.CreateRoute(route); err != nil { log.Printf("Error creating default route for %s: %s", app.Name, err) } } return err }