mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
merge main
This commit is contained in:
commit
ad9f189144
7 changed files with 79 additions and 29 deletions
|
@ -220,7 +220,7 @@ func main() {
|
|||
}
|
||||
|
||||
// GENERATE REQUEST GENERATOR
|
||||
grgen := webhookgenerate.NewGenerator(pclient, stopCh, log.Log.WithName("GenerateRequestGenerator"))
|
||||
grgen := webhookgenerate.NewGenerator(pclient, pInformer.Kyverno().V1().GenerateRequests(), stopCh, log.Log.WithName("GenerateRequestGenerator"))
|
||||
|
||||
// GENERATE CONTROLLER
|
||||
// - applies generate rules on resources based on generate requests created by webhook
|
||||
|
@ -308,6 +308,7 @@ func main() {
|
|||
pclient,
|
||||
client,
|
||||
tlsPair,
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
kubeInformer.Rbac().V1().RoleBindings(),
|
||||
kubeInformer.Rbac().V1().ClusterRoleBindings(),
|
||||
|
@ -341,7 +342,7 @@ func main() {
|
|||
|
||||
go reportReqGen.Run(2, stopCh)
|
||||
go prgen.Run(1, stopCh)
|
||||
go grgen.Run(1)
|
||||
go grgen.Run(1, stopCh)
|
||||
go configData.Run(stopCh)
|
||||
go policyCtrl.Run(2, stopCh)
|
||||
go eventGenerator.Run(3, stopCh)
|
||||
|
|
|
@ -185,13 +185,13 @@ func (c *Controller) deleteGR(obj interface{}) {
|
|||
for _, resource := range gr.Status.GeneratedResources {
|
||||
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
|
||||
logger.Error(err, "failed to fetch generated resource", "resource", resource.Name)
|
||||
return
|
||||
}
|
||||
|
||||
if r != nil && r.GetLabels()["policy.kyverno.io/synchronize"] == "enable" {
|
||||
if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil && !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
||||
logger.Error(err, "failed to delete the generated resource", "resource", r.GetName())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func (c *Controller) processGR(gr *kyverno.GenerateRequest) error {
|
||||
|
@ -134,15 +135,20 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
|||
// Removing GR if rule is failed. Used when the generate condition failed but gr exist
|
||||
for _, r := range engineResponse.PolicyResponse.Rules {
|
||||
if !r.Success {
|
||||
|
||||
logger.V(4).Info("querying all generate requests")
|
||||
grList, err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).List(contextdefault.TODO(), metav1.ListOptions{})
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
"policyName": engineResponse.PolicyResponse.Policy,
|
||||
"resourceName": engineResponse.PolicyResponse.Resource.Name,
|
||||
"resourceKind": engineResponse.PolicyResponse.Resource.Kind,
|
||||
"ResourceNamespace": engineResponse.PolicyResponse.Resource.Namespace,
|
||||
}))
|
||||
grList, err := c.grLister.List(selector)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to list generate requests")
|
||||
logger.Error(err, "failed to get generate request for the resource", "kind", engineResponse.PolicyResponse.Resource.Kind, "name", engineResponse.PolicyResponse.Resource.Name, "namespace", engineResponse.PolicyResponse.Resource.Namespace)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range grList.Items {
|
||||
for _, v := range grList {
|
||||
if engineResponse.PolicyResponse.Policy == v.Spec.Policy && engineResponse.PolicyResponse.Resource.Name == v.Spec.Resource.Name && engineResponse.PolicyResponse.Resource.Kind == v.Spec.Resource.Kind && engineResponse.PolicyResponse.Resource.Namespace == v.Spec.Resource.Namespace {
|
||||
err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -57,6 +57,7 @@ type Controller struct {
|
|||
|
||||
// grSynced returns true if the Generate Request store has been synced at least once
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
// dynamic shared informer factory
|
||||
dynamicInformer dynamicinformer.DynamicSharedInformerFactory
|
||||
|
||||
|
@ -113,7 +114,7 @@ func NewController(
|
|||
c.grLister = grInformer.Lister().GenerateRequests(config.KyvernoNamespace)
|
||||
|
||||
c.policySynced = policyInformer.Informer().HasSynced
|
||||
c.grSynced = policyInformer.Informer().HasSynced
|
||||
c.grSynced = grInformer.Informer().HasSynced
|
||||
|
||||
//TODO: dynamic registration
|
||||
// Only supported for namespaces
|
||||
|
|
|
@ -6,15 +6,20 @@ import (
|
|||
"time"
|
||||
|
||||
backoff "github.com/cenkalti/backoff"
|
||||
"github.com/gardener/controller-manager-library/pkg/logger"
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/constant"
|
||||
"k8s.io/api/admission/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenerateRequests provides interface to manage generate requests
|
||||
|
@ -35,15 +40,20 @@ type Generator struct {
|
|||
client *kyvernoclient.Clientset
|
||||
stopCh <-chan struct{}
|
||||
log logr.Logger
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
grSynced cache.InformerSynced
|
||||
}
|
||||
|
||||
// NewGenerator returns a new instance of Generate-Request resource generator
|
||||
func NewGenerator(client *kyvernoclient.Clientset, stopCh <-chan struct{}, log logr.Logger) *Generator {
|
||||
func NewGenerator(client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
|
||||
gen := &Generator{
|
||||
ch: make(chan GeneratorChannel, 1000),
|
||||
client: client,
|
||||
stopCh: stopCh,
|
||||
log: log,
|
||||
ch: make(chan GeneratorChannel, 1000),
|
||||
client: client,
|
||||
stopCh: stopCh,
|
||||
log: log,
|
||||
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
|
||||
grSynced: grInformer.Informer().HasSynced,
|
||||
}
|
||||
return gen
|
||||
}
|
||||
|
@ -69,7 +79,7 @@ func (g *Generator) Apply(gr kyverno.GenerateRequestSpec, action v1beta1.Operati
|
|||
}
|
||||
|
||||
// Run starts the generate request spec
|
||||
func (g *Generator) Run(workers int) {
|
||||
func (g *Generator) Run(workers int, stopCh <-chan struct{}) {
|
||||
logger := g.log
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
|
@ -78,6 +88,11 @@ func (g *Generator) Run(workers int) {
|
|||
logger.V(4).Info("shutting down")
|
||||
}()
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, g.grSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < workers; i++ {
|
||||
go wait.Until(g.processApply, constant.GenerateControllerResync, g.stopCh)
|
||||
}
|
||||
|
@ -98,7 +113,7 @@ func (g *Generator) processApply() {
|
|||
func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action v1beta1.Operation) error {
|
||||
// create/update a generate request
|
||||
|
||||
if err := retryApplyResource(g.client, grSpec, g.log, action); err != nil {
|
||||
if err := retryApplyResource(g.client, grSpec, g.log, action, g.grLister); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -107,10 +122,9 @@ func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action v1beta1.
|
|||
// -> receiving channel to take requests to create request
|
||||
// use worker pattern to read and create the CR resource
|
||||
|
||||
func retryApplyResource(client *kyvernoclient.Clientset,
|
||||
grSpec kyverno.GenerateRequestSpec,
|
||||
log logr.Logger,
|
||||
action v1beta1.Operation) error {
|
||||
func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.GenerateRequestSpec,
|
||||
log logr.Logger, action v1beta1.Operation, grLister kyvernolister.GenerateRequestNamespaceLister) error {
|
||||
|
||||
var i int
|
||||
var err error
|
||||
|
||||
|
@ -126,14 +140,20 @@ func retryApplyResource(client *kyvernoclient.Clientset,
|
|||
// generate requests created in kyverno namespace
|
||||
isExist := false
|
||||
if action == v1beta1.Create || action == v1beta1.Update {
|
||||
|
||||
log.V(4).Info("querying all generate requests")
|
||||
grList, err := client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).List(context.TODO(), metav1.ListOptions{})
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
"policyName": grSpec.Policy,
|
||||
"resourceName": grSpec.Resource.Name,
|
||||
"resourceKind": grSpec.Resource.Kind,
|
||||
"ResourceNamespace": grSpec.Resource.Namespace,
|
||||
}))
|
||||
grList, err := grLister.List(selector)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request for the resource", "kind", grSpec.Resource.Kind, "name", grSpec.Resource.Name, "namespace", grSpec.Resource.Namespace)
|
||||
return err
|
||||
}
|
||||
|
||||
for i, v := range grList.Items {
|
||||
for _, v := range grList {
|
||||
if grSpec.Policy == v.Spec.Policy && grSpec.Resource.Name == v.Spec.Resource.Name && grSpec.Resource.Kind == v.Spec.Resource.Kind && grSpec.Resource.Namespace == v.Spec.Resource.Namespace {
|
||||
gr.SetLabels(map[string]string{
|
||||
"resources-update": "true",
|
||||
|
@ -142,7 +162,7 @@ func retryApplyResource(client *kyvernoclient.Clientset,
|
|||
v.Spec.Context = gr.Spec.Context
|
||||
v.Spec.Policy = gr.Spec.Policy
|
||||
v.Spec.Resource = gr.Spec.Resource
|
||||
_, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Update(context.TODO(), &grList.Items[i], metav1.UpdateOptions{})
|
||||
_, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Update(context.TODO(), v, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -151,6 +171,12 @@ func retryApplyResource(client *kyvernoclient.Clientset,
|
|||
}
|
||||
if !isExist {
|
||||
gr.SetGenerateName("gr-")
|
||||
gr.SetLabels(map[string]string{
|
||||
"policyName": grSpec.Policy,
|
||||
"resourceName": grSpec.Resource.Name,
|
||||
"resourceKind": grSpec.Resource.Kind,
|
||||
"ResourceNamespace": grSpec.Resource.Namespace,
|
||||
})
|
||||
_, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Create(context.TODO(), &gr, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
v1beta1 "k8s.io/api/admission/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
//HandleGenerate handles admission-requests for policies with generate rules
|
||||
|
@ -54,14 +55,20 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
|||
engineResponse := engine.Generate(policyContext)
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if !rule.Success {
|
||||
|
||||
ws.log.V(4).Info("querying all generate requests")
|
||||
grList, err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).List(contextdefault.TODO(), metav1.ListOptions{})
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
"policyName": engineResponse.PolicyResponse.Policy,
|
||||
"resourceName": engineResponse.PolicyResponse.Resource.Name,
|
||||
"resourceKind": engineResponse.PolicyResponse.Resource.Kind,
|
||||
"ResourceNamespace": engineResponse.PolicyResponse.Resource.Namespace,
|
||||
}))
|
||||
grList, err := ws.grLister.List(selector)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to list generate request")
|
||||
logger.Error(err, "failed to get generate request for the resource", "kind", engineResponse.PolicyResponse.Resource.Kind, "name", engineResponse.PolicyResponse.Resource.Name, "namespace", engineResponse.PolicyResponse.Resource.Namespace)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range grList.Items {
|
||||
for _, v := range grList {
|
||||
if engineResponse.PolicyResponse.Policy == v.Spec.Policy && engineResponse.PolicyResponse.Resource.Name == v.Spec.Resource.Name && engineResponse.PolicyResponse.Resource.Kind == v.Spec.Resource.Kind && engineResponse.PolicyResponse.Resource.Namespace == v.Spec.Resource.Namespace {
|
||||
err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -43,6 +43,12 @@ type WebhookServer struct {
|
|||
client *client.Client
|
||||
kyvernoClient *kyvernoclient.Clientset
|
||||
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
|
||||
// grSynced returns true if the Generate Request store has been synced at least once
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
// list/get cluster policy resource
|
||||
pLister kyvernolister.ClusterPolicyLister
|
||||
|
||||
|
@ -118,6 +124,7 @@ func NewWebhookServer(
|
|||
kyvernoClient *kyvernoclient.Clientset,
|
||||
client *client.Client,
|
||||
tlsPair *tlsutils.PemPair,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
rbInformer rbacinformer.RoleBindingInformer,
|
||||
crbInformer rbacinformer.ClusterRoleBindingInformer,
|
||||
|
@ -153,6 +160,8 @@ func NewWebhookServer(
|
|||
ws := &WebhookServer{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
|
||||
grSynced: grInformer.Informer().HasSynced,
|
||||
pLister: pInformer.Lister(),
|
||||
pSynced: pInformer.Informer().HasSynced,
|
||||
rbLister: rbInformer.Lister(),
|
||||
|
@ -460,7 +469,7 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
|
|||
// RunAsync TLS server in separate thread and returns control immediately
|
||||
func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
|
||||
logger := ws.log
|
||||
if !cache.WaitForCacheSync(stopCh, ws.pSynced, ws.rbSynced, ws.crbSynced, ws.rSynced, ws.crSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, ws.grSynced, ws.pSynced, ws.rbSynced, ws.crbSynced, ws.rSynced, ws.crSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue