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