// Copyright (C) 2019 Marius Schellenberger package main import ( "log" "os" "os/signal" "syscall" "time" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" ) func init() { log.SetFlags(log.Flags() | log.Lshortfile) } var emptyFinalizers = []byte(`{"metadata":{"finalizers":null}}`) func main() { cfg, err := rest.InClusterConfig() if err != nil { log.Fatalf("error configuring kube client: %s\n", err) } cl, err := kubernetes.NewForConfig(cfg) if err != nil { log.Fatalf("error creating new kube client: %s\n", err) } factory := informers.NewSharedInformerFactory(cl, time.Second*30) pvcInformer := factory.Core().V1().PersistentVolumeClaims().Informer() pvcInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { pvc, ok := obj.(*corev1.PersistentVolumeClaim) if ok { log.Printf("pvc added: %s/%s\n", pvc.Namespace, pvc.Name) } }, DeleteFunc: func(obj interface{}) { pvc, ok := obj.(*corev1.PersistentVolumeClaim) if ok { log.Printf("pvc deleted: %s/%s\n", pvc.Namespace, pvc.Name) } }, UpdateFunc: func(_, obj interface{}) { pvc, ok := obj.(*corev1.PersistentVolumeClaim) if !ok || pvc.DeletionTimestamp == nil || pvc.OwnerReferences == nil { return } if pvc.OwnerReferences[0].APIVersion == "tekton.dev/v1alpha1" && pvc.OwnerReferences[0].Kind == "PipelineRun" { pvs := cl.CoreV1().PersistentVolumes() pv, err := pvs.Get(pvc.Spec.VolumeName, metav1.GetOptions{}) if err != nil { log.Printf("error getting pv %s: %s\n", pvc.Spec.VolumeName, err) return } if pv.Finalizers != nil { _, err = pvs.Patch(pv.Name, types.MergePatchType, emptyFinalizers) if err != nil { log.Printf("error patching pv %s: %s\n", pv.Name, err) return } } pvcs := cl.CoreV1().PersistentVolumeClaims(pvc.Namespace) if pvc.Finalizers != nil { _, err = pvcs.Patch(pvc.Name, types.MergePatchType, emptyFinalizers) if err != nil { log.Printf("error patching pvc %s/%s: %s\n", pvc.Namespace, pvc.Name, err) return } } log.Printf("pvc patched: %s/%s\n", pvc.Namespace, pvc.Name) } }, }) stop := make(chan struct{}) factory.Start(stop) log.Println("started pvc watcher") sigs := make(chan os.Signal) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) log.Println("started signal handler") sig := <-sigs close(stop) log.Printf("signal: %s\n", sig.String()) }