Skip to content

Commit

Permalink
support for dynamic reloads
Browse files Browse the repository at this point in the history
  • Loading branch information
gondor committed Apr 9, 2017
1 parent 3d3c017 commit 905c79e
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ devconf.json
dockerconf.json
temp
Dockerfile.temp
tmp
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ RUN apt-get update \

COPY beethoven /usr/sbin/beethoven
COPY scripts/run.sh /bin/run.sh

RUN chmod a+x /bin/run.sh

COPY scripts/supervisord.conf /etc/supervisord.tmpl

ENTRYPOINT ["/bin/run.sh"]
ENTRYPOINT ["/bin/run.sh"]
49 changes: 47 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ type Config struct {
// Enivronment variable: BT_MARATHON_URLS
MarthonUrls []string `json:"marthon_urls" envconfig:"marathon_urls"`

// The Marathon ID for Beethoven (optional). If set,
// will allow for reloading new configuration changes (if using user Data below).
MarathonServiceId string `json:"marathon_service_id"`

// The basic auth username - if applicable
// Enivronment variable: BT_USERNAME
Username string `json:"username"`
Expand All @@ -52,13 +56,21 @@ type Config struct {
// Location of the nginx.conf - default: /etc/nginx/nginx.conf
NginxConfig string `json:"nginx_config"`


// User defined configuration data that can be used as part of the template parsing
// if Beethoven is launched with --root-apps=false .
Data map[string]interface{}

/* Internal */
Version string `json:"-"`
Version string `json:"-"`
conext *reloadContext `json:"-"`
}

type reloadContext struct {
server string
name string
label string
profile string
filename string
}

var (
Expand Down Expand Up @@ -140,6 +152,7 @@ func loadFromFile(configFile string) (*Config, error) {
if err := encoder.UnMarshalFile(configFile, cfg); err != nil {
return nil, err
}
cfg.conext = &reloadContext{filename: configFile}
return cfg.loadDefaults(), nil
}

Expand All @@ -161,11 +174,43 @@ func loadFromRemote(server, appName, label, profile string) (*Config, error) {
if err := client.Fetch(cfg); err != nil {
return nil, err
}
cfg.conext = &reloadContext{
server: server,
name: appName,
label: label,
profile: profile,
}
return cfg.loadDefaults(), nil
}

/* Config receivers */

// Reload will re-fetch/load the a subset of the configuration and apply it.
// The data applied is "Data" and "FilterRegExStr" values
func (c *Config) Reload() bool {
newCfg, err := loadConfigFromContext(c.conext)
if err != nil {
log.Errorf("Error reloading configuration: %s", err.Error())
return false
}

c.Data = newCfg.Data

if c.FilterRegExStr != newCfg.FilterRegExStr {
c.FilterRegExStr = newCfg.FilterRegExStr
c.ParseRegEx()
}
log.Info("Configuration successfully reloaded")
return true
}

func loadConfigFromContext(c *reloadContext) (*Config, error) {
if c.filename != "" {
return loadFromFile(c.filename)
}
return loadFromRemote(c.server, c.name, c.label, c.profile)
}

// HttpPort is the port we serve the API with
// default 7777 if config port is undefined
func (c *Config) HttpPort() int {
Expand Down
4 changes: 4 additions & 0 deletions generator/marathon.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func (g *Generator) initReloadWatcher() {
}
}

func (g *Generator) ReloadConfiguration() {
g.generateConfig()
}

func (g *Generator) generateConfig() {
if err := g.buildAppMeta(); err != nil {
log.Error("Skipping config generation...")
Expand Down
2 changes: 1 addition & 1 deletion generator/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (g *Generator) writeConfiguration() (bool, error) {
}

g.tracker.SetLastConfigRendered(time.Now())
log.Info("wrote config: %s, contents: \n\n%s", tplFilename, result)
log.Info("wrote config: %s, contents: \n\n%s", tplFilename, result)

if g.cfg.DryRun() {
log.Debug("Has Changed from Config : %v", g.templateAndConfMatch(tplFilename))
Expand Down
20 changes: 19 additions & 1 deletion proxy/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package proxy
import (
"fmt"
"github.com/ContainX/depcon/pkg/encoding"
"net/http"
"io/ioutil"
"net/http"
)

func (p *Proxy) getStatus(w http.ResponseWriter, r *http.Request) {
Expand All @@ -24,3 +24,21 @@ func (p *Proxy) getConfig(w http.ResponseWriter, r *http.Request) {
w.Write(b)
}
}

func (p *Proxy) reloadConfig(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
if p.cfg.Reload() {
log.Info("Triggering configuration reload")
p.generator.ReloadConfiguration()
}
} else {
log.Error("Reload Configuration - invalid method %s", r.Method)
}
}

func (p *Proxy) reloadAll(w http.ResponseWriter, r *http.Request) {
if p.cfg.MarathonServiceId != "" {
// Will trigger reload config on all instances of Beethoven in a cluster
// if invoked.
}
}
6 changes: 6 additions & 0 deletions proxy/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/ContainX/beethoven/config"
"github.com/ContainX/beethoven/generator"
"github.com/ContainX/beethoven/tracker"
"github.com/ContainX/depcon/pkg/logger"
"github.com/gorilla/mux"
"net/http"
)
Expand All @@ -17,6 +18,10 @@ const (
}`
)

var (
log = logger.GetLogger("beethoven.proxy")
)

type Proxy struct {
cfg *config.Config
httpServer *http.Server
Expand All @@ -35,6 +40,7 @@ func (p *Proxy) initRoutes() {
p.mux.HandleFunc("/bt", p.getVersion)
p.mux.HandleFunc("/bt/status/", p.getStatus)
p.mux.HandleFunc("/bt/config/", p.getConfig)
p.mux.HandleFunc("/bt/reload/", p.reloadConfig)
}

func (p *Proxy) Serve() {
Expand Down

0 comments on commit 905c79e

Please sign in to comment.