Skip to content

Commit

Permalink
Merge pull request #713 from remind101/transactions
Browse files Browse the repository at this point in the history
Remove store
  • Loading branch information
ejholmes committed Jan 6, 2016
2 parents cf235f4 + 6aa583d commit 3d0995d
Show file tree
Hide file tree
Showing 21 changed files with 650 additions and 585 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* Allow floating point numbers to be provided when scaling the memory on a process [#694](https://github.com/remind101/empire/pull/694).
* Empire will now update the SSL certificate on the associated ELB if it changes from `emp cert-attach` [#700](https://github.com/remind101/empire/pull/700).
* The Tugboat integration now updates the deployment status with any errors that occurred [#709](https://github.com/remind101/empire/pull/709).
* Deploying a non-existent docker image to Empire will no longer create an app [#713](https://github.com/remind101/empire/pull/713).
* It's no longer necessary to re-deploy an application when scaling a process with new CPU or memory constraints [#713](https://github.com/remind101/empire/pull/713).

**Security**

Expand Down
179 changes: 81 additions & 98 deletions apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,35 +104,6 @@ func (q AppsQuery) Scope(db *gorm.DB) *gorm.DB {
return scope.Scope(db)
}

// AppsFind returns the first matching release.
func (s *store) AppsFind(scope Scope) (*App, error) {
var app App
return &app, s.First(scope, &app)
}

// Apps returns all apps matching the scope.
func (s *store) Apps(scope Scope) ([]*App, error) {
var apps []*App
// Default to ordering by name.
scope = ComposedScope{Order("name"), scope}
return apps, s.Find(scope, &apps)
}

// AppsCreate persists an app.
func (s *store) AppsCreate(app *App) (*App, error) {
return appsCreate(s.db, app)
}

// AppsUpdate updates an app.
func (s *store) AppsUpdate(app *App) error {
return appsUpdate(s.db, app)
}

// AppsDestroy destroys an app.
func (s *store) AppsDestroy(app *App) error {
return appsDestroy(s.db, app)
}

// AppID returns a scope to find an app by id.
func AppID(id string) func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
Expand All @@ -144,71 +115,27 @@ type appsService struct {
*Empire
}

func (s *appsService) AppsDestroy(ctx context.Context, app *App) error {
if err := s.Scheduler.Remove(ctx, app.ID); err != nil {
// Destroy destroys removes an app from the scheduler, then destroys it here.
func (s *appsService) Destroy(ctx context.Context, db *gorm.DB, app *App) error {
if err := appsDestroy(db, app); err != nil {
return err
}

return s.store.AppsDestroy(app)
return s.Scheduler.Remove(ctx, app.ID)
}

// AppsEnsureRepo will set the repo if it's not set.
func (s *appsService) AppsEnsureRepo(app *App, repo string) error {
if app.Repo != nil {
return nil
}

app.Repo = &repo

return s.store.AppsUpdate(app)
}

// AppsFindOrCreateByRepo first attempts to find an app by repo, falling back to
// creating a new app.
func (s *appsService) AppsFindOrCreateByRepo(repo string) (*App, error) {
n := AppNameFromRepo(repo)
a, err := s.store.AppsFind(AppsQuery{Name: &n})
if err != nil && err != gorm.RecordNotFound {
return a, err
}

// If the app wasn't found, create a new app.
if err != gorm.RecordNotFound {
return a, s.AppsEnsureRepo(a, repo)
}

a = &App{
Name: n,
Repo: &repo,
func (s *appsService) Restart(ctx context.Context, db *gorm.DB, opts RestartOpts) error {
if opts.PID != "" {
return s.Scheduler.Stop(ctx, opts.PID)
}

return s.store.AppsCreate(a)
}

// AppsCreate inserts the app into the database.
func appsCreate(db *gorm.DB, app *App) (*App, error) {
return app, db.Create(app).Error
}

// AppsUpdate updates an app.
func appsUpdate(db *gorm.DB, app *App) error {
return db.Save(app).Error
}

// AppsDestroy destroys an app.
func appsDestroy(db *gorm.DB, app *App) error {
return db.Delete(app).Error
}

// scaler is a small service for scaling an apps process.
type scaler struct {
*Empire
return s.releases.ReleaseApp(ctx, db, opts.App)
}

func (s *scaler) Scale(ctx context.Context, opts ScaleOpts) (*Process, error) {
func (s *appsService) Scale(ctx context.Context, db *gorm.DB, opts ScaleOpts) (*Process, error) {
app, t, quantity, c := opts.App, opts.Process, opts.Quantity, opts.Constraints

release, err := s.store.ReleasesFind(ReleasesQuery{App: app})
release, err := releasesFind(db, ReleasesQuery{App: app})
if err != nil {
return nil, err
}
Expand All @@ -217,13 +144,8 @@ func (s *scaler) Scale(ctx context.Context, opts ScaleOpts) (*Process, error) {
return nil, &ValidationError{Err: fmt.Errorf("no releases for %s", app.Name)}
}

f, err := s.store.Formation(ProcessesQuery{Release: release})
if err != nil {
return nil, err
}

p, ok := f[t]
if !ok {
p := release.Process(t)
if p == nil {
return nil, &ValidationError{Err: fmt.Errorf("no %s process type in release", t)}
}

Expand All @@ -240,22 +162,83 @@ func (s *scaler) Scale(ctx context.Context, opts ScaleOpts) (*Process, error) {
p.Constraints = *c
}

if err := s.store.ProcessesUpdate(p); err != nil {
if err := processesUpdate(db, p); err != nil {
return nil, err
}

// If there are no changes to the process size, we can do a quick scale
// up, otherwise, we will resubmit the release to the scheduler.
if c == nil {
err = s.Scheduler.Scale(ctx, release.AppID, string(p.Type), uint(quantity))
} else {
err = s.releases.Release(ctx, release)
}

if err != nil {
return p, err
}

return p, s.PublishEvent(event)
}

// restarter is a small service for restarting an apps processes.
type restarter struct {
*Empire
// appsEnsureRepo will set the repo if it's not set.
func appsEnsureRepo(db *gorm.DB, app *App, repo string) error {
if app.Repo != nil {
return nil
}

app.Repo = &repo

return appsUpdate(db, app)
}

func (s *restarter) Restart(ctx context.Context, opts RestartOpts) error {
if opts.PID != "" {
return s.Scheduler.Stop(ctx, opts.PID)
// appsFindOrCreateByRepo first attempts to find an app by repo, falling back to
// creating a new app.
func appsFindOrCreateByRepo(db *gorm.DB, repo string) (*App, error) {
n := AppNameFromRepo(repo)
a, err := appsFind(db, AppsQuery{Name: &n})
if err != nil && err != gorm.RecordNotFound {
return a, err
}

// If the app wasn't found, create a new app.
if err != gorm.RecordNotFound {
return a, appsEnsureRepo(db, a, repo)
}

return s.releaser.ReleaseApp(ctx, opts.App)
a = &App{
Name: n,
Repo: &repo,
}

return appsCreate(db, a)
}

// appsFind finds a single app given the scope.
func appsFind(db *gorm.DB, scope Scope) (*App, error) {
var app App
return &app, first(db, scope, &app)
}

// apps finds all apps matching the scope.
func apps(db *gorm.DB, scope Scope) ([]*App, error) {
var apps []*App
// Default to ordering by name.
scope = ComposedScope{Order("name"), scope}
return apps, find(db, scope, &apps)
}

// appsCreate inserts the app into the database.
func appsCreate(db *gorm.DB, app *App) (*App, error) {
return app, db.Create(app).Error
}

// appsUpdate updates an app.
func appsUpdate(db *gorm.DB, app *App) error {
return db.Save(app).Error
}

// appsDestroy destroys an app.
func appsDestroy(db *gorm.DB, app *App) error {
return db.Delete(app).Error
}
11 changes: 7 additions & 4 deletions certs.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package empire

import "golang.org/x/net/context"
import (
"github.com/jinzhu/gorm"
"golang.org/x/net/context"
)

type certsService struct {
*Empire
}

func (s *certsService) CertsAttach(ctx context.Context, app *App, cert string) error {
func (s *certsService) CertsAttach(ctx context.Context, db *gorm.DB, app *App, cert string) error {
app.Cert = cert

if err := s.store.AppsUpdate(app); err != nil {
if err := appsUpdate(db, app); err != nil {
return err
}

if err := s.releaser.ReleaseApp(ctx, app); err != nil {
if err := s.releases.ReleaseApp(ctx, db, app); err != nil {
if err == ErrNoReleases {
return nil
}
Expand Down
5 changes: 2 additions & 3 deletions cmd/empire/factories.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/aws/aws-sdk-go/aws/session"
"github.com/codegangsta/cli"
"github.com/inconshreveable/log15"
"github.com/jinzhu/gorm"
"github.com/remind101/empire"
"github.com/remind101/empire/events/sns"
"github.com/remind101/empire/pkg/dockerutil"
Expand All @@ -24,8 +23,8 @@ import (

// DB ===================================

func newDB(c *cli.Context) (*gorm.DB, error) {
return empire.NewDB(c.String(FlagDB))
func newDB(c *cli.Context) (*empire.DB, error) {
return empire.OpenDB(c.String(FlagDB))
}

// Empire ===============================
Expand Down
10 changes: 6 additions & 4 deletions cmd/empire/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import (
"log"

"github.com/codegangsta/cli"
"github.com/remind101/empire"
)

func runMigrate(c *cli.Context) {
path := c.String(FlagDBPath)
db := c.String(FlagDB)
db, err := newDB(c)
if err != nil {
log.Fatal(err)
}

errors, ok := empire.Migrate(db, path)
path := c.String(FlagDBPath)
errors, ok := db.MigrateUp(path)
if !ok {
log.Fatal(errors)
}
Expand Down
37 changes: 17 additions & 20 deletions configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,11 @@ func (q ConfigsQuery) Scope(db *gorm.DB) *gorm.DB {
return scope.Scope(db)
}

// ConfigsFirst returns the first matching config.
func (s *store) ConfigsFirst(scope Scope) (*Config, error) {
// configsFind returns the first matching config.
func configsFind(db *gorm.DB, scope Scope) (*Config, error) {
var config Config
scope = ComposedScope{Order("created_at desc"), scope}
return &config, s.First(scope, &config)
}

// ConfigsCreate persists the Config.
func (s *store) ConfigsCreate(config *Config) (*Config, error) {
return configsCreate(s.db, config)
return &config, first(db, scope, &config)
}

// ConfigsCreate inserts a Config in the database.
Expand All @@ -123,20 +118,20 @@ type configsService struct {
*Empire
}

func (s *configsService) Set(ctx context.Context, opts SetOpts) (*Config, error) {
func (s *configsService) Set(ctx context.Context, db *gorm.DB, opts SetOpts) (*Config, error) {
app, vars := opts.App, opts.Vars

old, err := s.Config(app)
old, err := s.Config(db, app)
if err != nil {
return nil, err
}

c, err := s.store.ConfigsCreate(NewConfig(old, vars))
c, err := configsCreate(db, NewConfig(old, vars))
if err != nil {
return c, err
}

release, err := s.store.ReleasesFind(ReleasesQuery{App: app})
release, err := releasesFind(db, ReleasesQuery{App: app})
if err != nil {
if err == gorm.RecordNotFound {
err = nil
Expand All @@ -146,7 +141,7 @@ func (s *configsService) Set(ctx context.Context, opts SetOpts) (*Config, error)
}

// Create new release based on new config and old slug
_, err = s.releases.ReleasesCreate(ctx, &Release{
_, err = s.releases.Create(ctx, db, &Release{
App: release.App,
Config: c,
Slug: release.Slug,
Expand All @@ -156,18 +151,20 @@ func (s *configsService) Set(ctx context.Context, opts SetOpts) (*Config, error)
}

// Returns configs for latest release or the latest configs if there are no releases.
func (s *configsService) Config(app *App) (*Config, error) {
r, err := s.store.ReleasesFind(ReleasesQuery{App: app})
func (s *configsService) Config(db *gorm.DB, app *App) (*Config, error) {
r, err := releasesFind(db, ReleasesQuery{App: app})
if err != nil {
if err == gorm.RecordNotFound {
// It's possible to have config without releases, this handles that.
c, err := s.store.ConfigsFirst(ConfigsQuery{App: app})
c, err := configsFind(db, ConfigsQuery{App: app})
if err != nil {
if err == gorm.RecordNotFound {
return s.store.ConfigsCreate(&Config{
App: app,
Vars: make(Vars),
})
// Return an empty config.
return &Config{
AppID: app.ID,
App: app,
Vars: make(Vars),
}, nil
}
return nil, err
}
Expand Down
Loading

0 comments on commit 3d0995d

Please sign in to comment.