A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
73
fork

Configure Feed

Select the types of activity you want to include in your feed.

at test 432 lines 13 kB view raw
1#!/bin/bash 2# 3# ATCR End-to-End Test Script 4# Tests single-arch and multi-arch image push/pull flows 5# 6# Usage: 7# ./test-e2e.sh # Run full test suite 8# ./test-e2e.sh --multi # Skip to multi-arch test only 9# REGISTRY=localhost:5000 ./test-e2e.sh # Custom registry 10# NAMESPACE=myuser ./test-e2e.sh # Custom namespace 11# VERBOSE=0 ./test-e2e.sh # Hide docker output 12# 13# To see bash command execution, edit this file and uncomment 'set -x' below 14# 15 16set -e 17 18# Verbose mode - shows docker command output 19# Set VERBOSE=0 to hide docker output: VERBOSE=0 ./test-e2e.sh 20VERBOSE="${VERBOSE:-1}" 21 22# Bash trace mode - shows every bash command as it executes 23# Uncomment the line below to see bash commands as they execute 24# set -x 25 26# Colors for output 27RED='\033[0;31m' 28GREEN='\033[0;32m' 29YELLOW='\033[1;33m' 30BLUE='\033[0;34m' 31NC='\033[0m' # No Color 32 33# Configuration 34REGISTRY="${REGISTRY:-127.0.0.1:5000}" 35NAMESPACE="${NAMESPACE:-evan.jarrett.net}" 36IMAGE_NAME="test-image" 37TAG="latest" 38MULTI_ARCH_TAG="multiarch" 39 40# Full image references 41SINGLE_ARCH_IMAGE="${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG}" 42MULTI_ARCH_IMAGE="${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${MULTI_ARCH_TAG}" 43AMD64_IMAGE="${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG}-amd64" 44ARM64_IMAGE="${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${TAG}-arm64" 45 46# Temporary directory for test images 47BUILD_DIR=$(mktemp -d) 48 49# Cleanup function 50cleanup() { 51 log_info "Cleaning up..." 52 rm -rf ${BUILD_DIR} 53 54 # Clean up any dangling manifest lists 55 docker manifest rm ${MULTI_ARCH_IMAGE} 2>/dev/null || true 56} 57 58trap cleanup EXIT 59 60# Logging functions 61log_info() { 62 echo -e "${GREEN}[INFO]${NC} $1" 63} 64 65log_error() { 66 echo -e "${RED}[ERROR]${NC} $1" 67} 68 69log_warn() { 70 echo -e "${YELLOW}[WARN]${NC} $1" 71} 72 73log_step() { 74 echo -e "\n${GREEN}==>${NC} $1" 75} 76 77log_cmd() { 78 echo -e "${BLUE}[CMD]${NC} $*" 79 if [ "$VERBOSE" = "1" ]; then 80 "$@" 81 else 82 "$@" > /dev/null 2>&1 83 fi 84} 85 86# Check if docker compose services are running 87check_compose_services() { 88 log_step "Checking docker compose services..." 89 90 if ! docker compose ps | grep -q "Up"; then 91 log_warn "Some services may not be running. Starting services..." 92 docker compose up -d 93 sleep 5 94 fi 95 96 # Check for errors in logs 97 log_info "Checking for errors in service logs..." 98 if docker compose logs --tail=50 | grep -i "error" | grep -v "level=error msg=\"error processing" | grep -v "test"; then 99 log_warn "Found some errors in logs (may be normal)" 100 else 101 log_info "No critical errors found in recent logs" 102 fi 103} 104 105# Build a simple test image 106build_single_arch_image() { 107 log_step "Building single-arch test image..." 108 109 cat > ${BUILD_DIR}/Dockerfile <<EOF 110FROM alpine:latest 111 112# Add some content to make the image non-trivial 113RUN apk add --no-cache curl bash 114 115# Create a test file with some content 116RUN echo "This is a test image created at \$(date)" > /test.txt 117RUN echo "Architecture: \$(uname -m)" >> /test.txt 118 119# Add a simple script 120RUN echo '#!/bin/sh' > /test.sh && \\ 121 echo 'echo "Test image running successfully!"' >> /test.sh && \\ 122 echo 'cat /test.txt' >> /test.sh && \\ 123 chmod +x /test.sh 124 125CMD ["/test.sh"] 126EOF 127 128 log_cmd docker build -t ${SINGLE_ARCH_IMAGE} ${BUILD_DIR} 129 log_info "Built single-arch image: ${SINGLE_ARCH_IMAGE}" 130} 131 132# Build multi-arch images using docker manifest create (old school!) 133build_multi_arch_images() { 134 log_step "Building multi-arch images (amd64 and arm64) using docker manifest..." 135 136 # Create Dockerfile for multi-arch builds 137 cat > ${BUILD_DIR}/Dockerfile.multiarch <<EOF 138FROM alpine:latest 139 140ARG TARGETARCH=unknown 141ARG TARGETOS=linux 142 143# Add some content to make the image non-trivial 144RUN apk add --no-cache curl bash 145 146# Create a test file with arch info 147RUN echo "This is a multi-arch test image" > /test.txt 148RUN echo "Target OS: \${TARGETOS}" >> /test.txt 149RUN echo "Target Architecture: \${TARGETARCH}" >> /test.txt 150RUN echo "Built at: \$(date)" >> /test.txt 151 152# Add a simple script 153RUN echo '#!/bin/sh' > /test.sh && \\ 154 echo 'echo "Multi-arch test image running!"' >> /test.sh && \\ 155 echo 'cat /test.txt' >> /test.sh && \\ 156 chmod +x /test.sh 157 158CMD ["/test.sh"] 159EOF 160 161 # Build amd64 image 162 log_info "Building amd64 image..." 163 log_cmd docker build \ 164 --platform linux/amd64 \ 165 --build-arg TARGETARCH=amd64 \ 166 --build-arg TARGETOS=linux \ 167 -t ${AMD64_IMAGE} \ 168 -f ${BUILD_DIR}/Dockerfile.multiarch \ 169 ${BUILD_DIR} 170 171 # Push amd64 image 172 log_info "Pushing amd64 image..." 173 echo -e "${BLUE}[CMD]${NC} docker push ${AMD64_IMAGE}" 174 if ! docker push ${AMD64_IMAGE}; then 175 log_error "Failed to push amd64 image" 176 return 1 177 fi 178 179 # Build arm64 image 180 log_info "Building arm64 image..." 181 log_cmd docker build \ 182 --platform linux/arm64 \ 183 --build-arg TARGETARCH=arm64 \ 184 --build-arg TARGETOS=linux \ 185 -t ${ARM64_IMAGE} \ 186 -f ${BUILD_DIR}/Dockerfile.multiarch \ 187 ${BUILD_DIR} 188 189 # Push arm64 image 190 log_info "Pushing arm64 image..." 191 echo -e "${BLUE}[CMD]${NC} docker push ${ARM64_IMAGE}" 192 if ! docker push ${ARM64_IMAGE}; then 193 log_error "Failed to push arm64 image" 194 return 1 195 fi 196 197 # Create manifest list 198 log_info "Creating multi-arch manifest list..." 199 echo -e "${BLUE}[CMD]${NC} docker manifest create --insecure ${MULTI_ARCH_IMAGE} ${AMD64_IMAGE} ${ARM64_IMAGE}" 200 docker manifest create --insecure ${MULTI_ARCH_IMAGE} \ 201 ${AMD64_IMAGE} \ 202 ${ARM64_IMAGE} 203 204 # Annotate manifests with platform info 205 log_info "Annotating manifest with platform info..." 206 docker manifest annotate ${MULTI_ARCH_IMAGE} ${AMD64_IMAGE} \ 207 --os linux --arch amd64 208 docker manifest annotate ${MULTI_ARCH_IMAGE} ${ARM64_IMAGE} \ 209 --os linux --arch arm64 210 211 # Push the manifest list 212 log_info "Pushing multi-arch manifest list..." 213 echo -e "${BLUE}[CMD]${NC} docker manifest push --insecure ${MULTI_ARCH_IMAGE}" 214 docker manifest push --insecure ${MULTI_ARCH_IMAGE} 215 216 log_info "Multi-arch manifest created and pushed: ${MULTI_ARCH_IMAGE}" 217} 218 219# Push single-arch image and verify digest 220push_single_arch_image() { 221 log_step "Pushing single-arch image..." 222 223 echo -e "${BLUE}[CMD]${NC} docker push ${SINGLE_ARCH_IMAGE}" 224 local push_output 225 push_output=$(docker push ${SINGLE_ARCH_IMAGE} 2>&1 | tee /dev/tty) 226 227 # Extract and verify digest 228 local digest 229 digest=$(echo "$push_output" | grep -oP 'digest: \K[a-z0-9:]+' | tail -1) 230 231 if [ -z "$digest" ]; then 232 log_error "Failed to get digest from push output" 233 return 1 234 fi 235 236 log_info "Pushed with digest: ${digest}" 237 238 # Verify we can reference by digest 239 log_info "Verifying digest reference..." 240 echo -e "${BLUE}[CMD]${NC} docker manifest inspect --insecure ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}@${digest}" 241 docker manifest inspect --insecure "${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}@${digest}" 242 log_info "Digest verification successful!" 243} 244 245# Verify multi-arch manifest 246verify_multi_arch_manifest() { 247 log_step "Verifying multi-arch manifest..." 248 249 echo -e "${BLUE}[CMD]${NC} docker manifest inspect --insecure ${MULTI_ARCH_IMAGE}" 250 local manifest 251 manifest=$(docker manifest inspect --insecure ${MULTI_ARCH_IMAGE} | tee /dev/tty) 252 253 # Check for both architectures (check for "amd64" and "arm64" in platform.architecture) 254 if echo "$manifest" | grep -q '"architecture": "amd64"'; then 255 log_info "Found linux/amd64 manifest" 256 else 257 log_error "Missing linux/amd64 manifest" 258 return 1 259 fi 260 261 if echo "$manifest" | grep -q '"architecture": "arm64"'; then 262 log_info "Found linux/arm64 manifest" 263 else 264 log_error "Missing linux/arm64 manifest" 265 return 1 266 fi 267 268 # Extract digest 269 local digest 270 digest=$(echo "$manifest" | jq -r '.manifests[0].digest' 2>/dev/null || echo "$manifest" | grep -oP 'sha256:[a-f0-9]+' | head -1) 271 272 if [ -n "$digest" ]; then 273 log_info "Multi-arch manifest digest: ${digest}" 274 fi 275} 276 277# Remove local images 278cleanup_local_images() { 279 log_step "Removing local images..." 280 281 echo -e "${BLUE}[CMD]${NC} docker rmi ${SINGLE_ARCH_IMAGE}" 282 docker rmi ${SINGLE_ARCH_IMAGE} || true 283 284 echo -e "${BLUE}[CMD]${NC} docker rmi ${AMD64_IMAGE}" 285 docker rmi ${AMD64_IMAGE} || true 286 287 echo -e "${BLUE}[CMD]${NC} docker rmi ${ARM64_IMAGE}" 288 docker rmi ${ARM64_IMAGE} || true 289 290 echo -e "${BLUE}[CMD]${NC} docker rmi ${MULTI_ARCH_IMAGE}" 291 docker rmi ${MULTI_ARCH_IMAGE} || true 292 293 # Clean up manifest list 294 docker manifest rm ${MULTI_ARCH_IMAGE} 2>/dev/null || true 295 296 # Also remove any cached layers 297 log_info "Pruning dangling images..." 298 log_cmd docker image prune -f 299 300 log_info "Local images removed" 301} 302 303# Pull images back 304pull_images() { 305 log_step "Pulling images back from registry..." 306 307 # Pull single-arch image 308 log_info "Pulling single-arch image..." 309 echo -e "${BLUE}[CMD]${NC} docker pull ${SINGLE_ARCH_IMAGE}" 310 if docker pull ${SINGLE_ARCH_IMAGE}; then 311 log_info "Successfully pulled: ${SINGLE_ARCH_IMAGE}" 312 else 313 log_error "Failed to pull single-arch image" 314 return 1 315 fi 316 317 # Pull multi-arch image 318 log_info "Pulling multi-arch image..." 319 echo -e "${BLUE}[CMD]${NC} docker pull ${MULTI_ARCH_IMAGE}" 320 if docker pull ${MULTI_ARCH_IMAGE}; then 321 log_info "Successfully pulled: ${MULTI_ARCH_IMAGE}" 322 else 323 log_error "Failed to pull multi-arch image" 324 return 1 325 fi 326} 327 328# Test running the images 329test_images() { 330 log_step "Testing pulled images..." 331 332 # Test single-arch image 333 log_info "Running single-arch image..." 334 log_cmd docker run --rm ${SINGLE_ARCH_IMAGE} 335 336 # Test multi-arch image 337 log_info "Running multi-arch image..." 338 log_cmd docker run --rm ${MULTI_ARCH_IMAGE} 339 340 log_info "All images ran successfully!" 341} 342 343# Check for errors in compose logs after operations 344check_compose_logs() { 345 log_step "Checking compose logs for errors..." 346 347 local error_count 348 error_count=$(docker compose logs --tail=100 | grep -i "error" | grep -v "level=error msg=\"error processing" | grep -v "test" | wc -l) 349 350 if [ "$error_count" -gt 0 ]; then 351 log_warn "Found ${error_count} error messages in logs:" 352 docker compose logs --tail=100 | grep -i "error" | grep -v "level=error msg=\"error processing" | grep -v "test" | tail -10 353 else 354 log_info "No errors found in compose logs" 355 fi 356} 357 358# Multi-arch only test flow 359multi_arch_only() { 360 log_step "Starting ATCR multi-arch test (skipping single-arch)" 361 log_info "Registry: ${REGISTRY}" 362 log_info "Namespace: ${NAMESPACE}" 363 log_info "Build directory: ${BUILD_DIR}" 364 log_info "Verbose mode: ${VERBOSE} (set VERBOSE=0 to hide docker output)" 365 366 # Check prerequisites 367 if ! command -v docker &> /dev/null; then 368 log_error "Docker is not installed" 369 exit 1 370 fi 371 372 if ! command -v jq &> /dev/null; then 373 log_warn "jq is not installed - some checks may be limited" 374 fi 375 376 # Run multi-arch test steps only 377 check_compose_services 378 build_multi_arch_images 379 verify_multi_arch_manifest 380 cleanup_local_images 381 pull_images 382 log_info "Running multi-arch image..." 383 log_cmd docker run --rm ${MULTI_ARCH_IMAGE} 384 check_compose_logs 385 386 log_step "Multi-arch test completed successfully!" 387 echo -e "${GREEN}========================================${NC}" 388 echo -e "${GREEN}Multi-arch test passed!${NC}" 389 echo -e "${GREEN}========================================${NC}" 390} 391 392# Main test flow 393main() { 394 log_step "Starting ATCR end-to-end test" 395 log_info "Registry: ${REGISTRY}" 396 log_info "Namespace: ${NAMESPACE}" 397 log_info "Build directory: ${BUILD_DIR}" 398 log_info "Verbose mode: ${VERBOSE} (set VERBOSE=0 to hide docker output)" 399 400 # Check prerequisites 401 if ! command -v docker &> /dev/null; then 402 log_error "Docker is not installed" 403 exit 1 404 fi 405 406 if ! command -v jq &> /dev/null; then 407 log_warn "jq is not installed - some checks may be limited" 408 fi 409 410 # Run test steps 411 check_compose_services 412 build_single_arch_image 413 push_single_arch_image 414 build_multi_arch_images 415 verify_multi_arch_manifest 416 cleanup_local_images 417 pull_images 418 test_images 419 check_compose_logs 420 421 log_step "End-to-end test completed successfully!" 422 echo -e "${GREEN}========================================${NC}" 423 echo -e "${GREEN}All tests passed!${NC}" 424 echo -e "${GREEN}========================================${NC}" 425} 426 427# Parse arguments 428if [ "$1" = "--multi" ]; then 429 multi_arch_only 430else 431 main "$@" 432fi