美文网首页
通过discovery client简化informer使用

通过discovery client简化informer使用

作者: wwq2020 | 来源:发表于2021-12-24 15:10 被阅读0次

    背景

    有时候我们需要建立多个gvr的informer,需要类似的代码写很多遍

    解决方案

    可以通过discovery client获取到支持list,watch的gvr批量创建informer,简化使用

    package main
    
    import (
        "fmt"
        "sync"
    
        corev1 "k8s.io/api/core/v1"
        "k8s.io/apimachinery/pkg/api/meta"
        "k8s.io/apimachinery/pkg/runtime"
        "k8s.io/apimachinery/pkg/runtime/schema"
        "k8s.io/client-go/discovery"
        "k8s.io/client-go/dynamic"
        "k8s.io/client-go/dynamic/dynamicinformer"
        k8sscheme "k8s.io/client-go/kubernetes/scheme"
        "k8s.io/client-go/rest"
        "k8s.io/client-go/tools/cache"
        "stash.weimob.com/devops/go_common/app"
    )
    
    func main() {
        restConfig := &rest.Config{
            Host:        "yourhost",
            BearerToken: "yourtoken",
        }
    
        discoverClientSet := discovery.NewDiscoveryClientForConfigOrDie(restConfig)
        dynamicClient := dynamic.NewForConfigOrDie(restConfig)
    
        informer := dynamicinformer.NewDynamicSharedInformerFactory(dynamicClient, 0)
    
        preferredResources, err := discoverClientSet.ServerPreferredResources()
        if err != nil {
            panic(err)
        }
    
        gvrs := make(map[schema.GroupVersionResource][]string)
        for _, each := range preferredResources {
            gv, err := schema.ParseGroupVersion(each.GroupVersion)
            if err != nil {
                panic(err)
            }
            for _, resource := range each.APIResources {
                gvrs[schema.GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: resource.Name}] = resource.Verbs
            }
        }
        m := make(map[schema.GroupVersionKind]map[string]map[string]runtime.Unstructured)
        var lock sync.Mutex
        eventHandler := cache.ResourceEventHandlerFuncs{
            AddFunc: func(obj interface{}) {
                raw := obj.(runtime.Unstructured)
                gvk := raw.GetObjectKind().GroupVersionKind()
                lock.Lock()
                defer lock.Unlock()
                metaInfo, err := meta.Accessor(obj)
                if err != nil {
                    panic(err)
                }
                gvkM, exist := m[gvk]
                if !exist {
                    gvkM = make(map[string]map[string]runtime.Unstructured)
                    m[gvk] = gvkM
                }
                namespace := metaInfo.GetNamespace()
                namesapceM, exist := gvkM[namespace]
                if !exist {
                    namesapceM = make(map[string]runtime.Unstructured)
                    gvkM[namespace] = namesapceM
                }
                name := metaInfo.GetName()
                namesapceM[name] = raw
            },
            UpdateFunc: func(oldObj, newObj interface{}) {
                lock.Lock()
                defer lock.Unlock()
                oldRaw := oldObj.(runtime.Unstructured)
                oldGvk := oldRaw.GetObjectKind().GroupVersionKind()
                oldMetaInfo, err := meta.Accessor(oldObj)
                if err != nil {
                    panic(err)
                }
                oldGvkM, exist := m[oldGvk]
                if !exist {
                    oldGvkM = make(map[string]map[string]runtime.Unstructured)
                    m[oldGvk] = oldGvkM
                }
                oldNamespace := oldMetaInfo.GetNamespace()
                oldNamesapceM, exist := oldGvkM[oldNamespace]
                if !exist {
                    oldNamesapceM = make(map[string]runtime.Unstructured)
                    oldGvkM[oldNamespace] = oldNamesapceM
                }
                oldName := oldMetaInfo.GetName()
                delete(oldNamesapceM, oldName)
    
                newRaw := newObj.(runtime.Unstructured)
                newGvk := newRaw.GetObjectKind().GroupVersionKind()
                newMetaInfo, err := meta.Accessor(newObj)
                if err != nil {
                    panic(err)
                }
                newGvkM, exist := m[newGvk]
                if !exist {
                    newGvkM = make(map[string]map[string]runtime.Unstructured)
                    m[newGvk] = newGvkM
                }
                newNamespace := newMetaInfo.GetNamespace()
                newNamesapceM, exist := newGvkM[newNamespace]
                if !exist {
                    newNamesapceM = make(map[string]runtime.Unstructured)
                    newGvkM[newNamespace] = newNamesapceM
                }
                newName := newMetaInfo.GetName()
                newNamesapceM[newName] = newRaw
            },
            DeleteFunc: func(obj interface{}) {
                lock.Lock()
                defer lock.Unlock()
                oldRaw := obj.(runtime.Unstructured)
                oldGvk := oldRaw.GetObjectKind().GroupVersionKind()
                oldMetaInfo, err := meta.Accessor(obj)
                if err != nil {
                    panic(err)
                }
                oldGvkM, exist := m[oldGvk]
                if !exist {
                    oldGvkM = make(map[string]map[string]runtime.Unstructured)
                    m[oldGvk] = oldGvkM
                }
                oldNamespace := oldMetaInfo.GetNamespace()
                oldNamesapceM, exist := oldGvkM[oldNamespace]
                if !exist {
                    oldNamesapceM = make(map[string]runtime.Unstructured)
                    oldGvkM[oldNamespace] = oldNamesapceM
                }
                oldName := oldMetaInfo.GetName()
                delete(oldNamesapceM, oldName)
    
            },
        }
        for gvr, verbs := range gvrs {
            if !hasListWatch(verbs) {
                continue
            }
            i := informer.ForResource(gvr).Informer()
            i.AddEventHandler(eventHandler)
            fmt.Println(verbs, gvr.String())
        }
        informer.Start(app.Done())
        informer.WaitForCacheSync(app.Done())
        pod := &corev1.Pod{}
        getter := func(namespace, name string, dest runtime.Object) {
            kinds, _, err := k8sscheme.Scheme.ObjectKinds(pod)
            if err != nil {
                panic(err)
            }
            kind := kinds[0]
            obj := m[kind][namespace][name ]
    
            runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(),dest)
            
        }
        getter("demonamespace", "demoname", pod)
    
    }
    
    func hasListWatch(verbs []string) bool {
        return hasVerb(verbs, "list") && hasVerb(verbs, "watch")
    }
    
    func hasVerb(verbs []string, dest string) bool {
        for _, each := range verbs {
            if each == dest {
                return true
            }
        }
        return false
    }
    
    

    相关文章

      网友评论

          本文标题:通过discovery client简化informer使用

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