2025-10-07 10:59:52 +01:00

293 lines
9.1 KiB
Plaintext

#!/usr/bin/env nu
# Initialize OCI registry with required namespaces and policies
export def main [
--registry-type: string = "zot" # zot, harbor, distribution
--registry-url: string = "localhost:5000"
--admin-password: string = "admin"
--skip-test
] {
print "🚀 Initializing OCI registry..."
print $" Type: ($registry_type)"
print $" URL: ($registry_url)"
# Wait for registry to be healthy
print "\n⏳ Waiting for registry to be ready..."
wait-for-registry-health $registry_url
# Create namespaces
print "\n📦 Creating namespaces..."
create-default-namespaces $registry_url $registry_type $admin_password
# Setup policies
print "\n🔒 Configuring access policies..."
setup-access-policies $registry_url $registry_type $admin_password
# Push test image (unless skipped)
if not $skip_test {
print "\n🧪 Pushing test image..."
push-test-image $registry_url $registry_type
}
print "\n✅ OCI registry initialized successfully!"
print "\n📊 Registry Information:"
get-registry-info $registry_url $registry_type
}
def wait-for-registry-health [registry_url: string] {
mut retries = 30
mut attempt = 1
while $retries > 0 {
print $" Attempt ($attempt)/30..."
let result = (do {
http get $"http://($registry_url)/v2/"
} | complete)
if $result.exit_code == 0 {
print " ✓ Registry is healthy"
return
}
$retries = ($retries - 1)
$attempt = ($attempt + 1)
sleep 2sec
}
error make {msg: "Registry failed to become healthy after 60 seconds"}
}
def create-default-namespaces [
registry_url: string
registry_type: string
admin_password: string
] {
let namespaces = [
{
name: "provisioning-extensions"
description: "Extension packages (providers, taskservs, clusters)"
public: false
}
{
name: "provisioning-kcl"
description: "KCL schema packages"
public: false
}
{
name: "provisioning-platform"
description: "Platform service images (orchestrator, control-center, etc.)"
public: false
}
{
name: "provisioning-test"
description: "Test images and artifacts"
public: true
}
]
for namespace in $namespaces {
print $" Creating ($namespace.name)..."
print $" Description: ($namespace.description)"
print $" Public: ($namespace.public)"
# Create namespace (method depends on registry type)
match $registry_type {
"zot" => {
# Zot creates namespaces implicitly on first push
print " ✓ Will be created on first push"
}
"harbor" => {
# Harbor requires API call to create project
create-harbor-project $registry_url $namespace.name $namespace.description $namespace.public $admin_password
}
"distribution" => {
# Distribution creates namespaces implicitly
print " ✓ Will be created on first push"
}
_ => {
print $" ⚠ Unknown registry type: ($registry_type)"
}
}
}
}
def setup-access-policies [
registry_url: string
registry_type: string
admin_password: string
] {
# Configure access policies based on registry type
match $registry_type {
"zot" => {
# Zot policies in config.json
print " ✓ Policies configured via config.json"
print " - provisioning-extensions: authenticated users"
print " - provisioning-kcl: authenticated users"
print " - provisioning-platform: private"
print " - provisioning-test: public read"
}
"harbor" => {
# Harbor policies via API
print " Configuring Harbor policies..."
setup-harbor-policies $registry_url $admin_password
}
"distribution" => {
# Distribution uses htpasswd
print " ✓ Policies configured via htpasswd"
print " - All authenticated users: push/pull"
print " - Anonymous: pull only public repos"
}
_ => {
print $" ⚠ Unknown registry type: ($registry_type)"
}
}
}
def push-test-image [registry_url: string, registry_type: string] {
print $" Pushing test artifact to ($registry_url)/provisioning-test/hello:latest"
# Create minimal OCI artifact using oras or docker
let result = (do {
# Try to push using docker if available
docker pull hello-world:latest | complete
} | complete)
if $result.exit_code == 0 {
let tag_result = (do {
docker tag hello-world:latest $"($registry_url)/provisioning-test/hello:latest"
} | complete)
if $tag_result.exit_code == 0 {
let push_result = (do {
docker push $"($registry_url)/provisioning-test/hello:latest"
} | complete)
if $push_result.exit_code == 0 {
print " ✓ Test image pushed successfully"
return
}
}
}
print " ⚠ Could not push test image (docker may not be available)"
print " This is optional and can be done manually later"
}
def create-harbor-project [
registry_url: string
project_name: string
description: string
public: bool
admin_password: string
] {
# API call to create Harbor project
let body = {
project_name: $project_name
metadata: {
public: ($public | into string)
}
storage_limit: -1
}
let auth = $"admin:($admin_password)" | encode base64
let result = (do {
http post $"http://($registry_url)/api/v2.0/projects" $body --headers {
"Authorization": $"Basic ($auth)"
"Content-Type": "application/json"
}
} | complete)
if $result.exit_code == 0 {
print $" ✓ Project created"
} else {
print $" ⚠ Could not create project (may already exist)"
}
}
def setup-harbor-policies [registry_url: string, admin_password: string] {
# Setup Harbor policies via API
let projects = ["provisioning-extensions", "provisioning-kcl", "provisioning-platform", "provisioning-test"]
for project in $projects {
print $" Configuring policies for ($project)..."
# Set retention policy
let retention = {
rules: [
{
disabled: false
action: "retain"
params: {
latestPushedK: 10
}
tag_selectors: [
{
kind: "doublestar"
decoration: "matches"
pattern: "**"
}
]
scope_selectors: {
repository: [
{
kind: "doublestar"
decoration: "matches"
pattern: "**"
}
]
}
}
]
algorithm: "or"
}
# Additional Harbor-specific configurations
print $" ✓ Policies configured"
}
}
def get-registry-info [registry_url: string, registry_type: string] -> table {
let info = match $registry_type {
"zot" => {
[
{key: "Type", value: "Zot (lightweight)"}
{key: "Version", value: "2.0.1"}
{key: "API", value: $"http://($registry_url)/v2/"}
{key: "UI", value: $"http://($registry_url)/"}
{key: "Metrics", value: $"http://($registry_url)/metrics"}
{key: "Features", value: "Search, UI, Metrics, Scrub, GC"}
]
}
"harbor" => {
[
{key: "Type", value: "Harbor (full-featured)"}
{key: "Version", value: "2.9.0"}
{key: "API", value: $"http://($registry_url)/api/v2.0/"}
{key: "UI", value: $"http://($registry_url)/"}
{key: "Features", value: "Replication, Scanning, RBAC, Webhooks"}
]
}
"distribution" => {
[
{key: "Type", value: "Distribution (OCI standard)"}
{key: "Version", value: "2.8"}
{key: "API", value: $"http://($registry_url)/v2/"}
{key: "UI", value: $"http://($registry_url):8080/"}
{key: "Metrics", value: $"http://($registry_url):5001/metrics"}
{key: "Features", value: "OCI-compliant, Lightweight, Fast"}
]
}
_ => {
[
{key: "Type", value: "Unknown"}
{key: "URL", value: $registry_url}
]
}
}
$info | table
}