简介
之前介绍过sigs.k8s.io controller-runtime系列之十 sourceeventhandler分析sigs.k8s.io controller-runtime-sourceeventhandler 。
本文主要介绍pkg/finalizer的源码分析。
目录结构
- types.go
- Registerer接口
// Registerer持有Register方法,它将检查key是否已经注册,如果已存在,返回异常;如果未注册,它会将Finalizer添加到终结器map中作为提供的键的值。 type Registerer interface { Register(key string, f Finalizer) error }
- Finalizer接口
// Finalizer 持有 Finalize,它将根据设置的删除时间戳添加/删除终结器,并返回obj 是否需要更新的Result。 type Finalizer interface { Finalize(context.Context, client.Object) (Result, error) }
- Finalizers接口
// Finalizers实现Finalizer和Registerer接口,如果提供的对象具有删除时间戳,则移除所有已注册的 Finalizer,如果没有,则设置所有已注册的Finalizer。 type Finalizers interface { Registerer Finalizer }
- finalizer.go
- Registerer接口
// 类型定义finalizers 为map类型 type finalizers map[string]Finalizer // Result结构体保存有关对象的哪些部分被Finalizer更新的信息。 type Result struct { // 如果至少有一个对象的非状态字段被某个已注册的Finalizer更新,则更新为真。 Updated bool // 如果至少有一个对象的状态字段被某个已注册的Finalizer更新,则 StatusUpdated 将为真。 StatusUpdated bool } // 返回一个新的finalizers结构体 func NewFinalizers() Finalizers { return finalizers{} } // 实现Registerer接口 func (f finalizers) Register(key string, finalizer Finalizer) error { // 如果map中存在key 返回error if _, ok := f[key]; ok { return fmt.Errorf("finalizer for key %q already registered", key) } // 添加到map中 f[key] = finalizer return nil } // 实现Finalizer接口 func (f finalizers) Finalize(ctx context.Context, obj client.Object) (Result, error) { var ( res Result errList []error ) // 默认没有更新非状态字段 res.Updated = false for key, finalizer := range f { // obj没有删除时间戳并且obj的Finalizer字段中不包含key if dt := obj.GetDeletionTimestamp(); dt.IsZero() && !controllerutil.ContainsFinalizer(obj, key) { // 添加key到obj的Finalizers(会判断是否存在,存在就do empty) controllerutil.AddFinalizer(obj, key) // 更新更新非状态字段为true res.Updated = true } // 如果删除事件不为空并且obj的Finalizers包含key else if !dt.IsZero() && controllerutil.ContainsFinalizer(obj, key) { // 自定义实现的Finalizer,从obj中add/delete finalizerRes, err := finalizer.Finalize(ctx, obj) if err != nil { // 即使finalizer失败,它也可能需要发出信号来更新对象(例如,它可能会设置条件并需要状态更新)。 res.Updated = res.Updated || finalizerRes.Updated res.StatusUpdated = res.StatusUpdated || finalizerRes.StatusUpdated errList = append(errList, fmt.Errorf("finalizer %q failed: %v", key, err)) } else { // 如果finalizer成功,我们从对象的元数据中删除Finalizer,并设置更新非状态字段为true。 res.Updated = true controllerutil.RemoveFinalizer(obj, key) // finalizer也可能更新了状态。 res.StatusUpdated = res.StatusUpdated || finalizerRes.StatusUpdated } } } return res, kerrors.NewAggregate(errList) }