# OCI Registry Service Integration use ../config/loader.nu get-config # Start registry service export def start-oci-registry [ registry_type: string = "zot" config_path?: string ] -> bool { print $"Starting OCI registry service \(($registry_type)\)..." let registry_dir = get-registry-directory $registry_type if not ($registry_dir | path exists) { print $"ERROR: Registry directory not found: ($registry_dir)" return false } cd $registry_dir let compose_file = if ($config_path | is-empty) { "docker-compose.yml" } else { $config_path } let result = (^docker-compose -f $compose_file up -d | complete) if $result.exit_code == 0 { print "✅ Registry service started" return true } else { print $"ERROR: Failed to start registry: ($result.stderr)" return false } } # Stop registry service export def stop-oci-registry [ registry_type: string = "zot" ] -> bool { print $"Stopping OCI registry service \(($registry_type)\)..." let registry_dir = get-registry-directory $registry_type if not ($registry_dir | path exists) { print $"ERROR: Registry directory not found: ($registry_dir)" return false } cd $registry_dir let result = (^docker-compose down | complete) if $result.exit_code == 0 { print "✅ Registry service stopped" return true } else { print $"ERROR: Failed to stop registry: ($result.stderr)" return false } } # Get registry status export def get-oci-registry-status [ registry_type: string = "zot" ] -> record { let registry_dir = get-registry-directory $registry_type if not ($registry_dir | path exists) { return { running: false error: "Registry directory not found" } } cd $registry_dir let result = (^docker-compose ps --format json | complete) if $result.exit_code != 0 { return { running: false error: $result.stderr } } let containers = ($result.stdout | from json) let running = ($containers | all { |c| $c.State == "running" }) { running: $running containers: $containers type: $registry_type } } # Check registry health export def check-oci-registry-health [ registry_url: string ] -> bool { let result = (do { http get $"http://($registry_url)/v2/" --timeout 5sec } | complete) $result.exit_code == 0 } # Get registry info export def get-oci-registry-info [ registry_url: string ] -> record { # Try to fetch catalog let catalog_result = (do { http get $"http://($registry_url)/v2/_catalog" } | complete) let catalog = if $catalog_result.exit_code == 0 { $catalog_result.stdout | from json } else { {repositories: []} } # Count namespaces let namespaces = ($catalog.repositories | each { |r| $r | split row "/" | first } | uniq | length) { url: $registry_url healthy: ($catalog_result.exit_code == 0) repositories: ($catalog.repositories | length) namespaces: $namespaces timestamp: (date now | format date "%Y-%m-%d %H:%M:%S") } } # Get repository list export def get-oci-registry-repositories [ registry_url: string ] -> list { let result = (do { http get $"http://($registry_url)/v2/_catalog" } | complete) if $result.exit_code != 0 { return [] } let catalog = ($result.stdout | from json) $catalog.repositories } # Get repository tags export def get-oci-repository-tags [ registry_url: string repository: string ] -> list { let result = (do { http get $"http://($registry_url)/v2/($repository)/tags/list" } | complete) if $result.exit_code != 0 { return [] } let tags = ($result.stdout | from json) $tags.tags | default [] } # Get manifest for image export def get-oci-image-manifest [ registry_url: string repository: string tag: string ] -> record { let result = (do { http get $"http://($registry_url)/v2/($repository)/manifests/($tag)" --headers { "Accept": "application/vnd.oci.image.manifest.v1+json" } } | complete) if $result.exit_code != 0 { return {} } $result.stdout | from json } # Delete image tag export def delete-oci-image-tag [ registry_url: string repository: string tag: string ] -> bool { # First get the manifest digest let manifest_result = (do { http get $"http://($registry_url)/v2/($repository)/manifests/($tag)" --headers { "Accept": "application/vnd.oci.image.manifest.v1+json" } --full } | complete) if $manifest_result.exit_code != 0 { print $"ERROR: Failed to get manifest: ($manifest_result.stderr)" return false } let manifest = ($manifest_result.stdout | from json) let digest = ($manifest.headers | where name == "Docker-Content-Digest" | first | get value) # Delete using digest let delete_result = (do { http delete $"http://($registry_url)/v2/($repository)/manifests/($digest)" } | complete) if $delete_result.exit_code == 0 { print $"✅ Image ($repository):($tag) deleted" return true } else { print $"ERROR: Failed to delete image: ($delete_result.stderr)" return false } } # Garbage collection (Zot) export def run-oci-registry-gc [ registry_type: string = "zot" ] -> bool { match $registry_type { "zot" => { # Zot runs GC automatically based on config print "ℹ Zot runs garbage collection automatically" print " Check config.json for GC settings" return true } "distribution" => { # Distribution requires manual GC print "Running garbage collection..." let registry_dir = get-registry-directory $registry_type let result = (^docker-compose exec registry \ registry garbage-collect /etc/docker/registry/config.yml | complete) if $result.exit_code == 0 { print "✅ Garbage collection completed" return true } else { print $"ERROR: GC failed: ($result.stderr)" return false } } "harbor" => { print "ℹ Harbor runs GC via UI or API" print " Use Harbor admin interface for GC" return true } _ => { print $"ERROR: Unknown registry type: ($registry_type)" return false } } } # Get registry metrics (if available) export def get-oci-registry-metrics [ registry_url: string registry_type: string = "zot" ] -> string { let metrics_url = match $registry_type { "zot" => $"http://($registry_url)/metrics" "distribution" => $"http://($registry_url):5001/metrics" _ => null } if ($metrics_url | is-empty) { return "Metrics not available for this registry type" } let result = (do { http get $metrics_url } | complete) if $result.exit_code == 0 { $result.stdout } else { $"ERROR: Failed to fetch metrics: ($result.stderr)" } } # Helper: Get registry directory def get-registry-directory [registry_type: string] -> string { let config = (get-config) let base_path = ($config | get paths.base) $"($base_path)/provisioning/platform/oci-registry/($registry_type)" } # Push artifact to registry export def push-oci-artifact [ registry_url: string repository: string tag: string artifact_path: string ] -> bool { if not ($artifact_path | path exists) { print $"ERROR: Artifact not found: ($artifact_path)" return false } # This would require oras or docker buildx print "ℹ Use 'oras push' or 'docker push' to upload artifacts" print $" Target: ($registry_url)/($repository):($tag)" print $" Artifact: ($artifact_path)" false } # Pull artifact from registry export def pull-oci-artifact [ registry_url: string repository: string tag: string output_path: string ] -> bool { # This would require oras or docker pull print "ℹ Use 'oras pull' or 'docker pull' to download artifacts" print $" Source: ($registry_url)/($repository):($tag)" print $" Output: ($output_path)" false }