Repository: mrsked/mrsk
File: test/cli/healthcheck_test.rb (Ruby)

Code before:
      .with(:docker, :run, "--rm", "curlimages/curl:latest", "--silent", "--output", "/dev/null", "--write-out", "'%{http_code}'", "--max-time", "2", "http://localhost:3999/up", raise_on_non_zero_exit: false)
      .returns("error message")
    SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info)
      .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :logs, "--tail", 50, "2>&1")

    exception = assert_raises SSHKit::Runner::ExecuteError do
      run_command("perform")
    end
    assert_equal "Exception while executing on host 1.1.1.1: Health check against /up failed to run: error message", exception.message
  end

  test "perform failing to connect" 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(:docker, :run, "--rm", "curlimages/curl:latest", "--silent", "--output", "/dev/null", "--write-out", "'%{http_code}'", "--max-time", "2", "http://localhost:3999/up", raise_on_non_zero_exit: false)
      .returns("000")
    SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info)
      .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :logs, "--tail", 50, "2>&1")

    exception = assert_raises SSHKit::Runner::ExecuteError do
      run_command("perform")
    end
    assert_equal "Exception while executing on host 1.1.1.1: Health check against /up failed to connect", exception.message
  end

  test "perform failing with server error" 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(:docker, :run, "--rm", "curlimages/curl:latest", "--silent", "--output", "/dev/null", "--write-out", "'%{http_code}'", "--max-time", "2", "http://localhost:3999/up", raise_on_non_zero_exit: false)
      .returns("500")
    SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info)
      .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--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


Review comment (suggestion):
We no longer have "missing curl" errors to worry about. Add a test for `000` status, indicating the curl didn't get an HTTP response at all.

Code after:
    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\"", "--health-cmd", "\"curl -f http://localhost:3000/up || exit 1\"", "--health-interval", "\"1s\"", "dhh/app:999")
    SSHKit::Backend::Abstract.any_instance.stubs(:execute)
      .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :container, :rm, raise_on_non_zero_exit: false)

    # Continually report unhealthy
    SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info)
      .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :inspect, "--format", "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'")
      .returns("unhealthy")

    # Capture logs when failing
    SSHKit::Backend::Abstract.any_instance.stubs(:capture_with_info)
      .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :logs, "--tail", 50, "2>&1")
      .returns("some log output")

    exception = assert_raises do
      run_command("perform")
    end
    assert_match "container not ready (unhealthy)", exception.message
  end

  private
    def run_command(*command)
      stdouted { Mrsk::Cli::Healthcheck.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
    end
end