# OCI Registry Management Commands use ../config/loader.nu get-config # Start OCI registry export def "oci-registry start" [ --type: string = "zot" # zot, harbor, distribution --config: string --detach (-d) ] { print $"๐Ÿš€ Starting OCI registry \(($type)\)..." let registry_path = get-registry-path $type if not ($registry_path | path exists) { error make { msg: $"Registry path not found: ($registry_path)" } } cd $registry_path let compose_file = if ($config | is-empty) { "docker-compose.yml" } else { $config } let flags = if $detach { ["-d"] } else { [] } ^docker-compose -f $compose_file up ...$flags if $detach { print "โœ… Registry started in background" print $" Use 'oci-registry logs --type ($type)' to view logs" print $" Use 'oci-registry status --type ($type)' to check status" } } # Stop OCI registry export def "oci-registry stop" [ --type: string = "zot" --remove-volumes (-v) ] { print $"๐Ÿ›‘ Stopping OCI registry \(($type)\)..." let registry_path = get-registry-path $type cd $registry_path let flags = if $remove_volumes { ["-v"] } else { [] } ^docker-compose down ...$flags print "โœ… Registry stopped" } # Get registry status export def "oci-registry status" [ --type: string = "zot" --format: string = "table" # table, json ] -> any { let registry_path = get-registry-path $type cd $registry_path let containers = (^docker-compose ps --format json | from json) match $format { "json" => { $containers } "table" => { $containers | select Name State Status } _ => { $containers | select Name State Status } } } # Initialize registry (create namespaces, policies) export def "oci-registry init" [ --type: string = "zot" --registry-url: string = "localhost:5000" --admin-password: string = "admin" --skip-test ] { let script_path = $"(get-oci-registry-root)/scripts/init-registry.nu" let args = [ "--registry-type" $type "--registry-url" $registry_url "--admin-password" $admin_password ] let args = if $skip_test { $args | append ["--skip-test"] } else { $args } nu $script_path ...$args } # Configure registry setting export def "oci-registry configure" [ --type: string = "zot" setting: string value: string ] { print $"โš™๏ธ Configuring ($setting) = ($value)..." match $type { "zot" => { configure-zot-setting $setting $value } "harbor" => { configure-harbor-setting $setting $value } "distribution" => { configure-distribution-setting $setting $value } _ => { error make { msg: $"Unknown registry type: ($type)" } } } } # Get registry logs export def "oci-registry logs" [ --type: string = "zot" --follow (-f) --tail: int = 100 ] { let registry_path = get-registry-path $type cd $registry_path let flags = if $follow { ["--follow", "--tail", ($tail | into string)] } else { ["--tail", ($tail | into string)] } ^docker-compose logs ...$flags } # Health check export def "oci-registry health" [ --type: string = "zot" --registry-url: string = "localhost:5000" ] -> record { print "๐Ÿฅ Checking registry health..." let api_check = check-api-health $registry_url let catalog_check = check-catalog-health $registry_url let metrics_check = check-metrics-health $registry_url $type let overall = $api_check.healthy and $catalog_check.healthy { healthy: $overall api: $api_check catalog: $catalog_check metrics: $metrics_check timestamp: (date now | format date "%Y-%m-%d %H:%M:%S") } } # Push test image export def "oci-registry test-push" [ --registry-url: string = "localhost:5000" ] { print "๐Ÿงช Pushing test image..." # Pull hello-world ^docker pull hello-world:latest # Tag for our registry ^docker tag hello-world:latest $"($registry_url)/provisioning-test/hello:latest" # Push to registry ^docker push $"($registry_url)/provisioning-test/hello:latest" print "โœ… Test image pushed successfully" } # Pull test image export def "oci-registry test-pull" [ --registry-url: string = "localhost:5000" ] { print "๐Ÿงช Pulling test image..." ^docker pull $"($registry_url)/provisioning-test/hello:latest" print "โœ… Test image pulled successfully" } # List namespaces export def "oci-registry namespaces" [ --registry-url: string = "localhost:5000" --type: string = "zot" ] -> table { let result = (do { http get $"http://($registry_url)/v2/_catalog" } | complete) if $result.exit_code != 0 { error make { msg: $"Failed to fetch catalog: ($result.stderr)" } } let repos = ($result.stdout | from json | get repositories) let namespaces = ($repos | each { |repo| $repo | split row "/" | first } | uniq) $namespaces | each { |ns| let repo_count = ($repos | where { |r| $r | str starts-with $ns } | length) { namespace: $ns repositories: $repo_count } } } # Create namespace export def "oci-registry namespace create" [ name: string --registry-url: string = "localhost:5000" --type: string = "zot" ] { print $"๐Ÿ“ฆ Creating namespace: ($name)..." match $type { "zot" => { print " โ„น Namespace will be created on first push" } "harbor" => { create-harbor-namespace $registry_url $name } "distribution" => { print " โ„น Namespace will be created on first push" } _ => { error make { msg: $"Unknown registry type: ($type)" } } } } # Delete namespace export def "oci-registry namespace delete" [ name: string --registry-url: string = "localhost:5000" --type: string = "zot" --force ] { if not $force { let confirm = (input $"โš ๏ธ Delete namespace '($name)'? This will remove all images. \(y/N\): ") if $confirm != "y" { print "Cancelled" return } } print $"๐Ÿ—‘๏ธ Deleting namespace: ($name)..." match $type { "harbor" => { delete-harbor-namespace $registry_url $name } _ => { print $" โš  Namespace deletion not supported for ($type)" print " Delete all images manually and run garbage collection" } } } # Helper functions def get-registry-path [type: string] -> string { let root = get-oci-registry-root $"($root)/($type)" } def get-oci-registry-root [] -> string { let config = (get-config) let base_path = ($config | get paths.base) $"($base_path)/provisioning/platform/oci-registry" } def check-api-health [registry_url: string] -> record { let result = (do { http get $"http://($registry_url)/v2/" --timeout 5sec } | complete) { healthy: ($result.exit_code == 0) message: (if $result.exit_code == 0 { "OK" } else { $result.stderr }) } } def check-catalog-health [registry_url: string] -> record { let result = (do { http get $"http://($registry_url)/v2/_catalog" --timeout 5sec } | complete) { healthy: ($result.exit_code == 0) message: (if $result.exit_code == 0 { "OK" } else { $result.stderr }) } } def check-metrics-health [registry_url: string, type: string] -> record { let metrics_url = match $type { "zot" => $"http://($registry_url)/metrics" "distribution" => $"http://($registry_url):5001/metrics" _ => null } if ($metrics_url | is-empty) { return { healthy: false message: "Metrics not supported" } } let result = (do { http get $metrics_url --timeout 5sec } | complete) { healthy: ($result.exit_code == 0) message: (if $result.exit_code == 0 { "OK" } else { "Not available" }) } } def configure-zot-setting [setting: string, value: string] { print " โ„น Zot configuration requires editing config.json and restarting" print $" Setting: ($setting)" print $" Value: ($value)" } def configure-harbor-setting [setting: string, value: string] { print " โ„น Harbor configuration via API not fully implemented" print $" Setting: ($setting)" print $" Value: ($value)" } def configure-distribution-setting [setting: string, value: string] { print " โ„น Distribution configuration requires editing config.yml and restarting" print $" Setting: ($setting)" print $" Value: ($value)" } def create-harbor-namespace [registry_url: string, name: string] { print " โ„น Harbor project creation requires authentication" print $" Run: oci-registry init --type harbor" } def delete-harbor-namespace [registry_url: string, name: string] { print " โ„น Harbor project deletion requires authentication" print $" Use Harbor UI or API with admin credentials" }