2020-09-23 02:41:49 +05:30
package resourcecache
import (
"github.com/go-logr/logr"
2020-10-07 11:12:31 -07:00
dclient "github.com/kyverno/kyverno/pkg/dclient"
2020-09-23 02:41:49 +05:30
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic/dynamicinformer"
"k8s.io/client-go/rest"
)
// ResourceCacheIface - allows the creation, deletion and saving the resource informers as a cache
type ResourceCacheIface interface {
RunAllInformers ( log logr . Logger )
CreateResourceInformer ( log logr . Logger , resource string ) ( bool , error )
StopResourceInformer ( log logr . Logger , resource string ) bool
GetGVRCache ( resource string ) * GVRCache
}
// ResourceCache ...
type ResourceCache struct {
dinformer dynamicinformer . DynamicSharedInformerFactory
// match - matches the resources for which the informers needs to be created.
// if the matches contains any resource name then the informers are created for only that resource
// else informers are created for all the server supported resources
match [ ] string
// excludes the creation of informers for a specific resources
// if a specific resource is available in both match and exclude then exclude overrides it
exclude [ ] string
// GVRCacheData - stores the informers and lister object for a resource.
// it uses resource name as key (For ex :- namespaces for Namespace, pods for Pod, clusterpolicies for ClusterPolicy etc)
// GVRCache stores GVR (Group Version Resource) for the resource, Informer() instance and Lister() instance for that resource.
GVRCacheData map [ string ] * GVRCache
}
2020-12-15 17:55:01 -08:00
// NewResourceCache - initializes the ResourceCache where it initially stores the GVR and Namespaced condition for the allowed resources in GVRCacheData
2020-09-23 02:41:49 +05:30
func NewResourceCache ( log logr . Logger , config * rest . Config , dclient * dclient . Client , match [ ] string , exclude [ ] string ) ( ResourceCacheIface , error ) {
logger := log . WithName ( "resourcecache" )
discoveryIface := dclient . GetDiscoveryCache ( )
cacheData := make ( map [ string ] * GVRCache )
dInformer := dclient . NewDynamicSharedInformerFactory ( 0 )
resCache := & ResourceCache { GVRCacheData : cacheData , dinformer : dInformer , match : match , exclude : exclude }
2020-11-30 12:54:48 -08:00
if resCache . matchGVRKey ( "configmaps" ) {
_ , ok := resCache . GVRCacheData [ "configmaps" ]
if ! ok {
updateGVRCacheForConfigMap ( resCache )
}
} else {
2020-11-30 23:26:49 -08:00
err := updateGVRCache ( logger , resCache , discoveryIface )
2020-11-30 12:54:48 -08:00
if err != nil {
2020-11-30 23:26:49 -08:00
logger . Error ( err , "error in updateGVRCache function" )
2020-11-30 12:54:48 -08:00
return nil , err
}
2020-09-23 02:41:49 +05:30
}
2020-11-30 12:54:48 -08:00
2020-09-23 02:41:49 +05:30
return resCache , nil
}
2020-11-30 12:54:48 -08:00
func updateGVRCacheForConfigMap ( resc * ResourceCache ) {
gvrc := & GVRCache {
GVR : schema . GroupVersionResource {
Version : "v1" ,
Resource : "configmaps" ,
} ,
Namespaced : true ,
}
resc . GVRCacheData [ "configmaps" ] = gvrc
}
2020-11-30 23:26:49 -08:00
func updateGVRCache ( log logr . Logger , resc * ResourceCache , discoveryIface discovery . CachedDiscoveryInterface ) error {
2020-09-23 02:41:49 +05:30
serverResources , err := discoveryIface . ServerPreferredResources ( )
if err != nil {
return err
}
2020-11-30 12:54:48 -08:00
2020-09-23 02:41:49 +05:30
for _ , serverResource := range serverResources {
groupVersion := serverResource . GroupVersion
for _ , resource := range serverResource . APIResources {
gv , err := schema . ParseGroupVersion ( groupVersion )
if err != nil {
return err
}
mok := resc . matchGVRKey ( resource . Name )
if ! mok {
continue
}
eok := resc . excludeGVRKey ( resource . Name )
if eok {
continue
}
_ , ok := resc . GVRCacheData [ resource . Name ]
if ! ok {
gvrc := & GVRCache { GVR : gv . WithResource ( resource . Name ) , Namespaced : resource . Namespaced }
resc . GVRCacheData [ resource . Name ] = gvrc
}
}
}
2020-11-30 12:54:48 -08:00
2020-09-23 02:41:49 +05:30
return nil
}