Skip to content

Commit

Permalink
config: scheduler generated from config, core: scheduler with middlew…
Browse files Browse the repository at this point in the history
…ares
  • Loading branch information
mcuadros committed Oct 4, 2015
1 parent aa9de83 commit f3f9f94
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 99 deletions.
85 changes: 62 additions & 23 deletions cli/config.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,83 @@
package cli

import (
"github.com/mcuadros/go-defaults"
"github.com/fsouza/go-dockerclient"
"github.com/mcuadros/ofelia/core"
"github.com/mcuadros/ofelia/middlewares"
"github.com/op/go-logging"

"github.com/mcuadros/go-defaults"
"gopkg.in/gcfg.v1"
)

const logFormat = "%{color}%{shortfile} ▶ %{level}%{color:reset} %{message}"

// Config contains the configuration
type Config struct {
Global struct {
middlewares.SlackConfig
}
Jobs map[string]*ExecJobConfig `gcfg:"Job"`
}

// LoadFile loads the content into the Config struct
func (c *Config) LoadFile(filename string) error {
err := gcfg.ReadFileInto(c, filename)
if err != nil {
return err
// BuildFromFile buils a scheduler using the config from a file
func BuildFromFile(filename string) (*core.Scheduler, error) {
c := &Config{}
if err := gcfg.ReadFileInto(c, filename); err != nil {
return nil, err
}

c.loadDefaults()
return nil
return c.build()
}

func (c *Config) loadDefaults() {
// BuildFromString buils a scheduler using the config from a string
func BuildFromString(config string) (*core.Scheduler, error) {
c := &Config{}
if err := gcfg.ReadStringInto(c, config); err != nil {
return nil, err
}

return c.build()
}

func (c *Config) build() (*core.Scheduler, error) {
defaults.SetDefaults(c)

d, err := c.buildDockerClient()
if err != nil {
return nil, err
}

sh := core.NewScheduler(c.buildLogger())
c.buildSchedulerMiddlewares(sh)

for name, j := range c.Jobs {
j.Client = d
j.Name = name
defaults.SetDefaults(j)
j.buildMiddlewares()
sh.AddJob(j)
}

return sh, nil
}

func (c *Config) buildDockerClient() (*docker.Client, error) {
d, err := docker.NewClientFromEnv()
if err != nil {
return nil, err
}

return d, nil
}

func (c *Config) buildLogger() core.Logger {
logging.SetFormatter(logging.MustStringFormatter(logFormat))

return logging.MustGetLogger("ofelia")
}

func (c *Config) buildSchedulerMiddlewares(sh *core.Scheduler) {
sh.Use(middlewares.NewSlack(&c.Global.SlackConfig))
}

// ExecJobConfig contains all configuration params needed to build a ExecJob
Expand All @@ -38,17 +87,7 @@ type ExecJobConfig struct {
middlewares.SlackConfig
}

// Build instanciates all the middlewares configured
func (c *ExecJobConfig) Build() {
var ms []core.Middleware
ms = append(ms, middlewares.NewOverlap(&c.OverlapConfig))
ms = append(ms, middlewares.NewSlack(&c.SlackConfig))

for _, m := range ms {
if m == nil {
continue
}

c.ExecJob.Use(m)
}
func (c *ExecJobConfig) buildMiddlewares() {
c.ExecJob.Use(middlewares.NewOverlap(&c.OverlapConfig))
c.ExecJob.Use(middlewares.NewSlack(&c.SlackConfig))
}
21 changes: 19 additions & 2 deletions cli/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,34 @@ type SuiteConfig struct{}

var _ = Suite(&SuiteConfig{})

func (s *SuiteConfig) TestBuildFromString(c *C) {
sh, err := BuildFromString(`
[job "foo"]
schedule = @every 10s
container = test
[job "bar"]
schedule = @every 10s
container = test
`)

c.Assert(err, IsNil)
c.Assert(sh.Jobs, HasLen, 2)
c.Assert(sh.Jobs[0].GetName(), Equals, "foo")
c.Assert(sh.Jobs[1].GetName(), Equals, "bar")
}

func (s *SuiteConfig) TestExecJobBuildEmpty(c *C) {
j := &ExecJobConfig{}
j.Build()
j.buildMiddlewares()

c.Assert(j.Middlewares(), HasLen, 0)
}

func (s *SuiteConfig) TestExecJobBuild(c *C) {
j := &ExecJobConfig{}
j.OverlapConfig.NoOverlap = true
j.Build()
j.buildMiddlewares()

c.Assert(j.Middlewares(), HasLen, 1)
}
36 changes: 6 additions & 30 deletions cli/daemon.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package cli

import (
"fmt"
"os"
"os/signal"
"syscall"

"github.com/fsouza/go-dockerclient"
"github.com/mcuadros/ofelia/core"
"github.com/op/go-logging"
)

// DaemonCommand daemon process
Expand All @@ -17,7 +14,6 @@ type DaemonCommand struct {

config *Config
scheduler *core.Scheduler
logger *logging.Logger
signals chan os.Signal
done chan bool
}
Expand All @@ -40,25 +36,12 @@ func (c *DaemonCommand) Execute(args []string) error {
}

func (c *DaemonCommand) boot() error {
c.buildLogger()

c.config = &Config{}
if err := c.config.LoadFile(c.ConfigFile); err != nil {
return err
}

d, err := docker.NewClientFromEnv()
sh, err := BuildFromFile(c.ConfigFile)
if err != nil {
return err
}

c.scheduler = core.NewScheduler(c.logger)
for _, j := range c.config.Jobs {
j.Client = d
j.Build()
c.scheduler.AddJob(j)
}

c.scheduler = sh
return nil
}

Expand All @@ -79,7 +62,9 @@ func (c *DaemonCommand) setSignals() {

go func() {
sig := <-c.signals
c.logger.Warning("Signal recieved: %s, shuting down the process\n", sig)
c.scheduler.Logger.Warning(
"Signal recieved: %s, shuting down the process\n", sig,
)

c.done <- true
}()
Expand All @@ -91,15 +76,6 @@ func (c *DaemonCommand) shutdown() error {
return nil
}

fmt.Println("Waiting running jobs.")
c.scheduler.Logger.Warning("Waiting running jobs.")
return c.scheduler.Stop()
}

const logFormat = "%{color}%{shortfile} ▶ %{level}%{color:reset} %{message}"

func (c *DaemonCommand) buildLogger() {
logging.SetFormatter(logging.MustStringFormatter(logFormat))

c.logger = logging.MustGetLogger("ofelia")

}
9 changes: 6 additions & 3 deletions cli/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ type ValidateCommand struct {
// Execute runs the validation command
func (c *ValidateCommand) Execute(args []string) error {
fmt.Printf("Validating %q ... ", c.ConfigFile)
config := &Config{}
if err := config.LoadFile(c.ConfigFile); err != nil {
config, err := BuildFromFile(c.ConfigFile)
if err != nil {
fmt.Println("ERROR")
return err
}
Expand All @@ -20,7 +20,10 @@ func (c *ValidateCommand) Execute(args []string) error {
fmt.Printf("Found %d jobs:\n", len(config.Jobs))

for _, j := range config.Jobs {
fmt.Printf("- name: %s schedule: %q command: %q\n", j.Name, j.Schedule, j.Command)
fmt.Printf(
"- name: %s schedule: %q command: %q\n",
j.GetName(), j.GetSchedule(), j.GetCommand(),
)
}

return nil
Expand Down
43 changes: 39 additions & 4 deletions core/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/rand"
"fmt"
"io"
"reflect"
"time"
)

Expand Down Expand Up @@ -80,10 +81,6 @@ func (c *Context) Stop(err error) {
c.Job.NotifyStop()
}

type Middleware interface {
Run(*Context) error
}

type Execution struct {
ID string
Date time.Time
Expand Down Expand Up @@ -119,6 +116,44 @@ func (e *Execution) Stop(err error) {
}
}

type Middleware interface {
Run(*Context) error
}

type middlewareContainer struct {
m map[string]Middleware
order []string
}

func (c *middlewareContainer) Use(ms ...Middleware) {
if c.m == nil {
c.m = make(map[string]Middleware, 0)
}

for _, m := range ms {
if m == nil {
continue
}

t := reflect.TypeOf(m).String()
if _, ok := c.m[t]; ok {
continue
}

c.order = append(c.order, t)
c.m[t] = m
}
}

func (c *middlewareContainer) Middlewares() []Middleware {
var ms []Middleware
for _, t := range c.order {
ms = append(ms, c.m[t])
}

return ms
}

type Logger interface {
Critical(format string, args ...interface{})
Debug(format string, args ...interface{})
Expand Down
Loading

0 comments on commit f3f9f94

Please sign in to comment.