From 44ac008a34905eb4ceb540a213a2238e4545b4df Mon Sep 17 00:00:00 2001 From: Taras <9948629+taraspos@users.noreply.github.com> Date: Thu, 26 Dec 2024 14:04:27 +0000 Subject: [PATCH] feat(`job-run`): Add `volumes-from` parameter (#309) * add volumes-from option * Add tests * Update jobs.md --------- Co-authored-by: Martin Tomisch --- cli/config_test.go | 118 ++++++++++++++++++++++++++++++++++++++++++- cli/docker-labels.go | 10 +--- core/runjob.go | 4 +- docs/jobs.md | 12 ++++- 4 files changed, 133 insertions(+), 11 deletions(-) diff --git a/cli/config_test.go b/cli/config_test.go index 8c42818ba..65e04804b 100644 --- a/cli/config_test.go +++ b/cli/config_test.go @@ -1,12 +1,14 @@ package cli import ( + "encoding/json" "testing" defaults "github.com/mcuadros/go-defaults" "github.com/mcuadros/ofelia/core" "github.com/mcuadros/ofelia/middlewares" . "gopkg.in/check.v1" + gcfg "gopkg.in/gcfg.v1" ) func Test(t *testing.T) { TestingT(t) } @@ -68,6 +70,76 @@ func (s *SuiteConfig) TestExecJobBuild(c *C) { c.Assert(j.Middlewares(), HasLen, 1) } +func (s *SuiteConfig) TestConfigIni(c *C) { + testcases := []struct { + Ini string + ExpectedConfig Config + Comment string + }{ + { + Ini: ` + [job-exec "foo"] + schedule = @every 10s + command = echo \"foo\" + `, + ExpectedConfig: Config{ + ExecJobs: map[string]*ExecJobConfig{ + "foo": {ExecJob: core.ExecJob{BareJob: core.BareJob{ + Schedule: "@every 10s", + Command: `echo "foo"`, + }}}, + }, + }, + Comment: "Test job-exec", + }, + { + Ini: ` + [job-run "foo"] + schedule = @every 10s + environment = "KEY1=value1" + Environment = "KEY2=value2" + `, + ExpectedConfig: Config{ + RunJobs: map[string]*RunJobConfig{ + "foo": {RunJob: core.RunJob{BareJob: core.BareJob{ + Schedule: "@every 10s", + }, + Environment: []string{"KEY1=value1", "KEY2=value2"}, + }}, + }, + }, + Comment: "Test job-run with Env Variables", + }, + { + Ini: ` + [job-run "foo"] + schedule = @every 10s + volumes-from = "volume1" + volumes-from = "volume2" + `, + ExpectedConfig: Config{ + RunJobs: map[string]*RunJobConfig{ + "foo": {RunJob: core.RunJob{BareJob: core.BareJob{ + Schedule: "@every 10s", + }, + VolumesFrom: []string{"volume1", "volume2"}, + }}, + }, + }, + Comment: "Test job-run with Env Variables", + }, + } + + for _, t := range testcases { + conf := Config{} + err := gcfg.ReadStringInto(&conf, t.Ini) + c.Assert(err, IsNil) + if !c.Check(conf, DeepEquals, t.ExpectedConfig) { + c.Errorf("Test %q\nExpected %s, but got %s", t.Comment, toJSON(t.ExpectedConfig), toJSON(conf)) + } + } +} + func (s *SuiteConfig) TestLabelsConfig(c *C) { testcases := []struct { Labels map[string]map[string]string @@ -285,12 +357,56 @@ func (s *SuiteConfig) TestLabelsConfig(c *C) { }, Comment: "Test run job with environment variables", }, + { + Labels: map[string]map[string]string{ + "some": { + requiredLabel: "true", + serviceLabel: "true", + labelPrefix + "." + jobRun + ".job1.schedule": "schedule1", + labelPrefix + "." + jobRun + ".job1.command": "command1", + labelPrefix + "." + jobRun + ".job1.volumes-from": "test123", + labelPrefix + "." + jobRun + ".job2.schedule": "schedule2", + labelPrefix + "." + jobRun + ".job2.command": "command2", + labelPrefix + "." + jobRun + ".job2.volumes-from": `["test321", "test456"]`, + }, + }, + ExpectedConfig: Config{ + RunJobs: map[string]*RunJobConfig{ + "job1": { + RunJob: core.RunJob{ + BareJob: core.BareJob{ + Schedule: "schedule1", + Command: "command1", + }, + VolumesFrom: []string{"test123"}, + }, + }, + "job2": { + RunJob: core.RunJob{ + BareJob: core.BareJob{ + Schedule: "schedule2", + Command: "command2", + }, + VolumesFrom: []string{"test321", "test456"}, + }, + }, + }, + }, + Comment: "Test run job with volumes-from", + }, } for _, t := range testcases { var conf = Config{} err := conf.buildFromDockerLabels(t.Labels) c.Assert(err, IsNil) - c.Assert(conf, DeepEquals, t.ExpectedConfig) + if !c.Check(conf, DeepEquals, t.ExpectedConfig) { + c.Errorf("Test %q\nExpected %s, but got %s", t.Comment, toJSON(t.ExpectedConfig), toJSON(conf)) + } } } + +func toJSON(any interface{}) string { + b, _ := json.MarshalIndent(any, "", " ") + return string(b) +} diff --git a/cli/docker-labels.go b/cli/docker-labels.go index 23a235d8b..663a11c6d 100644 --- a/cli/docker-labels.go +++ b/cli/docker-labels.go @@ -174,19 +174,13 @@ func (c *Config) buildFromDockerLabels(labels map[string]map[string]string) erro } func setJobParam(params map[string]interface{}, paramName, paramVal string) { - switch paramName { - case "volume": + switch strings.ToLower(paramName) { + case "volume", "environment", "volumes-from": arr := []string{} // allow providing JSON arr of volume mounts if err := json.Unmarshal([]byte(paramVal), &arr); err == nil { params[paramName] = arr return } - case "environment": - arr := []string{} // allow providing JSON arr of env keyvalues - if err := json.Unmarshal([]byte(paramVal), &arr); err == nil { - params[paramName] = arr - return - } } params[paramName] = paramVal diff --git a/core/runjob.go b/core/runjob.go index 35ed80b62..6022c51c8 100644 --- a/core/runjob.go +++ b/core/runjob.go @@ -34,6 +34,7 @@ type RunJob struct { Hostname string Container string Volume []string + VolumesFrom []string `gcfg:"volumes-from" mapstructure:"volumes-from,"` Environment []string containerID string @@ -176,7 +177,8 @@ func (j *RunJob) buildContainer() (*docker.Container, error) { }, NetworkingConfig: &docker.NetworkingConfig{}, HostConfig: &docker.HostConfig{ - Binds: j.Volume, + Binds: j.Volume, + VolumesFrom: j.VolumesFrom, }, }) diff --git a/docs/jobs.md b/docs/jobs.md index 3cc252d42..0686d0d6f 100644 --- a/docs/jobs.md +++ b/docs/jobs.md @@ -5,6 +5,10 @@ - [job-local](#job-local) - [job-service-run](#job-service-run) + +>[!IMPORTANT] +>Configuration keys are not case sensitive + ## Job-exec This job is executed inside a running container. Similar to `docker exec` @@ -114,10 +118,16 @@ This job can be used in 2 situations: - **INI config**: `Volume` setting can be provided multiple times for multiple mounts. - **Labels config**: multiple mounts has to be provided as JSON array: `["/test/tmp:/test/tmp:ro", "/test/tmp:/test/tmp:rw"]` - *default*: Optional field, no default. +- **Volumes-From** + - *description*: Use the volumes from another container. + - *value*: The name of the container, from which the volumes will be used. + - **INI config**: setting can be provided multiple times for multiple mounts. + - **Labels config**: multiple mounts has to be provided as JSON array: `["container-foo", "bar-container"]` + - *default*: Optional field, no default. - **Environment** - *description*: Environment variables you want to set in the running container. - *value*: Same format as used with `-e` flag within `docker run`. For example: `FOO=bar` - - **INI config**: `Environment` setting can be provided multiple times for multiple environment variables. + - **INI config**: setting can be provided multiple times for multiple environment variables. - **Labels config**: multiple environment variables has to be provided as JSON array: `["FOO=bar", "BAZ=qux"]` - *default*: Optional field, no default.