Global option for designating primary host only

This commit is contained in:
David Heinemeier Hansson
2023-01-20 17:18:32 +01:00
parent 79b5ed179e
commit 31389bc7b5
7 changed files with 49 additions and 43 deletions

View File

@@ -39,50 +39,34 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.info) }
end
desc "exec [CMD]", "Execute a custom task on servers passed in as CMD='bin/rake some:task'"
option :once, type: :boolean, default: false, desc: "Only perform command on primary host"
desc "exec [CMD]", "Execute a custom command on servers"
option :run, type: :boolean, default: false, desc: "Start a new container to run the command rather than reusing existing"
def exec(cmd)
runner = options[:run] ? :run_exec : :exec
if options[:once]
on(MRSK.config.primary_host) { puts capture_with_info(*MRSK.app.send(runner, cmd)) }
else
on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.send(runner, cmd)) }
end
end
desc "console", "Start Rails Console on primary host"
option :host, desc: "Start console on a different host"
desc "console", "Start Rails Console on primary host (or specific host set by --hosts)"
def console
host = options[:host] || MRSK.config.primary_host
run_locally do
puts "Launching Rails console on #{host}..."
exec MRSK.app.console(host: host)
puts "Launching Rails console on #{MRSK.primary_host}..."
exec MRSK.app.console(host: MRSK.primary_host)
end
end
desc "bash", "Start a bash session on primary host"
option :host, desc: "Start bash on a different host"
def bash
host = options[:host] || MRSK.config.primary_host
run_locally do
puts "Launching bash session on #{host}..."
exec MRSK.app.bash(host: host)
puts "Launching bash session on #{MRSK.primary_host}..."
exec MRSK.app.bash(host: MRSK.primary_host)
end
end
desc "runner [EXPRESSION]", "Execute Rails runner with given expression"
option :once, type: :boolean, default: false, desc: "Only perform runner on primary host"
def runner(expression)
if options[:once]
on(MRSK.config.primary_host) { puts capture_with_info(*MRSK.app.exec("bin/rails", "runner", "'#{expression}'")) }
else
on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.exec("bin/rails", "runner", "'#{expression}'")) }
end
end
desc "containers", "List all the app containers currently on servers"
def containers

View File

@@ -9,6 +9,7 @@ module Mrsk::Cli
class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
class_option :primary, type: :boolean, aliases: "-p", desc: "Run commands only on primary host instead of all"
class_option :hosts, aliases: "-h", desc: "Run commands on these hosts instead of all (separate by comma)"
class_option :roles, aliases: "-r", desc: "Run commands on these roles instead of all (separate by comma)"
@@ -25,9 +26,11 @@ module Mrsk::Cli
MRSK.tap do |commander|
commander.config_file = Pathname.new(File.expand_path(options[:config_file]))
commander.destination = options[:destination]
commander.hosts = options[:hosts]&.split(",")
commander.roles = options[:roles]&.split(",")
commander.verbose = options[:verbose]
commander.specific_hosts = options[:hosts]&.split(",")
commander.specific_roles = options[:roles]&.split(",")
commander.specific_primary! if options[:primary]
end
end

View File

@@ -1,3 +1,5 @@
require "active_support/core_ext/enumerable"
require "mrsk/configuration"
require "mrsk/commands/app"
require "mrsk/commands/builder"
@@ -16,20 +18,26 @@ class Mrsk::Commander
@config ||= Mrsk::Configuration.create_from(config_file, destination: destination).tap { |config| setup_with(config) }
end
def hosts=(hosts)
@hosts = hosts if hosts.present?
attr_accessor :specific_hosts
def specific_primary!
self.specific_hosts = [ config.primary_web_host ]
end
def roles=(role_names)
@hosts = config.roles.select { |r| role_names.include?(r.name) }.flat_map(&:hosts) if role_names.present?
def specific_roles=(role_names)
self.specific_hosts = config.roles.select { |r| role_names.include?(r.name) }.flat_map(&:hosts) if role_names.present?
end
def primary_host
specific_hosts&.sole || config.primary_web_host
end
def hosts
@hosts || config.all_hosts
specific_hosts || config.all_hosts
end
def traefik_hosts
@hosts || config.traefik_hosts
specific_hosts || config.traefik_hosts
end

View File

@@ -57,11 +57,11 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
*command
end
def console(host: config.primary_host)
def console(host:)
exec_over_ssh "bin/rails", "c", host: host
end
def bash(host: config.primary_host)
def bash(host:)
exec_over_ssh "bash", host: host
end

View File

@@ -52,7 +52,7 @@ class Mrsk::Configuration
roles.flat_map(&:hosts)
end
def primary_host
def primary_web_host
role(:web).hosts.first
end
@@ -101,8 +101,8 @@ class Mrsk::Configuration
def to_h
{
roles: role_names,
hosts: hosts,
primary_host: primary_host,
hosts: all_hosts,
primary_host: primary_web_host,
version: version,
repository: repository,
absolute_image: absolute_image,

View File

@@ -13,17 +13,24 @@ class CommanderTest < ActiveSupport::TestCase
test "overwriting hosts" do
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
@mrsk.hosts = [ "1.2.3.4", "1.2.3.5" ]
@mrsk.specific_hosts = [ "1.2.3.4", "1.2.3.5" ]
assert_equal [ "1.2.3.4", "1.2.3.5" ], @mrsk.hosts
end
test "overwriting hosts with roles" do
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
@mrsk.roles = [ "workers", "web" ]
@mrsk.specific_roles = [ "workers", "web" ]
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
@mrsk.roles = [ "workers" ]
@mrsk.specific_roles = [ "workers" ]
assert_equal [ "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
end
test "overwriting hosts with primary" do
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
@mrsk.specific_primary!
assert_equal [ "1.1.1.1" ], @mrsk.hosts
end
end

View File

@@ -48,9 +48,9 @@ class ConfigurationTest < ActiveSupport::TestCase
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @config_with_roles.all_hosts
end
test "primary host" do
assert_equal "1.1.1.1", @config.primary_host
assert_equal "1.1.1.1", @config_with_roles.primary_host
test "primary web host" do
assert_equal "1.1.1.1", @config.primary_web_host
assert_equal "1.1.1.1", @config_with_roles.primary_web_host
end
test "traefik hosts" do
@@ -123,4 +123,8 @@ class ConfigurationTest < ActiveSupport::TestCase
config = Mrsk::Configuration.create_from dest_config_file, destination: "missing"
end
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=>"123", :repository=>"dhh/app", :absolute_image=>"dhh/app:123", :service_with_version=>"app-123", :env_args=>["-e", "REDIS_URL=redis://x/y"], :ssh_options=>{:user=>"root", :auth_methods=>["publickey"]} }, @config.to_h)
end
end