diff --git a/README.md b/README.md index e133176e..e3626f4f 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,15 @@ If the referenced secret ENVs are missing, the configuration will be halted with Note: Marking an ENV as secret currently only redacts its value in the output for MRSK. The ENV is still injected in the clear into the container at runtime. +### Adding volumes + +You can add custom volumes into the app containers using `volumes`: + +```yaml +volumes: + - "/local/path:/container/path" +``` + ### Splitting servers into different roles If your application uses separate hosts for running jobs or other roles beyond the default web running, you can specify these hosts and their custom entrypoint command like so: diff --git a/lib/mrsk/commands/app.rb b/lib/mrsk/commands/app.rb index e1faf9dc..73d0990a 100644 --- a/lib/mrsk/commands/app.rb +++ b/lib/mrsk/commands/app.rb @@ -10,6 +10,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base "--name", config.service_with_version, *rails_master_key_arg, *role.env_args, + *config.volumes, *role.label_args, config.absolute_image, role.cmd @@ -43,6 +44,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base ("-it" if interactive), *rails_master_key_arg, *config.env_args, + *config.volumes, config.service_with_version, *command end @@ -53,6 +55,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base "--rm", *rails_master_key_arg, *config.env_args, + *config.volumes, config.absolute_image, *command end diff --git a/lib/mrsk/configuration.rb b/lib/mrsk/configuration.rb index 179cb5f3..ebf2e2d7 100644 --- a/lib/mrsk/configuration.rb +++ b/lib/mrsk/configuration.rb @@ -40,7 +40,6 @@ class Mrsk::Configuration ensure_required_keys_present if validate end - def roles @roles ||= role_names.collect { |role_name| Role.new(role_name, config: self) } end @@ -61,7 +60,6 @@ class Mrsk::Configuration roles.select(&:running_traefik?).flat_map(&:hosts) end - def version @version end @@ -78,7 +76,6 @@ class Mrsk::Configuration "#{service}-#{version}" end - def env_args if config.env.present? argumentize_env_with_secrets(config.env) @@ -87,6 +84,12 @@ class Mrsk::Configuration end end + def volumes + return unless config.volumes.present? + + config.volumes.map { |volume| "--volume #{volume}" } + end + def ssh_user config.ssh_user || "root" end @@ -110,11 +113,11 @@ class Mrsk::Configuration service_with_version: service_with_version, env_args: env_args, ssh_options: ssh_options, - builder: config.builder + builder: config.builder, + volumes: volumes }.compact end - private attr_accessor :config diff --git a/test/commands/app_test.rb b/test/commands/app_test.rb index 5297b6fa..15f72d66 100644 --- a/test/commands/app_test.rb +++ b/test/commands/app_test.rb @@ -15,6 +15,13 @@ class CommandsAppTest < ActiveSupport::TestCase [:docker, :run, "-d", "--restart unless-stopped", "--name", "app-missing", "-e", "RAILS_MASTER_KEY=456", "--label", "service=app", "--label", "role=web", "--label", "traefik.http.routers.app.rule='PathPrefix(`/`)'", "--label", "traefik.http.services.app.loadbalancer.healthcheck.path=/up", "--label", "traefik.http.services.app.loadbalancer.healthcheck.interval=1s", "--label", "traefik.http.middlewares.app.retry.attempts=3", "--label", "traefik.http.middlewares.app.retry.initialinterval=500ms", "dhh/app:missing"], @app.run end + test "run with volumes" do + @config[:volumes] = ["/local/path:/container/path" ] + + assert_equal \ + [:docker, :run, "-d", "--restart unless-stopped", "--name", "app-missing", "-e", "RAILS_MASTER_KEY=456", "--volume /local/path:/container/path", "--label", "service=app", "--label", "role=web", "--label", "traefik.http.routers.app.rule='PathPrefix(`/`)'", "--label", "traefik.http.services.app.loadbalancer.healthcheck.path=/up", "--label", "traefik.http.services.app.loadbalancer.healthcheck.interval=1s", "--label", "traefik.http.middlewares.app.retry.attempts=3", "--label", "traefik.http.middlewares.app.retry.initialinterval=500ms", "dhh/app:missing"], @app.run + end + test "run with" do assert_equal \ [ :docker, :run, "--rm", "-e", "RAILS_MASTER_KEY=456", "dhh/app:missing", "bin/rails", "db:setup" ], diff --git a/test/configuration_test.rb b/test/configuration_test.rb index eff0ddac..46b99338 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -9,7 +9,8 @@ class ConfigurationTest < ActiveSupport::TestCase service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" }, env: { "REDIS_URL" => "redis://x/y" }, - servers: [ "1.1.1.1", "1.1.1.2" ] + servers: [ "1.1.1.1", "1.1.1.2" ], + volumes: ["/local/path:/container/path"] } @config = Mrsk::Configuration.new(@deploy) @@ -84,15 +85,14 @@ class ConfigurationTest < ActiveSupport::TestCase assert_equal "app-missing", @config.service_with_version end - test "env args" do assert_equal [ "-e", "REDIS_URL=redis://x/y" ], @config.env_args end test "env args with clear and secrets" do ENV["PASSWORD"] = "secret123" - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ - env: { "clear" => { "PORT" => "3000" }, "secret" => [ "PASSWORD" ] } + config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ + env: { "clear" => { "PORT" => "3000" }, "secret" => [ "PASSWORD" ] } }) }) assert_equal [ "-e", "PASSWORD=secret123", "-e", "PORT=3000" ], config.env_args @@ -103,8 +103,8 @@ class ConfigurationTest < ActiveSupport::TestCase test "env args with only secrets" do ENV["PASSWORD"] = "secret123" - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ - env: { "secret" => [ "PASSWORD" ] } + config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ + env: { "secret" => [ "PASSWORD" ] } }) }) assert_equal [ "-e", "PASSWORD=secret123" ], config.env_args @@ -114,8 +114,8 @@ class ConfigurationTest < ActiveSupport::TestCase end test "env args with missing secret" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ - env: { "secret" => [ "PASSWORD" ] } + config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ + env: { "secret" => [ "PASSWORD" ] } }) }) assert_raises(KeyError) do @@ -134,6 +134,9 @@ class ConfigurationTest < ActiveSupport::TestCase assert_equal "456", @config.master_key end + test "volumes" do + assert_equal ["--volume /local/path:/container/path"], @config.volumes + end test "erb evaluation of yml config" do config = Mrsk::Configuration.create_from Pathname.new(File.expand_path("fixtures/deploy.erb.yml", __dir__)) @@ -159,6 +162,6 @@ class ConfigurationTest < ActiveSupport::TestCase end test "to_h" do - assert_equal({ :roles=>["web"], :hosts=>["1.1.1.1", "1.1.1.2"], :primary_host=>"1.1.1.1", :version=>"missing", :repository=>"dhh/app", :absolute_image=>"dhh/app:missing", :service_with_version=>"app-missing", :env_args=>["-e", "REDIS_URL=redis://x/y"], :ssh_options=>{:user=>"root", :auth_methods=>["publickey"]} }, @config.to_h) + assert_equal({ :roles=>["web"], :hosts=>["1.1.1.1", "1.1.1.2"], :primary_host=>"1.1.1.1", :version=>"missing", :repository=>"dhh/app", :absolute_image=>"dhh/app:missing", :service_with_version=>"app-missing", :env_args=>["-e", "REDIS_URL=redis://x/y"], :ssh_options=>{:user=>"root", :auth_methods=>["publickey"]}, :volumes=>["--volume /local/path:/container/path"] }, @config.to_h) end end