blob: c61c82ab1ebf063b71c4748d489e28574cfacc42 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package controller
import (
"context"
"errors"
"os"
"time"
"github.com/apache/doris-operator/pkg/common/utils/resource"
sc "github.com/apache/doris-operator/pkg/controller/sub_controller"
corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// PVCFinalizerReconciler completes an already requested PVC deletion independently
// of the parent CR. It never initiates deletion or removes other controllers'
// protection, and covers DCR as well as every DDC component.
type PVCFinalizerReconciler struct {
client.Client
APIReader client.Reader
}
var _ Controller = &PVCFinalizerReconciler{}
func (r *PVCFinalizerReconciler) Init(mgr ctrl.Manager, options *Options) {
reconciler := &PVCFinalizerReconciler{Client: mgr.GetClient(), APIReader: mgr.GetAPIReader()}
b := ctrl.NewControllerManagedBy(mgr).Named("doris-pvc-finalizer").
For(&corev1.PersistentVolumeClaim{}, builder.WithPredicates(predicate.NewPredicateFuncs(pvcDeletionRequested)))
if err := b.Complete(reconciler); err != nil {
ctrl.Log.Error(err, "unable to create PVC finalizer controller")
os.Exit(1)
}
}
func pvcDeletionRequested(obj client.Object) bool {
pvc, ok := obj.(*corev1.PersistentVolumeClaim)
return ok && !pvc.DeletionTimestamp.IsZero() && len(resource.ManagedPVCFinalizers(pvc)) != 0
}
// +kubebuilder:rbac:groups="",resources=persistentvolumeclaims,verbs=get;list;watch;patch;update
// +kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch
func (r *PVCFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
reader := r.APIReader
if reader == nil {
reader = r.Client
}
var pvc corev1.PersistentVolumeClaim
if err := reader.Get(ctx, req.NamespacedName, &pvc); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
if !pvcDeletionRequested(&pvc) {
return ctrl.Result{}, nil
}
lifecycle := &sc.DisaggregatedSubDefaultController{K8sclient: r.Client, APIReader: reader}
if err := lifecycle.FinishPVCDeletion(ctx, &pvc); err != nil {
if errors.Is(err, sc.ErrPVCInUse) {
// Pod termination need not produce another PVC event. Poll until
// scheduled references are gone, including terminating Pods.
return ctrl.Result{RequeueAfter: 5 * time.Second}, nil
}
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}