Skip to content

Commit

Permalink
fix file config update
Browse files Browse the repository at this point in the history
  • Loading branch information
linxiaozhi committed Dec 22, 2023
1 parent 0967b4f commit 12fba57
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 125 deletions.
9 changes: 7 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
FROM golang:1.17.1-alpine AS builder
FROM golang:1.17-alpine AS builder

LABEL org.opencontainers.image.description Cron alternative for Docker Swarm enviornments.

RUN if [ "mirrors.ustc.edu.cn" != "" ] ; then sed -i "s/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g" /etc/apk/repositories ; fi
RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct

RUN apk --no-cache add gcc musl-dev

WORKDIR ${GOPATH}/src/github.com/PremoWeb/Chadburn
COPY . ${GOPATH}/src/github.com/PremoWeb/Chadburn

RUN go build -o /go/bin/chadburn .

FROM alpine:3.15.0
FROM alpine

RUN if [ "mirrors.ustc.edu.cn" != "" ] ; then sed -i "s/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g" /etc/apk/repositories ; fi

RUN apk --update --no-cache add ca-certificates tzdata

Expand Down
104 changes: 39 additions & 65 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package cli
import (
"github.com/PremoWeb/Chadburn/core"
"github.com/PremoWeb/Chadburn/middlewares"

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

Expand Down Expand Up @@ -62,17 +62,17 @@ func BuildFromString(config string, logger core.Logger) (*Config, error) {
}

// Call this only once at app init
func (c *Config) InitializeApp(configFile string, dd bool) error {
func (c *Config) InitializeApp(daemon *DaemonCommand) error {
c.sh = core.NewScheduler(c.logger)
c.buildSchedulerMiddlewares(c.sh)

var err error
c.configHandler, err = NewFileConfigHandler(configFile, c, c.logger)
c.configHandler, err = NewFileConfigHandler(daemon.ConfigFile, c, c.logger)
if err != nil {
return err
}

if !dd {
if !daemon.DisableDocker {
c.dockerHandler, err = NewDockerHandler(c, c.logger)
if err != nil {
return err
Expand Down Expand Up @@ -120,13 +120,35 @@ func (c *Config) buildSchedulerMiddlewares(sh *core.Scheduler) {
sh.Use(middlewares.NewGotify(&c.Global.GotifyConfig))
}

func (c *Config) updateExecJobs(newConfig *Config) {
c.Global = newConfig.Global
c.buildSchedulerMiddlewares(c.sh)
func (c *Config) updateExecJobs(newConfig *Config, isDockerLabels bool) {
isConfigClobalUpdate := false
if !isDockerLabels {
oldHash, err := hashstructure.Hash(c.Global, hashstructure.FormatV2, nil)
if err != nil {
c.logger.Errorf("config global old hash err:%s", err.Error())
}

newhash, newerr := hashstructure.Hash(newConfig.Global, hashstructure.FormatV2, nil)
if newerr != nil {
c.logger.Errorf("config global new hash err:%s", newerr.Error())
}

if oldHash != newhash {
isConfigClobalUpdate = true
}

c.logger.Debugf("config global hash old:%d new:%d", oldHash, newhash)

if isConfigClobalUpdate {
c.Global = newConfig.Global
c.buildSchedulerMiddlewares(c.sh)
}
}

// Calculate the delta
for name, j := range c.ExecJobs {
// this prevents deletion of jobs that were added by reading a configuration file
if j.FromDockerLabel {
if (isDockerLabels && !j.FromDockerLabel) || (!isDockerLabels && j.FromDockerLabel) {
continue
}

Expand All @@ -141,7 +163,7 @@ func (c *Config) updateExecJobs(newConfig *Config) {
defaults.SetDefaults(newJob)
newJob.Client = c.dockerHandler.GetInternalDockerClient()
newJob.Name = newJobsName
if newJob.Hash() != j.Hash() {
if newJob.Hash() != j.Hash() || isConfigClobalUpdate {
// Remove from the scheduler
c.sh.RemoveJob(j)
// Add the job back to the scheduler
Expand Down Expand Up @@ -185,66 +207,18 @@ func (c *Config) dockerLabelsUpdate(labels map[string]map[string]string) {
var parsedLabelConfig Config
parsedLabelConfig.buildFromDockerLabels(labels)

// Calculate the delta
for name, j := range c.ExecJobs {
// this prevents deletion of jobs that were added by reading a configuration file
if !j.FromDockerLabel {
continue
}

found := false
for newJobsName, newJob := range parsedLabelConfig.ExecJobs {
// Check if the schedule has changed
if name == newJobsName {
found = true
// There is a slight race condition were a job can be canceled / restarted with different params
// so, lets take care of it by simply restarting
// For the hash to work properly, we must fill the fields before calling it
defaults.SetDefaults(newJob)
newJob.Client = c.dockerHandler.GetInternalDockerClient()
newJob.Name = newJobsName
if newJob.Hash() != j.Hash() {
// Remove from the scheduler
c.sh.RemoveJob(j)
// Add the job back to the scheduler
newJob.buildMiddlewares()
c.sh.AddJob(newJob)
// Update the job config
c.ExecJobs[name] = newJob
}
break
}
}
if !found {
// Remove the job
c.sh.RemoveJob(j)
delete(c.ExecJobs, name)
}
}

// Check for aditions
for newJobsName, newJob := range parsedLabelConfig.ExecJobs {
found := false
for name := range c.ExecJobs {
if name == newJobsName {
found = true
break
}
}
if !found {
defaults.SetDefaults(newJob)
newJob.Client = c.dockerHandler.GetInternalDockerClient()
newJob.Name = newJobsName
newJob.buildMiddlewares()
c.sh.AddJob(newJob)
c.ExecJobs[newJobsName] = newJob
}
}
newConfig := NewConfig(c.logger)
newConfig.Global = parsedLabelConfig.Global
newConfig.ExecJobs = parsedLabelConfig.ExecJobs
newConfig.RunJobs = parsedLabelConfig.RunJobs
newConfig.LocalJobs = parsedLabelConfig.LocalJobs
newConfig.ServiceJobs = parsedLabelConfig.ServiceJobs

c.updateExecJobs(newConfig, true)
}

func (c *Config) fileConfigUpdate(newConfig *Config) {
c.updateExecJobs(newConfig)
c.updateExecJobs(newConfig, false)
}

// ExecJobConfig contains all configuration params needed to build a ExecJob
Expand Down
2 changes: 1 addition & 1 deletion cli/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (c *DaemonCommand) boot() (err error) {
c.Logger.Debugf("Cannot read config file: %q", err)
}

err = config.InitializeApp(c.ConfigFile, c.DisableDocker)
err = config.InitializeApp(c)
if err != nil {
c.Logger.Criticalf("Can't start the app: %v", err)
}
Expand Down
64 changes: 33 additions & 31 deletions cli/file_config_handler.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package cli

import (
"crypto/sha256"
"fmt"
"github.com/PremoWeb/Chadburn/core"
"io"
"os"
"time"
"github.com/fsnotify/fsnotify"
)

type FileConfigHandler struct {
Expand All @@ -29,37 +25,43 @@ func NewFileConfigHandler(configFile string, notifier fileConfigUpdate, logger c
}

func (c *FileConfigHandler) watch() {
cfgHash := c.getCfgHash(c.ConfigFile)
tick := time.Tick(10000 * time.Millisecond)
for {
select {
case <-tick:
newCfgHash := c.getCfgHash(c.ConfigFile)
if cfgHash != newCfgHash {
c.logger.Debugf("config file has changed,old hash:%s,new hash:%s", cfgHash, newCfgHash)
config, err := BuildFromFile(c.ConfigFile, c.logger)
if err != nil {
c.logger.Debugf("Cannot read config file: %q", err)
watcher, err := fsnotify.NewWatcher()
if err != nil {
c.logger.Errorf("create watcher err:%s", err.Error())
}
defer watcher.Close()

go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}

if (event.Has(fsnotify.Write) || event.Has(fsnotify.Create)) && event.Name == c.ConfigFile {

c.logger.Debugf("config file has changed %s", event.Name)

config, err := BuildFromFile(c.ConfigFile, c.logger)
if err != nil {
c.logger.Debugf("Cannot read config file: %q", err)
}
c.notifier.fileConfigUpdate(config)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
c.notifier.fileConfigUpdate(config)
cfgHash = newCfgHash
c.logger.Errorf("watcher err:%s", err.Error())
}
}
}
}
}()

func (c *FileConfigHandler) getCfgHash(filename string) string {
file, err := os.Open(filename)
defer file.Close()
err = watcher.Add(c.ConfigFile)
if err != nil {
c.logger.Errorf("filename:%s,err:%s", filename, err.Error())
}

hash := sha256.New()
if _, err := io.Copy(hash, file); err != nil {
c.logger.Errorf("filename:%s,err:%s", filename, err.Error())
c.logger.Errorf("watcher err:%s", err.Error())
}
sum := fmt.Sprintf("%x", hash.Sum(nil))

return sum
select {}
}
1 change: 1 addition & 0 deletions core/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ func (c *middlewareContainer) Use(ms ...Middleware) {
}

t := reflect.TypeOf(m).String()
// 注释允许替换中间件
//if _, ok := c.m[t]; ok {
// continue
//}
Expand Down
41 changes: 38 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/PremoWeb/Chadburn

go 1.15
go 1.17

require (
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
Expand All @@ -9,6 +9,7 @@ require (
github.com/gobs/args v0.0.0-20180315064131-86002b4df18c
github.com/jessevdk/go-flags v1.4.0
github.com/mcuadros/go-defaults v1.2.0
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/mitchellh/mapstructure v1.3.3
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/robfig/cron/v3 v3.0.1
Expand All @@ -18,9 +19,43 @@ require (
)

require (
github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/Microsoft/go-winio v0.4.15-0.20200113171025-3fe6c5262873 // indirect
github.com/Microsoft/hcsshim v0.8.7 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/containerd/containerd v1.3.0 // indirect
github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c // indirect
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/gogo/protobuf v1.3.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/gorilla/mux v1.7.4 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
github.com/kr/text v0.1.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v0.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/sirupsen/logrus v1.6.0 // indirect
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
golang.org/x/sys v0.4.0 // indirect
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect
google.golang.org/grpc v1.31.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
)

require (
github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23
github.com/fsnotify/fsnotify v1.7.0
github.com/prometheus/client_golang v1.13.0
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
Loading

0 comments on commit 12fba57

Please sign in to comment.