From dddd190f9eb059d8782a773ed3366974ab78d9f6 Mon Sep 17 00:00:00 2001 From: Alexey Blinov Date: Tue, 2 May 2023 11:55:19 +0500 Subject: [PATCH 1/3] add docker compose profiles support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` full: description: Run all services runner: docker_compose compose: profiles: [workers, backend] ``` Config like this will run `docker compose --profile workers --profile backend up` command. Run options and service configs are ignored even if provided. Can also be a part of subcommand: ``` rails: description: Run Rails commands service: backend command: bundle exec rails subcommands: all: description: Run Rails server, Sidekiq and RabbitMQ workers compose: profiles: [workers, backend] ``` There is an issue with Ctrl+C command in this case: ``` ... Aborting on container exit... [+] Running 9/9 ✔ Container app-realtime-1 Stopped 10.4s ✔ Container app Stopped 0.3s ✔ Container app-rabbitmq-1 Stopped 1.3s ✔ Container app-sidekiq-1 Stopped 10.3s ✔ Container app-faye-1 Stopped 0.2s ✔ Container app-mongodb-1 Stopped 0.2s ✔ Container app-memcached-1 Stopped 0.2s ✔ Container app-database-1 Stopped 1.9s ✔ Container app-redis-1 Stopped 0.1s canceled $ docker container ls --all CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES 67475bb645b3 app-dev:latest "/app/.dockerdev/ent…" About a minute ago Exited (137) 24 seconds ago app-realtime-1 47ab521ae5c7 app-dev:latest "/app/.dockerdev/ent…" About a minute ago Exited (137) 24 seconds ago app-sidekiq-1 22e7a9bd7faf app-dev:latest "/app/.dockerdev/ent…" About a minute ago Exited (1) 34 seconds ago app c96e42e35f18 srv-faye:latest "docker-entrypoint.s…" About a minute ago Exited (0) 24 seconds ago app-faye-1 1816e2dfac59 rabbitmq:3.9.7-management "docker-entrypoint.s…" About a minute ago Exited (0) 33 seconds ago app-rabbitmq-1 6fc9360684fc memcached:1.5.22-alpine "docker-entrypoint.s…" About a minute ago Exited (0) 24 seconds ago app-memcached-1 aa9bde5cf18e redis:5-bullseye "docker-entrypoint.s…" About a minute ago Exited (0) 24 seconds ago app-redis-1 677beebb60a2 mariadb:10.2 "docker-entrypoint.s…" About a minute ago Exited (0) 22 seconds ago app-database-1 014529fd2f5e mongo:4.4.8 "docker-entrypoint.s…" About a minute ago Exited (0) 24 seconds ago app-mongodb-1 ``` I.e. on Ctrl+C, containers are not removed. So, the next `dip up` command may raise an error about missing network. To resolve, `dip down` can be used. Also, `dip down` was slightly updated to remove orphan containers by adding `--remove-orphans` flag. --- README.md | 6 ++++ lib/dip/cli.rb | 2 +- lib/dip/commands/compose.rb | 2 +- .../commands/runners/docker_compose_runner.rb | 22 ++++++++++++++ lib/dip/interaction_tree.rb | 1 + .../runners/docker_compose_runner_spec.rb | 29 +++++++++++++++++++ 6 files changed, 60 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e85604..d8eac75 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,12 @@ interaction: compose: run_options: [service-ports, use-aliases] + stack: + description: Run full stack (server, workers, etc.) + runner: docker_compose + compose: + profiles: [web, workers] + sidekiq: description: Run sidekiq in background service: worker diff --git a/lib/dip/cli.rb b/lib/dip/cli.rb index bec7422..fd528aa 100644 --- a/lib/dip/cli.rb +++ b/lib/dip/cli.rb @@ -78,7 +78,7 @@ def down(*argv) require_relative "commands/down_all" Dip::Commands::DownAll.new.execute else - compose("down", *argv) + compose("down", *argv.push("--remove-orphans")) end end diff --git a/lib/dip/commands/compose.rb b/lib/dip/commands/compose.rb index 433759c..5724e8e 100644 --- a/lib/dip/commands/compose.rb +++ b/lib/dip/commands/compose.rb @@ -13,7 +13,7 @@ class Compose < Dip::Command attr_reader :argv, :config, :shell def initialize(*argv, shell: true) - @argv = argv + @argv = argv.compact @shell = shell @config = ::Dip.config.compose || {} end diff --git a/lib/dip/commands/runners/docker_compose_runner.rb b/lib/dip/commands/runners/docker_compose_runner.rb index 3360090..03170fc 100644 --- a/lib/dip/commands/runners/docker_compose_runner.rb +++ b/lib/dip/commands/runners/docker_compose_runner.rb @@ -9,6 +9,7 @@ module Runners class DockerComposeRunner < Base def execute Commands::Compose.new( + *compose_profiles, command[:compose][:method], *compose_arguments, shell: command[:shell] @@ -17,6 +18,16 @@ def execute private + def compose_profiles + return [] if command[:compose][:profiles].empty? + + update_command_for_profiles + + command[:compose][:profiles].each_with_object([]) do |profile, argv| + argv.concat(["--profile", profile]) + end + end + def compose_arguments compose_argv = command[:compose][:run_options].dup @@ -57,6 +68,17 @@ def published_ports [] end end + + def update_command_for_profiles + # NOTE: When using profiles, the method is always `up`. + # This is because `docker-compose` does not support profiles + # for other commands. Also, run options need to be removed + # because they are not supported by `up`. + command[:compose][:method] = "up" + command[:command] = "" + command[:service] = nil + command[:compose][:run_options] = [] + end end end end diff --git a/lib/dip/interaction_tree.rb b/lib/dip/interaction_tree.rb index 3f9f318..b49cd5c 100644 --- a/lib/dip/interaction_tree.rb +++ b/lib/dip/interaction_tree.rb @@ -68,6 +68,7 @@ def build_command(entry) environment: entry[:environment] || {}, compose: { method: entry.dig(:compose, :method) || entry[:compose_method] || "run", + profiles: Array(entry.dig(:compose, :profiles)), run_options: compose_run_options(entry.dig(:compose, :run_options) || entry[:compose_run_options]) } } diff --git a/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb b/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb index bd89893..f97e820 100644 --- a/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb +++ b/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb @@ -136,6 +136,22 @@ it { expected_exec("docker-compose", ["run", "--rm", "app", "rspec"], env: hash_including("RAILS_ENV" => "test")) } end + context "when config with profiles" do + let(:commands) do + { + stack: { + runner: "docker_compose", + compose_run_options: ["foo", "-bar", "--baz=qux"], + compose: {profiles: ["foo", "bar"]} + } + } + end + + before { cli.start "run stack".shellsplit } + + it { expected_exec("docker-compose", ["--profile", "foo", "--profile", "bar", "up"]) } + end + context "when config with subcommands" do let(:commands) { {rails: {service: "app", command: "rails", subcommands: subcommands}} } let(:subcommands) { {s: {command: "rails server"}} } @@ -188,5 +204,18 @@ env: hash_including("RAILS_ENV" => "test")) end end + + context "when config with profiles" do + let(:subcommands) do + {all: { + compose_run_options: ["foo", "-bar", "--baz=qux"], + compose: {profiles: ["foo", "bar"]}} + } + end + + before { cli.start "run rails all".shellsplit } + + it { expected_exec("docker-compose", ["--profile", "foo", "--profile", "bar", "up"]) } + end end end From 81be61e02945c7b33a06e95f8c84ae9c140c3720 Mon Sep 17 00:00:00 2001 From: Alexey Blinov Date: Sat, 6 May 2023 16:39:09 +0500 Subject: [PATCH 2/3] fix rubocop findings --- spec/lib/dip/commands/compose_spec.rb | 12 ++++++------ .../commands/runners/docker_compose_runner_spec.rb | 8 +++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/spec/lib/dip/commands/compose_spec.rb b/spec/lib/dip/commands/compose_spec.rb index f61d3c4..a574da1 100644 --- a/spec/lib/dip/commands/compose_spec.rb +++ b/spec/lib/dip/commands/compose_spec.rb @@ -76,16 +76,16 @@ context "when config contains multiple docker-compose files", config: true do context "and some files are not exist" do let(:config) { {compose: {files: %w[file1.yml file2.yml file3.yml]}} } - let(:file1) { fixture_path("empty", "file1.yml") } - let(:file2) { fixture_path("empty", "file2.yml") } - let(:file3) { fixture_path("empty", "file3.yml") } + let(:global_file) { fixture_path("empty", "file1.yml") } + let(:local_file) { fixture_path("empty", "file2.yml") } + let(:override_file) { fixture_path("empty", "file3.yml") } before do allow_any_instance_of(Pathname).to receive(:exist?) do |obj| case obj.to_s - when file1, file3 + when global_file, override_file true - when file2 + when local_file false else File.exist?(obj.to_s) @@ -95,7 +95,7 @@ cli.start "compose run".shellsplit end - it { expected_exec("docker-compose", ["--file", file1, "--file", file3, "run"]) } + it { expected_exec("docker-compose", ["--file", global_file, "--file", override_file, "run"]) } end context "and a file name contains env var", env: true do diff --git a/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb b/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb index f97e820..b992793 100644 --- a/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb +++ b/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb @@ -207,9 +207,11 @@ context "when config with profiles" do let(:subcommands) do - {all: { - compose_run_options: ["foo", "-bar", "--baz=qux"], - compose: {profiles: ["foo", "bar"]}} + { + all: { + compose_run_options: ["foo", "-bar", "--baz=qux"], + compose: {profiles: ["foo", "bar"]} + } } end From 1e38172d0c53e433b4c1322c72f503c4c5a27036 Mon Sep 17 00:00:00 2001 From: Alexey Blinov Date: Sun, 14 May 2023 18:53:17 +0500 Subject: [PATCH 3/3] do not nullify `service` option when profiles are used --- lib/dip/commands/runners/docker_compose_runner.rb | 1 - spec/lib/dip/commands/runners/docker_compose_runner_spec.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/dip/commands/runners/docker_compose_runner.rb b/lib/dip/commands/runners/docker_compose_runner.rb index 03170fc..669c536 100644 --- a/lib/dip/commands/runners/docker_compose_runner.rb +++ b/lib/dip/commands/runners/docker_compose_runner.rb @@ -76,7 +76,6 @@ def update_command_for_profiles # because they are not supported by `up`. command[:compose][:method] = "up" command[:command] = "" - command[:service] = nil command[:compose][:run_options] = [] end end diff --git a/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb b/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb index b992793..a5803b7 100644 --- a/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb +++ b/spec/lib/dip/commands/runners/docker_compose_runner_spec.rb @@ -217,7 +217,7 @@ before { cli.start "run rails all".shellsplit } - it { expected_exec("docker-compose", ["--profile", "foo", "--profile", "bar", "up"]) } + it { expected_exec("docker-compose", ["--profile", "foo", "--profile", "bar", "up", "app"]) } end end end