From 306db13a83c71eaba0874af6b20ccc7d8bcfa86d Mon Sep 17 00:00:00 2001 From: Carlos Becker Date: Mon, 18 Mar 2024 17:08:54 +0100 Subject: [PATCH] Make job-local work with docker labels --- cli/config.go | 59 ++++++++++++++++++++++++++++++++++++++++++++ cli/docker-labels.go | 1 + core/localjob.go | 8 ++++++ 3 files changed, 68 insertions(+) diff --git a/cli/config.go b/cli/config.go index 570d68a..183baab 100644 --- a/cli/config.go +++ b/cli/config.go @@ -119,6 +119,8 @@ func (c *Config) dockerLabelsUpdate(labels map[string]map[string]string) { var parsedLabelConfig Config parsedLabelConfig.buildFromDockerLabels(labels) + // -- Refresh ExecJobs -- + // Calculate the delta for name, j := range c.ExecJobs { // this prevents deletion of jobs that were added by reading a configuration file @@ -175,6 +177,62 @@ func (c *Config) dockerLabelsUpdate(labels map[string]map[string]string) { } } + // -- Refresh LocalJobs -- + + // Calculate the delta + for name, j := range c.LocalJobs { + // this prevents deletion of jobs that were added by reading a configuration file + if !j.FromDockerLabel { + continue + } + + found := false + for newJobsName, newJob := range parsedLabelConfig.LocalJobs { + // 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.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.LocalJobs[name] = newJob + } + break + } + } + if !found { + // Remove the job + c.sh.RemoveJob(j) + delete(c.LocalJobs, name) + } + } + + // Check for aditions + for newJobsName, newJob := range parsedLabelConfig.LocalJobs { + found := false + for name := range c.LocalJobs { + if name == newJobsName { + found = true + break + } + } + if !found { + defaults.SetDefaults(newJob) + newJob.Name = newJobsName + newJob.buildMiddlewares() + c.sh.AddJob(newJob) + c.LocalJobs[newJobsName] = newJob + } + } + } // ExecJobConfig contains all configuration params needed to build a ExecJob @@ -231,6 +289,7 @@ type LocalJobConfig struct { middlewares.SaveConfig `mapstructure:",squash"` middlewares.MailConfig `mapstructure:",squash"` middlewares.GotifyConfig `mapstructure:",squash"` + FromDockerLabel bool `mapstructure:"fromDockerLabel"` } func (c *LocalJobConfig) buildMiddlewares() { diff --git a/cli/docker-labels.go b/cli/docker-labels.go index 511a42a..a15ec26 100644 --- a/cli/docker-labels.go +++ b/cli/docker-labels.go @@ -59,6 +59,7 @@ func (c *Config) buildFromDockerLabels(labels map[string]map[string]string) erro case jobType == jobLocal && isServiceContainer: if _, ok := localJobs[jobName]; !ok { localJobs[jobName] = make(map[string]interface{}) + localJobs[jobName]["fromDockerLabel"] = true } setJobParam(localJobs[jobName], jopParam, v) case jobType == jobServiceRun && isServiceContainer: diff --git a/core/localjob.go b/core/localjob.go index 8089189..1a3e6e3 100644 --- a/core/localjob.go +++ b/core/localjob.go @@ -2,6 +2,7 @@ package core import ( "os/exec" + "reflect" "github.com/gobs/args" ) @@ -16,6 +17,13 @@ func NewLocalJob() *LocalJob { return &LocalJob{} } +// Returns a hash of all the job attributes. Used to detect changes +func (j *LocalJob) Hash() string { + var hash string + getHash(reflect.TypeOf(j).Elem(), reflect.ValueOf(j).Elem(), &hash) + return hash +} + func (j *LocalJob) Run(ctx *Context) error { cmd, err := j.buildCommand(ctx) if err != nil {