feat: harbor integration — EnsureProject + per-namespace image path

- internal/harbor/client.go: новый пакет, EnsureProject (GET+POST idempotent)
- config.go: добавлены HarborUser/HarborPass (из HARBOR_USER/HARBOR_PASS env)
- builder.go: Projecter интерфейс, harborClient поле, ImageRef: {host}/{ns}/{func}:{tag}
  EnsureProject вызывается перед каждым Build()
- function_controller.go: HarborClient поле, EnsureProject при создании k8s NS
- main.go: создание harbor.Client если HARBOR_USER+HARBOR_PASS заданы
- operator.yaml: REGISTRY_HOST=pearlharbor..., HARBOR_USER=admin, v0.1.24
- hack/create-registry-secret.sh: переписан для Harbor (HARBOR_USER/HARBOR_PASS)

Смена registry — только через REGISTRY_HOST в ConfigMap, больше нигде.
This commit is contained in:
“Naeel”
2026-03-11 14:58:04 +04:00
parent 6443f21ddc
commit babd8e6109
7 changed files with 185 additions and 34 deletions
+12 -3
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-03-08
// Изменено: 2026-03-11
// FunctionReconciler — основной контроллер оператора.
// Следит за CRD Function и управляет lifecycle функции:
// Pending → Building (запуск kaniko Job) → Ready (образ собран, Deployment создан) / Failed
@@ -25,6 +25,7 @@ import (
slessv1alpha1 "gitea-naeel.giteak8s.services.ngcloud.ru/naeel/sless/api/v1alpha1"
"gitea-naeel.giteak8s.services.ngcloud.ru/naeel/sless/internal/builder"
"gitea-naeel.giteak8s.services.ngcloud.ru/naeel/sless/internal/harbor"
)
// FunctionReconciler reconciles a Function object
@@ -32,8 +33,9 @@ type FunctionReconciler struct {
client.Client
Scheme *runtime.Scheme
Builder *builder.Builder
RegistrySecret string // имя Secret с docker credentials (для imagePullSecrets в подах функций)
OperatorNamespace string // namespace оператора — откуда копируем RegistrySecret в sless-fn-*
RegistrySecret string // имя Secret с docker credentials (для imagePullSecrets в подах функций)
OperatorNamespace string // namespace оператора — откуда копируем RegistrySecret в sless-fn-*
HarborClient *harbor.Client // nil — Harbor не используется, EnsureProject пропускается
}
//+kubebuilder:rbac:groups=sless.kube5s.ru,resources=functions,verbs=get;list;watch;create;update;patch;delete
@@ -183,6 +185,13 @@ func (r *FunctionReconciler) ensureDeployment(ctx context.Context, fn *slessv1al
if err := r.Create(ctx, ns); err != nil {
return ctrl.Result{}, fmt.Errorf("create function namespace: %w", err)
}
// Создаём Harbor-проект для namespace сразу при создании k8s NS (best-effort).
// Если не удалось — EnsureProject повторит вызов внутри Build().
if r.HarborClient != nil {
if err := r.HarborClient.EnsureProject(ctx, fn.Namespace); err != nil {
log.FromContext(ctx).Error(err, "harbor ensure project on ns create", "project", fn.Namespace)
}
}
} else {
return ctrl.Result{}, fmt.Errorf("get function namespace: %w", err)
}