fix: destroy route cleanup bug — delete Service+Ingress on trigger/function deletion
- controllers/trigger_controller.go: handleTriggerDeletion теперь удаляет Service
и Ingress из sless-fn-{ns} при удалении HTTP-триггера
- controllers/function_controller.go: handleDeletion теперь удаляет Service и Ingress
(имена совпадают с fn.Name); добавлен импорт netv1
- terraform/provider trigger_resource.go: Delete ждёт пока GetTrigger вернёт 404
(до 90с) — провайдер не возвращает успех раньше чем cleanup завершён
- examples: версия провайдера обновлена до ~> 0.1.11
Operator: naeel/sless-operator:v0.1.17
Provider: v0.1.11
Fixes DESTROY_ROUTE_CLEANUP_BUG.md
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
netv1 "k8s.io/api/networking/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -302,7 +303,7 @@ func (r *FunctionReconciler) ensureRegistrySecret(ctx context.Context, targetNS
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleDeletion обрабатывает удаление Function: удаляет Deployment и убирает finalizer.
|
||||
// handleDeletion обрабатывает удаление Function: удаляет Deployment, Service, Ingress и убирает finalizer.
|
||||
func (r *FunctionReconciler) handleDeletion(ctx context.Context, fn *slessv1alpha1.Function) (ctrl.Result, error) {
|
||||
deployNS := "sless-fn-" + fn.Namespace
|
||||
dep := &appsv1.Deployment{}
|
||||
@@ -310,6 +311,17 @@ func (r *FunctionReconciler) handleDeletion(ctx context.Context, fn *slessv1alph
|
||||
_ = r.Delete(ctx, dep)
|
||||
}
|
||||
|
||||
// Удаляем Service и Ingress — созданы HTTP триггером, но именованы по функции.
|
||||
// Если function_controller не удалит их, Ingress остаётся после destroy → 502.
|
||||
svc := &corev1.Service{}
|
||||
if err := r.Get(ctx, client.ObjectKey{Name: fn.Name, Namespace: deployNS}, svc); err == nil {
|
||||
_ = r.Delete(ctx, svc)
|
||||
}
|
||||
ing := &netv1.Ingress{}
|
||||
if err := r.Get(ctx, client.ObjectKey{Name: fn.Name, Namespace: deployNS}, ing); err == nil {
|
||||
_ = r.Delete(ctx, ing)
|
||||
}
|
||||
|
||||
fn.Finalizers = removeString(fn.Finalizers, finalizerName)
|
||||
if err := r.Update(ctx, fn); err != nil {
|
||||
return ctrl.Result{}, fmt.Errorf("remove finalizer: %w", err)
|
||||
|
||||
@@ -282,8 +282,25 @@ func (r *TriggerReconciler) handleTriggerDeletion(ctx context.Context, tr *sless
|
||||
_ = r.Delete(ctx, cj)
|
||||
}
|
||||
}
|
||||
// Ingress/Service для HTTP триггеров оставляем — они могут быть нужны другим триггерам,
|
||||
// полная очистка происходит при удалении Function через function_controller finalizer
|
||||
|
||||
// Для HTTP триггеров удаляем Service и Ingress из sless-fn-{namespace}.
|
||||
// Имена ресурсов совпадают с именем функции (FunctionRef).
|
||||
// Без этого Ingress остаётся висеть после destroy и endpoint возвращает 502.
|
||||
if tr.Spec.Type == slessv1alpha1.TriggerTypeHTTP {
|
||||
deployNS := "sless-fn-" + tr.Namespace
|
||||
fnName := tr.Spec.FunctionRef
|
||||
|
||||
svc := &corev1.Service{}
|
||||
if err := r.Get(ctx, client.ObjectKey{Name: fnName, Namespace: deployNS}, svc); err == nil {
|
||||
_ = r.Delete(ctx, svc)
|
||||
}
|
||||
|
||||
ing := &netv1.Ingress{}
|
||||
if err := r.Get(ctx, client.ObjectKey{Name: fnName, Namespace: deployNS}, ing); err == nil {
|
||||
_ = r.Delete(ctx, ing)
|
||||
}
|
||||
}
|
||||
|
||||
tr.Finalizers = removeString(tr.Finalizers, triggerFinalizer)
|
||||
if err := r.Update(ctx, tr); err != nil {
|
||||
return ctrl.Result{}, fmt.Errorf("remove trigger finalizer: %w", err)
|
||||
|
||||
@@ -8,7 +8,7 @@ terraform {
|
||||
required_providers {
|
||||
sless = {
|
||||
source = "terra.k8c.ru/naeel/sless"
|
||||
version = "~> 0.1.10"
|
||||
version = "~> 0.1.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ terraform {
|
||||
# Провайдер для управления serverless функциями через sless API
|
||||
sless = {
|
||||
source = "terra.k8c.ru/naeel/sless"
|
||||
version = "~> 0.1.10"
|
||||
version = "~> 0.1.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ terraform {
|
||||
required_providers {
|
||||
sless = {
|
||||
source = "terra.k8c.ru/naeel/sless"
|
||||
version = "~> 0.1.10"
|
||||
version = "~> 0.1.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ terraform {
|
||||
required_providers {
|
||||
sless = {
|
||||
source = "terra.k8c.ru/naeel/sless"
|
||||
version = "~> 0.1.10"
|
||||
version = "~> 0.1.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,9 +209,28 @@ func (r *TriggerResource) Delete(ctx context.Context, req resource.DeleteRequest
|
||||
return
|
||||
}
|
||||
|
||||
if err := r.client.DeleteTrigger(ctx, r.client.Namespace, state.Name.ValueString()); err != nil {
|
||||
name := state.Name.ValueString()
|
||||
if err := r.client.DeleteTrigger(ctx, r.client.Namespace, name); err != nil {
|
||||
resp.Diagnostics.AddError("delete trigger", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Ждём, пока триггер исчезнет из API.
|
||||
// Финалайзер контроллера снимается ПОСЛЕ того, как Service+Ingress удалены,
|
||||
// поэтому когда GetTrigger возвращает nil (404) — маршрут уже убран и endpoint мёртв.
|
||||
deadline := time.Now().Add(90 * time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
tr, err := r.client.GetTrigger(ctx, r.client.Namespace, name)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("wait trigger gone", err.Error())
|
||||
return
|
||||
}
|
||||
if tr == nil {
|
||||
return // триггер исчез — cleanup завершён
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
resp.Diagnostics.AddError("wait trigger gone", fmt.Sprintf("trigger %s still exists after 90s", name))
|
||||
}
|
||||
|
||||
// trToModel конвертирует API-ответ → state модель.
|
||||
|
||||
Reference in New Issue
Block a user