-
Notifications
You must be signed in to change notification settings - Fork 3
Add BATS tests for image structure and runtime #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
d1f4e57
test: add BATS tests
tobybellwood 563b15c
chore: fix BATS test
tobybellwood 7b109dd
fix: update BATS tests for dynamic container naming and port discovery
tobybellwood 60fb41e
fix: update runtime BATS tests to handle timeout and container exposu…
tobybellwood 9f3a759
fix: improve BATS tests for HAProxy stats page accessibility and outp…
tobybellwood File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| IMAGE_NAME ?= pygmystack/haproxy | ||
| IMAGE_TAG ?= test | ||
| FULL_IMAGE := $(IMAGE_NAME):$(IMAGE_TAG) | ||
|
|
||
| .DEFAULT_GOAL := help | ||
|
|
||
| .PHONY: help build test test-bats test-structure test-runtime validate-config up down shell clean | ||
|
|
||
| help: ## Show this help | ||
| @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \ | ||
| awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}' | ||
|
|
||
| build: ## Build the Docker image | ||
| docker build --tag $(FULL_IMAGE) . | ||
|
|
||
| test: build ## Build image and run all tests (requires: brew install bats-core) | ||
| @command -v bats >/dev/null 2>&1 || { \ | ||
| echo "Error: bats is not installed. Install with: brew install bats-core"; \ | ||
| exit 1; \ | ||
| } | ||
| IMAGE_NAME=$(FULL_IMAGE) bats --tap tests/ | ||
|
|
||
| test-bats: ## Run all BATS tests without rebuilding the image | ||
| @command -v bats >/dev/null 2>&1 || { \ | ||
| echo "Error: bats is not installed. Install with: brew install bats-core"; \ | ||
| exit 1; \ | ||
| } | ||
| IMAGE_NAME=$(FULL_IMAGE) bats --tap tests/ | ||
|
|
||
| test-structure: ## Run image structure tests only (no Docker socket required) | ||
| @command -v bats >/dev/null 2>&1 || { \ | ||
| echo "Error: bats is not installed. Install with: brew install bats-core"; \ | ||
| exit 1; \ | ||
| } | ||
| IMAGE_NAME=$(FULL_IMAGE) bats --tap tests/image_structure.bats | ||
|
|
||
| test-runtime: ## Run container runtime and integration tests (Docker socket required) | ||
| @command -v bats >/dev/null 2>&1 || { \ | ||
| echo "Error: bats is not installed. Install with: brew install bats-core"; \ | ||
| exit 1; \ | ||
| } | ||
| IMAGE_NAME=$(FULL_IMAGE) bats --tap tests/runtime.bats | ||
|
|
||
| validate-config: ## Validate the default haproxy.cfg syntax | ||
| docker run --rm $(FULL_IMAGE) haproxy -c -f /app/haproxy.cfg | ||
|
|
||
| up: ## Start the stack with docker compose | ||
| docker compose up -d | ||
|
|
||
| down: ## Stop the stack with docker compose | ||
| docker compose down | ||
|
|
||
| shell: ## Open an interactive shell inside the container | ||
| docker run --rm -it --entrypoint bash $(FULL_IMAGE) | ||
|
|
||
| clean: ## Remove the local test Docker image | ||
| docker rmi $(FULL_IMAGE) 2>/dev/null || true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| #!/usr/bin/env bats | ||
| # Image structure tests — verify binaries, files, and configuration baked into | ||
| # the image. These tests run ephemeral containers and do not require access to | ||
| # the Docker socket. | ||
|
|
||
| IMAGE="${IMAGE_NAME:-pygmystack/haproxy:test}" | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Binaries | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "haproxy binary is available in PATH" { | ||
| run docker run --rm --entrypoint which "${IMAGE}" haproxy | ||
| [ "$status" -eq 0 ] | ||
| [ -n "$output" ] | ||
| } | ||
|
|
||
| @test "haproxy version is 2.9.x" { | ||
| run docker run --rm "${IMAGE}" sh -c 'haproxy -v 2>&1' | ||
| [ "$status" -eq 0 ] | ||
| [[ "$output" =~ "2.9" ]] | ||
| } | ||
|
|
||
| @test "docker-gen binary is available in PATH" { | ||
| run docker run --rm --entrypoint which "${IMAGE}" docker-gen | ||
| [ "$status" -eq 0 ] | ||
| [ -n "$output" ] | ||
| } | ||
|
|
||
| @test "bash is installed" { | ||
| run docker run --rm "${IMAGE}" sh -c 'bash --version 2>&1' | ||
| [ "$status" -eq 0 ] | ||
| [[ "$output" =~ "GNU bash" ]] | ||
| } | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Required files | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "/app/haproxy.cfg exists" { | ||
| run docker run --rm "${IMAGE}" test -f /app/haproxy.cfg | ||
| [ "$status" -eq 0 ] | ||
| } | ||
|
|
||
| @test "/app/haproxy.tmpl exists" { | ||
| run docker run --rm "${IMAGE}" test -f /app/haproxy.tmpl | ||
| [ "$status" -eq 0 ] | ||
| } | ||
|
|
||
| @test "/app/docker-entrypoint.sh is executable" { | ||
| run docker run --rm "${IMAGE}" test -x /app/docker-entrypoint.sh | ||
| [ "$status" -eq 0 ] | ||
| } | ||
|
|
||
| @test "/app/haproxy_start.sh is executable" { | ||
| run docker run --rm "${IMAGE}" test -x /app/haproxy_start.sh | ||
| [ "$status" -eq 0 ] | ||
| } | ||
|
|
||
| @test "/app/haproxy_reload.sh is executable" { | ||
| run docker run --rm "${IMAGE}" test -x /app/haproxy_reload.sh | ||
| [ "$status" -eq 0 ] | ||
| } | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Container environment | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "working directory is /app" { | ||
| run docker run --rm --entrypoint sh "${IMAGE}" -c 'pwd' | ||
| [ "$status" -eq 0 ] | ||
| [ "$output" = "/app" ] | ||
| } | ||
|
|
||
| @test "DOCKER_HOST is set to the expected unix socket path" { | ||
| run docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' "${IMAGE}" | ||
| [ "$status" -eq 0 ] | ||
| [[ "$output" =~ "DOCKER_HOST=unix:///tmp/docker.sock" ]] | ||
| } | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # HAProxy config validation | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "haproxy config checker accepts a valid config" { | ||
| # The baked-in haproxy.cfg is an intentionally minimal bootstrap config | ||
| # (no backend) that docker-gen immediately replaces at runtime. Instead, | ||
| # verify that the haproxy binary itself correctly validates a well-formed | ||
| # config, proving the binary is functional. | ||
| run docker run --rm --entrypoint sh "${IMAGE}" -c ' | ||
| cat > /tmp/valid.cfg <<HPXY | ||
| global | ||
| daemon | ||
| maxconn 1024 | ||
| defaults | ||
| mode http | ||
| timeout client 60s | ||
| timeout connect 60s | ||
| timeout server 60s | ||
| frontend http | ||
| bind :80 | ||
| default_backend be | ||
| backend be | ||
| mode http | ||
| HPXY | ||
| haproxy -c -f /tmp/valid.cfg' | ||
| [ "$status" -eq 0 ] | ||
| } | ||
|
|
||
| # --------------------------------------------------------------------------- | ||
| # Exposed ports (image metadata) | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| @test "image exposes port 80" { | ||
| run docker inspect --format='{{json .Config.ExposedPorts}}' "${IMAGE}" | ||
| [ "$status" -eq 0 ] | ||
| [[ "$output" =~ "80/tcp" ]] | ||
| } | ||
|
|
||
| @test "image exposes port 443" { | ||
| run docker inspect --format='{{json .Config.ExposedPorts}}' "${IMAGE}" | ||
| [ "$status" -eq 0 ] | ||
| [[ "$output" =~ "443/tcp" ]] | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.