Files
omnex/control-plane/api/internal/demos/demos.go
T
Nuxgrid d4009d329c
ci-api / test (push) Successful in 22m1s
ci-web / test (push) Successful in 13m23s
chore: update
2026-08-02 13:48:21 +02:00

142 lines
4.7 KiB
Go

// Package demos : cœur métier — cycle de vie des démos client déployées
// dans le cluster (une démo = un namespace isolé, TTL 30 jours).
package demos
import (
"errors"
"time"
)
// Paramètres durée de vie. Pas de quota sur le nombre de démos : seule
// limite réelle, le pool de ressources externes (voir PoolSizePerService).
const (
TTL = 30 * 24 * time.Hour // durée de vie d'une démo
PoolSizePerService = 5 // slots par service externe poolé
)
// Services externes gérés par pool pré-provisionné (non auto-créables par API).
// TomTom n'y figure pas : ses clés sont créées à la volée par le worker.
const (
ServiceTelegram = "telegram"
ServiceNowPayments = "nowpayments"
)
// PooledServices : services nécessitant un slot de pool par démo.
var PooledServices = []string{ServiceTelegram, ServiceNowPayments}
const (
StorageLocal = "local"
StorageS3 = "s3"
)
var (
ErrInvalidStorageDriver = errors.New("storage_driver doit être 'local' ou 's3'")
ErrS3ConfigIncomplete = errors.New("s3_bucket et s3_endpoint sont requis pour le stockage S3")
)
// ProvisionConfig : réglages saisis par l'admin à la création (popup de
// déploiement), propagés jusqu'au chart backend. Jamais persisté en base —
// notamment les secrets (token Telegram, clés NowPayments), qui ne
// transitent que par le fichier de valeurs Helm temporaire puis le Secret
// k8s du chart, comme les autres secrets.
type ProvisionConfig struct {
// TelegramBotUsername alimente TELEGRAM_BOT_USERNAME (lu par le backend
// au démarrage). TELEGRAM_WEBHOOK_URL est calculée automatiquement
// (URL publique de la démo) ; TELEGRAM_WEBHOOK_SECRET reste généré par
// le pool de ressources (ServiceTelegram), jamais saisi par l'admin.
TelegramBotUsername string
TelegramBotToken string
// NowPaymentsAPIKey écrase NOWPAYMENTS_API_KEY. NowPaymentsIPNSecret,
// s'il est fourni, écrase le secret pré-provisionné par le pool
// (ServiceNowPayments) — sinon celui du pool reste utilisé.
NowPaymentsAPIKey string
NowPaymentsIPNSecret string
StorageDriver string // "local" | "s3", "" => "local"
S3Bucket string
S3Endpoint string
// Load-balancer Telegram (chart lbtelegram) : installé seulement si au
// moins un bot est renseigné. Le reste de la config du chart (DSN
// postgres/redis, secrets JWT/webhook/backend-link) est généré par le
// provisioner, pas saisi par l'admin.
LBBot1Username string
LBBot1Token string
LBBot2Username string
LBBot2Token string
// Compte admin de l'application déployée (pas le compte omnex de
// l'admin qui lance la démo) — requis : sans lui, personne ne peut se
// connecter au backoffice de la démo. Créé directement en base une fois
// postgres/redis/backend/frontend Running (voir HelmProvisioner.Provision),
// car la table users n'existe qu'après la migration du backend au
// premier démarrage.
AdminUsername string
AdminPassword string
}
// LBTelegramEnabled indique si au moins un bot du load-balancer est configuré.
func (c ProvisionConfig) LBTelegramEnabled() bool {
return c.LBBot1Username != "" || c.LBBot2Username != ""
}
// Validate vérifie la cohérence du choix de stockage.
func (c ProvisionConfig) Validate() error {
switch c.StorageDriver {
case "", StorageLocal:
return nil
case StorageS3:
if c.S3Bucket == "" || c.S3Endpoint == "" {
return ErrS3ConfigIncomplete
}
return nil
default:
return ErrInvalidStorageDriver
}
}
// Status : état d'une démo.
type Status string
const (
StatusPending Status = "pending" // créée, pas encore prise par le worker
StatusProvisioning Status = "provisioning" // worker en train de déployer
StatusReady Status = "ready" // démo accessible
StatusExpiring Status = "expiring" // teardown en cours
StatusExpired Status = "expired" // détruite / TTL atteint
StatusFailed Status = "failed" // échec de provisioning
)
func (s Status) Valid() bool {
switch s {
case StatusPending, StatusProvisioning, StatusReady, StatusExpiring, StatusExpired, StatusFailed:
return true
}
return false
}
// Active indique si la démo occupe des ressources (compte dans la capacité).
func (s Status) Active() bool {
switch s {
case StatusPending, StatusProvisioning, StatusReady, StatusExpiring:
return true
}
return false
}
// Extendable : on ne prolonge que des démos encore vivantes.
func (s Status) Extendable() bool {
switch s {
case StatusProvisioning, StatusReady:
return true
}
return false
}
// ResourceStatus : état d'un slot de pool.
type ResourceStatus string
const (
ResourceFree ResourceStatus = "free"
ResourceBorrowed ResourceStatus = "borrowed"
)