Daemon/host/role accessories

Allow the hosts for accessories to be specified by host or role, or on
all app hosts by setting `daemon: true`.

```
  # Single host
  mysql:
    host: 1.1.1.1
  # Multiple hosts
  redis:
    hosts:
      - 1.1.1.1
      - 1.1.1.2
  # By role
  monitoring:
    roles:
      - web
      - jobs
```
This commit is contained in:
Donal McBreen
2023-03-28 13:05:09 +01:00
parent cec82ac641
commit c06585fef4
10 changed files with 165 additions and 56 deletions

View File

@@ -19,9 +19,11 @@ class CliAccessoryTest < CliTestCase
run_command("boot", "all").tap do |output|
assert_match /docker login.*on 1.1.1.3/, output
assert_match /docker login.*on 1.1.1.4/, output
assert_match /docker login.*on 1.1.1.1/, output
assert_match /docker login.*on 1.1.1.2/, output
assert_match "docker run --name app-mysql --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 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", output
assert_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.4", output
assert_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.1", output
assert_match "docker run --name app-redis --detach --restart unless-stopped --log-opt max-size=\"10m\" --publish 6379:6379 --volume $PWD/app-redis/data:/data --label service=\"app-redis\" redis:latest on 1.1.1.2", output
end
end

View File

@@ -10,7 +10,7 @@ class CliMainTest < CliTestCase
end
test "deploy" do
invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" }
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:server:bootstrap", [], invoke_options)
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:registry:login", [], invoke_options)
@@ -31,7 +31,7 @@ class CliMainTest < CliTestCase
end
test "deploy with skip_push" do
invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" }
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:server:bootstrap", [], invoke_options)
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:registry:login", [], invoke_options)
@@ -54,7 +54,7 @@ class CliMainTest < CliTestCase
end
test "redeploy" do
invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" }
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:deliver", [], invoke_options)
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options)
@@ -67,7 +67,7 @@ class CliMainTest < CliTestCase
end
test "redeploy with skip_push" do
invoke_options = { "config_file" => "test/fixtures/deploy_with_accessories.yml", "skip_broadcast" => false, "version" => "999" }
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:pull", [], invoke_options)
Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options)
@@ -92,7 +92,7 @@ class CliMainTest < CliTestCase
Mrsk::Cli::Main.any_instance.stubs(:container_name_available?).returns(true)
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info).with(:docker, :ps, "--filter", "label=service=app", "--format", "\"{{.Names}}\"", "|", "sed 's/-/\\n/g'", "|", "tail -n 1").returns("version-to-rollback\n").at_least_once
run_command("rollback", "123").tap do |output|
run_command("rollback", "123", config_file: "deploy_with_accessories").tap do |output|
assert_match "Start version 123", output
assert_match "docker start app-123", output
assert_match "docker container ls --all --filter name=^app-version-to-rollback$ --quiet | xargs docker stop", output, "Should stop the container that was previously running"
@@ -126,7 +126,7 @@ class CliMainTest < CliTestCase
end
test "config" do
run_command("config", config_file: "deploy_with_accessories").tap do |output|
run_command("config", config_file: "deploy_simple").tap do |output|
config = YAML.load(output)
assert_equal ["web"], config[:roles]
@@ -224,7 +224,7 @@ class CliMainTest < CliTestCase
end
test "remove with confirmation" do
run_command("remove", "-y").tap do |output|
run_command("remove", "-y", config_file: "deploy_with_accessories").tap do |output|
assert_match /docker container stop traefik/, output
assert_match /docker container prune --force --filter label=org.opencontainers.image.title=Traefik/, output
assert_match /docker image prune --all --force --filter label=org.opencontainers.image.title=Traefik/, output
@@ -253,7 +253,7 @@ class CliMainTest < CliTestCase
end
private
def run_command(*command, config_file: "deploy_with_accessories")
def run_command(*command, config_file: "deploy_simple")
stdouted { Mrsk::Cli::Main.start([*command, "-c", "test/fixtures/#{config_file}.yml"]) }
end
end

View File

@@ -4,7 +4,10 @@ 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" ],
servers: {
"web" => [ "1.1.1.1", "1.1.1.2" ],
"workers" => [ "1.1.1.3", "1.1.1.4" ]
},
env: { "REDIS_URL" => "redis://x/y" },
accessories: {
"mysql" => {
@@ -29,7 +32,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
},
"redis" => {
"image" => "redis:latest",
"host" => "1.1.1.6",
"hosts" => [ "1.1.1.6", "1.1.1.7" ],
"port" => "6379:6379",
"labels" => {
"cache" => true
@@ -44,6 +47,21 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
"cpus" => 4,
"memory" => "2GB"
}
},
"monitoring" => {
"image" => "monitoring:latest",
"roles" => [ "web" ],
"port" => "4321:4321",
"labels" => {
"cache" => true
},
"env" => {
"STATSD_PORT" => "8126"
},
"options" => {
"cpus" => 4,
"memory" => "2GB"
}
}
}
}
@@ -62,8 +80,9 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
end
test "host" do
assert_equal "1.1.1.5", @config.accessory(:mysql).host
assert_equal "1.1.1.6", @config.accessory(:redis).host
assert_equal ["1.1.1.5"], @config.accessory(:mysql).hosts
assert_equal ["1.1.1.6", "1.1.1.7"], @config.accessory(:redis).hosts
assert_equal ["1.1.1.1", "1.1.1.2"], @config.accessory(:monitoring).hosts
end
test "missing host" do
@@ -71,10 +90,21 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
@config = Mrsk::Configuration.new(@deploy)
assert_raises(ArgumentError) do
@config.accessory(:mysql).host
@config.accessory(:mysql).hosts
end
end
test "setting host, hosts and roles" do
@deploy[:accessories]["mysql"]["hosts"] = true
@deploy[:accessories]["mysql"]["roles"] = true
@config = Mrsk::Configuration.new(@deploy)
exception = assert_raises(ArgumentError) do
@config.accessory(:mysql).hosts
end
assert_equal "Specify one of `host`, `hosts` or `roles` for accessory `mysql`", exception.message
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

8
test/fixtures/deploy_simple.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
service: app
image: dhh/app
servers:
- "1.1.1.1"
- "1.1.1.2"
registry:
username: user
password: pw

View File

@@ -1,8 +1,12 @@
service: app
image: dhh/app
servers:
- 1.1.1.1
- 1.1.1.2
web:
- "1.1.1.1"
- "1.1.1.2"
workers:
- "1.1.1.3"
- "1.1.1.4"
registry:
username: user
password: pw
@@ -23,7 +27,8 @@ accessories:
- data:/var/lib/mysql
redis:
image: redis:latest
host: 1.1.1.4
roles:
- web
port: 6379
directories:
- data:/data