From 7023e0e6fc9869b5750548da7ee174c25e30f7ae Mon Sep 17 00:00:00 2001 From: Naeel Date: Sun, 22 Mar 2026 17:51:05 +0300 Subject: [PATCH] feat(builder): add REGISTRY_PROJECT for easy registry migration DockerHub (flat): REGISTRY_HOST=naeel, REGISTRY_PROJECT= -> naeel/{nsPrefix}-{func}:{tag} Harbor/GCR (project): REGISTRY_HOST=host, REGISTRY_PROJECT=proj -> host/proj/{func}:{tag} Switch registry by changing 2 env vars only. --- internal/builder/builder.go | 50 ++++++++++++++++++++++++++----------- internal/config/config.go | 9 +++++++ main.go | 7 +++--- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/internal/builder/builder.go b/internal/builder/builder.go index ddfccb6..5269a62 100644 --- a/internal/builder/builder.go +++ b/internal/builder/builder.go @@ -28,10 +28,11 @@ type Projecter interface { // Builder — управляет сборкой Docker образов через kaniko Jobs в k8s. type Builder struct { - client client.Client - builderImage string // образ kaniko - registryHost string // куда пушим образ (Harbor: host; DockerHub: user/org) - registrySecret string // имя k8s Secret с docker-кредами для kaniko + client client.Client + builderImage string // образ kaniko + registryHost string // куда пушим образ (DockerHub: "naeel"; Harbor: "host") + registryProject string // проект/org внутри registry (Harbor: project; DockerHub: пусто) + registrySecret string // имя k8s Secret с docker-кредами для kaniko s3Endpoint string // откуда kaniko берёт код s3AccessKey string s3SecretKey string @@ -42,9 +43,10 @@ type Builder struct { // Config — параметры для создания Builder'а. type Config struct { - BuilderImage string - RegistryHost string - RegistrySecret string // имя k8s Secret с .dockerconfigjson для пуша образов + BuilderImage string + RegistryHost string + RegistryProject string // пусто = DockerHub-режим (2 уровня); задан = project-режим (3 уровня) + RegistrySecret string // имя k8s Secret с .dockerconfigjson для пуша образов S3Endpoint string S3AccessKey string S3SecretKey string @@ -56,10 +58,11 @@ type Config struct { // New создаёт новый Builder. func New(c client.Client, cfg Config) *Builder { return &Builder{ - client: c, - builderImage: cfg.BuilderImage, - registryHost: cfg.RegistryHost, - registrySecret: cfg.RegistrySecret, + client: c, + builderImage: cfg.BuilderImage, + registryHost: cfg.RegistryHost, + registryProject: cfg.RegistryProject, + registrySecret: cfg.RegistrySecret, s3Endpoint: cfg.S3Endpoint, s3AccessKey: cfg.S3AccessKey, s3SecretKey: cfg.S3SecretKey, @@ -72,15 +75,32 @@ func New(c client.Client, cfg Config) *Builder { // ImageRef возвращает полный путь к образу в registry для данной функции и версии. // Тег = первые 12 символов sha256(s3Key): уникален per build, не меняется при // повторном reconcile с тем же s3Key, не требует хаков с :latest. -// Формат: {registryHost}/{namespace}/{funcName}:{tag} // -// Harbor: pearlharbor.registryk8s.services.ngcloud.ru/{ns}/{func}:{tag} +// Два режима — переключаются через REGISTRY_PROJECT env без пересборки оператора: // -// Чтобы сменить реестр — достаточно изменить REGISTRY_HOST в одном месте (ConfigMap). +// project-режим (REGISTRY_PROJECT задан): +// {host}/{project}/{func}:{tag} +// Для: Harbor, GCR, GHCR, любой registry с project-изоляцией +// Пример: pearlharbor.host/myproject/chaos-echo:abc123 +// +// flat-режим (REGISTRY_PROJECT пуст): +// {host}/{nsPrefix}-{func}:{tag} +// Для: DockerHub (max 2 уровня: user/repo) +// nsPrefix = первые 8 символов namespace — tenant-изоляция в имени репо +// Пример: naeel/slessffd1-chaos-echo:abc123 func (b *Builder) ImageRef(namespace, funcName, s3Key string) string { h := sha256.Sum256([]byte(s3Key)) tag := fmt.Sprintf("%x", h[:6]) // 12 hex-символов - return fmt.Sprintf("%s/%s/%s:%s", b.registryHost, namespace, funcName, tag) + if b.registryProject != "" { + // project-режим: Harbor / GCR / GHCR + return fmt.Sprintf("%s/%s/%s:%s", b.registryHost, b.registryProject, funcName, tag) + } + // flat-режим: DockerHub (только 2 уровня) + nsPrefix := namespace + if len(nsPrefix) > 8 { + nsPrefix = nsPrefix[:8] + } + return fmt.Sprintf("%s/%s-%s:%s", b.registryHost, nsPrefix, funcName, tag) } // Build запускает kaniko Job для сборки образа функции. diff --git a/internal/config/config.go b/internal/config/config.go index ebc243e..b88c543 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -29,6 +29,12 @@ type Config struct { // Registry — куда пушим собранные образы функций (DockerHub: "naeel", приватный: "host:port/prefix") RegistryHost string + // RegistryProject — опциональный проект/организация внутри registry. + // Если задан, imageRef = {host}/{project}/{func}:{tag} (Harbor, GCR, GHCR, любой с project-изоляцией) + // Если пуст, imageRef = {host}/{nsPrefix}-{func}:{tag} (DockerHub — только 2 уровня) + // Смена реестра = смена REGISTRY_HOST + REGISTRY_PROJECT без пересборки оператора. + RegistryProject string + // RegistrySecret — имя k8s Secret типа kubernetes.io/dockerconfigjson // Монтируется в kaniko Job для авторизации в registry. // Создаётся через hack/create-registry-secret.sh @@ -113,6 +119,9 @@ func Load() (*Config, error) { return nil, fmt.Errorf("REGISTRY_HOST is required") } + // REGISTRY_PROJECT — опциональный проект/org (Harbor: namespace; DockerHub: пусто) + cfg.RegistryProject = os.Getenv("REGISTRY_PROJECT") + // Secret с docker-кредами для kaniko (опционально — без него push в приватный registry упадёт) cfg.RegistrySecret = os.Getenv("REGISTRY_SECRET") if cfg.RegistrySecret == "" { diff --git a/main.go b/main.go index d46e65c..35c4a23 100644 --- a/main.go +++ b/main.go @@ -131,9 +131,10 @@ func main() { } bldr := builder.New(mgr.GetClient(), builder.Config{ - BuilderImage: cfg.BuilderImage, - RegistryHost: cfg.RegistryHost, - RegistrySecret: cfg.RegistrySecret, + BuilderImage: cfg.BuilderImage, + RegistryHost: cfg.RegistryHost, + RegistryProject: cfg.RegistryProject, + RegistrySecret: cfg.RegistrySecret, S3Endpoint: cfg.S3Endpoint, S3AccessKey: cfg.S3AccessKey, S3SecretKey: cfg.S3SecretKey,