美文网首页
controller-runtime patch

controller-runtime patch

作者: allenhaozi | 来源:发表于2020-12-27 22:04 被阅读0次

    controller-runtime patch

    Patch
    github

    // Writer knows how to create, delete, and update Kubernetes objects.
    type Writer interface {
        // Create saves the object obj in the Kubernetes cluster.
        Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error
    
        // Delete deletes the given obj from Kubernetes cluster.
        Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error
    
        // Update updates the given obj in the Kubernetes cluster. obj must be a
        // struct pointer so that obj can be updated with the content returned by the Server.
        Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error
    
        // Patch patches the given obj in the Kubernetes cluster. obj must be a
        // struct pointer so that obj can be updated with the content returned by the Server.
        Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error
    
        // DeleteAllOf deletes all objects of the given type matching the given options.
        DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...DeleteAllOfOption) error
    }
    

    Patch接口
    主要三个参数

    1. obj

    2. patch

    // Patch is a patch that can be applied to a Kubernetes object.
    type Patch interface {
        // Type is the PatchType of the patch.
        Type() types.PatchType
        // Data is the raw data representing the patch.
        Data(obj runtime.Object) ([]byte, error)
    }
    

    3. opts


    假设我们调用时候

    r.Patch(ctx, desired, client.MergeFrom(obj), ao...)
    

    client.MergeFrom 是一个实现了 上面Patch接口结构体mergeFromPatch
    结构体如下
    这里的一个核心函数是 CreateMergePatch

    // MergeFrom creates a Patch that patches using the merge-patch strategy with the given object as base.
    func MergeFrom(obj runtime.Object) Patch {
        return &mergeFromPatch{from: obj}
    }
    
    type mergeFromPatch struct {
        from runtime.Object
        opts MergeFromOptions
    }
    
    // Type implements patch.
    func (s *mergeFromPatch) Type() types.PatchType {
        return types.MergePatchType
    }
    
    // Data implements Patch.
    func (s *mergeFromPatch) Data(obj runtime.Object) ([]byte, error) {
        originalJSON, err := json.Marshal(s.from)
        if err != nil {
            return nil, err
        }
    
        modifiedJSON, err := json.Marshal(obj)
        if err != nil {
            return nil, err
        }
    
        data, err := jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
        if err != nil {
            return nil, err
        }
    
        if s.opts.OptimisticLock {
            dataMap := map[string]interface{}{}
            if err := json.Unmarshal(data, &dataMap); err != nil {
                return nil, err
            }
            fromMeta, ok := s.from.(metav1.Object)
            if !ok {
                return nil, fmt.Errorf("cannot use OptimisticLock, from object %q is not a valid metav1.Object", s.from)
            }
            resourceVersion := fromMeta.GetResourceVersion()
            if len(resourceVersion) == 0 {
                return nil, fmt.Errorf("cannot use OptimisticLock, from object %q does not have any resource version we can use", s.from)
            }
            u := &unstructured.Unstructured{Object: dataMap}
            u.SetResourceVersion(resourceVersion)
            data, err = json.Marshal(u)
            if err != nil {
                return nil, err
            }
        }
    
        return data, nil
    }
    

    然后我们再看一下 client.Patch函数的实现

    // Patch implements client.Client
    func (c *typedClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error {
        o, err := c.cache.getObjMeta(obj)
        if err != nil {
            return err
        }
    
        data, err := patch.Data(obj)
        if err != nil {
            return err
        }
    
        patchOpts := &PatchOptions{}
        return o.Patch(patch.Type()).
            NamespaceIfScoped(o.GetNamespace(), o.isNamespaced()).
            Resource(o.resource()).
            Name(o.GetName()).
            VersionedParams(patchOpts.ApplyOptions(opts).AsPatchOptions(), c.paramCodec).
            Body(data).
            Do(ctx).
            Into(obj)
    }
    
    

    r.Patch(ctx, desired, client.MergeFrom(current), ao...)
    回看我们的调用
    在client.Patch的实现中

    • client.MergeFrom(obj) 返回一个 mergeFromPatch 的结构体并给其from赋值
    • 然后在client.Patch中调用了这个结构体的Data()方法, 并将desired传入
    • 关键的地方来了 这里核心是使用 jsonpatch.CreateMergePatch
      • current 作为 originalJSON
      • desired 作为 modifiedJSON
        合并做merge

    相关文章

      网友评论

          本文标题:controller-runtime patch

          本文链接:https://www.haomeiwen.com/subject/uzdanktx.html