From 85a0267447b74ebac2cec1e18a08f2e117006c36 Mon Sep 17 00:00:00 2001 From: Yoann Lecuyer Date: Tue, 14 Mar 2023 23:29:00 +0100 Subject: [PATCH 1/7] Minor: Properly require active_support --- lib/mrsk.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mrsk.rb b/lib/mrsk.rb index 19b86051..70cbad40 100644 --- a/lib/mrsk.rb +++ b/lib/mrsk.rb @@ -1,6 +1,7 @@ module Mrsk end +require "active_support" require "zeitwerk" loader = Zeitwerk::Loader.for_gem From aae290cefc8e42920543a061ff93a2fd61b47365 Mon Sep 17 00:00:00 2001 From: Samuel Sieg Date: Wed, 15 Mar 2023 16:48:12 +0100 Subject: [PATCH 2/7] Add CLI tests for remaining commands that are not tested yet --- test/cli/accessory_test.rb | 125 ++++++++++++++++++++++++++++++----- test/cli/app_test.rb | 96 +++++++++++++++++++-------- test/cli/build_test.rb | 57 ++++++++++++++++ test/cli/healthcheck_test.rb | 64 ++++++++++++++++++ test/cli/prune_test.rb | 29 ++++++++ test/cli/registry_test.rb | 23 +++++++ test/cli/traefik_test.rb | 85 ++++++++++++++++++++++++ 7 files changed, 436 insertions(+), 43 deletions(-) create mode 100644 test/cli/healthcheck_test.rb create mode 100644 test/cli/prune_test.rb create mode 100644 test/cli/registry_test.rb create mode 100644 test/cli/traefik_test.rb diff --git a/test/cli/accessory_test.rb b/test/cli/accessory_test.rb index 19bf4187..55a1be0b 100644 --- a/test/cli/accessory_test.rb +++ b/test/cli/accessory_test.rb @@ -1,46 +1,137 @@ require_relative "cli_test_case" class CliAccessoryTest < CliTestCase + test "boot" do + Mrsk::Cli::Accessory.any_instance.expects(:directories).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:upload).with("mysql") + + run_command("boot", "mysql").tap do |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 + end + end + + test "boot all" do + Mrsk::Cli::Accessory.any_instance.expects(:directories).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:upload).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:directories).with("redis") + Mrsk::Cli::Accessory.any_instance.expects(:upload).with("redis") + + run_command("boot", "all").tap do |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 + end + end + test "upload" do - assert_match "test/fixtures/files/my.cnf app-mysql/etc/mysql/my.cnf", run_command("upload", "mysql") + run_command("upload", "mysql").tap do |output| + assert_match "mkdir -p app-mysql/etc/mysql", output + assert_match "test/fixtures/files/my.cnf app-mysql/etc/mysql/my.cnf", output + assert_match "chmod 755 app-mysql/etc/mysql/my.cnf", output + end end test "directories" do assert_match "mkdir -p $PWD/app-mysql/data", run_command("directories", "mysql") end - test "remove service direcotry" do - assert_match "rm -rf app-mysql", run_command("remove_service_directory", "mysql") + test "reboot" do + Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:boot).with("mysql") + + run_command("reboot", "mysql") end - test "boot" do - assert_match "Running 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", run_command("boot", "mysql") + test "start" do + assert_match "docker container start app-mysql", run_command("start", "mysql") + end + + test "stop" do + assert_match "docker container stop app-mysql", run_command("stop", "mysql") + end + + test "restart" do + Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:start).with("mysql") + + run_command("restart", "mysql") + end + + test "details" do + assert_match "docker ps --filter label=service=app-mysql", run_command("details", "mysql") + end + + test "details with all" do + run_command("details", "all").tap do |output| + assert_match "docker ps --filter label=service=app-mysql", output + assert_match "docker ps --filter label=service=app-redis", output + end end test "exec" do run_command("exec", "mysql", "mysql -v").tap do |output| - assert_match /Launching command from new container/, output - assert_match /mysql -v/, output + assert_match "Launching command from new container", output + assert_match "mysql -v", output end end test "exec with reuse" do run_command("exec", "mysql", "--reuse", "mysql -v").tap do |output| - assert_match /Launching command from existing container/, output - assert_match %r[docker exec app-mysql mysql -v], output + assert_match "Launching command from existing container", output + assert_match "docker exec app-mysql mysql -v", output end end + test "logs" do + SSHKit::Backend::Abstract.any_instance.stubs(:exec) + .with("ssh -t root@1.1.1.3 'docker logs app-mysql --timestamps --tail 10 2>&1'") + + assert_match "docker logs app-mysql --tail 100 --timestamps 2>&1", run_command("logs", "mysql") + end + + test "logs with follow" do + SSHKit::Backend::Abstract.any_instance.stubs(:exec) + .with("ssh -t root@1.1.1.3 'docker logs app-mysql --timestamps --tail 10 --follow 2>&1'") + + assert_match "docker logs app-mysql --timestamps --tail 10 --follow 2>&1", run_command("logs", "mysql", "--follow") + end + test "remove with confirmation" do - run_command("remove", "mysql", "-y").tap do |output| - assert_match /docker container stop app-mysql/, output - assert_match /docker image prune --all --force --filter label=service=app-mysql/, output - assert_match /rm -rf app-mysql/, output - end + Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:remove_image).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:remove_service_directory).with("mysql") + + run_command("remove", "mysql", "-y") + end + + test "remove all with confirmation" do + Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:remove_image).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:remove_service_directory).with("mysql") + Mrsk::Cli::Accessory.any_instance.expects(:stop).with("redis") + Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("redis") + Mrsk::Cli::Accessory.any_instance.expects(:remove_image).with("redis") + Mrsk::Cli::Accessory.any_instance.expects(:remove_service_directory).with("redis") + + run_command("remove", "all", "-y") + end + + test "remove_container" do + assert_match "docker container prune --force --filter label=service=app-mysql", run_command("remove_container", "mysql") + end + + test "remove_image" do + assert_match "docker image prune --all --force --filter label=service=app-mysql", run_command("remove_image", "mysql") + end + + test "remove_service_directory" do + assert_match "rm -rf app-mysql", run_command("remove_service_directory", "mysql") end private - def run_command(*command) - stdouted { Mrsk::Cli::Accessory.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } - end + def run_command(*command) + stdouted { Mrsk::Cli::Accessory.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + end end diff --git a/test/cli/app_test.rb b/test/cli/app_test.rb index 76f59a80..36fc0691 100644 --- a/test/cli/app_test.rb +++ b/test/cli/app_test.rb @@ -9,8 +9,8 @@ class CliAppTest < CliTestCase .returns("123") # old version run_command("boot").tap do |output| - assert_match /docker run --detach --restart unless-stopped/, output - assert_match /docker container ls --all --filter name=app-123 --quiet | xargs docker stop/, output + assert_match "docker run --detach --restart unless-stopped", output + assert_match "docker container ls --all --filter name=app-123 --quiet | xargs docker stop", output end end @@ -28,10 +28,10 @@ class CliAppTest < CliTestCase .returns([ :docker, :run ]) run_command("boot").tap do |output| - assert_match /Rebooting container with same version 999 already deployed/, output # Can't start what's already running - assert_match /docker container ls --all --filter name=app-999 --quiet | xargs docker container rm/, output # Stop old running - assert_match /docker container ls --all --filter name=app-999 --quiet | xargs docker container rm/, output # Remove old container - assert_match /docker run/, output # Start new container + assert_match "Rebooting container with same version 999 already deployed", output # Can't start what's already running + assert_match "docker container ls --all --filter name=app-999 --quiet | xargs docker container rm", output # Stop old running + assert_match "docker container ls --all --filter name=app-999 --quiet | xargs docker container rm", output # Remove old container + assert_match "docker run", output # Start new container end ensure Thread.report_on_exception = true @@ -39,46 +39,90 @@ class CliAppTest < CliTestCase test "start" do run_command("start").tap do |output| - assert_match /docker start app-999/, output + assert_match "docker start app-999", output end end test "stop" do run_command("stop").tap do |output| - assert_match /docker ps --quiet --filter label=service=app \| xargs docker stop/, output + assert_match "docker ps --quiet --filter label=service=app | xargs docker stop", output end end test "details" do run_command("details").tap do |output| - assert_match /docker ps --filter label=service=app/, output - end - end - - test "remove" do - run_command("remove").tap do |output| - assert_match /docker ps --quiet --filter label=service=app | xargs docker stop/, output - assert_match /docker container prune --force --filter label=service=app/, output - assert_match /docker image prune --all --force --filter label=service=app/, output - end - end - - test "remove_container" do - run_command("remove_container", "1234567").tap do |output| - assert_match /docker container ls --all --filter name=app-1234567 --quiet \| xargs docker container rm/, output + assert_match "docker ps --filter label=service=app", output end end test "exec" do run_command("exec", "ruby -v").tap do |output| - assert_match /ruby -v/, output + assert_match "ruby -v", output end end test "exec with reuse" do run_command("exec", "--reuse", "ruby -v").tap do |output| - assert_match %r[docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1], output # Get current version - assert_match %r[docker exec app-999 ruby -v], output + assert_match "docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1", output # Get current version + assert_match "docker exec app-999 ruby -v", output + end + end + + test "containers" do + run_command("containers").tap do |output| + assert_match "docker container ls --all --filter label=service=app", output + end + end + + test "images" do + run_command("images").tap do |output| + assert_match "docker image ls dhh/app", output + end + end + + test "logs" do + SSHKit::Backend::Abstract.any_instance.stubs(:exec) + .with("ssh -t root@1.1.1.1 'docker ps --quiet --filter label=service=app | xargs docker logs --timestamps --tail 10 2>&1'") + + assert_match "docker ps --quiet --filter label=service=app | xargs docker logs --tail 100 2>&1", run_command("logs") + end + + test "logs with follow" do + SSHKit::Backend::Abstract.any_instance.stubs(:exec) + .with("ssh -t root@1.1.1.1 'docker ps --quiet --filter label=service=app | xargs docker logs --timestamps --tail 10 --follow 2>&1'") + + assert_match "docker ps --quiet --filter label=service=app | xargs docker logs --timestamps --tail 10 --follow 2>&1", run_command("logs", "--follow") + end + + test "remove" do + Mrsk::Cli::App.any_instance.expects(:stop) + Mrsk::Cli::App.any_instance.expects(:remove_containers) + Mrsk::Cli::App.any_instance.expects(:remove_images) + + run_command("remove") + end + + test "remove_container" do + run_command("remove_container", "1234567").tap do |output| + assert_match "docker container ls --all --filter name=app-1234567 --quiet | xargs docker container rm", output + end + end + + test "remove_containers" do + run_command("remove_containers").tap do |output| + assert_match "docker container prune --force --filter label=service=app", output + end + end + + test "remove_images" do + run_command("remove_images").tap do |output| + assert_match "docker image prune --all --force --filter label=service=app", output + end + end + + test "version" do + run_command("version").tap do |output| + assert_match "docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1", output end end diff --git a/test/cli/build_test.rb b/test/cli/build_test.rb index 3d5f4431..44802549 100644 --- a/test/cli/build_test.rb +++ b/test/cli/build_test.rb @@ -1,6 +1,31 @@ require_relative "cli_test_case" class CliBuildTest < CliTestCase + test "deliver" do + Mrsk::Cli::Build.any_instance.expects(:push) + Mrsk::Cli::Build.any_instance.expects(:pull) + + run_command("deliver") + end + + test "push" do + run_command("push").tap do |output| + assert_match /docker buildx build --push --platform linux\/amd64,linux\/arm64 --builder mrsk-app-multiarch -t dhh\/app:999 -t dhh\/app:latest --label service="app" --file Dockerfile \. as .*@localhost/, output + end + end + + test "push without builder" do + Mrsk::Cli::Build.any_instance.stubs(:create).returns(true) + SSHKit::Backend::Abstract.any_instance.stubs(:execute) + .raises(SSHKit::Command::Failed.new("no builder")) + .then + .returns(true) + + run_command("push").tap do |output| + assert_match /Missing compatible builder, so creating a new one first/, output + end + end + test "pull" do run_command("pull").tap do |output| assert_match /docker image rm --force dhh\/app:999/, output @@ -8,6 +33,38 @@ class CliBuildTest < CliTestCase end end + test "create" do + run_command("create").tap do |output| + assert_match /docker buildx create --use --name mrsk-app-multiarch/, output + end + end + + test "create with error" do + SSHKit::Backend::Abstract.any_instance.stubs(:execute) + .raises(SSHKit::Command::Failed.new("stderr=error")) + + run_command("create").tap do |output| + assert_match /Couldn't create remote builder: error/, output + end + end + + test "remove" do + run_command("remove").tap do |output| + assert_match /docker buildx rm mrsk-app-multiarch/, output + end + end + + test "details" do + SSHKit::Backend::Abstract.any_instance.stubs(:capture) + .with(:docker, :context, :ls, "&&", :docker, :buildx, :ls) + .returns("docker builder info") + + run_command("details").tap do |output| + assert_match /Builder: multiarch/, output + assert_match /docker builder info/, output + end + end + private def run_command(*command) stdouted { Mrsk::Cli::Build.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } diff --git a/test/cli/healthcheck_test.rb b/test/cli/healthcheck_test.rb new file mode 100644 index 00000000..7b296393 --- /dev/null +++ b/test/cli/healthcheck_test.rb @@ -0,0 +1,64 @@ +require_relative "cli_test_case" + +class CliHealthcheckTest < CliTestCase + test "perform" do + SSHKit::Backend::Abstract.any_instance.stubs(:sleep) # No sleeping when retrying + SSHKit::Backend::Abstract.any_instance.stubs(:execute) + .with(:docker, :container, :ls, "--all", "--filter", "name=healthcheck-app", "--quiet", "|", :xargs, :docker, :stop, raise_on_non_zero_exit: false) + SSHKit::Backend::Abstract.any_instance.stubs(:execute) + .with(:docker, :run, "--detach", "--name", "healthcheck-app-999", "--publish", "3999:3000", "--label", "service=healthcheck-app", "-e", "MRSK_CONTAINER_NAME=\"healthcheck-app\"", "dhh/app:999") + SSHKit::Backend::Abstract.any_instance.stubs(:execute) + .with(:docker, :container, :ls, "--all", "--filter", "name=healthcheck-app", "--quiet", "|", :xargs, :docker, :container, :rm, raise_on_non_zero_exit: false) + + # Fail twice to test retry logic + SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info) + .with(:curl, "--silent", "--output", "/dev/null", "--write-out", "'%{http_code}'", "--max-time", "2", "http://localhost:3999/up") + .raises(SSHKit::Command::Failed) + .then + .raises(SSHKit::Command::Failed) + .then + .returns("200") + + run_command("perform").tap do |output| + assert_match "Health check against /up failed to respond, retrying in 1s...", output + assert_match "Health check against /up failed to respond, retrying in 2s...", output + assert_match "Health check against /up succeeded with 200 OK!", output + end + end + + test "perform failing because of curl" do + # Prevent expected failures from outputting to terminal + Thread.report_on_exception = false + + SSHKit::Backend::Abstract.any_instance.stubs(:execute) # No need to execute anything here + SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info) + .with(:curl, "--silent", "--output", "/dev/null", "--write-out", "'%{http_code}'", "--max-time", "2", "http://localhost:3999/up") + .returns("curl: command not found") + SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info) + .with(:docker, :container, :ls, "--all", "--filter", "name=healthcheck-app", "--quiet", "|", :xargs, :docker, :logs, "--tail", 50, "2>&1") + + exception = assert_raises SSHKit::Runner::ExecuteError do + run_command("perform") + end + assert_match "Health check against /up failed to return 200 OK!", exception.message + end + + test "perform failing for unknown reason" do + SSHKit::Backend::Abstract.any_instance.stubs(:execute) # No need to execute anything here + SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info) + .with(:curl, "--silent", "--output", "/dev/null", "--write-out", "'%{http_code}'", "--max-time", "2", "http://localhost:3999/up") + .returns("500") + SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info) + .with(:docker, :container, :ls, "--all", "--filter", "name=healthcheck-app", "--quiet", "|", :xargs, :docker, :logs, "--tail", 50, "2>&1") + + exception = assert_raises do + run_command("perform") + end + assert_match "Health check against /up failed with status 500", exception.message + end + + private + def run_command(*command) + stdouted { Mrsk::Cli::Healthcheck.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + end +end diff --git a/test/cli/prune_test.rb b/test/cli/prune_test.rb new file mode 100644 index 00000000..15e54575 --- /dev/null +++ b/test/cli/prune_test.rb @@ -0,0 +1,29 @@ +require_relative "cli_test_case" + +class CliPruneTest < CliTestCase + test "all" do + Mrsk::Cli::Prune.any_instance.expects(:containers) + Mrsk::Cli::Prune.any_instance.expects(:images) + + run_command("all") + end + + test "images" do + run_command("images").tap do |output| + assert_match "docker image prune --all --force --filter label=service=app --filter until=168h on 1.1.1.1", output + assert_match "docker image prune --all --force --filter label=service=app --filter until=168h on 1.1.1.2", output + end + end + + test "containers" do + run_command("containers").tap do |output| + assert_match "docker container prune --force --filter label=service=app --filter until=72h on 1.1.1.1", output + assert_match "docker container prune --force --filter label=service=app --filter until=72h on 1.1.1.2", output + end + end + + private + def run_command(*command) + stdouted { Mrsk::Cli::Prune.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + end +end diff --git a/test/cli/registry_test.rb b/test/cli/registry_test.rb new file mode 100644 index 00000000..d100402c --- /dev/null +++ b/test/cli/registry_test.rb @@ -0,0 +1,23 @@ +require_relative "cli_test_case" + +class CliRegistryTest < CliTestCase + test "login" do + run_command("login").tap do |output| + assert_match /docker login -u \[REDACTED\] -p \[REDACTED\] as .*@localhost/, output + assert_match "docker login -u [REDACTED] -p [REDACTED] on 1.1.1.1", output + assert_match "docker login -u [REDACTED] -p [REDACTED] on 1.1.1.2", output + end + end + + test "logout" do + run_command("logout").tap do |output| + assert_match "docker logout on 1.1.1.1", output + assert_match "docker logout on 1.1.1.2", output + end + end + + private + def run_command(*command) + stdouted { Mrsk::Cli::Registry.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + end +end diff --git a/test/cli/traefik_test.rb b/test/cli/traefik_test.rb new file mode 100644 index 00000000..7eda6019 --- /dev/null +++ b/test/cli/traefik_test.rb @@ -0,0 +1,85 @@ +require_relative "cli_test_case" + +class CliTraefikTest < CliTestCase + test "boot" do + run_command("boot").tap do |output| + assert_match "docker run --name traefik --detach --restart unless-stopped --log-opt max-size=10m --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock traefik --providers.docker --log.level=DEBUG", output + end + end + + test "reboot" do + Mrsk::Cli::Traefik.any_instance.expects(:stop) + Mrsk::Cli::Traefik.any_instance.expects(:remove_container) + Mrsk::Cli::Traefik.any_instance.expects(:boot) + + run_command("reboot") + end + + test "start" do + run_command("start").tap do |output| + assert_match "docker container start traefik", output + end + end + + test "stop" do + run_command("stop").tap do |output| + assert_match "docker container stop traefik", output + end + end + + test "restart" do + Mrsk::Cli::Traefik.any_instance.expects(:stop) + Mrsk::Cli::Traefik.any_instance.expects(:start) + + run_command("restart") + end + + test "details" do + run_command("details").tap do |output| + assert_match "docker ps --filter name=traefik", output + end + end + + test "logs" do + SSHKit::Backend::Abstract.any_instance.stubs(:capture) + .with(:docker, :logs, "traefik", " --tail 100", "--timestamps", "2>&1") + .returns("Log entry") + + run_command("logs").tap do |output| + assert_match "Traefik Host: 1.1.1.1", output + assert_match "Log entry", output + end + end + + test "logs with follow" do + SSHKit::Backend::Abstract.any_instance.stubs(:exec) + .with("ssh -t root@1.1.1.1 'docker logs traefik --timestamps --tail 10 --follow 2>&1'") + + assert_match "docker logs traefik --timestamps --tail 10 --follow", run_command("logs", "--follow") + end + + test "remove" do + Mrsk::Cli::Traefik.any_instance.expects(:stop) + Mrsk::Cli::Traefik.any_instance.expects(:remove_container) + Mrsk::Cli::Traefik.any_instance.expects(:remove_image) + + run_command("remove") + end + + test "remove_container" do + run_command("remove_container").tap do |output| + assert_match "docker container prune --force --filter label=org.opencontainers.image.title=Traefik", output + end + end + + test "remove_image" do + run_command("remove_image").tap do |output| + assert_match "docker image prune --all --force --filter label=org.opencontainers.image.title=Traefik", output + end + end + + private + def run_command(*command) + stdouted { Mrsk::Cli::Traefik.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + end +end From d33b723afb9468ac1ab73447a772ee356b403f79 Mon Sep 17 00:00:00 2001 From: Samuel Sieg Date: Thu, 16 Mar 2023 08:24:54 +0100 Subject: [PATCH 3/7] Don't report exception --- test/cli/healthcheck_test.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/cli/healthcheck_test.rb b/test/cli/healthcheck_test.rb index 7b296393..a9adc353 100644 --- a/test/cli/healthcheck_test.rb +++ b/test/cli/healthcheck_test.rb @@ -2,6 +2,9 @@ require_relative "cli_test_case" class CliHealthcheckTest < CliTestCase test "perform" do + # Prevent expected failures from outputting to terminal + Thread.report_on_exception = false + SSHKit::Backend::Abstract.any_instance.stubs(:sleep) # No sleeping when retrying SSHKit::Backend::Abstract.any_instance.stubs(:execute) .with(:docker, :container, :ls, "--all", "--filter", "name=healthcheck-app", "--quiet", "|", :xargs, :docker, :stop, raise_on_non_zero_exit: false) From b166f3fbf44e7afb3c828829a6bc8c2ba83cde6d Mon Sep 17 00:00:00 2001 From: Samuel Sieg Date: Thu, 16 Mar 2023 08:29:10 +0100 Subject: [PATCH 4/7] Don't report exception here too --- test/cli/healthcheck_test.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/cli/healthcheck_test.rb b/test/cli/healthcheck_test.rb index a9adc353..55d1c9ec 100644 --- a/test/cli/healthcheck_test.rb +++ b/test/cli/healthcheck_test.rb @@ -47,6 +47,9 @@ class CliHealthcheckTest < CliTestCase end test "perform failing for unknown reason" do + # Prevent expected failures from outputting to terminal + Thread.report_on_exception = false + SSHKit::Backend::Abstract.any_instance.stubs(:execute) # No need to execute anything here SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info) .with(:curl, "--silent", "--output", "/dev/null", "--write-out", "'%{http_code}'", "--max-time", "2", "http://localhost:3999/up") From dae8b144699c38ec86d76dda4b35f3dbcef4a3de Mon Sep 17 00:00:00 2001 From: Samuel Sieg Date: Thu, 16 Mar 2023 08:35:12 +0100 Subject: [PATCH 5/7] Fix indentation --- test/cli/accessory_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/cli/accessory_test.rb b/test/cli/accessory_test.rb index 55a1be0b..fc6c25fb 100644 --- a/test/cli/accessory_test.rb +++ b/test/cli/accessory_test.rb @@ -131,7 +131,7 @@ class CliAccessoryTest < CliTestCase end private - def run_command(*command) - stdouted { Mrsk::Cli::Accessory.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } - end + def run_command(*command) + stdouted { Mrsk::Cli::Accessory.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + end end From 2de5250486d6338ed06abd9658ca53d03275887e Mon Sep 17 00:00:00 2001 From: Samuel Sieg Date: Fri, 17 Mar 2023 16:29:25 +0100 Subject: [PATCH 6/7] Add tests for `Mrsk::Utils` --- test/utils_test.rb | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 test/utils_test.rb diff --git a/test/utils_test.rb b/test/utils_test.rb new file mode 100644 index 00000000..0588ecb9 --- /dev/null +++ b/test/utils_test.rb @@ -0,0 +1,38 @@ +require "test_helper" + +class UtilsTest < ActiveSupport::TestCase + test "argumentize" do + assert_equal [ "--label", "foo=\"\\`bar\\`\"", "--label", "baz=\"qux\"", "--label", :quux ], \ + Mrsk::Utils.argumentize("--label", { foo: "`bar`", baz: "qux", quux: nil }) + end + + test "argumentize with redacted" do + assert_kind_of SSHKit::Redaction, \ + Mrsk::Utils.argumentize("--label", { foo: "bar" }, redacted: true).last + end + + test "argumentize_env_with_secrets" do + ENV.expects(:fetch).with("FOO").returns("secret") + assert_equal [ "-e", "FOO=\"secret\"", "-e", "BAZ=\"qux\"" ], \ + Mrsk::Utils.argumentize_env_with_secrets({ "secret" => [ "FOO" ], "clear" => { BAZ: "qux" } }) + end + + test "optionize" do + assert_equal [ "--foo", "\"bar\"", "--baz", "\"qux\"", "--quux" ], \ + Mrsk::Utils.optionize({ foo: "bar", baz: "qux", quux: true }) + end + + test "optionize with" do + assert_equal [ "--foo=\"bar\"", "--baz=\"qux\"", "--quux" ], \ + Mrsk::Utils.optionize({ foo: "bar", baz: "qux", quux: true }, with: "=") + end + + test "redact" do + assert_kind_of SSHKit::Redaction, Mrsk::Utils.redact("secret") + assert_equal "secret", Mrsk::Utils.redact("secret") + end + + test "escape_shell_value" do + assert_equal "\"\\`foo\\`\"", Mrsk::Utils.escape_shell_value("`foo`") + end +end From c3d0382935bbceb6f1d171d58c3de82ed6f7ce64 Mon Sep 17 00:00:00 2001 From: Samuel Sieg Date: Fri, 17 Mar 2023 16:31:10 +0100 Subject: [PATCH 7/7] Add another assertion for `escape_shell_value` --- test/utils_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/utils_test.rb b/test/utils_test.rb index 0588ecb9..f2af428b 100644 --- a/test/utils_test.rb +++ b/test/utils_test.rb @@ -33,6 +33,7 @@ class UtilsTest < ActiveSupport::TestCase end test "escape_shell_value" do + assert_equal "\"foo\"", Mrsk::Utils.escape_shell_value("foo") assert_equal "\"\\`foo\\`\"", Mrsk::Utils.escape_shell_value("`foo`") end end