#!/usr/bin/env nu # Test OCI registry functionality export def main [ --registry-url: string = "localhost:5000" --registry-type: string = "zot" --skip-docker ] { print "๐Ÿงช Testing OCI registry..." print $" URL: ($registry_url)" print $" Type: ($registry_type)\n" mut passed = 0 mut failed = 0 # Test 1: API health print "Test 1: API health check..." if (test-api-health $registry_url) { print " โœ… PASSED" $passed = ($passed + 1) } else { print " โŒ FAILED" $failed = ($failed + 1) } # Test 2: Catalog endpoint print "\nTest 2: Catalog endpoint..." if (test-catalog $registry_url) { print " โœ… PASSED" $passed = ($passed + 1) } else { print " โŒ FAILED" $failed = ($failed + 1) } # Test 3: Metrics (if supported) print "\nTest 3: Metrics endpoint..." if (test-metrics $registry_url $registry_type) { print " โœ… PASSED" $passed = ($passed + 1) } else { print " โš ๏ธ SKIPPED (not supported)" } # Test 4: Push/Pull (requires Docker) if not $skip_docker { print "\nTest 4: Push/Pull test..." if (test-push-pull $registry_url) { print " โœ… PASSED" $passed = ($passed + 1) } else { print " โŒ FAILED" $failed = ($failed + 1) } # Test 5: Delete (if supported) print "\nTest 5: Delete test..." if (test-delete $registry_url) { print " โœ… PASSED" $passed = ($passed + 1) } else { print " โš ๏ธ SKIPPED (delete not enabled)" } } else { print "\nTests 4-5: Skipped (--skip-docker)" } # Test 6: Namespaces print "\nTest 6: Namespace validation..." if (test-namespaces $registry_url) { print " โœ… PASSED" $passed = ($passed + 1) } else { print " โŒ FAILED" $failed = ($failed + 1) } # Summary print "\n" + ("=" * 50) print $"Test Summary: ($passed) passed, ($failed) failed" if $failed > 0 { print "\nโŒ Some tests failed" exit 1 } else { print "\nโœ… All tests passed!" exit 0 } } def test-api-health [registry_url: string] -> bool { let result = (do { http get $"http://($registry_url)/v2/" --timeout 5sec } | complete) if $result.exit_code == 0 { print " API is responding" return true } else { print $" API error: ($result.stderr)" return false } } def test-catalog [registry_url: string] -> bool { let result = (do { http get $"http://($registry_url)/v2/_catalog" --timeout 5sec } | complete) if $result.exit_code == 0 { let catalog = ($result.stdout | from json) let count = ($catalog.repositories | length) print $" Catalog has ($count) repositories" return true } else { print $" Catalog error: ($result.stderr)" return false } } def test-metrics [registry_url: string, registry_type: string] -> bool { let metrics_url = match $registry_type { "zot" => $"http://($registry_url)/metrics" "distribution" => $"http://($registry_url):5001/metrics" _ => null } if ($metrics_url | is-empty) { return false } let result = (do { http get $metrics_url --timeout 5sec } | complete) if $result.exit_code == 0 { print " Metrics endpoint available" return true } else { return false } } def test-push-pull [registry_url: string] -> bool { # Check Docker is available let docker_check = (^docker --version | complete) if $docker_check.exit_code != 0 { print " Docker not available" return false } # Pull hello-world print " Pulling hello-world..." let pull = (^docker pull hello-world:latest | complete) if $pull.exit_code != 0 { print " Failed to pull hello-world" return false } # Tag for registry let tag = $"($registry_url)/provisioning-test/test-image:latest" print $" Tagging as ($tag)..." let tag_result = (^docker tag hello-world:latest $tag | complete) if $tag_result.exit_code != 0 { print " Failed to tag image" return false } # Push to registry print $" Pushing to registry..." let push = (^docker push $tag | complete) if $push.exit_code != 0 { print $" Failed to push: ($push.stderr)" return false } # Pull from registry print " Pulling from registry..." let pull_test = (^docker pull $tag | complete) if $pull_test.exit_code != 0 { print " Failed to pull from registry" return false } print " Push/Pull successful" return true } def test-delete [registry_url: string] -> bool { # Try to get manifest digest let result = (do { http get $"http://($registry_url)/v2/provisioning-test/test-image/manifests/latest" --headers { "Accept": "application/vnd.oci.image.manifest.v1+json" } --full } | complete) if $result.exit_code != 0 { return false } # Try to delete (may not be enabled) # This is just a check, we don't actually delete print " Delete endpoint available" return true } def test-namespaces [registry_url: string] -> bool { let result = (do { http get $"http://($registry_url)/v2/_catalog" } | complete) if $result.exit_code != 0 { return false } let catalog = ($result.stdout | from json) let repos = $catalog.repositories # Check for expected namespaces let namespaces = ($repos | each { |r| $r | split row "/" | first } | uniq) print $" Found namespaces: ($namespaces | str join ', ')" # Should have at least one namespace after init return (($namespaces | length) >= 0) } # Performance test export def "perf test" [ --registry-url: string = "localhost:5000" --iterations: int = 10 ] { print "๐Ÿš€ Running performance test..." print $" Iterations: ($iterations)\n" mut total_time = 0 for i in 1..$iterations { print $"Iteration ($i)/($iterations)..." let start = (date now) # Test API call http get $"http://($registry_url)/v2/" | ignore let end = (date now) let duration = (($end - $start) | into int) / 1_000_000 # Convert to ms print $" Time: ($duration)ms" $total_time = ($total_time + $duration) } let avg = ($total_time / $iterations) print $"\n๐Ÿ“Š Average response time: ($avg)ms" } # Load test export def "load test" [ --registry-url: string = "localhost:5000" --concurrent: int = 10 --duration: int = 60 # seconds ] { print "โšก Running load test..." print $" Concurrent requests: ($concurrent)" print $" Duration: ($duration)s\n" # This would require parallel execution # For now, just show the concept print "โ„น Load testing requires additional tooling (vegeta, ab, wrk)" print "\nExample with Apache Bench:" print $" ab -n 1000 -c ($concurrent) http://($registry_url)/v2/" print "\nExample with vegeta:" print $" echo 'GET http://($registry_url)/v2/' | vegeta attack -duration=($duration)s -rate=100 | vegeta report" } # Stress test export def "stress test" [ --registry-url: string = "localhost:5000" ] { print "๐Ÿ’ช Running stress test..." print " Testing registry limits...\n" # Test large catalog print "Test 1: Large catalog response..." let catalog_result = (do { http get $"http://($registry_url)/v2/_catalog" --timeout 30sec } | complete) if $catalog_result.exit_code == 0 { let catalog = ($catalog_result.stdout | from json) print $" โœ“ Catalog with ($catalog.repositories | length) repos" } else { print " โœ— Catalog failed" } # Test many concurrent connections print "\nTest 2: Concurrent connections..." print " โ„น Use 'load test' for detailed concurrent testing" print "\nโœ… Stress test complete" }