WIP
This commit is contained in:
@@ -5,6 +5,7 @@ class CliAppTest < CliTestCase
|
||||
stub_running
|
||||
run_command("boot").tap do |output|
|
||||
assert_match "docker tag dhh/app:latest dhh/app:latest", output
|
||||
assert_match /docker rename app-web-latest app-web-latest_replaced_[0-9a-f]{16}/, output
|
||||
assert_match /docker run --detach --restart unless-stopped --name app-web-latest --hostname 1.1.1.1-[0-9a-f]{12} /, output
|
||||
assert_match "docker container ls --all --filter name=^app-web-123$ --quiet | xargs docker stop", output
|
||||
end
|
||||
@@ -13,26 +14,12 @@ class CliAppTest < CliTestCase
|
||||
test "boot will rename if same version is already running" do
|
||||
run_command("details") # Preheat Kamal const
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :container, :ls, "--filter", "name=^app-web-latest$", "--quiet", raise_on_non_zero_exit: false)
|
||||
.returns("12345678") # running version
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-latest$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")
|
||||
.returns("running") # health check
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :ps, "--filter", "label=service=app", "--filter", "label=role=web", "--filter", "status=running", "--filter", "status=restarting", "--latest", "--format", "\"{{.Names}}\"", "|", "while read line; do echo ${line#app-web-}; done", raise_on_non_zero_exit: false)
|
||||
.returns("123") # old version
|
||||
|
||||
stub_running
|
||||
run_command("boot").tap do |output|
|
||||
assert_match /Renaming container .* to .* as already deployed on 1.1.1.1/, output # Rename
|
||||
assert_match /docker rename app-web-latest app-web-latest_replaced_[0-9a-f]{16}/, output
|
||||
assert_match /docker run --detach --restart unless-stopped --name app-web-latest --hostname 1.1.1.1-[0-9a-f]{12} /, output
|
||||
assert_match "docker container ls --all --filter name=^app-web-123$ --quiet | xargs docker stop", output
|
||||
end
|
||||
ensure
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
test "boot uses group strategy when specified" do
|
||||
@@ -45,9 +32,27 @@ class CliAppTest < CliTestCase
|
||||
run_command("boot", config: :with_boot_strategy)
|
||||
end
|
||||
|
||||
test "boot without traefik file provider raises exception" do
|
||||
Thread.report_on_exception = false
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{index .Args 1 }}'", :traefik)
|
||||
.returns("[--providers.docker --log.level=DEBUG --accesslog --accesslog.format=json]").at_least_once
|
||||
|
||||
assert_raises(SSHKit::Runner::ExecuteError, "Exception while executing on host 1.1.1.1: File provider not enabled, you'll need to run `kamal traefik reboot` to deploy") do
|
||||
run_command("boot")
|
||||
end
|
||||
ensure
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
test "boot errors leave lock in place" do
|
||||
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999" }
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{index .Args 1 }}'", :traefik)
|
||||
.returns("[--providers.docker --providers.file.directory=/var/run/traefik-config --providers.file.watch --log.level=DEBUG --accesslog --accesslog.format=json]").at_least_once
|
||||
|
||||
Kamal::Cli::App.any_instance.expects(:using_version).raises(RuntimeError)
|
||||
|
||||
assert !KAMAL.holding_lock?
|
||||
@@ -58,6 +63,13 @@ class CliAppTest < CliTestCase
|
||||
end
|
||||
|
||||
test "start" do
|
||||
SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info)
|
||||
.with { |*args| args == [ :docker, :inspect, "-f '{{index .Args 1 }}'", :traefik ] }
|
||||
.returns("[--providers.docker --providers.file.directory=/var/run/traefik-config --providers.file.watch --log.level=DEBUG --accesslog --accesslog.format=json]").at_least_once
|
||||
SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info)
|
||||
.with { |*args| args != [ :docker, :inspect, "-f '{{index .Args 1 }}'", :traefik ] }
|
||||
.returns("").at_least_once
|
||||
|
||||
run_command("start").tap do |output|
|
||||
assert_match "docker start app-web-999", output
|
||||
end
|
||||
@@ -124,7 +136,7 @@ class CliAppTest < CliTestCase
|
||||
|
||||
test "exec" do
|
||||
run_command("exec", "ruby -v").tap do |output|
|
||||
assert_match "docker run --rm dhh/app:latest ruby -v", output
|
||||
assert_match "docker run --rm --env-file .kamal/env/roles/app-web.env dhh/app:latest ruby -v", output
|
||||
end
|
||||
end
|
||||
|
||||
@@ -180,10 +192,26 @@ class CliAppTest < CliTestCase
|
||||
end
|
||||
|
||||
def stub_running
|
||||
SecureRandom.stubs(:hex).with(16).returns("12345678901234567890123456789012")
|
||||
SecureRandom.stubs(:hex).with(6).returns("123456789012")
|
||||
SecureRandom.stubs(:hex).with(8).returns("1234567890123456")
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info).returns("123") # old version
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{index .Args 1 }}'", :traefik)
|
||||
.returns("[--providers.docker --providers.file.directory=/var/run/traefik-config --providers.file.watch --log.level=DEBUG --accesslog --accesslog.format=json]").at_least_once
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-latest$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")
|
||||
.returns("running") # health check
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'", "app-web-latest")
|
||||
.returns("172.17.0.3").at_least_once
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :exec, :traefik, :wget, "-qSO", "/dev/null", "http://localhost:80/up", "2>&1", "|", :grep, "-i", "X-Kamal-Run-ID", "|", :cut, "-d ' ' -f 4")
|
||||
.returns("12345678901234567890123456789012").at_least_once
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class CliHealthcheckTest < CliTestCase
|
||||
# Prevent expected failures from outputting to terminal
|
||||
Thread.report_on_exception = false
|
||||
|
||||
Kamal::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying
|
||||
Object.any_instance.stubs(:sleep) # No sleeping when retrying
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||
.with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :stop, raise_on_non_zero_exit: false)
|
||||
@@ -28,13 +28,15 @@ class CliHealthcheckTest < CliTestCase
|
||||
assert_match "container not ready (unhealthy), retrying in 2s (attempt 2/7)...", output
|
||||
assert_match "Container is healthy!", output
|
||||
end
|
||||
ensure
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
test "perform failing to become healthy" do
|
||||
# Prevent expected failures from outputting to terminal
|
||||
Thread.report_on_exception = false
|
||||
|
||||
Kamal::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying
|
||||
Object.any_instance.stubs(:sleep) # No sleeping when retrying
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||
.with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :stop, raise_on_non_zero_exit: false)
|
||||
@@ -62,6 +64,8 @@ class CliHealthcheckTest < CliTestCase
|
||||
run_command("perform")
|
||||
end
|
||||
assert_match "container not ready (unhealthy)", exception.message
|
||||
ensure
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -66,7 +66,7 @@ class CliMainTest < CliTestCase
|
||||
.with { |*args| args == [ :mkdir, "-p", ".kamal" ] }
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||
.with { |*arg| arg[0..1] == [:mkdir, ".kamal/lock-app"] }
|
||||
.with { |*args| args[0..1] == [:mkdir, ".kamal/lock-app"] }
|
||||
.raises(RuntimeError, "mkdir: cannot create directory ‘kamal_lock-app’: File exists")
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_debug)
|
||||
@@ -75,6 +75,8 @@ class CliMainTest < CliTestCase
|
||||
assert_raises(Kamal::Cli::LockError) do
|
||||
run_command("deploy")
|
||||
end
|
||||
ensure
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
test "deploy error when locking" do
|
||||
@@ -90,6 +92,8 @@ class CliMainTest < CliTestCase
|
||||
assert_raises(SSHKit::Runner::ExecuteError) do
|
||||
run_command("deploy")
|
||||
end
|
||||
ensure
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
test "deploy errors during outside section leave remove lock" do
|
||||
@@ -173,9 +177,14 @@ class CliMainTest < CliTestCase
|
||||
assert_match /docker container ls --all --filter name=\^app-web-nonsense\$ --quiet/, output
|
||||
assert_match /The app version 'nonsense' is not available as a container/, output
|
||||
end
|
||||
ensure
|
||||
Thread.report_on_exception = true
|
||||
end
|
||||
|
||||
test "rollback good version" do
|
||||
SecureRandom.stubs(:hex).with(16).returns("12345678901234567890123456789012")
|
||||
SecureRandom.stubs(:hex).with(6).returns("123456789012")
|
||||
|
||||
[ "web", "workers" ].each do |role|
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :container, :ls, "--filter", "name=^app-#{role}-123$", "--quiet", raise_on_non_zero_exit: false)
|
||||
@@ -191,6 +200,18 @@ class CliMainTest < CliTestCase
|
||||
.returns("running").at_least_once # health check
|
||||
end
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'", "app-web-123")
|
||||
.returns("172.17.0.3").at_least_once
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{index .Args 1 }}'", :traefik)
|
||||
.returns("[--providers.docker --providers.file.directory=/var/run/traefik-config --providers.file.watch --log.level=DEBUG --accesslog --accesslog.format=json]").at_least_once
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :exec, :traefik, :wget, "-qSO", "/dev/null", "http://localhost:80/up", "2>&1", "|", :grep, "-i", "X-Kamal-Run-ID", "|", :cut, "-d ' ' -f 4")
|
||||
.returns("12345678901234567890123456789012").at_least_once
|
||||
|
||||
Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true)
|
||||
hook_variables = { version: 123, service_version: "app@123", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "rollback" }
|
||||
|
||||
@@ -207,8 +228,13 @@ class CliMainTest < CliTestCase
|
||||
test "rollback without old version" do
|
||||
Kamal::Cli::Main.any_instance.stubs(:container_available?).returns(true)
|
||||
|
||||
Kamal::Utils::HealthcheckPoller.stubs(:sleep)
|
||||
Object.stubs(:sleep)
|
||||
SecureRandom.stubs(:hex).with(16).returns("12345678901234567890123456789012")
|
||||
SecureRandom.stubs(:hex).with(6).returns("123456789012")
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{index .Args 1 }}'", :traefik)
|
||||
.returns("[--providers.docker --providers.file.directory=/var/run/traefik-config --providers.file.watch --log.level=DEBUG --accesslog --accesslog.format=json]").at_least_once
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :container, :ls, "--filter", "name=^app-web-123$", "--quiet", raise_on_non_zero_exit: false)
|
||||
.returns("").at_least_once
|
||||
@@ -218,6 +244,13 @@ class CliMainTest < CliTestCase
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :container, :ls, "--all", "--filter", "name=^app-web-123$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")
|
||||
.returns("running").at_least_once # health check
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :inspect, "-f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'", "app-web-123")
|
||||
.returns("172.17.0.3").at_least_once
|
||||
|
||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info)
|
||||
.with(:docker, :exec, :traefik, :wget, "-qSO", "/dev/null", "http://localhost:80/up", "2>&1", "|", :grep, "-i", "X-Kamal-Run-ID", "|", :cut, "-d ' ' -f 4")
|
||||
.returns("12345678901234567890123456789012").at_least_once
|
||||
|
||||
run_command("rollback", "123").tap do |output|
|
||||
assert_match "Start container with version 123", output
|
||||
|
||||
@@ -4,7 +4,7 @@ class CliTraefikTest < CliTestCase
|
||||
test "boot" do
|
||||
run_command("boot").tap do |output|
|
||||
assert_match "docker login", output
|
||||
assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --env-file .kamal/env/traefik/traefik.env --log-opt max-size=\"10m\" #{Kamal::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", output
|
||||
assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/traefik-config:/var/run/traefik-config --env-file .kamal/env/traefik/traefik.env --log-opt max-size=\"10m\" #{Kamal::Configuration::Traefik::Static::DEFAULT_IMAGE} --providers.docker --providers.file.directory=\"/var/run/traefik-config\" --providers.file.watch --log.level=\"DEBUG\"", output
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,11 +14,13 @@ class CliTraefikTest < CliTestCase
|
||||
run_command("reboot").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 run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --env-file .kamal/env/traefik/traefik.env --log-opt max-size=\"10m\" #{Kamal::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", output
|
||||
assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --volume $(pwd)/.kamal/traefik-config:/var/run/traefik-config --env-file .kamal/env/traefik/traefik.env --log-opt max-size=\"10m\" #{Kamal::Configuration::Traefik::Static::DEFAULT_IMAGE} --providers.docker --providers.file.directory=\"/var/run/traefik-config\" --providers.file.watch --log.level=\"DEBUG\"", output
|
||||
end
|
||||
end
|
||||
|
||||
test "reboot --rolling" do
|
||||
Object.any_instance.stubs(:sleep)
|
||||
|
||||
run_command("reboot", "--rolling").tap do |output|
|
||||
assert_match "Running docker container prune --force --filter label=org.opencontainers.image.title=Traefik on 1.1.1.1", output
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user