From 03488bc67ad24e1857948882b970154026d3a5b4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 23 Jan 2023 13:36:47 +0100 Subject: [PATCH] Add managed accessory directories --- lib/mrsk/cli/accessory.rb | 20 ++++++++++--- lib/mrsk/commands/accessory.rb | 10 +++++-- lib/mrsk/configuration/accessory.rb | 34 ++++++++++++++++++++--- test/cli/accessory_test.rb | 14 +++++++++- test/configuration/accessory_test.rb | 9 +++++- test/fixtures/deploy_with_accessories.yml | 8 +++--- 6 files changed, 78 insertions(+), 17 deletions(-) diff --git a/lib/mrsk/cli/accessory.rb b/lib/mrsk/cli/accessory.rb index cf3775ec..90245dd4 100644 --- a/lib/mrsk/cli/accessory.rb +++ b/lib/mrsk/cli/accessory.rb @@ -6,6 +6,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base if name == "all" MRSK.accessory_names.each { |accessory_name| boot(accessory_name) } else + directories(name) upload(name) accessory = MRSK.accessory(name) @@ -19,6 +20,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base on(accessory.host) do accessory.files.each do |(local, remote)| accessory.ensure_local_file_present(local) + execute *accessory.make_directory_for(remote) upload! local, remote execute :chmod, "755", remote @@ -26,6 +28,16 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base end end + desc "directories [NAME]", "Create accessory directories on host" + def directories(name) + accessory = MRSK.accessory(name) + on(accessory.host) do + accessory.directories.keys.each do |host_path| + execute *accessory.make_directory(host_path) + end + end + end + desc "reboot [NAME]", "Reboot accessory on host (stop container, remove container, start new container)" def reboot(name) stop(name) @@ -114,7 +126,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base stop(name) remove_container(name) remove_image(name) - remove_files(name) + remove_service_directory(name) end end @@ -130,9 +142,9 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base on(accessory.host) { execute *accessory.remove_image } end - desc "remove_files [NAME]", "Remove accessory directory used for uploaded files from host" - def remove_files(name) + desc "remove_service_directory [NAME]", "Remove accessory directory used for uploaded files and data directories from host" + def remove_service_directory(name) accessory = MRSK.accessory(name) - on(accessory.host) { execute *accessory.remove_files } + on(accessory.host) { execute *accessory.remove_service_directory } end end diff --git a/lib/mrsk/commands/accessory.rb b/lib/mrsk/commands/accessory.rb index 8791eed6..4e02c469 100644 --- a/lib/mrsk/commands/accessory.rb +++ b/lib/mrsk/commands/accessory.rb @@ -2,7 +2,7 @@ require "mrsk/commands/base" class Mrsk::Commands::Accessory < Mrsk::Commands::Base attr_reader :accessory_config - delegate :service_name, :image, :host, :port, :files, :env_args, :volume_args, :label_args, to: :accessory_config + delegate :service_name, :image, :host, :port, :files, :directories, :env_args, :volume_args, :label_args, to: :accessory_config def initialize(config, name:) super(config) @@ -76,10 +76,14 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base end def make_directory_for(remote_file) - [ :mkdir, "-p", Pathname.new(remote_file).dirname.to_s ] + make_directory Pathname.new(remote_file).dirname.to_s end - def remove_files + def make_directory(path) + [ :mkdir, "-p", path ] + end + + def remove_service_directory [ :rm, "-rf", service_name ] end diff --git a/lib/mrsk/configuration/accessory.rb b/lib/mrsk/configuration/accessory.rb index 5d36063c..9b0fad45 100644 --- a/lib/mrsk/configuration/accessory.rb +++ b/lib/mrsk/configuration/accessory.rb @@ -50,8 +50,15 @@ class Mrsk::Configuration::Assessory end || {} end + def directories + specifics["directories"]&.to_h do |host_to_container_mapping| + host_relative_path, container_path = host_to_container_mapping.split(":") + [ expand_host_path(host_relative_path), container_path ] + end || {} + end + def volumes - (specifics["volumes"] || []) + remote_files_as_volumes + specific_volumes + remote_files_as_volumes + remote_directories_as_volumes end def volume_args @@ -73,18 +80,37 @@ class Mrsk::Configuration::Assessory end end + def read_dynamic_file(local_file) + StringIO.new(ERB.new(IO.read(local_file)).result) + end + def expand_remote_file(remote_file) service_name + remote_file end + def specific_volumes + specifics["volumes"] || [] + end + def remote_files_as_volumes specifics["files"]&.collect do |local_to_remote_mapping| _, remote_file = local_to_remote_mapping.split(":") - "$PWD/#{expand_remote_file(remote_file)}:#{remote_file}" + "#{service_data_directory + remote_file}:#{remote_file}" end || [] end - def read_dynamic_file(local_file) - StringIO.new(ERB.new(IO.read(local_file)).result) + def remote_directories_as_volumes + specifics["directories"]&.collect do |host_to_container_mapping| + host_relative_path, container_path = host_to_container_mapping.split(":") + [ expand_host_path(host_relative_path), container_path ].join(":") + end || [] + end + + def expand_host_path(host_relative_path) + "#{service_data_directory}/#{host_relative_path}" + end + + def service_data_directory + "$PWD/#{service_name}" end end diff --git a/test/cli/accessory_test.rb b/test/cli/accessory_test.rb index 5ecd473b..d92d1579 100644 --- a/test/cli/accessory_test.rb +++ b/test/cli/accessory_test.rb @@ -14,9 +14,21 @@ class CliAccessoryTest < ActiveSupport::TestCase assert_match "test/fixtures/files/my.cnf app-mysql/etc/mysql/my.cnf", command end + test "directories" do + command = stdouted { Mrsk::Cli::Accessory.start(["directories", "mysql", "-c", "test/fixtures/deploy_with_accessories.yml"]) } + + assert_match "mkdir -p $PWD/app-mysql/data", command + end + + test "remove service direcotry" do + command = stdouted { Mrsk::Cli::Accessory.start(["remove_service_directory", "mysql", "-c", "test/fixtures/deploy_with_accessories.yml"]) } + + assert_match "rm -rf app-mysql", command + end + test "boot" do command = stdouted { Mrsk::Cli::Accessory.start(["boot", "mysql", "-c", "test/fixtures/deploy_with_accessories.yml"]) } - assert_match "Running docker run --name app-mysql -d --restart unless-stopped -p 3306:3306 -e [REDACTED] -e MYSQL_ROOT_HOST=% --volume /var/lib/mysql:/var/lib/mysql --volume $PWD/app-mysql/etc/mysql/my.cnf:/etc/mysql/my.cnf --label service=app-mysql mysql:5.7 on 1.1.1.3", command + assert_match "Running docker run --name app-mysql -d --restart unless-stopped -p 3306:3306 -e [REDACTED] -e MYSQL_ROOT_HOST=% --volume $PWD/app-mysql/etc/mysql/my.cnf:/etc/mysql/my.cnf --volume $PWD/app-mysql/data:/var/lib/mysql --label service=app-mysql mysql:5.7 on 1.1.1.3", command end end diff --git a/test/configuration/accessory_test.rb b/test/configuration/accessory_test.rb index 54c39bfa..2098d0fa 100644 --- a/test/configuration/accessory_test.rb +++ b/test/configuration/accessory_test.rb @@ -23,6 +23,9 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase "files" => [ "config/mysql/my.cnf:/etc/mysql/my.cnf", "db/structure.sql:/docker-entrypoint-initdb.d/structure.sql" + ], + "directories" => [ + "data:/var/lib/mysql" ] }, "redis" => { @@ -87,7 +90,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase end test "volume args" do - assert_equal ["--volume", "$PWD/app-mysql/etc/mysql/my.cnf:/etc/mysql/my.cnf", "--volume", "$PWD/app-mysql/docker-entrypoint-initdb.d/structure.sql:/docker-entrypoint-initdb.d/structure.sql"], @config.accessory(:mysql).volume_args + assert_equal ["--volume", "$PWD/app-mysql/etc/mysql/my.cnf:/etc/mysql/my.cnf", "--volume", "$PWD/app-mysql/docker-entrypoint-initdb.d/structure.sql:/docker-entrypoint-initdb.d/structure.sql", "--volume", "$PWD/app-mysql/data:/var/lib/mysql"], @config.accessory(:mysql).volume_args assert_equal ["--volume", "/var/lib/redis:/data"], @config.accessory(:redis).volume_args end @@ -97,4 +100,8 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase assert_equal "This was dynamically expanded", @config.accessory(:mysql).files.keys[2].read end + + test "directories" do + assert_equal({"$PWD/app-mysql/data"=>"/var/lib/mysql"}, @config.accessory(:mysql).directories) + end end diff --git a/test/fixtures/deploy_with_accessories.yml b/test/fixtures/deploy_with_accessories.yml index e4f82fce..ee9d84fb 100644 --- a/test/fixtures/deploy_with_accessories.yml +++ b/test/fixtures/deploy_with_accessories.yml @@ -17,13 +17,13 @@ accessories: MYSQL_ROOT_HOST: '%' secret: - MYSQL_ROOT_PASSWORD - volumes: - - /var/lib/mysql:/var/lib/mysql files: - test/fixtures/files/my.cnf:/etc/mysql/my.cnf + directories: + - data:/var/lib/mysql redis: image: redis:latest host: 1.1.1.4 port: 6379 - volumes: - - /var/lib/redis:/data + directories: + - data:/data