简介

之前介绍过sigs.k8s.io controller-runtime系列之十 sourceeventhandler分析sigs.k8s.io controller-runtime-sourceeventhandler
本文主要介绍pkg/finalizer的源码分析。

目录结构

  1. 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
    }
    
  2. 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)
    }
    
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐