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:
parent
62f4aa4271
commit
c5ebb73231
3 changed files with 52 additions and 29 deletions
|
@ -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",
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
)
|
||||
|
||||
type Manager interface {
|
||||
Lock()
|
||||
Unlock()
|
||||
UseOpenAPIDocument(*openapiv2.Document) error
|
||||
DeleteCRDFromPreviousSync()
|
||||
ParseCRD(unstructured.Unstructured)
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Reference in a new issue