mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
* Extends match / exclude to use apiGroup and apiVersion Signed-off-by: vyankatesh <vyankatesh@neualto.com> * fix gvk issue Signed-off-by: vyankatesh <vyankatesh@neualto.com> Co-authored-by: vyankatesh <vyankatesh@neualto.com>
This commit is contained in:
parent
adb381705f
commit
9e831ec959
8 changed files with 73 additions and 46 deletions
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
|
@ -64,3 +65,15 @@ func GetNamespaceLabels(namespaceObj *v1.Namespace, logger logr.Logger) map[stri
|
|||
}
|
||||
return namespaceUnstructured.GetLabels()
|
||||
}
|
||||
|
||||
// GetKindFromGVK - get kind and APIVersion from GVK
|
||||
func GetKindFromGVK(str string) (apiVersion string, kind string) {
|
||||
if strings.Count(str, "/") == 0 {
|
||||
return "", str
|
||||
}
|
||||
splitString := strings.Split(str, "/")
|
||||
if strings.Count(str, "/") == 1 {
|
||||
return splitString[0], splitString[1]
|
||||
}
|
||||
return splitString[0] + "/" + splitString[1], splitString[2]
|
||||
}
|
||||
|
|
|
@ -21,14 +21,15 @@ func filterRules(policyContext *PolicyContext) *response.EngineResponse {
|
|||
kind := policyContext.NewResource.GetKind()
|
||||
name := policyContext.NewResource.GetName()
|
||||
namespace := policyContext.NewResource.GetNamespace()
|
||||
|
||||
apiVersion := policyContext.NewResource.GetAPIVersion()
|
||||
resp := &response.EngineResponse{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: policyContext.Policy.Name,
|
||||
Resource: response.ResourceSpec{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
APIVersion: apiVersion,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -28,10 +28,21 @@ type EngineStats struct {
|
|||
RulesAppliedCount int
|
||||
}
|
||||
|
||||
func checkKind(kinds []string, resourceKind string) bool {
|
||||
func checkKind(kinds []string, resource unstructured.Unstructured) bool {
|
||||
for _, kind := range kinds {
|
||||
if resourceKind == kind {
|
||||
return true
|
||||
SplitGVK := strings.Split(kind, "/")
|
||||
if len(SplitGVK) == 1 {
|
||||
if resource.GetKind() == kind {
|
||||
return true
|
||||
}
|
||||
} else if len(SplitGVK) == 2 {
|
||||
if resource.GroupVersionKind().Kind == SplitGVK[1] && resource.GroupVersionKind().Version == SplitGVK[0] {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if resource.GroupVersionKind().Group == SplitGVK[0] && resource.GroupVersionKind().Kind == SplitGVK[2] && (resource.GroupVersionKind().Version == SplitGVK[1] || resource.GroupVersionKind().Version == "*") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +124,7 @@ func doesResourceMatchConditionBlock(conditionBlock kyverno.ResourceDescription,
|
|||
var errs []error
|
||||
|
||||
if len(conditionBlock.Kinds) > 0 {
|
||||
if !checkKind(conditionBlock.Kinds, resource.GetKind()) {
|
||||
if !checkKind(conditionBlock.Kinds, resource) {
|
||||
errs = append(errs, fmt.Errorf("kind does not match %v", conditionBlock.Kinds))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,7 +218,7 @@ func (gen *Generator) syncHandler(key Info) error {
|
|||
func (gen *Generator) getResource(key Info) (obj *unstructured.Unstructured, err error) {
|
||||
lister, ok := gen.resCache.GetGVRCache(key.Kind)
|
||||
if !ok {
|
||||
if lister, err = gen.resCache.CreateResourceInformer(key.Kind); err != nil {
|
||||
if lister, err = gen.resCache.CreateGVKInformer(key.Kind); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,15 +51,14 @@ func (pc *PolicyController) processExistingResources(policy *kyverno.ClusterPoli
|
|||
}
|
||||
}
|
||||
|
||||
func (pc *PolicyController) registerResource(kind string) (err error) {
|
||||
genericCache, ok := pc.resCache.GetGVRCache(kind)
|
||||
func (pc *PolicyController) registerResource(gvk string) (err error) {
|
||||
genericCache, ok := pc.resCache.GetGVRCache(gvk)
|
||||
if !ok {
|
||||
if genericCache, err = pc.resCache.CreateResourceInformer(kind); err != nil {
|
||||
return fmt.Errorf("failed to create informer for %s: %v", kind, err)
|
||||
if genericCache, err = pc.resCache.CreateGVKInformer(gvk); err != nil {
|
||||
return fmt.Errorf("failed to create informer for %s: %v", gvk, err)
|
||||
}
|
||||
}
|
||||
|
||||
pc.rm.RegisterScope(kind, genericCache.IsNamespaced())
|
||||
pc.rm.RegisterScope(gvk, genericCache.IsNamespaced())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
// ResourceCache - allows the creation, deletion and saving the resource informers as a cache
|
||||
type ResourceCache interface {
|
||||
CreateInformers(resources ...string) []error
|
||||
CreateResourceInformer(resource string) (GenericCache, error)
|
||||
CreateGVKInformer(kind string) (GenericCache, error)
|
||||
StopResourceInformer(resource string)
|
||||
GetGVRCache(resource string) (GenericCache, bool)
|
||||
}
|
||||
|
|
|
@ -2,45 +2,21 @@ package resourcecache
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
)
|
||||
|
||||
// CreateInformers ...
|
||||
func (resc *resourceCache) CreateInformers(resources ...string) []error {
|
||||
var errs []error
|
||||
for _, resource := range resources {
|
||||
if _, err := resc.CreateResourceInformer(resource); err != nil {
|
||||
if _, err := resc.CreateGVKInformer(resource); err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to create informer for %s: %v", resource, err))
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// CreateResourceInformer creates informer for the given resource
|
||||
func (resc *resourceCache) CreateResourceInformer(resource string) (GenericCache, error) {
|
||||
gc, ok := resc.GetGVRCache(resource)
|
||||
if ok {
|
||||
return gc, nil
|
||||
}
|
||||
|
||||
apiResource, gvr, err := resc.dclient.DiscoveryClient.FindResource("", resource)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find API resource %s", resource)
|
||||
}
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
genInformer := resc.dinformer.ForResource(gvr)
|
||||
gvrIface := NewGVRCache(gvr, apiResource.Namespaced, stopCh, genInformer)
|
||||
|
||||
resc.gvrCache.Set(resource, gvrIface)
|
||||
resc.dinformer.Start(stopCh)
|
||||
|
||||
if synced := resc.dinformer.WaitForCacheSync(stopCh); !synced[gvr] {
|
||||
return nil, fmt.Errorf("informer for %s hasn't synced", gvr)
|
||||
}
|
||||
|
||||
return gvrIface, nil
|
||||
}
|
||||
|
||||
// StopResourceInformer - delete the given resource information from ResourceCache and stop watching for the given resource
|
||||
func (resc *resourceCache) StopResourceInformer(resource string) {
|
||||
res, ok := resc.GetGVRCache(resource)
|
||||
|
@ -61,3 +37,29 @@ func (resc *resourceCache) GetGVRCache(resource string) (GenericCache, bool) {
|
|||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// CreateGVKInformer creates informer for the given gvk
|
||||
func (resc *resourceCache) CreateGVKInformer(gvk string) (GenericCache, error) {
|
||||
gc, ok := resc.GetGVRCache(gvk)
|
||||
if ok {
|
||||
return gc, nil
|
||||
}
|
||||
gv, k := common.GetKindFromGVK(gvk)
|
||||
apiResource, gvr, err := resc.dclient.DiscoveryClient.FindResource(gv, k)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find API resource %s", gvk)
|
||||
}
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
genInformer := resc.dinformer.ForResource(gvr)
|
||||
gvrIface := NewGVRCache(gvr, apiResource.Namespaced, stopCh, genInformer)
|
||||
|
||||
resc.gvrCache.Set(gvk, gvrIface)
|
||||
resc.dinformer.Start(stopCh)
|
||||
|
||||
if synced := resc.dinformer.WaitForCacheSync(stopCh); !synced[gvr] {
|
||||
return nil, fmt.Errorf("informer for %s hasn't synced", gvr)
|
||||
}
|
||||
|
||||
return gvrIface, nil
|
||||
}
|
||||
|
|
|
@ -310,9 +310,10 @@ func transform(userRequestInfo kyverno.RequestInfo, er *response.EngineResponse)
|
|||
gr := kyverno.GenerateRequestSpec{
|
||||
Policy: er.PolicyResponse.Policy,
|
||||
Resource: kyverno.ResourceSpec{
|
||||
Kind: er.PolicyResponse.Resource.Kind,
|
||||
Namespace: er.PolicyResponse.Resource.Namespace,
|
||||
Name: er.PolicyResponse.Resource.Name,
|
||||
Kind: er.PolicyResponse.Resource.Kind,
|
||||
Namespace: er.PolicyResponse.Resource.Namespace,
|
||||
Name: er.PolicyResponse.Resource.Name,
|
||||
APIVersion: er.PolicyResponse.Resource.APIVersion,
|
||||
},
|
||||
Context: kyverno.GenerateRequestContext{
|
||||
UserRequestInfo: userRequestInfo,
|
||||
|
|
Loading…
Add table
Reference in a new issue