1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

fix: lock schema manager when updating it (#7704)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-06-29 06:39:09 +02:00 committed by GitHub
parent 62f4aa4271
commit c5ebb73231
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 29 deletions

View file

@ -72,6 +72,8 @@ func (c *controller) Run(ctx context.Context, workers int) {
}
func (c *controller) sync() {
c.manager.Lock()
defer c.manager.Unlock()
c.client.Discovery().DiscoveryCache().Invalidate()
crds, err := c.client.GetDynamicInterface().Resource(runtimeSchema.GroupVersionResource{
Group: "apiextensions.k8s.io",

View file

@ -7,6 +7,8 @@ import (
)
type Manager interface {
Lock()
Unlock()
UseOpenAPIDocument(*openapiv2.Document) error
DeleteCRDFromPreviousSync()
ParseCRD(unstructured.Unstructured)

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"strings"
"sync"
"github.com/go-logr/logr"
"github.com/google/gnostic/compiler"
@ -49,6 +50,7 @@ type manager struct {
kindToAPIVersions cmap.ConcurrentMap[string, apiVersions]
logger logr.Logger
lock sync.Mutex
}
// apiVersions stores all available gvks for a kind, a gvk is "/" separated string
@ -86,40 +88,25 @@ func NewManager(logger logr.Logger) (*manager, error) {
return mgr, nil
}
func (o *manager) Lock() {
o.lock.Lock()
}
func (o *manager) Unlock() {
o.lock.Unlock()
}
// ValidateResource ...
func (o *manager) ValidateResource(patchedResource unstructured.Unstructured, apiVersion, kind string) error {
var err error
gvk := kind
if apiVersion != "" {
gvk = apiVersion + "/" + kind
}
kind, _ = o.gvkToDefinitionName.Get(gvk)
schema := o.models.LookupModel(kind)
if schema == nil {
// Check if kind is a CRD
schema, err = o.getCRDSchema(kind)
if err != nil || schema == nil {
return fmt.Errorf("pre-validation: couldn't find model %s, err: %v", kind, err)
}
delete(patchedResource.Object, "kind")
}
if errs := validation.ValidateModel(patchedResource.UnstructuredContent(), schema, kind); len(errs) > 0 {
var errorMessages []string
for i := range errs {
errorMessages = append(errorMessages, errs[i].Error())
}
return fmt.Errorf(strings.Join(errorMessages, "\n\n"))
}
return nil
o.Lock()
defer o.Unlock()
return o.validateResource(patchedResource, apiVersion, kind)
}
// ValidatePolicyMutation ...
func (o *manager) ValidatePolicyMutation(policy kyvernov1.PolicyInterface) error {
o.Lock()
defer o.Unlock()
kindToRules := make(map[string][]kyvernov1.Rule)
for _, rule := range autogen.ComputeRules(policy) {
if rule.HasMutate() {
@ -166,7 +153,7 @@ func (o *manager) ValidatePolicyMutation(policy kyvernov1.PolicyInterface) error
}
if kind != "*" {
err = o.ValidateResource(*patchedResource.DeepCopy(), "", kind)
err = o.validateResource(*patchedResource.DeepCopy(), "", kind)
if err != nil {
return fmt.Errorf("mutate result violates resource schema: %w", err)
}
@ -176,6 +163,38 @@ func (o *manager) ValidatePolicyMutation(policy kyvernov1.PolicyInterface) error
return nil
}
// ValidateResource ...
func (o *manager) validateResource(patchedResource unstructured.Unstructured, apiVersion, kind string) error {
var err error
gvk := kind
if apiVersion != "" {
gvk = apiVersion + "/" + kind
}
kind, _ = o.gvkToDefinitionName.Get(gvk)
schema := o.models.LookupModel(kind)
if schema == nil {
// Check if kind is a CRD
schema, err = o.getCRDSchema(kind)
if err != nil || schema == nil {
return fmt.Errorf("pre-validation: couldn't find model %s, err: %v", kind, err)
}
delete(patchedResource.Object, "kind")
}
if errs := validation.ValidateModel(patchedResource.UnstructuredContent(), schema, kind); len(errs) > 0 {
var errorMessages []string
for i := range errs {
errorMessages = append(errorMessages, errs[i].Error())
}
return fmt.Errorf(strings.Join(errorMessages, "\n\n"))
}
return nil
}
func (o *manager) UseOpenAPIDocument(doc *openapiv2.Document) error {
for _, definition := range doc.GetDefinitions().AdditionalProperties {
definitionName := definition.GetName()