Add command execution

This commit is contained in:
David Heinemeier Hansson
2023-01-09 14:36:33 +01:00
parent 9641ce0edd
commit fe52ce6547
3 changed files with 82 additions and 1 deletions

View File

@@ -50,6 +50,55 @@ Voila! All the servers are now serving the app on port 80. If you're just runnin
## Operations ## Operations
### Executing commands
If you need to execute commands inside the Rails containers, you can use `rake mrsk:app:exec`, `rake mrsk:app:exec:once`, `rake mrsk:app:exec:rails`, and `rake mrsk:app:exec:once:rails`. Examples:
```bash
# Runs command on all servers
rake mrsk:app:exec CMD='ruby -v'
App Host: xxx.xxx.xxx.xxx
ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
App Host: xxx.xxx.xxx.xxx
ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
# Runs command on first server
rake mrsk:app:exec:once CMD='cat .ruby-version'
3.1.3
# Runs Rails command on all servers
rake mrsk:app:exec:rails CMD=about
App Host: xxx.xxx.xxx.xxx
About your application's environment
Rails version 7.1.0.alpha
Ruby version ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
RubyGems version 3.3.26
Rack version 2.2.5
Middleware ActionDispatch::HostAuthorization, Rack::Sendfile, ActionDispatch::Static, ActionDispatch::Executor, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, ActionDispatch::RemoteIp, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::Callbacks, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ContentSecurityPolicy::Middleware, ActionDispatch::PermissionsPolicy::Middleware, Rack::Head, Rack::ConditionalGet, Rack::ETag, Rack::TempfileReaper
Application root /rails
Environment production
Database adapter sqlite3
Database schema version 20221231233303
App Host: xxx.xxx.xxx.xxx
About your application's environment
Rails version 7.1.0.alpha
Ruby version ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
RubyGems version 3.3.26
Rack version 2.2.5
Middleware ActionDispatch::HostAuthorization, Rack::Sendfile, ActionDispatch::Static, ActionDispatch::Executor, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, ActionDispatch::RemoteIp, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::Callbacks, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ContentSecurityPolicy::Middleware, ActionDispatch::PermissionsPolicy::Middleware, Rack::Head, Rack::ConditionalGet, Rack::ETag, Rack::TempfileReaper
Application root /rails
Environment production
Database adapter sqlite3
Database schema version 20221231233303
# Runs Rails command on first server
rake mrsk:app:exec:once:rails CMD='db:version'
database: storage/production.sqlite3
Current version: 20221231233303
```
### Inspecting ### Inspecting
You can see the state of your servers by running `rake mrsk:info`. It'll show something like this: You can see the state of your servers by running `rake mrsk:info`. It'll show something like this:
@@ -96,7 +145,7 @@ Note that by default old containers are pruned after 3 days when you run `rake m
### Removing ### Removing
... If you wish to remove the entire application, including Traefik, containers, images, and registry session, you can run `rake mrsk:remove`. This will leave the servers clean.
## Stage of development ## Stage of development

View File

@@ -36,6 +36,14 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
[ "docker ps -q #{service_filter.join(" ")} | xargs docker logs -f" ] [ "docker ps -q #{service_filter.join(" ")} | xargs docker logs -f" ]
end end
def exec(*command)
docker :exec,
"-e", redact("RAILS_MASTER_KEY=#{config.master_key}"),
*config.envs,
config.service_with_version,
*command
end
def list_containers def list_containers
docker :container, :ls, "-a", *service_filter docker :container, :ls, "-a", *service_filter
end end

View File

@@ -51,6 +51,30 @@ namespace :mrsk do
on(MRSK_CONFIG.servers) { |host| puts "App Host: #{host}\n" + capture(*app.info) + "\n\n" } on(MRSK_CONFIG.servers) { |host| puts "App Host: #{host}\n" + capture(*app.info) + "\n\n" }
end end
desc "Execute a custom task on servers passed in as CMD='bin/rake some:task'"
task :exec do
on(MRSK_CONFIG.servers) { |host| puts "App Host: #{host}\n" + capture(*app.exec(ENV["CMD"])) + "\n\n" }
end
namespace :exec do
desc "Execute Rails command on servers, like CMD='runner \"puts %(Hello World)\""
task :rails do
on(MRSK_CONFIG.servers) { |host| puts "App Host: #{host}\n" + capture(*app.exec("bin/rails", ENV["CMD"])) + "\n\n" }
end
desc "Execute a custom task on the first defined server"
task :once do
on(MRSK_CONFIG.servers.first) { |host| puts capture(*app.exec(ENV["CMD"])) }
end
namespace :once do
desc "Execute Rails command on the first defined server, like CMD='runner \"puts %(Hello World)\""
task :rails do
on(MRSK_CONFIG.servers.first) { puts capture(*app.exec("bin/rails", ENV["CMD"])) }
end
end
end
desc "List all the app containers currently on servers" desc "List all the app containers currently on servers"
task :containers do task :containers do
on(MRSK_CONFIG.servers) { |host| puts "App Host: #{host}\n" + capture(*app.list_containers) + "\n\n" } on(MRSK_CONFIG.servers) { |host| puts "App Host: #{host}\n" + capture(*app.list_containers) + "\n\n" }