provisioning-core/nulib/domain/oci_registry/service.nu

332 lines
8.4 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
}