From 1ab31a890c3be23ff5168c545263a6c0a50b7cd0 Mon Sep 17 00:00:00 2001 From: Jake Plimack Date: Tue, 26 Aug 2025 18:39:56 -0600 Subject: [PATCH 1/2] feat: make healthcheck work with http/https seamlessly without needing to provide a --health-cmd to docker/container-runtime Signed-off-by: Jake Plimack --- .gitignore | 3 ++ Dockerfile | 5 +- Makefile | 136 +++++++++++++++++++++++++++++++++++++++++++++++++ healthcheck.sh | 22 ++++++++ 4 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100755 healthcheck.sh diff --git a/.gitignore b/.gitignore index 68bc17f9..324097a3 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,6 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + +# Test certificate directories +redfish-test-certs.*/ diff --git a/Dockerfile b/Dockerfile index dd8a472c..1e400660 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,11 @@ RUN pip install --no-cache-dir --upgrade pip && \ COPY rfSsdpServer.py redfishMockupServer.py /usr/src/app/ COPY public-rackmount1 /usr/src/app/public-rackmount1 +# Copy healthcheck script +COPY healthcheck.sh /usr/src/app/ + # Env settings EXPOSE 8000 -HEALTHCHECK CMD curl --fail http://127.0.0.1:8000/redfish/v1 || exit 1 +HEALTHCHECK --interval=5s --timeout=3s --start-period=10s --retries=3 CMD /usr/src/app/healthcheck.sh WORKDIR /usr/src/app ENTRYPOINT ["python", "/usr/src/app/redfishMockupServer.py", "-H", "0.0.0.0"] diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..8c562789 --- /dev/null +++ b/Makefile @@ -0,0 +1,136 @@ +.PHONY: all build test test-http test-https clean clean-containers clean-certs help + +# Docker image name +IMAGE_NAME := redfish-mockup-server +IMAGE_TAG := test + +# Container names +HTTP_CONTAINER := redfish-http-test +HTTPS_CONTAINER := redfish-https-test + +# Ports +HTTP_PORT := 8456 +HTTPS_PORT := 8443 + +# Certificate paths (created in repo root) +CERT_DIR_TEMPLATE := redfish-test-certs.XXXXXX +CERT_DIR := $(shell mktemp -d ./$(CERT_DIR_TEMPLATE) 2>/dev/null || mktemp -d) +CERT_FILE := $(CERT_DIR)/cert.pem +KEY_FILE := $(CERT_DIR)/key.pem + +# Default target +all: build test + +# Build the Docker image +build: + @echo "Building Docker image $(IMAGE_NAME):$(IMAGE_TAG)..." + docker build -t $(IMAGE_NAME):$(IMAGE_TAG) . + +# Generate self-signed certificates for testing +$(CERT_FILE): + @echo "Generating self-signed SSL certificates in $(CERT_DIR)..." + @mkdir -p $(CERT_DIR) + @openssl req -x509 -nodes -newkey rsa:2048 \ + -keyout $(KEY_FILE) -out $(CERT_FILE) \ + -sha256 -days 365 \ + -subj "/C=US/ST=Test/L=Test/O=Test/OU=Test/CN=localhost" \ + 2>/dev/null + +# Test both HTTP and HTTPS +test: test-http test-https + @echo "All tests passed!" + +# Test HTTP mode +test-http: build clean-containers + @echo "Testing HTTP mode..." + @echo "Starting container..." + @docker run -d --name $(HTTP_CONTAINER) \ + -p $(HTTP_PORT):8000 \ + $(IMAGE_NAME):$(IMAGE_TAG) >/dev/null + @echo "Waiting for container to be healthy..." + @for i in 1 2 3 4 5 6 7 8 9 10; do \ + status=$$(docker inspect --format='{{.State.Health.Status}}' $(HTTP_CONTAINER) 2>/dev/null); \ + if [ "$$status" = "healthy" ]; then \ + echo "✓ HTTP container is healthy"; \ + break; \ + elif [ $$i -eq 10 ]; then \ + echo "✗ HTTP container failed to become healthy"; \ + docker logs $(HTTP_CONTAINER); \ + exit 1; \ + fi; \ + sleep 3; \ + done + @echo "Testing HTTP endpoint..." + @curl --fail --silent http://localhost:$(HTTP_PORT)/redfish/v1 >/dev/null && \ + echo "✓ HTTP endpoint is accessible" || \ + (echo "✗ HTTP endpoint is not accessible" && exit 1) + @docker stop $(HTTP_CONTAINER) >/dev/null + @docker rm $(HTTP_CONTAINER) >/dev/null + @echo "✓ HTTP mode test completed" + +# Test HTTPS mode +test-https: build clean-containers $(CERT_FILE) + @echo "Testing HTTPS mode..." + @echo "Starting container with SSL..." + @docker run -d --name $(HTTPS_CONTAINER) \ + -v $(CERT_DIR):/certs:ro \ + -p $(HTTPS_PORT):8000 \ + $(IMAGE_NAME):$(IMAGE_TAG) \ + --ssl --cert /certs/cert.pem --key /certs/key.pem >/dev/null + @echo "Waiting for container to be healthy..." + @for i in 1 2 3 4 5 6 7 8 9 10; do \ + status=$$(docker inspect --format='{{.State.Health.Status}}' $(HTTPS_CONTAINER) 2>/dev/null); \ + if [ "$$status" = "healthy" ]; then \ + echo "✓ HTTPS container is healthy"; \ + break; \ + elif [ $$i -eq 10 ]; then \ + echo "✗ HTTPS container failed to become healthy"; \ + docker logs $(HTTPS_CONTAINER); \ + exit 1; \ + fi; \ + sleep 3; \ + done + @echo "Testing HTTPS endpoint..." + @curl --fail --silent --insecure https://localhost:$(HTTPS_PORT)/redfish/v1 >/dev/null && \ + echo "✓ HTTPS endpoint is accessible" || \ + (echo "✗ HTTPS endpoint is not accessible" && exit 1) + @docker stop $(HTTPS_CONTAINER) >/dev/null + @docker rm $(HTTPS_CONTAINER) >/dev/null + @echo "✓ HTTPS mode test completed" + +# Run containers interactively for debugging +run-http: build + docker run --rm -it -p $(HTTP_PORT):8000 $(IMAGE_NAME):$(IMAGE_TAG) + +run-https: build $(CERT_FILE) + docker run --rm -it -v $(CERT_DIR):/certs:ro -p $(HTTPS_PORT):8000 \ + $(IMAGE_NAME):$(IMAGE_TAG) \ + --ssl --cert /certs/cert.pem --key /certs/key.pem + +# Clean up everything +clean: clean-containers clean-certs + @echo "Cleanup completed" + +# Clean up containers +clean-containers: + @docker stop $(HTTP_CONTAINER) 2>/dev/null || true + @docker stop $(HTTPS_CONTAINER) 2>/dev/null || true + @docker rm $(HTTP_CONTAINER) 2>/dev/null || true + @docker rm $(HTTPS_CONTAINER) 2>/dev/null || true + +# Clean up certificates +clean-certs: + @echo "Cleaning up certificate directories..." + @rm -rf ./redfish-test-certs.* + +# Show available targets +help: + @echo "Available targets:" + @echo " make build - Build the Docker image" + @echo " make test - Run all tests (HTTP and HTTPS)" + @echo " make test-http - Test HTTP mode only" + @echo " make test-https - Test HTTPS mode only" + @echo " make run-http - Run container in HTTP mode (interactive)" + @echo " make run-https - Run container in HTTPS mode (interactive)" + @echo " make clean - Clean up containers and certificates" + @echo " make help - Show this help message" \ No newline at end of file diff --git a/healthcheck.sh b/healthcheck.sh new file mode 100755 index 00000000..061ab226 --- /dev/null +++ b/healthcheck.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# Docker healthcheck script for Redfish Mockup Server +# Detects SSL mode and port from container arguments + +# Read the container's command arguments +ARGS=$(cat /proc/1/cmdline | tr '\0' ' ') + +# Detect port (default 8000) +PORT=8000 +if echo "$ARGS" | grep -q -- "--port"; then + # Extract port number after --port flag + PORT=$(echo "$ARGS" | sed -n 's/.*--port[[:space:]]*\([0-9]*\).*/\1/p') +fi + +# Detect SSL mode by checking for --ssl or -s flags +if echo "$ARGS" | grep -qE -- "(--ssl|-s[[:space:]])"; then + # HTTPS mode - use insecure flag to accept self-signed certificates + exec curl --insecure --fail "https://127.0.0.1:${PORT}/redfish/v1" || exit 1 +else + # HTTP mode + exec curl --fail "http://127.0.0.1:${PORT}/redfish/v1" || exit 1 +fi \ No newline at end of file From 62f5160ba551098e66fae46f7370503d900e2f99 Mon Sep 17 00:00:00 2001 From: Jake Plimack Date: Wed, 27 Aug 2025 22:16:33 -0600 Subject: [PATCH 2/2] fix: update GitHub Actions to use docker compose v2 Replace docker-compose (v1) with docker compose (v2) in GitHub Actions workflow as docker-compose is no longer available by default in GitHub runners. Signed-off-by: Jake Plimack --- .github/workflows/docker.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 39423322..2b6c2232 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -9,12 +9,12 @@ jobs: - uses: docker/setup-qemu-action@v3 - uses: docker/setup-buildx-action@v3.0.0 - name: Start containers - run: docker-compose up --build --force-recreate --detach + run: docker compose up --build --force-recreate --detach - name: Verify all tests completed successfully run: | set -x for testname in test-curl-nossl test-curl-ssl test-utils-nossl test-utils-ssl; do - name=$(docker-compose ps | grep ${testname} | awk '{print $1}') + name=$(docker compose ps | grep ${testname} | awk '{print $1}') rc=$(docker wait "${name}") if [ "${rc}" != "0" ]; then echo "test failed:" @@ -24,7 +24,7 @@ jobs: done - name: Logs if: always() - run: docker-compose logs + run: docker compose logs - name: Stop containers if: always() - run: docker-compose down --volumes --remove-orphans + run: docker compose down --volumes --remove-orphans