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

371 lines
9.2 KiB
Text
Raw Normal View History

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