openova/core/marketplace-api/handlers/provisioner.go
hatiyildiz 3c2f7e4cda feat(consolidation): Phase 1 — move Catalyst-Zero apps + CI + manifests into public monorepo
Per docs/PROVISIONING-PLAN.md Phase 1. Catalyst-Zero (the running deployment on Contabo k3s, namespaces catalyst/sme/marketplace/website) source code now lives in this public repo. Cutover to public-repo CI builds happens in Phase 2.

What moved (from openova-private → openova):
- apps/console/ → core/console/ (Astro+Svelte UI)
- apps/admin/ → core/admin/ (Astro+Svelte UI, includes canonical voucher/billing/tenants admin surface)
- apps/marketplace/ → core/marketplace/ (Astro+Svelte UI, 5-step Plan→Apps→Addons→Checkout→Review flow)
- website/marketplace-api/ → core/marketplace-api/ (Go backend with handlers/, provisioner/, store/)
- clusters/contabo-mkt/apps/catalyst/ → products/catalyst/chart/templates/ (catalyst-{ui,api} K8s manifests)
- clusters/contabo-mkt/apps/sme/services/ → products/catalyst/chart/templates/sme-services/ (15 manifests)
- clusters/contabo-mkt/apps/marketplace-api/ → products/catalyst/chart/templates/marketplace-api/
- 5 CI workflows (catalyst-build, marketplace-api-build, sme-{admin,console,marketplace}-build) → .github/workflows/, renamed to drop "sme-" prefix

Image refs updated:
- ghcr.io/openova-io/openova-private/catalyst-{ui,api} → ghcr.io/openova-io/openova/catalyst-{ui,api}
- ghcr.io/openova-io/openova-private/sme-{admin,console,marketplace} → ghcr.io/openova-io/openova/{admin,console,marketplace}
- ghcr.io/openova-io/openova-private/marketplace-api → ghcr.io/openova-io/openova/marketplace-api

Workflow path updates:
- paths: 'apps/{X}/**' → 'core/{X}/**'
- context: apps/{X} → core/{X}
- deploy paths: clusters/contabo-mkt/apps/{X}/.../{X}.yaml → products/catalyst/chart/templates/.../{X}.yaml
- deploy commit: git add clusters/ → git add products/

Deferred to follow-up phase:
- 8 legacy SME backend services (auth, billing, catalog, domain, gateway, notification, provisioning, tenant) keep their ghcr.io/openova-io/openova-private/sme-* image refs because their source code in openova-private/services/ has not yet been migrated to public repo. Tracked via TODO in core/README.md migration history.
- sme-services-build.yaml NOT migrated (matches deferred services).

Documentation updates:
- core/README.md rewritten to describe what's actually in this directory now (4 deployed modules, not the old Go-monorepo placeholder design)
- products/catalyst/README.md created with migration status table
- products/catalyst/chart/Chart.yaml created (umbrella bp-catalyst-platform chart)
- docs/IMPLEMENTATION-STATUS.md §1 + §2.1 + §6 updated: console/admin/marketplace/marketplace-api/catalyst-{ui,api} all flipped from 📐 to 🚧 (deployed but not yet wired to unified Catalyst contract); openova Sovereign description rewritten to make Catalyst-Zero status explicit; omantel target updated to omantel.omani.works on Hetzner.

Verification:
- 99 source files copied (verified via git ls-files count)
- All image refs updated except the 8 deferred legacy SME backend services (verified via grep openova-private)
- Workflow naming reflects unified Catalyst (no more "sme-" prefix)

Phase 2 next: trigger public-repo CI builds, GHCR images published under openova/ namespace, Flux source on Catalyst-Zero repointed to this repo, rolling update of Contabo pods to new image SHAs. Catalyst-Zero becomes self-built from the public repo.
2026-04-28 12:08:09 +02:00

81 lines
2.2 KiB
Go

package handlers
import (
"log"
"time"
"github.com/openova-io/openova-private/website/marketplace-api/store"
)
// runProvisioning simulates the async provisioning workflow.
// In production, this commits manifests to Git and polls Flux reconciliation status.
func (h *Handler) runProvisioning(p *store.Provision) {
sizeLabels := map[string]string{"xs": "XS", "s": "S", "m": "M", "l": "L"}
for i := range p.Steps {
now := time.Now()
p.Steps[i].Status = store.StatusProvisioning
p.Steps[i].StartedAt = &now
p.UpdatedAt = now
h.Store.UpdateProvision(p)
// Simulate work — in production this would be:
// 1. Git commit (vcluster.yaml, resource-quota.yaml, helmrelease.yaml)
// 2. Wait for Flux reconciliation webhook
// 3. Verify pod readiness
duration := 3*time.Second + time.Duration(i)*time.Second
time.Sleep(duration)
done := time.Now()
p.Steps[i].Status = store.StatusCompleted
p.Steps[i].DoneAt = &done
p.Steps[i].Message = "Done"
p.UpdatedAt = done
h.Store.UpdateProvision(p)
log.Printf("Provision %s: step %d/%d completed (%s)", p.ID, i+1, len(p.Steps), p.Steps[i].Name)
}
p.Status = store.StatusCompleted
p.UpdatedAt = time.Now()
h.Store.UpdateProvision(p)
// Create tenant record
tenant := &store.Tenant{
ID: p.TenantID,
CompanyName: p.CompanyName,
Email: p.Email,
Subdomain: p.Subdomain,
VClusterName: "vc-" + p.Subdomain,
VClusterStatus: "running",
Size: p.Size,
SizeLabel: sizeLabels[p.Size],
Apps: make([]store.App, 0, len(p.Apps)),
Domains: []store.Domain{
{
Domain: p.Subdomain + ".openova.cloud",
Type: "subdomain",
TLSReady: true,
CreatedAt: time.Now().Format(time.RFC3339),
},
},
CreatedAt: time.Now(),
}
for _, appSlug := range p.Apps {
tenant.Apps = append(tenant.Apps, store.App{
Slug: appSlug,
Name: appSlug, // In production, resolve from catalog
Status: "running",
URL: "https://" + appSlug + "." + p.Subdomain + ".openova.cloud",
Version: "latest",
DeployedAt: time.Now().Format(time.RFC3339),
Healthy: true,
})
}
h.Store.CreateTenant(tenant)
log.Printf("Provision %s completed: tenant %s created with %d apps", p.ID, p.TenantID, len(p.Apps))
}