From 43a1b42f8c522f70f8dd5e70b68d0fb48ea89949 Mon Sep 17 00:00:00 2001 From: Stephen van Beek Date: Fri, 10 Mar 2023 09:39:14 +0000 Subject: [PATCH 01/10] Added the additional_ports configuration ISSUE: https://github.com/mrsked/mrsk/issues/98 --- README.md | 36 +++++++++++++++++++++++++++++++++++ lib/mrsk/commands/traefik.rb | 9 +++++++++ test/commands/traefik_test.rb | 11 +++++++++++ 3 files changed, 56 insertions(+) diff --git a/README.md b/README.md index 56d26116..eb1f0aab 100644 --- a/README.md +++ b/README.md @@ -426,6 +426,42 @@ traefik: host_port: 8080 ``` +### Additional entrypoints for traefik + +You can configure additional ports and entrypoints for traefik list so: + +```yaml +traefik: + additional_ports: + - 9000 + - 9001 + args: + entrypoints.myentrypoint.address: ":9000" + entrypoints.otherentrypoint.address: ":9001" +``` + +Be aware, a lot of the out-of-the-box magic of mrsk is provided by traefik defaults so going down this path requires more manual configuration, like so: + +A more complete example including entrypoints would be: + +```yaml +service: myservice + +labels: + traefik.tcp.routers.other.rule: 'HostSNI(`*`)' + traefik.tcp.routers.other.entrypoints: otherentrypoint + traefik.tcp.services.other.loadbalancer.server.port: 9000 + traefik.http.routers.myservice.entrypoints: web + traefik.http.services.myservice.loadbalancer.server.port: 8080 + +traefik: + additional_ports: + - 9000 + args: + 'entrypoints.web.address=:80': true + 'entrypoints.otherentrypoint.address=:9000': true +``` + ### Configuring build args for new images Build arguments that aren't secret can also be configured: diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index b9ff19c1..acda3cf5 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -9,6 +9,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base "--restart", "unless-stopped", "--log-opt", "max-size=#{MAX_LOG_SIZE}", "--publish", port, + *additional_ports, "--volume", "/var/run/docker.sock:/var/run/docker.sock", "traefik", "--providers.docker", @@ -54,6 +55,14 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base end private + def additional_ports + if args = config.raw_config.dig(:traefik, "additional_ports") + args.collect { |value| "--publish #{value}:#{value}" }.compact + else + [] + end + end + def cmd_option_args if args = config.traefik["args"] optionize args, with: "=" diff --git a/test/commands/traefik_test.rb b/test/commands/traefik_test.rb index 5ca51e13..58d0a557 100644 --- a/test/commands/traefik_test.rb +++ b/test/commands/traefik_test.rb @@ -19,6 +19,17 @@ class CommandsTraefikTest < ActiveSupport::TestCase new_command.run.join(" ") end + test "run with additional entrypoints" do + assert_equal \ + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + new_command.run.join(" ") + + @config[:traefik]["additional_ports"] = %w[9000 9001] + assert_equal \ + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --publish 9000:9000 --publish 9001:9001 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + new_command.run.join(" ") + end + test "run without configuration" do @config.delete(:traefik) From 2cea12c56bc0330c9281dd321f69e9040dfe783c Mon Sep 17 00:00:00 2001 From: Stephen van Beek Date: Fri, 10 Mar 2023 14:08:06 +0000 Subject: [PATCH 02/10] Modified in response to PR comments --- README.md | 9 +++++---- lib/mrsk/commands/traefik.rb | 9 ++++----- test/commands/traefik_test.rb | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index eb1f0aab..448d8aaf 100644 --- a/README.md +++ b/README.md @@ -426,13 +426,13 @@ traefik: host_port: 8080 ``` -### Additional entrypoints for traefik +### Configure entrypoints for traefik -You can configure additional ports and entrypoints for traefik list so: +You can override the ports and entrypoints for traefik list so: ```yaml traefik: - additional_ports: + ports: - 9000 - 9001 args: @@ -455,7 +455,8 @@ labels: traefik.http.services.myservice.loadbalancer.server.port: 8080 traefik: - additional_ports: + ports: + - 80 - 9000 args: 'entrypoints.web.address=:80': true diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index acda3cf5..a6e2e229 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -8,8 +8,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base "--detach", "--restart", "unless-stopped", "--log-opt", "max-size=#{MAX_LOG_SIZE}", - "--publish", port, - *additional_ports, + *published_ports, "--volume", "/var/run/docker.sock:/var/run/docker.sock", "traefik", "--providers.docker", @@ -55,11 +54,11 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base end private - def additional_ports - if args = config.raw_config.dig(:traefik, "additional_ports") + def published_ports + if args = config.raw_config.dig(:traefik, "ports") args.collect { |value| "--publish #{value}:#{value}" }.compact else - [] + ["--publish #{port}"] end end diff --git a/test/commands/traefik_test.rb b/test/commands/traefik_test.rb index 58d0a557..300565c0 100644 --- a/test/commands/traefik_test.rb +++ b/test/commands/traefik_test.rb @@ -19,14 +19,14 @@ class CommandsTraefikTest < ActiveSupport::TestCase new_command.run.join(" ") end - test "run with additional entrypoints" do + test "run with ports configured" do assert_equal \ "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") - @config[:traefik]["additional_ports"] = %w[9000 9001] + @config[:traefik]["ports"] = %w[9000 9001] assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --publish 9000:9000 --publish 9001:9001 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 9000:9000 --publish 9001:9001 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end From 2db1bfde00ea2c6223eb204a49f67f249bcfc3fa Mon Sep 17 00:00:00 2001 From: Stephen van Beek Date: Tue, 14 Mar 2023 19:55:37 +0000 Subject: [PATCH 03/10] Added volume configuration in response to issue coments --- README.md | 35 ++++++++++++++++++++++++----------- lib/mrsk/commands/traefik.rb | 14 +++++++++++--- test/commands/traefik_test.rb | 24 +++++++++++++++++++++++- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 448d8aaf..c84d34ad 100644 --- a/README.md +++ b/README.md @@ -426,21 +426,31 @@ traefik: host_port: 8080 ``` -### Configure entrypoints for traefik +### Configure docker options for traefik -You can override the ports and entrypoints for traefik list so: +We allow users to override the published ports and bound volumes for the traefik container like so: ```yaml traefik: - ports: + options: + publish: - 9000 - - 9001 - args: - entrypoints.myentrypoint.address: ":9000" - entrypoints.otherentrypoint.address: ":9001" + - 80 ``` -Be aware, a lot of the out-of-the-box magic of mrsk is provided by traefik defaults so going down this path requires more manual configuration, like so: +Note, this fully overrides any defaults. If you choose to do this, then you'll like need to start out by copying the +default configuration: + +```yaml +traefik: + options: + publish: + - 80 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + args: + 'entrypoints.web.address=:80': true +``` A more complete example including entrypoints would be: @@ -455,9 +465,12 @@ labels: traefik.http.services.myservice.loadbalancer.server.port: 8080 traefik: - ports: - - 80 - - 9000 + options: + publish: + - 80 + - 9000 + volumes: + - /var/run/docker.sock:/var/run/docker.sock args: 'entrypoints.web.address=:80': true 'entrypoints.otherentrypoint.address=:9000': true diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index a6e2e229..65654751 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -9,7 +9,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base "--restart", "unless-stopped", "--log-opt", "max-size=#{MAX_LOG_SIZE}", *published_ports, - "--volume", "/var/run/docker.sock:/var/run/docker.sock", + *volumes, "traefik", "--providers.docker", "--log.level=DEBUG", @@ -55,13 +55,21 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base private def published_ports - if args = config.raw_config.dig(:traefik, "ports") - args.collect { |value| "--publish #{value}:#{value}" }.compact + if ports = config.raw_config.dig(:traefik, "options", "publish") + ports.collect { |value| "--publish #{value}:#{value}" }.compact else ["--publish #{port}"] end end + def volumes + if volumes = config.raw_config.dig(:traefik, "options", "volumes") + volumes.collect { |value| "--volume #{value}" }.compact + else + ["--volume /var/run/docker.sock:/var/run/docker.sock"] + end + end + def cmd_option_args if args = config.traefik["args"] optionize args, with: "=" diff --git a/test/commands/traefik_test.rb b/test/commands/traefik_test.rb index 300565c0..a3f1adb2 100644 --- a/test/commands/traefik_test.rb +++ b/test/commands/traefik_test.rb @@ -24,12 +24,34 @@ class CommandsTraefikTest < ActiveSupport::TestCase "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") - @config[:traefik]["ports"] = %w[9000 9001] + @config[:traefik]["options"] = {"publish" => [9000, 9001]} assert_equal \ "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 9000:9000 --publish 9001:9001 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end + test "run with volumes configured" do + assert_equal \ + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + new_command.run.join(" ") + + @config[:traefik]["options"] = {"volumes" => %w[/var/run/docker.sock:/var/run/docker.sock ./letsencrypt/acme.json:/letsencrypt/acme.json] } + assert_equal \ + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + new_command.run.join(" ") + end + + test "run with ports and volumes configured" do + assert_equal \ + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + new_command.run.join(" ") + + @config[:traefik]["options"] = {"volumes" => %w[/var/run/docker.sock:/var/run/docker.sock ./letsencrypt/acme.json:/letsencrypt/acme.json], "publish" => [80, 8080] } + assert_equal \ + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --publish 8080:8080 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + new_command.run.join(" ") + end + test "run without configuration" do @config.delete(:traefik) From 53046efad4f5624ee8a942242bfa53d82a604be6 Mon Sep 17 00:00:00 2001 From: Stephen van Beek Date: Tue, 14 Mar 2023 20:11:09 +0000 Subject: [PATCH 04/10] Rebased on main --- README.md | 6 +++--- test/commands/traefik_test.rb | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c84d34ad..b5b65359 100644 --- a/README.md +++ b/README.md @@ -449,7 +449,7 @@ traefik: volumes: - /var/run/docker.sock:/var/run/docker.sock args: - 'entrypoints.web.address=:80': true + entrypoints.web.address: ':80' ``` A more complete example including entrypoints would be: @@ -472,8 +472,8 @@ traefik: volumes: - /var/run/docker.sock:/var/run/docker.sock args: - 'entrypoints.web.address=:80': true - 'entrypoints.otherentrypoint.address=:9000': true + entrypoints.web.address: ':80' + entrypoints.otherentrypoint.address: ':9000' ``` ### Configuring build args for new images diff --git a/test/commands/traefik_test.rb b/test/commands/traefik_test.rb index a3f1adb2..1d0cf17a 100644 --- a/test/commands/traefik_test.rb +++ b/test/commands/traefik_test.rb @@ -21,34 +21,34 @@ class CommandsTraefikTest < ActiveSupport::TestCase test "run with ports configured" do assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") @config[:traefik]["options"] = {"publish" => [9000, 9001]} assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 9000:9000 --publish 9001:9001 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 9000:9000 --publish 9001:9001 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end test "run with volumes configured" do assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") @config[:traefik]["options"] = {"volumes" => %w[/var/run/docker.sock:/var/run/docker.sock ./letsencrypt/acme.json:/letsencrypt/acme.json] } assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end test "run with ports and volumes configured" do assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") @config[:traefik]["options"] = {"volumes" => %w[/var/run/docker.sock:/var/run/docker.sock ./letsencrypt/acme.json:/letsencrypt/acme.json], "publish" => [80, 8080] } assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --publish 8080:8080 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format \"json\" --metrics.prometheus.buckets \"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --publish 8080:8080 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end From c2ca269eb6943194dd9a8917106d54d0a8bda4b2 Mon Sep 17 00:00:00 2001 From: Stephen van Beek Date: Tue, 14 Mar 2023 20:12:11 +0000 Subject: [PATCH 05/10] Fixed readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b5b65359..fcfeb439 100644 --- a/README.md +++ b/README.md @@ -436,6 +436,8 @@ traefik: publish: - 9000 - 80 + volumes: + - /tmp/example:/tmp/example ``` Note, this fully overrides any defaults. If you choose to do this, then you'll like need to start out by copying the From 9843c5e1ce8f7ac895340e6f6a3a6277776826ba Mon Sep 17 00:00:00 2001 From: Stephen van Beek Date: Tue, 14 Mar 2023 20:13:13 +0000 Subject: [PATCH 06/10] Fixed typos --- README.md | 2 +- lib/mrsk/commands/traefik.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fcfeb439..da56ed0a 100644 --- a/README.md +++ b/README.md @@ -449,7 +449,7 @@ traefik: publish: - 80 volumes: - - /var/run/docker.sock:/var/run/docker.sock + - /var/run/docker.sock:/var/run/docker.sock args: entrypoints.web.address: ':80' ``` diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index 65654751..f6017004 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -9,7 +9,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base "--restart", "unless-stopped", "--log-opt", "max-size=#{MAX_LOG_SIZE}", *published_ports, - *volumes, + *volumes, "traefik", "--providers.docker", "--log.level=DEBUG", From 4c542930c56ff1ab92fb15c97c7b926c6b9343ce Mon Sep 17 00:00:00 2001 From: Stephen van Beek Date: Wed, 15 Mar 2023 15:37:10 +0000 Subject: [PATCH 07/10] Allow arbitrary docker options for traefik --- README.md | 34 +++++++++++----------------------- lib/mrsk/commands/traefik.rb | 21 +++++++-------------- lib/mrsk/utils.rb | 10 ++++++++-- test/commands/traefik_test.rb | 14 +++++++------- 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index da56ed0a..1293e9da 100644 --- a/README.md +++ b/README.md @@ -428,33 +428,24 @@ traefik: ### Configure docker options for traefik -We allow users to override the published ports and bound volumes for the traefik container like so: - -```yaml -traefik: - options: - publish: - - 9000 - - 80 - volumes: - - /tmp/example:/tmp/example -``` - -Note, this fully overrides any defaults. If you choose to do this, then you'll like need to start out by copying the -default configuration: +We allow users to pass additional docker options to the trafik container like ```yaml traefik: options: publish: - - 80 + - 8080:8080 volumes: - - /var/run/docker.sock:/var/run/docker.sock - args: - entrypoints.web.address: ':80' + - /tmp/example.json:/tmp/example.json + memory: 512m ``` -A more complete example including entrypoints would be: +This will start the traefik container with a command like: `docker run ... --volume /tmp/example.json:/tmp/example.json --publish 8080:8080 ` + + +### Configure alternate entrypoints for traefik + +You can configure multiple entrypoints for traefik like so: ```yaml service: myservice @@ -469,10 +460,7 @@ labels: traefik: options: publish: - - 80 - - 9000 - volumes: - - /var/run/docker.sock:/var/run/docker.sock + - 9000:9000 args: entrypoints.web.address: ':80' entrypoints.otherentrypoint.address: ':9000' diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index f6017004..e09c527b 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -8,8 +8,9 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base "--detach", "--restart", "unless-stopped", "--log-opt", "max-size=#{MAX_LOG_SIZE}", - *published_ports, - *volumes, + "--publish", port, + "--volume", "/var/run/docker.sock:/var/run/docker.sock", + *docker_option_args, "traefik", "--providers.docker", "--log.level=DEBUG", @@ -54,19 +55,11 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base end private - def published_ports - if ports = config.raw_config.dig(:traefik, "options", "publish") - ports.collect { |value| "--publish #{value}:#{value}" }.compact + def docker_option_args + if args = config.raw_config.dig(:traefik, "options") + optionize args else - ["--publish #{port}"] - end - end - - def volumes - if volumes = config.raw_config.dig(:traefik, "options", "volumes") - volumes.collect { |value| "--volume #{value}" }.compact - else - ["--volume /var/run/docker.sock:/var/run/docker.sock"] + [] end end diff --git a/lib/mrsk/utils.rb b/lib/mrsk/utils.rb index 1e763250..249e2ded 100644 --- a/lib/mrsk/utils.rb +++ b/lib/mrsk/utils.rb @@ -25,15 +25,21 @@ module Mrsk::Utils # Returns a list of shell-dashed option arguments. If the value is true, it's treated like a value-less option. def optionize(args, with: nil) + flattened_args = flatten_args args options = if with - args.collect { |(key, value)| value == true ? "--#{key}" : "--#{key}#{with}#{escape_shell_value(value)}" } + flattened_args.collect { |(key, value)| value == true ? "--#{key}" : "--#{key}#{with}#{escape_shell_value(value)}" } else - args.collect { |(key, value)| [ "--#{key}", value == true ? nil : escape_shell_value(value) ] } + flattened_args.collect { |(key, value)| [ "--#{key}", value == true ? nil : escape_shell_value(value) ] } end options.flatten.compact end + # Flattens a one-to-many structure into an array of two-element arrays each containing a key-value pair + def flatten_args(args) + args.flat_map { |key, value| value.respond_to?('map') ? value.map { |entry| [key, entry] }: [[key, value]] } + end + # Copied from SSHKit::Backend::Abstract#redact to be available inside Commands classes def redact(arg) # Used in execute_command to hide redact() args a user passes in arg.to_s.extend(SSHKit::Redaction) # to_s due to our inability to extend Integer, etc diff --git a/test/commands/traefik_test.rb b/test/commands/traefik_test.rb index 1d0cf17a..f2b67f91 100644 --- a/test/commands/traefik_test.rb +++ b/test/commands/traefik_test.rb @@ -24,9 +24,9 @@ class CommandsTraefikTest < ActiveSupport::TestCase "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") - @config[:traefik]["options"] = {"publish" => [9000, 9001]} + @config[:traefik]["options"] = {"publish" => %w[9000:9000 9001:9001]} assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 9000:9000 --publish 9001:9001 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --publish \"9000:9000\" --publish \"9001:9001\" traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end @@ -35,20 +35,20 @@ class CommandsTraefikTest < ActiveSupport::TestCase "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") - @config[:traefik]["options"] = {"volumes" => %w[/var/run/docker.sock:/var/run/docker.sock ./letsencrypt/acme.json:/letsencrypt/acme.json] } + @config[:traefik]["options"] = {"volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json] } assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end - test "run with ports and volumes configured" do + test "run with several options configured" do assert_equal \ "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") - @config[:traefik]["options"] = {"volumes" => %w[/var/run/docker.sock:/var/run/docker.sock ./letsencrypt/acme.json:/letsencrypt/acme.json], "publish" => [80, 8080] } + @config[:traefik]["options"] = {"volume" => %w[./letsencrypt/acme.json:/letsencrypt/acme.json], "publish" => %w[8080:8080], "memory" => "512m"} assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --publish 8080:8080 --volume /var/run/docker.sock:/var/run/docker.sock --volume ./letsencrypt/acme.json:/letsencrypt/acme.json traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", + "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume \"./letsencrypt/acme.json:/letsencrypt/acme.json\" --publish \"8080:8080\" --memory \"512m\" traefik --providers.docker --log.level=DEBUG --accesslog.format=\"json\" --api.insecure --metrics.prometheus.buckets=\"0.1,0.3,1.2,5.0\"", new_command.run.join(" ") end From 9a909ba7ebbb7cca3503234c28ed3f17e413d7cb Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 23 Mar 2023 14:06:15 +0100 Subject: [PATCH 08/10] config.traefik is already nil safe --- lib/mrsk/commands/traefik.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index e09c527b..0b462fa0 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -56,7 +56,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base private def docker_option_args - if args = config.raw_config.dig(:traefik, "options") + if args = config.traefik["options"] optionize args else [] From 8b755c6973fa71b78c56e7f44b6387e95191154a Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 23 Mar 2023 14:24:34 +0100 Subject: [PATCH 09/10] Style --- lib/mrsk/commands/traefik.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/mrsk/commands/traefik.rb b/lib/mrsk/commands/traefik.rb index 0b462fa0..ee86543f 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/mrsk/commands/traefik.rb @@ -10,7 +10,7 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base "--log-opt", "max-size=#{MAX_LOG_SIZE}", "--publish", port, "--volume", "/var/run/docker.sock:/var/run/docker.sock", - *docker_option_args, + *docker_options_args, "traefik", "--providers.docker", "--log.level=DEBUG", @@ -55,12 +55,8 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base end private - def docker_option_args - if args = config.traefik["options"] - optionize args - else - [] - end + def docker_options_args + optionize(config.traefik["options"] || {}) end def cmd_option_args From 951a71f38eb38f893289de0db9451e499fd88dc7 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 23 Mar 2023 14:26:12 +0100 Subject: [PATCH 10/10] Style --- lib/mrsk/utils.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/mrsk/utils.rb b/lib/mrsk/utils.rb index 249e2ded..b7515c5b 100644 --- a/lib/mrsk/utils.rb +++ b/lib/mrsk/utils.rb @@ -25,11 +25,10 @@ module Mrsk::Utils # Returns a list of shell-dashed option arguments. If the value is true, it's treated like a value-less option. def optionize(args, with: nil) - flattened_args = flatten_args args options = if with - flattened_args.collect { |(key, value)| value == true ? "--#{key}" : "--#{key}#{with}#{escape_shell_value(value)}" } + flatten_args(args).collect { |(key, value)| value == true ? "--#{key}" : "--#{key}#{with}#{escape_shell_value(value)}" } else - flattened_args.collect { |(key, value)| [ "--#{key}", value == true ? nil : escape_shell_value(value) ] } + flatten_args(args).collect { |(key, value)| [ "--#{key}", value == true ? nil : escape_shell_value(value) ] } end options.flatten.compact @@ -37,7 +36,7 @@ module Mrsk::Utils # Flattens a one-to-many structure into an array of two-element arrays each containing a key-value pair def flatten_args(args) - args.flat_map { |key, value| value.respond_to?('map') ? value.map { |entry| [key, entry] }: [[key, value]] } + args.flat_map { |key, value| value.try(:map) { |entry| [key, entry] } || [ [ key, value ] ] } end # Copied from SSHKit::Backend::Abstract#redact to be available inside Commands classes