Back to Repositories

Testing Proxied Accessory Lifecycle Management in Kamal

This integration test suite validates the lifecycle management of proxied accessories in Kamal deployments, focusing on core operations like boot, stop, start, restart, and removal of netcat services. The test ensures proper container management and network connectivity verification.

Test Coverage Overview

The test suite provides comprehensive coverage of accessory container lifecycle operations within Kamal deployments.

  • Validates complete lifecycle management of proxied accessories
  • Tests container state transitions and health checks
  • Verifies network accessibility and service responses
  • Covers cleanup and resource removal scenarios

Implementation Analysis

The implementation uses Minitest framework with a structured approach to container management verification.

  • Utilizes helper methods for consistent state assertions
  • Implements HTTP request validation for service availability
  • Employs container inspection for runtime state verification
  • Uses command capture for detailed debugging

Technical Details

  • Built on Minitest integration testing framework
  • Uses Net::HTTP for service health checks
  • Implements custom assertions for container state verification
  • Integrates with Docker container inspection
  • Utilizes URI parsing for endpoint validation

Best Practices Demonstrated

The test suite exemplifies robust integration testing practices for container-based services.

  • Modular helper methods for reusable assertions
  • Comprehensive lifecycle testing
  • Proper error handling and debugging support
  • Clear test organization and method naming
  • Thorough service health verification

basecamp/kamal

test/integration/proxied_accessory_test.rb

            
require_relative "integration_test"

class ProxiedAccessoryTest < IntegrationTest
  test "boot, stop, start, restart, logs, remove" do
    @app = "app_with_proxied_accessory"

    kamal :deploy

    kamal :accessory, :boot, :netcat
    assert_accessory_running :netcat
    assert_netcat_is_up

    kamal :accessory, :stop, :netcat
    assert_accessory_not_running :netcat
    assert_netcat_not_found

    kamal :accessory, :start, :netcat
    assert_accessory_running :netcat
    assert_netcat_is_up

    kamal :accessory, :restart, :netcat
    assert_accessory_running :netcat
    assert_netcat_is_up

    kamal :accessory, :remove, :netcat, "-y"
    assert_accessory_not_running :netcat
    assert_netcat_not_found
  end

  private
    def assert_accessory_running(name)
      assert_match /registry:4443\/busybox:1.36.0   "sh -c 'echo \\"Start/, accessory_details(name)
    end

    def assert_accessory_not_running(name)
      assert_no_match /registry:4443\/busybox:1.36.0   "sh -c 'echo \\"Start/, accessory_details(name)
    end

    def accessory_details(name)
      kamal :accessory, :details, name, capture: true
    end

    def assert_netcat_is_up
      response = netcat_response
      debug_response_code(response, "200")
      assert_equal "200", response.code
    end

    def assert_netcat_not_found
      response = netcat_response
      debug_response_code(response, "404")
      assert_equal "404", response.code
    end

    def netcat_response
      uri = URI.parse("http://127.0.0.1:12345/up")
      http = Net::HTTP.new(uri.host, uri.port)
      request = Net::HTTP::Get.new(uri)
      request["Host"] = "netcat"

      http.request(request)
    end
end