Operate accessories

When you want mysql, redis, and the like under MRSK management
This commit is contained in:
David Heinemeier Hansson
2023-01-22 16:52:57 +01:00
parent 48f8f7cb57
commit 6b98eb3677
13 changed files with 453 additions and 3 deletions

View File

@@ -0,0 +1,13 @@
require "test_helper"
require "active_support/testing/stream"
require "mrsk/cli"
class CliAccessoryTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Stream
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 --volume /var/lib/mysql:/var/lib/mysql --label service=app-mysql mysql:5.7 on 1.1.1.3", command
end
end

View File

@@ -9,7 +9,7 @@ class CliMainTest < ActiveSupport::TestCase
end
test "version" do
version = capture(:stdout) { Mrsk::Cli::Main.new.version }.strip
version = stdouted { Mrsk::Cli::Main.new.version }
assert_equal Mrsk::VERSION, version
end
end

View File

@@ -0,0 +1,82 @@
require "test_helper"
require "mrsk/configuration"
require "mrsk/commands/accessory"
class CommandsAccessoryTest < ActiveSupport::TestCase
setup do
@config = {
service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" },
servers: [ "1.1.1.1" ],
accessories: {
"mysql" => {
"image" => "mysql:8.0",
"host" => "1.1.1.5",
"port" => "3306",
"env" => {
"clear" => {
"MYSQL_ROOT_HOST" => "%"
},
"secret" => [
"MYSQL_ROOT_PASSWORD"
]
}
},
"redis" => {
"image" => "redis:latest",
"host" => "1.1.1.6",
"port" => "6379:6379",
"labels" => {
"cache" => true
},
"env" => {
"SOMETHING" => "else"
},
"volumes" => [
"/var/lib/redis:/data"
]
}
}
}
@config = Mrsk::Configuration.new(@config)
@mysql = Mrsk::Commands::Accessory.new(@config, name: :mysql)
@redis = Mrsk::Commands::Accessory.new(@config, name: :redis)
end
test "run" do
assert_equal \
[:docker, :run, "--name", "app-mysql", "-d", "--restart", "unless-stopped", "-p", "3306:3306", "--label", "service=app-mysql", "mysql:8.0"], @mysql.run
assert_equal \
[:docker, :run, "--name", "app-redis", "-d", "--restart", "unless-stopped", "-p", "6379:6379", "--volume", "/var/lib/redis:/data", "--label", "service=app-redis", "--label", "cache=true", "redis:latest"], @redis.run
end
test "start" do
assert_equal [:docker, :container, :start, "app-mysql"], @mysql.start
end
test "stop" do
assert_equal [:docker, :container, :stop, "app-mysql"], @mysql.stop
end
test "info" do
assert_equal [:docker, :ps, "--filter", "name=app-mysql"], @mysql.info
end
test "logs" do
assert_equal [:docker, :logs, "app-mysql", "-t", "2>&1"], @mysql.logs
assert_equal [:docker, :logs, "app-mysql", " --since 5m", " -n 100", "-t", "2>&1", "|", "grep 'thing'"], @mysql.logs(since: "5m", lines: 100, grep: "thing")
end
test "follow logs" do
assert_equal "ssh -t root@1.1.1.5 'docker logs app-mysql -t -n 10 -f 2>&1'", @mysql.follow_logs
end
test "remove container" do
assert_equal [:docker, :container, :prune, "-f", "--filter", "label=name=app-mysql"], @mysql.remove_container
end
test "remove image" do
assert_equal [:docker, :image, :prune, "-a", "-f", "--filter", "label=name=app-mysql"], @mysql.remove_image
end
end

View File

@@ -0,0 +1,89 @@
require "test_helper"
require "mrsk/configuration"
class ConfigurationAccessoryTest < ActiveSupport::TestCase
setup do
@deploy = {
service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" },
servers: [ "1.1.1.1", "1.1.1.2" ],
env: { "REDIS_URL" => "redis://x/y" },
accessories: {
"mysql" => {
"image" => "mysql:8.0",
"host" => "1.1.1.5",
"port" => "3306",
"env" => {
"clear" => {
"MYSQL_ROOT_HOST" => "%"
},
"secret" => [
"MYSQL_ROOT_PASSWORD"
]
}
},
"redis" => {
"image" => "redis:latest",
"host" => "1.1.1.6",
"port" => "6379:6379",
"labels" => {
"cache" => true
},
"env" => {
"SOMETHING" => "else"
},
"volumes" => [
"/var/lib/redis:/data"
]
}
}
}
@config = Mrsk::Configuration.new(@deploy)
end
test "service name" do
assert_equal "app-mysql", @config.accessory(:mysql).service_name
assert_equal "app-redis", @config.accessory(:redis).service_name
end
test "port" do
assert_equal "3306:3306", @config.accessory(:mysql).port
assert_equal "6379:6379", @config.accessory(:redis).port
end
test "host" do
assert_equal "1.1.1.5", @config.accessory(:mysql).host
assert_equal "1.1.1.6", @config.accessory(:redis).host
end
test "missing host" do
@deploy[:accessories]["mysql"]["host"] = nil
@config = Mrsk::Configuration.new(@deploy)
assert_raises(ArgumentError) do
@config.accessory(:mysql).host
end
end
test "label args" do
assert_equal ["--label", "service=app-mysql"], @config.accessory(:mysql).label_args
assert_equal ["--label", "service=app-redis", "--label", "cache=true"], @config.accessory(:redis).label_args
end
test "env args with secret" do
ENV["MYSQL_ROOT_PASSWORD"] = "secret123"
assert_equal ["-e", "MYSQL_ROOT_PASSWORD=secret123", "-e", "MYSQL_ROOT_HOST=%"], @config.accessory(:mysql).env_args
assert @config.accessory(:mysql).env_args[1].is_a?(SSHKit::Redaction)
ensure
ENV["MYSQL_ROOT_PASSWORD"] = nil
end
test "env args without secret" do
assert_equal ["-e", "SOMETHING=else"], @config.accessory(:redis).env_args
end
test "volume args" do
assert_equal [], @config.accessory(:mysql).volume_args
assert_equal ["--volume", "/var/lib/redis:/data"], @config.accessory(:redis).volume_args
end
end

View File

@@ -0,0 +1,27 @@
service: app
image: dhh/app
servers:
- 1.1.1.1
- 1.1.1.2
registry:
username: user
password: pw
accessories:
mysql:
image: mysql:5.7
host: 1.1.1.3
port: 3306
env:
clear:
MYSQL_ROOT_HOST: '%'
secret:
- MYSQL_ROOT_PASSWORD
volumes:
- /var/lib/mysql:/var/lib/mysql
redis:
image: redis:8.0
host: 1.1.1.4
port: 6379
volumes:
- /var/lib/redis:/data

View File

@@ -2,8 +2,15 @@ require "bundler/setup"
require "active_support/test_case"
require "active_support/testing/autorun"
require "debug"
require "sshkit"
ActiveSupport::LogSubscriber.logger = ActiveSupport::Logger.new(STDOUT) if ENV["VERBOSE"]
SSHKit.config.backend = SSHKit::Backend::Printer
class ActiveSupport::TestCase
private
def stdouted
capture(:stdout) { yield }.strip
end
end