通过discovery client简化informer使用

2021-12-24  本文已影响0人  wwq2020

背景

有时候我们需要建立多个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
}

上一篇下一篇

猜你喜欢

热点阅读