Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify initialization of Empire core #692

Merged
merged 3 commits into from
Dec 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
**Features**

* `emp ps` now shows the correct uptime of the process thanks to ECS support [#683](https://github.com/remind101/empire/pull/683).
* You can now deploy images from unofficial Docker registries, such as Quay.io [#692](https://github.com/remind101/empire/pull/692).

## 0.9.2 (2015-10-27)

Expand Down
16 changes: 6 additions & 10 deletions apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/jinzhu/gorm"
"github.com/remind101/empire/scheduler"
"github.com/remind101/pkg/timex"
"golang.org/x/net/context"
)
Expand Down Expand Up @@ -142,12 +141,11 @@ func AppID(id string) func(*gorm.DB) *gorm.DB {
}

type appsService struct {
store *store
scheduler scheduler.Scheduler
*Empire
}

func (s *appsService) AppsDestroy(ctx context.Context, app *App) error {
if err := s.scheduler.Remove(ctx, app.ID); err != nil {
if err := s.Scheduler.Remove(ctx, app.ID); err != nil {
return err
}

Expand Down Expand Up @@ -204,8 +202,7 @@ func appsDestroy(db *gorm.DB, app *App) error {

// scaler is a small service for scaling an apps process.
type scaler struct {
store *store
scheduler scheduler.Scheduler
*Empire
}

func (s *scaler) Scale(ctx context.Context, app *App, t ProcessType, quantity int, c *Constraints) (*Process, error) {
Expand All @@ -228,7 +225,7 @@ func (s *scaler) Scale(ctx context.Context, app *App, t ProcessType, quantity in
return nil, &ValidationError{Err: fmt.Errorf("no %s process type in release", t)}
}

if err := s.scheduler.Scale(ctx, release.AppID, string(p.Type), uint(quantity)); err != nil {
if err := s.Scheduler.Scale(ctx, release.AppID, string(p.Type), uint(quantity)); err != nil {
return nil, err
}

Expand All @@ -243,13 +240,12 @@ func (s *scaler) Scale(ctx context.Context, app *App, t ProcessType, quantity in

// restarter is a small service for restarting an apps processes.
type restarter struct {
scheduler scheduler.Scheduler
releaser *releaser
*Empire
}

func (s *restarter) Restart(ctx context.Context, app *App, id string) error {
if id != "" {
return s.scheduler.Stop(ctx, id)
return s.Scheduler.Stop(ctx, id)
}

return s.releaser.ReleaseApp(ctx, app)
Expand Down
219 changes: 219 additions & 0 deletions cmd/empire/factories.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
package main

import (
"fmt"
"log"
"net/url"
"os"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"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/pkg/dockerutil"
"github.com/remind101/empire/pkg/runner"
"github.com/remind101/empire/pkg/sslcert"
"github.com/remind101/empire/scheduler"
"github.com/remind101/empire/scheduler/ecs"
"github.com/remind101/pkg/reporter"
"github.com/remind101/pkg/reporter/hb"
)

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

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

// Empire ===============================

func newEmpire(c *cli.Context) (*empire.Empire, error) {
db, err := newDB(c)
if err != nil {
return nil, err
}

docker, err := newDockerClient(c)
if err != nil {
return nil, err
}

reporter, err := newReporter(c)
if err != nil {
return nil, err
}

scheduler, err := newScheduler(c)
if err != nil {
return nil, err
}

certManager, err := newCertManager(c)
if err != nil {
return nil, err
}

logs, err := newLogsStreamer(c)
if err != nil {
return nil, err
}

e := empire.New(db, empire.Options{
Secret: c.String(FlagSecret),
})
e.Reporter = reporter
e.Scheduler = scheduler
e.CertManager = certManager
e.LogsStreamer = logs
e.ExtractProcfile = empire.PullAndExtract(docker)
e.Logger = newLogger()

return e, nil
}

// Scheduler ============================

func newScheduler(c *cli.Context) (scheduler.Scheduler, error) {
return newECSScheduler(c)
}

func newECSScheduler(c *cli.Context) (scheduler.Scheduler, error) {
config := ecs.Config{
AWS: newConfigProvider(c),
Cluster: c.String(FlagECSCluster),
ServiceRole: c.String(FlagECSServiceRole),
InternalSecurityGroupID: c.String(FlagELBSGPrivate),
ExternalSecurityGroupID: c.String(FlagELBSGPublic),
InternalSubnetIDs: c.StringSlice(FlagEC2SubnetsPrivate),
ExternalSubnetIDs: c.StringSlice(FlagEC2SubnetsPublic),
ZoneID: c.String(FlagRoute53InternalZoneID),
}

s, err := ecs.NewLoadBalancedScheduler(config)
if err != nil {
return nil, err
}

r, err := newDockerRunner(c)
if err != nil {
return nil, err
}

log.Println("Using ECS backend with the following configuration:")
log.Println(fmt.Sprintf(" Cluster: %v", config.Cluster))
log.Println(fmt.Sprintf(" ServiceRole: %v", config.ServiceRole))
log.Println(fmt.Sprintf(" InternalSecurityGroupID: %v", config.InternalSecurityGroupID))
log.Println(fmt.Sprintf(" ExternalSecurityGroupID: %v", config.ExternalSecurityGroupID))
log.Println(fmt.Sprintf(" InternalSubnetIDs: %v", config.InternalSubnetIDs))
log.Println(fmt.Sprintf(" ExternalSubnetIDs: %v", config.ExternalSubnetIDs))
log.Println(fmt.Sprintf(" ZoneID: %v", config.ZoneID))

return &scheduler.AttachedRunner{
Scheduler: s,
Runner: r,
}, nil
}

func newConfigProvider(c *cli.Context) client.ConfigProvider {
p := session.New()

if c.Bool(FlagAWSDebug) {
config := &aws.Config{}
config.WithLogLevel(1)
p = session.New(config)
}

return p
}

func newDockerRunner(c *cli.Context) (*runner.Runner, error) {
client, err := newDockerClient(c)
if err != nil {
return nil, err
}
return runner.NewRunner(client), nil
}

// DockerClient ========================

func newDockerClient(c *cli.Context) (*dockerutil.Client, error) {
socket := c.String(FlagDockerSocket)
certPath := c.String(FlagDockerCert)
auth, err := dockerAuth(c.String(FlagDockerAuth))
if err != nil {
return nil, err
}

return dockerutil.NewClient(auth, socket, certPath)
}

// CertManager =========================

func newCertManager(c *cli.Context) (sslcert.Manager, error) {
return newIAMCertManager(c)
}

func newIAMCertManager(c *cli.Context) (sslcert.Manager, error) {
return sslcert.NewIAMManager(newConfigProvider(c), "/empire/certs/"), nil
}

// LogStreamer =========================

func newLogsStreamer(c *cli.Context) (empire.LogsStreamer, error) {
switch c.String(FlagLogsStreamer) {
case "kinesis":
return newKinesisLogsStreamer(c)
default:
log.Println("Streaming logs are disabled")
return nil, nil
}
}

func newKinesisLogsStreamer(c *cli.Context) (empire.LogsStreamer, error) {
log.Println("Using Kinesis backend for log streaming")
return empire.NewKinesisLogsStreamer(), nil
}

// Logger ==============================

func newLogger() log15.Logger {
l := log15.New()
h := log15.StreamHandler(os.Stdout, log15.LogfmtFormat())
l.SetHandler(log15.LazyHandler(h))
return l
}

// Reporter ============================

func newReporter(c *cli.Context) (reporter.Reporter, error) {
u := c.String(FlagReporter)
if u == "" {
return empire.DefaultReporter, nil
}

uri, err := url.Parse(u)
if err != nil {
return nil, err
}

switch uri.Scheme {
case "hb":
log.Println("Using Honeybadger to report errors")
q := uri.Query()
return newHBReporter(q.Get("key"), q.Get("environment"))
default:
panic(fmt.Errorf("unknown reporter: %s", u))
}
}

func newHBReporter(key, env string) (reporter.Reporter, error) {
r := hb.NewReporter(key)
r.Environment = env

// Append here because `go vet` will complain about unkeyed fields,
// since it thinks MultiReporter is a struct literal.
return append(reporter.MultiReporter{}, empire.DefaultReporter, r), nil
}
79 changes: 0 additions & 79 deletions cmd/empire/main.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
package main

import (
"fmt"
"net/url"
"os"
"path"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/codegangsta/cli"
"github.com/fsouza/go-dockerclient"
"github.com/remind101/empire"
"github.com/remind101/empire/server/github"
"github.com/remind101/pkg/reporter"
"github.com/remind101/pkg/reporter/hb"
)

const (
Expand Down Expand Up @@ -247,78 +240,6 @@ func main() {
app.Run(os.Args)
}

func newEmpire(c *cli.Context) (*empire.Empire, error) {
opts := empire.Options{}

opts.Docker.Socket = c.String(FlagDockerSocket)
opts.Docker.CertPath = c.String(FlagDockerCert)
opts.AWSConfig = session.New()
if c.Bool(FlagAWSDebug) {
config := &aws.Config{}
config.WithLogLevel(1)
opts.AWSConfig = session.New(config)
}
opts.ECS.Cluster = c.String(FlagECSCluster)
opts.ECS.ServiceRole = c.String(FlagECSServiceRole)
opts.ELB.InternalSecurityGroupID = c.String(FlagELBSGPrivate)
opts.ELB.ExternalSecurityGroupID = c.String(FlagELBSGPublic)
opts.ELB.InternalSubnetIDs = c.StringSlice(FlagEC2SubnetsPrivate)
opts.ELB.ExternalSubnetIDs = c.StringSlice(FlagEC2SubnetsPublic)
opts.ELB.InternalZoneID = c.String(FlagRoute53InternalZoneID)
opts.DB = c.String(FlagDB)
opts.Secret = c.String(FlagSecret)
opts.LogsStreamer = c.String(FlagLogsStreamer)

auth, err := dockerAuth(c.String(FlagDockerAuth))
if err != nil {
return nil, err
}

opts.Docker.Auth = auth

e, err := empire.New(opts)
if err != nil {
return e, err
}

reporter, err := newReporter(c.String(FlagReporter))
if err != nil {
return e, err
}

e.Reporter = reporter

return e, nil
}

func newReporter(u string) (reporter.Reporter, error) {
if u == "" {
return empire.DefaultReporter, nil
}

uri, err := url.Parse(u)
if err != nil {
return nil, err
}

switch uri.Scheme {
case "hb":
q := uri.Query()
return newHBReporter(q.Get("key"), q.Get("environment"))
default:
panic(fmt.Errorf("unknown reporter: %s", u))
}
}

func newHBReporter(key, env string) (reporter.Reporter, error) {
r := hb.NewReporter(key)
r.Environment = env

// Append here because `go vet` will complain about unkeyed fields,
// since it thinks MultiReporter is a struct literal.
return append(reporter.MultiReporter{}, empire.DefaultReporter, r), nil
}

func dockerAuth(path string) (*docker.AuthConfigurations, error) {
f, err := os.Open(path)
if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ func configsCreate(db *gorm.DB, config *Config) (*Config, error) {
}

type configsService struct {
store *store
releases *releasesService
*Empire
}

func (s *configsService) ConfigsApply(ctx context.Context, app *App, vars Vars) (*Config, error) {
Expand Down
Loading