mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
Convert GenerateRequest to UpdateRequest for backward compatibility (#3730)
- Remove GenerateRequest Informer - Rename GenerateRequest to UpdateRequest in logs and vars - Fix initContainer leader election - Convert GenerateRequest to UpdateRequest in initContainer - Remove unused methods - Add printer column ruleType to UR Signed-off-by: ShutingZhao <shuting@nirmata.com>
This commit is contained in:
parent
de84b8071d
commit
a4815f77c4
24 changed files with 369 additions and 784 deletions
|
@ -26,7 +26,7 @@ import (
|
|||
// UpdateRequestStatus defines the observed state of UpdateRequest
|
||||
type UpdateRequestStatus struct {
|
||||
|
||||
// State represents state of the generate request.
|
||||
// State represents state of the update request.
|
||||
State UpdateRequestState `json:"state" yaml:"state"`
|
||||
|
||||
// Specifies request status message.
|
||||
|
@ -43,6 +43,7 @@ type UpdateRequestStatus struct {
|
|||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="Policy",type="string",JSONPath=".spec.policy"
|
||||
// +kubebuilder:printcolumn:name="RuleType",type="string",JSONPath=".spec.type"
|
||||
// +kubebuilder:printcolumn:name="ResourceKind",type="string",JSONPath=".spec.resource.kind"
|
||||
// +kubebuilder:printcolumn:name="ResourceName",type="string",JSONPath=".spec.resource.name"
|
||||
// +kubebuilder:printcolumn:name="ResourceNamespace",type="string",JSONPath=".spec.resource.namespace"
|
||||
|
@ -126,13 +127,13 @@ const (
|
|||
// Pending - the Request is yet to be processed or resource has not been created.
|
||||
Pending UpdateRequestState = "Pending"
|
||||
|
||||
// Failed - the Generate Request Controller failed to process the rules.
|
||||
// Failed - the Update Request Controller failed to process the rules.
|
||||
Failed UpdateRequestState = "Failed"
|
||||
|
||||
// Completed - the Generate Request Controller created resources defined in the policy.
|
||||
// Completed - the Update Request Controller created resources defined in the policy.
|
||||
Completed UpdateRequestState = "Completed"
|
||||
|
||||
// Skip - the Generate Request Controller skips to generate the resource.
|
||||
// Skip - the Update Request Controller skips to generate the resource.
|
||||
Skip UpdateRequestState = "Skip"
|
||||
)
|
||||
|
||||
|
|
|
@ -7388,6 +7388,9 @@ spec:
|
|||
- jsonPath: .spec.policy
|
||||
name: Policy
|
||||
type: string
|
||||
- jsonPath: .spec.type
|
||||
name: RuleType
|
||||
type: string
|
||||
- jsonPath: .spec.resource.kind
|
||||
name: ResourceKind
|
||||
type: string
|
||||
|
@ -7528,7 +7531,7 @@ spec:
|
|||
description: Specifies request status message.
|
||||
type: string
|
||||
state:
|
||||
description: State represents state of the generate request.
|
||||
description: State represents state of the update request.
|
||||
type: string
|
||||
required:
|
||||
- state
|
||||
|
|
|
@ -11,8 +11,11 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
engineUtils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/leaderelection"
|
||||
"github.com/kyverno/kyverno/pkg/policyreport"
|
||||
"github.com/kyverno/kyverno/pkg/signal"
|
||||
|
@ -22,6 +25,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/klog/v2/klogr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
@ -49,8 +53,8 @@ const (
|
|||
clusterPolicyReportKind string = "ClusterPolicyReport"
|
||||
reportChangeRequestKind string = "ReportChangeRequest"
|
||||
clusterReportChangeRequestKind string = "ClusterReportChangeRequest"
|
||||
policyViolation string = "PolicyViolation"
|
||||
clusterPolicyViolation string = "ClusterPolicyViolation"
|
||||
convertGenerateRequest string = "ConvertGenerateRequest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -89,6 +93,12 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
pclient, err := kyvernoclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
setupLog.Error(err, "Failed to create client")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Exit for unsupported version of kubernetes cluster
|
||||
if !utils.HigherThanKubernetesVersion(kubeClient.Discovery(), log.Log, 1, 16, 0) {
|
||||
os.Exit(1)
|
||||
|
@ -101,9 +111,7 @@ func main() {
|
|||
{reportChangeRequestKind, ""},
|
||||
{clusterReportChangeRequestKind, ""},
|
||||
|
||||
// clean up policy violation CRD
|
||||
{policyViolation, ""},
|
||||
{clusterPolicyViolation, ""},
|
||||
{convertGenerateRequest, ""},
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -138,7 +146,7 @@ func main() {
|
|||
name := tls.GenerateRootCASecretName(certProps)
|
||||
secret, err := kubeClient.CoreV1().Secrets(config.KyvernoNamespace).Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Log.Info("failed to fetch secret '%v': %v", name, err.Error())
|
||||
log.Log.Info("failed to fetch root CA secret", "name", name, "error", err.Error())
|
||||
|
||||
if !errors.IsNotFound(err) {
|
||||
os.Exit(1)
|
||||
|
@ -155,7 +163,7 @@ func main() {
|
|||
name = tls.GenerateTLSPairSecretName(certProps)
|
||||
secret, err = kubeClient.CoreV1().Secrets(config.KyvernoNamespace).Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Log.Info("failed to fetch secret '%v': %v", name, err.Error())
|
||||
log.Log.Info("failed to fetch TLS Pair secret", "name", name, "error", err.Error())
|
||||
|
||||
if !errors.IsNotFound(err) {
|
||||
os.Exit(1)
|
||||
|
@ -169,21 +177,17 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
_, err = kubeClient.CoordinationV1().Leases(config.KyvernoNamespace).Get(ctx, "kyvernopre-lock", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Log.Info("Lease 'kyvernopre-lock' not found. Starting clean-up...")
|
||||
} else {
|
||||
log.Log.Info("Clean-up complete. Leader exiting...")
|
||||
os.Exit(0)
|
||||
if err = acquireLeader(ctx, kubeClient); err != nil {
|
||||
log.Log.Info("Failed to create lease 'kyvernopre-lock'")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// use pipline to pass request to cleanup resources
|
||||
// generate requests
|
||||
in := gen(done, stopCh, requests...)
|
||||
// process requests
|
||||
// processing routine count : 2
|
||||
p1 := process(client, done, stopCh, in)
|
||||
p2 := process(client, done, stopCh, in)
|
||||
p1 := process(client, pclient, done, stopCh, in)
|
||||
p2 := process(client, pclient, done, stopCh, in)
|
||||
// merge results from processing routines
|
||||
for err := range merge(done, stopCh, p1, p2) {
|
||||
if err != nil {
|
||||
|
@ -197,18 +201,6 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
lease := coord.Lease{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "kyvernopre-lock",
|
||||
},
|
||||
}
|
||||
_, err = kubeClient.CoordinationV1().Leases(config.KyvernoNamespace).Create(ctx, &lease, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
log.Log.Info("Failed to create lease 'kyvernopre-lock'")
|
||||
}
|
||||
|
||||
log.Log.Info("Clean-up complete. Leader exiting...")
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
|
@ -221,7 +213,26 @@ func main() {
|
|||
le.Run(ctx)
|
||||
}
|
||||
|
||||
func executeRequest(client *client.Client, req request) error {
|
||||
func acquireLeader(ctx context.Context, kubeClient kubernetes.Interface) error {
|
||||
_, err := kubeClient.CoordinationV1().Leases(config.KyvernoNamespace).Get(ctx, "kyvernopre-lock", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Log.Info("Lease 'kyvernopre-lock' not found. Starting clean-up...")
|
||||
} else {
|
||||
log.Log.Info("Leader was elected, quiting")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
lease := coord.Lease{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "kyvernopre-lock",
|
||||
},
|
||||
}
|
||||
_, err = kubeClient.CoordinationV1().Leases(config.KyvernoNamespace).Create(ctx, &lease, metav1.CreateOptions{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func executeRequest(client *client.Client, kyvernoclient *kyvernoclient.Clientset, req request) error {
|
||||
switch req.kind {
|
||||
case policyReportKind:
|
||||
return removePolicyReport(client, req.kind)
|
||||
|
@ -231,8 +242,8 @@ func executeRequest(client *client.Client, req request) error {
|
|||
return removeReportChangeRequest(client, req.kind)
|
||||
case clusterReportChangeRequestKind:
|
||||
return removeClusterReportChangeRequest(client, req.kind)
|
||||
case policyViolation, clusterPolicyViolation:
|
||||
return removeViolationCRD(client)
|
||||
case convertGenerateRequest:
|
||||
return convertGR(kyvernoclient)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -272,14 +283,14 @@ func gen(done <-chan struct{}, stopCh <-chan struct{}, requests ...request) <-ch
|
|||
}
|
||||
|
||||
// processes the requests
|
||||
func process(client *client.Client, done <-chan struct{}, stopCh <-chan struct{}, requests <-chan request) <-chan error {
|
||||
func process(client *client.Client, kyvernoclient *kyvernoclient.Clientset, done <-chan struct{}, stopCh <-chan struct{}, requests <-chan request) <-chan error {
|
||||
logger := log.Log.WithName("process")
|
||||
out := make(chan error)
|
||||
go func() {
|
||||
defer close(out)
|
||||
for req := range requests {
|
||||
select {
|
||||
case out <- executeRequest(client, req):
|
||||
case out <- executeRequest(client, kyvernoclient, req):
|
||||
case <-done:
|
||||
logger.Info("done")
|
||||
return
|
||||
|
@ -419,21 +430,6 @@ func removeClusterReportChangeRequest(client *client.Client, kind string) error
|
|||
return nil
|
||||
}
|
||||
|
||||
func removeViolationCRD(client *client.Client) error {
|
||||
if err := client.DeleteResource("", "CustomResourceDefinition", "", "policyviolations.kyverno.io", false); err != nil {
|
||||
if !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to delete CRD policyViolation")
|
||||
}
|
||||
}
|
||||
|
||||
if err := client.DeleteResource("", "CustomResourceDefinition", "", "clusterpolicyviolations.kyverno.io", false); err != nil {
|
||||
if !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to delete CRD clusterPolicyViolation")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteResource(client *client.Client, apiversion, kind, ns, name string) {
|
||||
err := client.DeleteResource(apiversion, kind, ns, name, false)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
|
@ -467,3 +463,65 @@ func addSelectorLabel(client *client.Client, apiversion, kind, ns, name string)
|
|||
|
||||
log.Log.Info("successfully updated resource labels", "kind", kind, "name", name)
|
||||
}
|
||||
|
||||
func convertGR(pclient *kyvernoclient.Clientset) error {
|
||||
logger := log.Log.WithName("convertGenerateRequest")
|
||||
|
||||
var errors []error
|
||||
grs, err := pclient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to list update requests")
|
||||
return err
|
||||
}
|
||||
|
||||
for _, gr := range grs.Items {
|
||||
var ur = &urkyverno.UpdateRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "ur-",
|
||||
Namespace: config.KyvernoNamespace,
|
||||
Labels: gr.GetLabels(),
|
||||
},
|
||||
Spec: urkyverno.UpdateRequestSpec{
|
||||
Type: urkyverno.Generate,
|
||||
Policy: gr.Spec.Policy,
|
||||
Resource: *gr.Spec.Resource.DeepCopy(),
|
||||
Context: urkyverno.UpdateRequestSpecContext{
|
||||
UserRequestInfo: urkyverno.RequestInfo{
|
||||
Roles: gr.Spec.Context.UserRequestInfo.DeepCopy().Roles,
|
||||
ClusterRoles: gr.Spec.Context.UserRequestInfo.DeepCopy().ClusterRoles,
|
||||
AdmissionUserInfo: *gr.Spec.Context.UserRequestInfo.AdmissionUserInfo.DeepCopy(),
|
||||
},
|
||||
|
||||
AdmissionRequestInfo: urkyverno.AdmissionRequestInfoObject{
|
||||
AdmissionRequest: gr.Spec.Context.AdmissionRequestInfo.DeepCopy().AdmissionRequest,
|
||||
Operation: gr.Spec.Context.AdmissionRequestInfo.DeepCopy().Operation,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
new, err := pclient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), ur, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
logger.Info("failed to create UpdateRequest", "GR namespace", gr.GetNamespace(), "GR name", gr.GetName(), "err", err.Error())
|
||||
errors = append(errors, err)
|
||||
continue
|
||||
} else {
|
||||
logger.Info("successfully created UpdateRequest", "GR namespace", gr.GetNamespace(), "GR name", gr.GetName())
|
||||
}
|
||||
|
||||
new.Status.State = urkyverno.Pending
|
||||
if _, err := pclient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
|
||||
logger.Error(err, "failed to set UpdateRequest state to Pending")
|
||||
errors = append(errors, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := pclient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Delete(context.TODO(), gr.GetName(), metav1.DeleteOptions{}); err != nil {
|
||||
errors = append(errors, err)
|
||||
logger.Error(err, "failed to delete GR")
|
||||
}
|
||||
}
|
||||
|
||||
err = engineUtils.CombineErrors(errors)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
backwardcompatibility "github.com/kyverno/kyverno/pkg/compatibility"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/cosign"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
|
@ -288,7 +287,6 @@ func main() {
|
|||
client,
|
||||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
pInformer.Kyverno().V1().Policies(),
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
configData,
|
||||
eventGenerator,
|
||||
|
@ -305,22 +303,17 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
// GENERATE REQUEST GENERATOR
|
||||
grgen := webhookgenerate.NewGenerator(pclient,
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
urgen := webhookgenerate.NewGenerator(pclient,
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
stopCh,
|
||||
log.Log.WithName("UpdateRequestGenerator"))
|
||||
|
||||
// GENERATE CONTROLLER
|
||||
// - applies generate rules on resources based on generate requests created by webhook
|
||||
grc, err := background.NewController(
|
||||
urc, err := background.NewController(
|
||||
kubeClient,
|
||||
pclient,
|
||||
client,
|
||||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
pInformer.Kyverno().V1().Policies(),
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
eventGenerator,
|
||||
kubeInformer.Core().V1().Namespaces(),
|
||||
|
@ -332,15 +325,12 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
// GENERATE REQUEST CLEANUP
|
||||
// -- cleans up the generate requests that have not been processed(i.e. state = [Pending, Failed]) for more than defined timeout
|
||||
grcc, err := generatecleanup.NewController(
|
||||
kubeClient,
|
||||
pclient,
|
||||
client,
|
||||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
pInformer.Kyverno().V1().Policies(),
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
kubeInformer.Core().V1().Namespaces(),
|
||||
log.Log.WithName("GenerateCleanUpController"),
|
||||
|
@ -443,7 +433,6 @@ func main() {
|
|||
pclient,
|
||||
client,
|
||||
tlsPair,
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
kubeInformer.Rbac().V1().RoleBindings(),
|
||||
|
@ -457,12 +446,12 @@ func main() {
|
|||
webhookMonitor,
|
||||
configData,
|
||||
reportReqGen,
|
||||
grgen,
|
||||
urgen,
|
||||
auditHandler,
|
||||
cleanUp,
|
||||
log.Log.WithName("WebhookServer"),
|
||||
openAPIController,
|
||||
grc,
|
||||
urc,
|
||||
promConfig,
|
||||
)
|
||||
|
||||
|
@ -477,7 +466,7 @@ func main() {
|
|||
go certManager.Run(stopCh)
|
||||
go policyCtrl.Run(2, prgen.ReconcileCh, stopCh)
|
||||
go prgen.Run(1, stopCh)
|
||||
go grc.Run(genWorkers, stopCh)
|
||||
go urc.Run(genWorkers, stopCh)
|
||||
go grcc.Run(1, stopCh)
|
||||
}
|
||||
|
||||
|
@ -514,9 +503,6 @@ func main() {
|
|||
go webhookMonitor.Run(webhookCfg, certRenewer, eventGenerator, stopCh)
|
||||
}
|
||||
|
||||
go backwardcompatibility.AddLabels(pclient, pInformer.Kyverno().V1().GenerateRequests())
|
||||
go backwardcompatibility.AddCloneLabel(client, pInformer.Kyverno().V1().ClusterPolicies())
|
||||
|
||||
pInformer.Start(stopCh)
|
||||
kubeInformer.Start(stopCh)
|
||||
kubeKyvernoInformer.Start(stopCh)
|
||||
|
|
|
@ -21,6 +21,9 @@ spec:
|
|||
- jsonPath: .spec.policy
|
||||
name: Policy
|
||||
type: string
|
||||
- jsonPath: .spec.type
|
||||
name: RuleType
|
||||
type: string
|
||||
- jsonPath: .spec.resource.kind
|
||||
name: ResourceKind
|
||||
type: string
|
||||
|
@ -179,7 +182,7 @@ spec:
|
|||
description: Specifies request status message.
|
||||
type: string
|
||||
state:
|
||||
description: State represents state of the generate request.
|
||||
description: State represents state of the update request.
|
||||
type: string
|
||||
required:
|
||||
- state
|
||||
|
|
|
@ -11479,6 +11479,9 @@ spec:
|
|||
- jsonPath: .spec.policy
|
||||
name: Policy
|
||||
type: string
|
||||
- jsonPath: .spec.type
|
||||
name: RuleType
|
||||
type: string
|
||||
- jsonPath: .spec.resource.kind
|
||||
name: ResourceKind
|
||||
type: string
|
||||
|
@ -11637,7 +11640,7 @@ spec:
|
|||
description: Specifies request status message.
|
||||
type: string
|
||||
state:
|
||||
description: State represents state of the generate request.
|
||||
description: State represents state of the update request.
|
||||
type: string
|
||||
required:
|
||||
- state
|
||||
|
|
|
@ -11426,6 +11426,9 @@ spec:
|
|||
- jsonPath: .spec.policy
|
||||
name: Policy
|
||||
type: string
|
||||
- jsonPath: .spec.type
|
||||
name: RuleType
|
||||
type: string
|
||||
- jsonPath: .spec.resource.kind
|
||||
name: ResourceKind
|
||||
type: string
|
||||
|
@ -11584,7 +11587,7 @@ spec:
|
|||
description: Specifies request status message.
|
||||
type: string
|
||||
state:
|
||||
description: State represents state of the generate request.
|
||||
description: State represents state of the update request.
|
||||
type: string
|
||||
required:
|
||||
- state
|
||||
|
|
|
@ -417,7 +417,7 @@ UpdateRequestState
|
|||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>State represents state of the generate request.</p>
|
||||
<p>State represents state of the update request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -21,8 +21,8 @@ type StatusControl struct {
|
|||
Client kyvernoclient.Interface
|
||||
}
|
||||
|
||||
//Failed sets gr status.state to failed with message
|
||||
func (sc StatusControl) Failed(gr urkyverno.UpdateRequest, message string, genResources []kyverno.ResourceSpec) error {
|
||||
//Failed sets ur status.state to failed with message
|
||||
func (sc StatusControl) Failed(ur urkyverno.UpdateRequest, message string, genResources []kyverno.ResourceSpec) error {
|
||||
genR := &urkyverno.UpdateRequestStatus{
|
||||
State: urkyverno.Failed,
|
||||
Message: message,
|
||||
|
@ -36,17 +36,17 @@ func (sc StatusControl) Failed(gr urkyverno.UpdateRequest, message string, genRe
|
|||
"replace",
|
||||
genR,
|
||||
)
|
||||
_, err := PatchGenerateRequest(&gr, patch, sc.Client, "status")
|
||||
_, err := PatchUpdateRequest(&ur, patch, sc.Client, "status")
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to patch update request status", "name", gr.Name)
|
||||
log.Log.Error(err, "failed to patch update request status", "name", ur.Name)
|
||||
return err
|
||||
}
|
||||
log.Log.V(3).Info("updated update request status", "name", gr.Name, "status", string(kyverno.Failed))
|
||||
log.Log.V(3).Info("updated update request status", "name", ur.Name, "status", string(kyverno.Failed))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Success sets the gr status.state to completed and clears message
|
||||
func (sc StatusControl) Success(gr urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
// Success sets the ur status.state to completed and clears message
|
||||
func (sc StatusControl) Success(ur urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
genR := &urkyverno.UpdateRequestStatus{
|
||||
State: urkyverno.Completed,
|
||||
Message: "",
|
||||
|
@ -61,17 +61,17 @@ func (sc StatusControl) Success(gr urkyverno.UpdateRequest, genResources []kyver
|
|||
"replace",
|
||||
genR,
|
||||
)
|
||||
_, err := PatchGenerateRequest(&gr, patch, sc.Client, "status")
|
||||
_, err := PatchUpdateRequest(&ur, patch, sc.Client, "status")
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to patch update request status", "name", gr.Name)
|
||||
log.Log.Error(err, "failed to patch update request status", "name", ur.Name)
|
||||
return err
|
||||
}
|
||||
log.Log.V(3).Info("updated update request status", "name", gr.Name, "status", string(kyverno.Completed))
|
||||
log.Log.V(3).Info("updated update request status", "name", ur.Name, "status", string(kyverno.Completed))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Success sets the gr status.state to completed and clears message
|
||||
func (sc StatusControl) Skip(gr urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
// Success sets the ur status.state to completed and clears message
|
||||
func (sc StatusControl) Skip(ur urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
genR := &urkyverno.UpdateRequestStatus{
|
||||
State: urkyverno.Skip,
|
||||
Message: "",
|
||||
|
@ -86,11 +86,11 @@ func (sc StatusControl) Skip(gr urkyverno.UpdateRequest, genResources []kyverno.
|
|||
"replace",
|
||||
genR,
|
||||
)
|
||||
_, err := PatchGenerateRequest(&gr, patch, sc.Client, "status")
|
||||
_, err := PatchUpdateRequest(&ur, patch, sc.Client, "status")
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to update generate request status", "name", gr.Name)
|
||||
log.Log.Error(err, "failed to update UR status", "name", ur.Name)
|
||||
return err
|
||||
}
|
||||
log.Log.V(3).Info("updated update request status", "name", gr.Name, "status", string(kyverno.Skip))
|
||||
log.Log.V(3).Info("updated UR status", "name", ur.Name, "status", string(kyverno.Skip))
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -11,15 +11,15 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// PatchGenerateRequest patches a generate request object
|
||||
func PatchGenerateRequest(gr *urkyverno.UpdateRequest, patch jsonutils.Patch, client kyvernoclient.Interface, subresources ...string) (*urkyverno.UpdateRequest, error) {
|
||||
// PatchUpdateRequest patches a update request object
|
||||
func PatchUpdateRequest(ur *urkyverno.UpdateRequest, patch jsonutils.Patch, client kyvernoclient.Interface, subresources ...string) (*urkyverno.UpdateRequest, error) {
|
||||
data, err := patch.ToPatchBytes()
|
||||
if nil != err {
|
||||
return gr, err
|
||||
return ur, err
|
||||
}
|
||||
newGR, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Patch(context.TODO(), gr.Name, types.JSONPatchType, data, metav1.PatchOptions{}, subresources...)
|
||||
newUR, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Patch(context.TODO(), ur.Name, types.JSONPatchType, data, metav1.PatchOptions{}, subresources...)
|
||||
if err != nil {
|
||||
return gr, err
|
||||
return ur, err
|
||||
}
|
||||
return newGR, nil
|
||||
return newUR, nil
|
||||
}
|
||||
|
|
|
@ -9,17 +9,17 @@ import (
|
|||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
||||
func (c *Controller) processGR(gr urkyverno.UpdateRequest) error {
|
||||
logger := c.log.WithValues("kind", gr.Kind, "namespace", gr.Namespace, "name", gr.Name)
|
||||
func (c *Controller) processUR(ur urkyverno.UpdateRequest) error {
|
||||
logger := c.log.WithValues("kind", ur.Kind, "namespace", ur.Namespace, "name", ur.Name)
|
||||
// 1- Corresponding policy has been deleted
|
||||
// then we don't delete the generated resources
|
||||
|
||||
// 2- The trigger resource is deleted, then delete the generated resources
|
||||
if !ownerResourceExists(logger, c.client, gr) {
|
||||
deleteGR := false
|
||||
if !ownerResourceExists(logger, c.client, ur) {
|
||||
deleteUR := false
|
||||
// check retry count in annotaion
|
||||
grAnnotations := gr.Annotations
|
||||
if val, ok := grAnnotations["generate.kyverno.io/retry-count"]; ok {
|
||||
urAnnotations := ur.Annotations
|
||||
if val, ok := urAnnotations["generate.kyverno.io/retry-count"]; ok {
|
||||
retryCount, err := strconv.ParseUint(val, 10, 32)
|
||||
if err != nil {
|
||||
logger.Error(err, "unable to convert retry-count")
|
||||
|
@ -27,45 +27,45 @@ func (c *Controller) processGR(gr urkyverno.UpdateRequest) error {
|
|||
}
|
||||
|
||||
if retryCount >= 5 {
|
||||
deleteGR = true
|
||||
deleteUR = true
|
||||
}
|
||||
}
|
||||
|
||||
if deleteGR {
|
||||
if err := deleteGeneratedResources(logger, c.client, gr); err != nil {
|
||||
if deleteUR {
|
||||
if err := deleteGeneratedResources(logger, c.client, ur); err != nil {
|
||||
return err
|
||||
}
|
||||
// - trigger-resource is deleted
|
||||
// - generated-resources are deleted
|
||||
// - > Now delete the GenerateRequest CR
|
||||
return c.control.Delete(gr.Name)
|
||||
// - > Now delete the UpdateRequest CR
|
||||
return c.control.Delete(ur.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ownerResourceExists(log logr.Logger, client *dclient.Client, gr urkyverno.UpdateRequest) bool {
|
||||
_, err := client.GetResource("", gr.Spec.Resource.Kind, gr.Spec.Resource.Namespace, gr.Spec.Resource.Name)
|
||||
func ownerResourceExists(log logr.Logger, client *dclient.Client, ur urkyverno.UpdateRequest) bool {
|
||||
_, err := client.GetResource("", ur.Spec.Resource.Kind, ur.Spec.Resource.Namespace, ur.Spec.Resource.Name)
|
||||
// trigger resources has been deleted
|
||||
if apierrors.IsNotFound(err) {
|
||||
return false
|
||||
}
|
||||
if err != nil {
|
||||
log.Error(err, "failed to get resource", "genKind", gr.Spec.Resource.Kind, "genNamespace", gr.Spec.Resource.Namespace, "genName", gr.Spec.Resource.Name)
|
||||
log.Error(err, "failed to get resource", "genKind", ur.Spec.Resource.Kind, "genNamespace", ur.Spec.Resource.Namespace, "genName", ur.Spec.Resource.Name)
|
||||
}
|
||||
// if there was an error while querying the resources we don't delete the generated resources
|
||||
// but expect the deletion in next reconciliation loop
|
||||
return true
|
||||
}
|
||||
|
||||
func deleteGeneratedResources(log logr.Logger, client *dclient.Client, gr urkyverno.UpdateRequest) error {
|
||||
for _, genResource := range gr.Status.GeneratedResources {
|
||||
func deleteGeneratedResources(log logr.Logger, client *dclient.Client, ur urkyverno.UpdateRequest) error {
|
||||
for _, genResource := range ur.Status.GeneratedResources {
|
||||
err := client.DeleteResource("", genResource.Kind, genResource.Namespace, genResource.Name, false)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.V(3).Info("generated resource deleted", "genKind", gr.Spec.Resource.Kind, "genNamespace", gr.Spec.Resource.Namespace, "genName", gr.Spec.Resource.Name)
|
||||
log.V(3).Info("generated resource deleted", "genKind", ur.Spec.Resource.Kind, "genNamespace", ur.Spec.Resource.Namespace, "genName", ur.Spec.Resource.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -40,12 +40,12 @@ type Controller struct {
|
|||
kyvernoClient *kyvernoclient.Clientset
|
||||
|
||||
pInformer kyvernoinformer.ClusterPolicyInformer
|
||||
grInformer kyvernoinformer.GenerateRequestInformer
|
||||
urInformer urkyvernoinformer.UpdateRequestInformer
|
||||
|
||||
// control is used to delete the GR
|
||||
// control is used to delete the UR
|
||||
control ControlInterface
|
||||
|
||||
// gr that need to be synced
|
||||
// ur that need to be synced
|
||||
queue workqueue.RateLimitingInterface
|
||||
|
||||
// pLister can list/get cluster policy from the shared informer's store
|
||||
|
@ -54,9 +54,6 @@ type Controller struct {
|
|||
// npLister can list/get namespace policy from the shared informer's store
|
||||
npLister kyvernolister.PolicyLister
|
||||
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urkyvernolister.UpdateRequestNamespaceLister
|
||||
|
||||
|
@ -69,9 +66,6 @@ type Controller struct {
|
|||
// pSynced returns true if the Namespace policy has been synced at least once
|
||||
npSynced cache.InformerSynced
|
||||
|
||||
// grSynced returns true if the generate request store has been synced at least once
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
// urSynced returns true if the update request store has been synced at least once
|
||||
urSynced cache.InformerSynced
|
||||
|
||||
|
@ -89,7 +83,6 @@ func NewController(
|
|||
client *dclient.Client,
|
||||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
npInformer kyvernoinformer.PolicyInformer,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urkyvernoinformer.UpdateRequestInformer,
|
||||
namespaceInformer coreinformers.NamespaceInformer,
|
||||
log logr.Logger,
|
||||
|
@ -98,7 +91,7 @@ func NewController(
|
|||
kyvernoClient: kyvernoclient,
|
||||
client: client,
|
||||
pInformer: pInformer,
|
||||
grInformer: grInformer,
|
||||
urInformer: urInformer,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "generate-request-cleanup"),
|
||||
log: log,
|
||||
}
|
||||
|
@ -107,13 +100,11 @@ func NewController(
|
|||
|
||||
c.pLister = pInformer.Lister()
|
||||
c.npLister = npInformer.Lister()
|
||||
c.grLister = grInformer.Lister().GenerateRequests(config.KyvernoNamespace)
|
||||
c.urLister = urInformer.Lister().UpdateRequests(config.KyvernoNamespace)
|
||||
c.nsLister = namespaceInformer.Lister()
|
||||
|
||||
c.pSynced = pInformer.Informer().HasSynced
|
||||
c.npSynced = npInformer.Informer().HasSynced
|
||||
c.grSynced = grInformer.Informer().HasSynced
|
||||
c.urSynced = urInformer.Informer().HasSynced
|
||||
c.nsListerSynced = namespaceInformer.Informer().HasSynced
|
||||
|
||||
|
@ -131,77 +122,74 @@ func (c *Controller) deletePolicy(obj interface{}) {
|
|||
}
|
||||
p, ok = tombstone.Obj.(*kyverno.ClusterPolicy)
|
||||
if !ok {
|
||||
logger.Info("Tombstone contained object that is not a Generate Request", "obj", obj)
|
||||
logger.Info("Tombstone contained object that is not a Update Request", "obj", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
logger.V(4).Info("deleting policy", "name", p.Name)
|
||||
// clean up the GR
|
||||
// Get the corresponding GR
|
||||
// get the list of GR for the current Policy version
|
||||
rules := autogen.ComputeRules(p)
|
||||
|
||||
generatePolicyWithClone := pkgCommon.ProcessDeletePolicyForCloneGenerateRule(rules, c.client, p.GetName(), logger)
|
||||
|
||||
// get the generated resource name from generate request for log
|
||||
// get the generated resource name from update request for log
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: p.Name,
|
||||
}))
|
||||
|
||||
grList, err := c.urLister.List(selector)
|
||||
urList, err := c.urLister.List(selector)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request for the resource", "label", urkyverno.URGeneratePolicyLabel)
|
||||
logger.Error(err, "failed to get update request for the resource", "label", urkyverno.URGeneratePolicyLabel)
|
||||
return
|
||||
}
|
||||
|
||||
for _, gr := range grList {
|
||||
for _, generatedResource := range gr.Status.GeneratedResources {
|
||||
for _, ur := range urList {
|
||||
for _, generatedResource := range ur.Status.GeneratedResources {
|
||||
logger.V(4).Info("retaining resource", "apiVersion", generatedResource.APIVersion, "kind", generatedResource.Kind, "name", generatedResource.Name, "namespace", generatedResource.Namespace)
|
||||
}
|
||||
}
|
||||
|
||||
if !generatePolicyWithClone {
|
||||
grs, err := c.urLister.GetUpdateRequestsForClusterPolicy(p.Name)
|
||||
urs, err := c.urLister.GetUpdateRequestsForClusterPolicy(p.Name)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to generate request for the policy", "name", p.Name)
|
||||
logger.Error(err, "failed to update request for the policy", "name", p.Name)
|
||||
return
|
||||
}
|
||||
|
||||
for _, gr := range grs {
|
||||
logger.V(4).Info("enqueue the gr for cleanup", "gr name", gr.Name)
|
||||
c.addUR(gr)
|
||||
for _, ur := range urs {
|
||||
logger.V(4).Info("enqueue the ur for cleanup", "ur name", ur.Name)
|
||||
c.addUR(ur)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) addUR(obj interface{}) {
|
||||
gr := obj.(*urkyverno.UpdateRequest)
|
||||
c.enqueue(gr)
|
||||
ur := obj.(*urkyverno.UpdateRequest)
|
||||
c.enqueue(ur)
|
||||
}
|
||||
|
||||
func (c *Controller) updateUR(old, cur interface{}) {
|
||||
gr := cur.(*urkyverno.UpdateRequest)
|
||||
c.enqueue(gr)
|
||||
ur := cur.(*urkyverno.UpdateRequest)
|
||||
c.enqueue(ur)
|
||||
}
|
||||
|
||||
func (c *Controller) deleteUR(obj interface{}) {
|
||||
logger := c.log
|
||||
gr, ok := obj.(*urkyverno.UpdateRequest)
|
||||
ur, ok := obj.(*urkyverno.UpdateRequest)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
logger.Info("Couldn't get object from tombstone", "obj", obj)
|
||||
return
|
||||
}
|
||||
gr, ok = tombstone.Obj.(*urkyverno.UpdateRequest)
|
||||
ur, ok = tombstone.Obj.(*urkyverno.UpdateRequest)
|
||||
if !ok {
|
||||
logger.Info("ombstone contained object that is not a Generate Request", "obj", obj)
|
||||
logger.Info("ombstone contained object that is not a Update Request", "obj", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, resource := range gr.Status.GeneratedResources {
|
||||
for _, resource := range ur.Status.GeneratedResources {
|
||||
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "failed to fetch generated resource", "resource", resource.Name)
|
||||
|
@ -216,29 +204,29 @@ func (c *Controller) deleteUR(obj interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
logger.V(4).Info("deleting Generate Request CR", "name", gr.Name)
|
||||
logger.V(4).Info("deleting Update Request CR", "name", ur.Name)
|
||||
// sync Handler will remove it from the queue
|
||||
c.enqueue(gr)
|
||||
c.enqueue(ur)
|
||||
}
|
||||
|
||||
func (c *Controller) enqueue(gr *urkyverno.UpdateRequest) {
|
||||
func (c *Controller) enqueue(ur *urkyverno.UpdateRequest) {
|
||||
// skip enqueueing Pending requests
|
||||
if gr.Status.State == urkyverno.Pending {
|
||||
if ur.Status.State == urkyverno.Pending {
|
||||
return
|
||||
}
|
||||
|
||||
logger := c.log
|
||||
key, err := cache.MetaNamespaceKeyFunc(gr)
|
||||
key, err := cache.MetaNamespaceKeyFunc(ur)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to extract key")
|
||||
return
|
||||
}
|
||||
|
||||
logger.V(5).Info("enqueue generate request", "name", gr.Name)
|
||||
logger.V(5).Info("enqueue update request", "name", ur.Name)
|
||||
c.queue.Add(key)
|
||||
}
|
||||
|
||||
//Run starts the generate-request re-conciliation loop
|
||||
//Run starts the update-request re-conciliation loop
|
||||
func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
||||
logger := c.log
|
||||
defer utilruntime.HandleCrash()
|
||||
|
@ -246,7 +234,7 @@ func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
|||
logger.Info("starting")
|
||||
defer logger.Info("shutting down")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, c.pSynced, c.grSynced, c.urSynced, c.npSynced, c.nsListerSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, c.pSynced, c.urSynced, c.npSynced, c.nsListerSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
@ -255,7 +243,7 @@ func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
|||
DeleteFunc: c.deletePolicy, // we only cleanup if the policy is delete
|
||||
})
|
||||
|
||||
c.grInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
c.urInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addUR,
|
||||
UpdateFunc: c.updateUR,
|
||||
DeleteFunc: c.deleteUR,
|
||||
|
@ -269,7 +257,7 @@ func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
|||
}
|
||||
|
||||
// worker runs a worker thread that just de-queues items, processes them, and marks them done.
|
||||
// It enforces that the syncGenerateRequest is never invoked concurrently with the same key.
|
||||
// It enforces that the syncUpdateRequest is never invoked concurrently with the same key.
|
||||
func (c *Controller) worker() {
|
||||
for c.processNextWorkItem() {
|
||||
}
|
||||
|
@ -281,7 +269,7 @@ func (c *Controller) processNextWorkItem() bool {
|
|||
return false
|
||||
}
|
||||
defer c.queue.Done(key)
|
||||
err := c.syncGenerateRequest(key.(string))
|
||||
err := c.syncUpdateRequest(key.(string))
|
||||
c.handleErr(err, key)
|
||||
|
||||
return true
|
||||
|
@ -295,43 +283,43 @@ func (c *Controller) handleErr(err error, key interface{}) {
|
|||
}
|
||||
|
||||
if apierrors.IsNotFound(err) {
|
||||
logger.V(4).Info("dropping generate request", "key", key, "error", err.Error())
|
||||
logger.V(4).Info("dropping update request", "key", key, "error", err.Error())
|
||||
c.queue.Forget(key)
|
||||
return
|
||||
}
|
||||
|
||||
if c.queue.NumRequeues(key) < maxRetries {
|
||||
logger.V(3).Info("retrying generate request", "key", key, "error", err.Error())
|
||||
logger.V(3).Info("retrying update request", "key", key, "error", err.Error())
|
||||
c.queue.AddRateLimited(key)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(err, "failed to cleanup generate request", "key", key)
|
||||
logger.Error(err, "failed to cleanup update request", "key", key)
|
||||
c.queue.Forget(key)
|
||||
}
|
||||
|
||||
func (c *Controller) syncGenerateRequest(key string) error {
|
||||
func (c *Controller) syncUpdateRequest(key string) error {
|
||||
logger := c.log.WithValues("key", key)
|
||||
var err error
|
||||
startTime := time.Now()
|
||||
logger.V(4).Info("started syncing generate request", "startTime", startTime)
|
||||
logger.V(4).Info("started syncing update request", "startTime", startTime)
|
||||
defer func() {
|
||||
logger.V(4).Info("finished syncing generate request", "processingTIme", time.Since(startTime).String())
|
||||
logger.V(4).Info("finished syncing update request", "processingTIme", time.Since(startTime).String())
|
||||
}()
|
||||
_, grName, err := cache.SplitMetaNamespaceKey(key)
|
||||
_, urName, err := cache.SplitMetaNamespaceKey(key)
|
||||
if apierrors.IsNotFound(err) {
|
||||
logger.Info("generate request has been deleted")
|
||||
logger.Info("update request has been deleted")
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gr, err := c.urLister.Get(grName)
|
||||
ur, err := c.urLister.Get(urName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(gr.Spec.Policy)
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(ur.Spec.Policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -342,8 +330,8 @@ func (c *Controller) syncGenerateRequest(key string) error {
|
|||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
logger.Error(err, "failed to get clusterpolicy, deleting the generate request")
|
||||
err = c.control.Delete(gr.Name)
|
||||
logger.Error(err, "failed to get clusterpolicy, deleting the update request")
|
||||
err = c.control.Delete(ur.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -355,13 +343,13 @@ func (c *Controller) syncGenerateRequest(key string) error {
|
|||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
logger.Error(err, "failed to get policy, deleting the generate request")
|
||||
err = c.control.Delete(gr.Name)
|
||||
logger.Error(err, "failed to get policy, deleting the update request")
|
||||
err = c.control.Delete(ur.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return c.processGR(*gr)
|
||||
return c.processUR(*ur)
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ type GenerateController struct {
|
|||
// typed client for Kyverno CRDs
|
||||
kyvernoClient *kyvernoclient.Clientset
|
||||
|
||||
// grStatusControl is used to update GR status
|
||||
// urStatusControl is used to update UR status
|
||||
statusControl common.StatusControlInterface
|
||||
|
||||
// event generator interface
|
||||
|
@ -51,9 +51,6 @@ type GenerateController struct {
|
|||
|
||||
log logr.Logger
|
||||
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urlister.UpdateRequestNamespaceLister
|
||||
|
||||
|
@ -75,7 +72,6 @@ func NewGenerateController(
|
|||
client *dclient.Client,
|
||||
policyLister kyvernolister.ClusterPolicyLister,
|
||||
npolicyLister kyvernolister.PolicyLister,
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister,
|
||||
urLister urlister.UpdateRequestNamespaceLister,
|
||||
eventGen event.Interface,
|
||||
nsLister corelister.NamespaceLister,
|
||||
|
@ -91,7 +87,6 @@ func NewGenerateController(
|
|||
Config: dynamicConfig,
|
||||
policyLister: policyLister,
|
||||
npolicyLister: npolicyLister,
|
||||
grLister: grLister,
|
||||
urLister: urLister,
|
||||
}
|
||||
|
||||
|
@ -101,28 +96,28 @@ func NewGenerateController(
|
|||
return &c, nil
|
||||
}
|
||||
|
||||
func (c *GenerateController) ProcessGR(gr *urkyverno.UpdateRequest) error {
|
||||
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "apiVersion", gr.Spec.Resource.APIVersion, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
|
||||
func (c *GenerateController) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
||||
logger := c.log.WithValues("name", ur.Name, "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name)
|
||||
var err error
|
||||
var resource *unstructured.Unstructured
|
||||
var genResources []kyverno.ResourceSpec
|
||||
var precreatedResource bool
|
||||
|
||||
// 1 - Check if the resource exists
|
||||
resource, err = common.GetResource(c.client, gr.Spec, c.log)
|
||||
resource, err = common.GetResource(c.client, ur.Spec, c.log)
|
||||
if err != nil {
|
||||
// Don't update status
|
||||
// re-queueing the GR by updating the annotation
|
||||
// re-queueing the UR by updating the annotation
|
||||
// retry - 5 times
|
||||
logger.V(3).Info("resource does not exist or is pending creation, re-queueing", "details", err.Error(), "retry")
|
||||
updateAnnotation := true
|
||||
grAnnotations := gr.Annotations
|
||||
urAnnotations := ur.Annotations
|
||||
|
||||
if len(grAnnotations) == 0 {
|
||||
grAnnotations = make(map[string]string)
|
||||
grAnnotations["generate.kyverno.io/retry-count"] = "1"
|
||||
if len(urAnnotations) == 0 {
|
||||
urAnnotations = make(map[string]string)
|
||||
urAnnotations["generate.kyverno.io/retry-count"] = "1"
|
||||
} else {
|
||||
if val, ok := grAnnotations["generate.kyverno.io/retry-count"]; ok {
|
||||
if val, ok := urAnnotations["generate.kyverno.io/retry-count"]; ok {
|
||||
sleepCountInt64, err := strconv.ParseUint(val, 10, 32)
|
||||
if err != nil {
|
||||
logger.Error(err, "unable to convert retry-count")
|
||||
|
@ -135,20 +130,20 @@ func (c *GenerateController) ProcessGR(gr *urkyverno.UpdateRequest) error {
|
|||
} else {
|
||||
time.Sleep(time.Second * time.Duration(sleepCountInt))
|
||||
incrementedCountString := strconv.Itoa(sleepCountInt)
|
||||
grAnnotations["generate.kyverno.io/retry-count"] = incrementedCountString
|
||||
urAnnotations["generate.kyverno.io/retry-count"] = incrementedCountString
|
||||
}
|
||||
|
||||
} else {
|
||||
time.Sleep(time.Second * 1)
|
||||
grAnnotations["generate.kyverno.io/retry-count"] = "1"
|
||||
urAnnotations["generate.kyverno.io/retry-count"] = "1"
|
||||
}
|
||||
}
|
||||
|
||||
if updateAnnotation {
|
||||
gr.SetAnnotations(grAnnotations)
|
||||
_, err := c.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(contextdefault.TODO(), gr, metav1.UpdateOptions{})
|
||||
ur.SetAnnotations(urAnnotations)
|
||||
_, err := c.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(contextdefault.TODO(), ur, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update annotation in generate request for the resource", "generate request", gr.Name)
|
||||
logger.Error(err, "failed to update annotation in update request for the resource", "update request", ur.Name)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -163,38 +158,38 @@ func (c *GenerateController) ProcessGR(gr *urkyverno.UpdateRequest) error {
|
|||
|
||||
// 2 - Apply the generate policy on the resource
|
||||
namespaceLabels := pkgcommon.GetNamespaceSelectorsFromNamespaceLister(resource.GetKind(), resource.GetNamespace(), c.nsLister, logger)
|
||||
genResources, precreatedResource, err = c.applyGenerate(*resource, *gr, namespaceLabels)
|
||||
genResources, precreatedResource, err = c.applyGenerate(*resource, *ur, namespaceLabels)
|
||||
|
||||
if err != nil {
|
||||
// Need not update the status when policy doesn't apply on resource, because all the generate requests are removed by the cleanup controller
|
||||
// Need not update the status when policy doesn't apply on resource, because all the update requests are removed by the cleanup controller
|
||||
if strings.Contains(err.Error(), doesNotApply) {
|
||||
logger.V(4).Info("skipping updating status of generate request")
|
||||
logger.V(4).Info("skipping updating status of update request")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3 - Report failure Events
|
||||
events := common.FailedEvents(err, gr.Spec.Policy, "", event.GeneratePolicyController, resource, logger)
|
||||
events := common.FailedEvents(err, ur.Spec.Policy, "", event.GeneratePolicyController, resource, logger)
|
||||
c.eventGen.Add(events...)
|
||||
}
|
||||
|
||||
// 4 - Update Status
|
||||
return updateStatus(c.statusControl, *gr, err, genResources, precreatedResource)
|
||||
return updateStatus(c.statusControl, *ur, err, genResources, precreatedResource)
|
||||
}
|
||||
|
||||
const doesNotApply = "policy does not apply to resource"
|
||||
|
||||
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, gr urkyverno.UpdateRequest, namespaceLabels map[string]string) ([]kyverno.ResourceSpec, bool, error) {
|
||||
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "apiVersion", gr.Spec.Resource.APIVersion, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
|
||||
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, ur urkyverno.UpdateRequest, namespaceLabels map[string]string) ([]kyverno.ResourceSpec, bool, error) {
|
||||
logger := c.log.WithValues("name", ur.Name, "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name)
|
||||
// Get the list of rules to be applied
|
||||
// get policy
|
||||
// build context
|
||||
|
||||
logger.V(3).Info("applying generate policy rule")
|
||||
|
||||
policy, err := c.getPolicySpec(gr)
|
||||
policy, err := c.getPolicySpec(ur)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
for _, e := range gr.Status.GeneratedResources {
|
||||
for _, e := range ur.Status.GeneratedResources {
|
||||
resp, err := c.client.GetResource(e.APIVersion, e.Kind, e.Namespace, e.Name)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "failed to find generated resource", "name", e.Name)
|
||||
|
@ -214,39 +209,39 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, g
|
|||
return nil, false, err
|
||||
}
|
||||
|
||||
policyContext, precreatedResource, err := common.NewBackgroundContext(c.client, &gr, &policy, &resource, c.Config, namespaceLabels, logger)
|
||||
policyContext, precreatedResource, err := common.NewBackgroundContext(c.client, &ur, &policy, &resource, c.Config, namespaceLabels, logger)
|
||||
if err != nil {
|
||||
return nil, precreatedResource, err
|
||||
}
|
||||
|
||||
// check if the policy still applies to the resource
|
||||
engineResponse := engine.GenerateResponse(policyContext, gr)
|
||||
engineResponse := engine.GenerateResponse(policyContext, ur)
|
||||
if len(engineResponse.PolicyResponse.Rules) == 0 {
|
||||
logger.V(4).Info(doesNotApply)
|
||||
return nil, false, errors.New(doesNotApply)
|
||||
}
|
||||
|
||||
var applicableRules []string
|
||||
// Removing GR if rule is failed. Used when the generate condition failed but gr exist
|
||||
// Removing UR if rule is failed. Used when the generate condition failed but ur exist
|
||||
for _, r := range engineResponse.PolicyResponse.Rules {
|
||||
if r.Status != response.RuleStatusPass {
|
||||
logger.V(4).Info("querying all generate requests")
|
||||
logger.V(4).Info("querying all update requests")
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: engineResponse.PolicyResponse.Policy.Name,
|
||||
"generate.kyverno.io/resource-name": engineResponse.PolicyResponse.Resource.Name,
|
||||
"generate.kyverno.io/resource-kind": engineResponse.PolicyResponse.Resource.Kind,
|
||||
"generate.kyverno.io/resource-namespace": engineResponse.PolicyResponse.Resource.Namespace,
|
||||
}))
|
||||
grList, err := c.urLister.List(selector)
|
||||
urList, err := c.urLister.List(selector)
|
||||
if err != nil {
|
||||
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)
|
||||
logger.Error(err, "failed to get update request for the resource", "kind", engineResponse.PolicyResponse.Resource.Kind, "name", engineResponse.PolicyResponse.Resource.Name, "namespace", engineResponse.PolicyResponse.Resource.Namespace)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range grList {
|
||||
for _, v := range urList {
|
||||
err := c.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to delete generate request")
|
||||
logger.Error(err, "failed to delete update request")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -255,14 +250,14 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, g
|
|||
}
|
||||
|
||||
// Apply the generate rule on resource
|
||||
return c.applyGeneratePolicy(logger, policyContext, gr, applicableRules)
|
||||
return c.applyGeneratePolicy(logger, policyContext, ur, applicableRules)
|
||||
}
|
||||
|
||||
// getPolicySpec gets the policy spec from the ClusterPolicy/Policy
|
||||
func (c *GenerateController) getPolicySpec(gr urkyverno.UpdateRequest) (kyverno.ClusterPolicy, error) {
|
||||
func (c *GenerateController) getPolicySpec(ur urkyverno.UpdateRequest) (kyverno.ClusterPolicy, error) {
|
||||
var policy kyverno.ClusterPolicy
|
||||
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(gr.Spec.Policy)
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(ur.Spec.Policy)
|
||||
if err != nil {
|
||||
return policy, err
|
||||
}
|
||||
|
@ -287,18 +282,17 @@ func (c *GenerateController) getPolicySpec(gr urkyverno.UpdateRequest) (kyverno.
|
|||
}
|
||||
}
|
||||
|
||||
func updateStatus(statusControl common.StatusControlInterface, gr urkyverno.UpdateRequest, err error, genResources []kyverno.ResourceSpec, precreatedResource bool) error {
|
||||
func updateStatus(statusControl common.StatusControlInterface, ur urkyverno.UpdateRequest, err error, genResources []kyverno.ResourceSpec, precreatedResource bool) error {
|
||||
if err != nil {
|
||||
return statusControl.Failed(gr, err.Error(), genResources)
|
||||
return statusControl.Failed(ur, err.Error(), genResources)
|
||||
} else if precreatedResource {
|
||||
return statusControl.Skip(gr, genResources)
|
||||
return statusControl.Skip(ur, genResources)
|
||||
}
|
||||
|
||||
// Generate request successfully processed
|
||||
return statusControl.Success(gr, genResources)
|
||||
return statusControl.Success(ur, genResources)
|
||||
}
|
||||
|
||||
func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, gr urkyverno.UpdateRequest, applicableRules []string) (genResources []kyverno.ResourceSpec, processExisting bool, err error) {
|
||||
func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, ur urkyverno.UpdateRequest, applicableRules []string) (genResources []kyverno.ResourceSpec, processExisting bool, err error) {
|
||||
// Get the response as the actions to be performed on the resource
|
||||
// - - substitute values
|
||||
policy := policyContext.Policy
|
||||
|
@ -342,7 +336,7 @@ func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext
|
|||
}
|
||||
|
||||
if !processExisting {
|
||||
genResource, err = applyRule(log, c.client, rule, resource, jsonContext, policy.GetName(), gr)
|
||||
genResource, err = applyRule(log, c.client, rule, resource, jsonContext, policy.GetName(), ur)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to apply generate rule", "policy", policy.GetName(),
|
||||
"rule", rule.Name, "resource", resource.GetName(), "suggestion", "users need to grant Kyverno's service account additional privileges")
|
||||
|
@ -376,7 +370,7 @@ func getResourceInfo(object map[string]interface{}) (kind, name, namespace, apiv
|
|||
return
|
||||
}
|
||||
|
||||
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr urkyverno.UpdateRequest) (kyverno.ResourceSpec, error) {
|
||||
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, ur urkyverno.UpdateRequest) (kyverno.ResourceSpec, error) {
|
||||
var rdata map[string]interface{}
|
||||
var err error
|
||||
var mode ResourceMode
|
||||
|
@ -448,7 +442,7 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
// Add Synchronize label
|
||||
label := newResource.GetLabels()
|
||||
label["policy.kyverno.io/policy-name"] = policy
|
||||
label["policy.kyverno.io/gr-name"] = gr.Name
|
||||
label["policy.kyverno.io/gr-name"] = ur.Name
|
||||
delete(label, "generate.kyverno.io/clone-policy-name")
|
||||
if mode == Create {
|
||||
if rule.Generation.Synchronize {
|
||||
|
|
|
@ -15,9 +15,9 @@ func (c *Controller) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
|||
|
||||
case urkyverno.Generate:
|
||||
ctrl, _ := generate.NewGenerateController(c.kyvernoClient, c.client,
|
||||
c.policyLister, c.npolicyLister, c.grLister, c.urLister, c.eventGen, c.nsLister, c.log, c.Config,
|
||||
c.policyLister, c.npolicyLister, c.urLister, c.eventGen, c.nsLister, c.log, c.Config,
|
||||
)
|
||||
return ctrl.ProcessGR(ur)
|
||||
return ctrl.ProcessUR(ur)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -45,10 +45,10 @@ type Controller struct {
|
|||
// event generator interface
|
||||
eventGen event.Interface
|
||||
|
||||
// grStatusControl is used to update GR status
|
||||
// urStatusControl is used to update UR status
|
||||
statusControl common.StatusControlInterface
|
||||
|
||||
// GR that need to be synced
|
||||
// UR that need to be synced
|
||||
queue workqueue.RateLimitingInterface
|
||||
|
||||
// policyLister can list/get cluster policy from the shared informer's store
|
||||
|
@ -57,9 +57,6 @@ type Controller struct {
|
|||
// policyLister can list/get Namespace policy from the shared informer's store
|
||||
npolicyLister kyvernolister.PolicyLister
|
||||
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urlister.UpdateRequestNamespaceLister
|
||||
|
||||
|
@ -72,9 +69,6 @@ type Controller struct {
|
|||
// policySynced returns true if the Namespace policy store has been synced at least once
|
||||
npolicySynced cache.InformerSynced
|
||||
|
||||
// grSynced returns true if the Generate Request store has been synced at least once
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
// urSynced returns true if the Update Request store has been synced at least once
|
||||
urSynced cache.InformerSynced
|
||||
|
||||
|
@ -92,7 +86,6 @@ func NewController(
|
|||
client *dclient.Client,
|
||||
policyInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
npolicyInformer kyvernoinformer.PolicyInformer,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urkyvernoinformer.UpdateRequestInformer,
|
||||
eventGen event.Interface,
|
||||
namespaceInformer coreinformers.NamespaceInformer,
|
||||
|
@ -116,14 +109,6 @@ func NewController(
|
|||
|
||||
c.npolicySynced = npolicyInformer.Informer().HasSynced
|
||||
|
||||
c.grSynced = grInformer.Informer().HasSynced
|
||||
|
||||
grInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addGR,
|
||||
UpdateFunc: c.updateGR,
|
||||
DeleteFunc: c.deleteGR,
|
||||
})
|
||||
|
||||
c.urSynced = urInformer.Informer().HasSynced
|
||||
urInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addUR,
|
||||
|
@ -133,7 +118,6 @@ func NewController(
|
|||
|
||||
c.policyLister = policyInformer.Lister()
|
||||
c.npolicyLister = npolicyInformer.Lister()
|
||||
c.grLister = grInformer.Lister().GenerateRequests(config.KyvernoNamespace)
|
||||
c.urLister = urInformer.Lister().UpdateRequests(config.KyvernoNamespace)
|
||||
|
||||
c.nsLister = namespaceInformer.Lister()
|
||||
|
@ -148,7 +132,7 @@ func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
|||
defer c.queue.ShutDown()
|
||||
defer c.log.Info("shutting down")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, c.policySynced, c.grSynced, c.urSynced, c.npolicySynced, c.nsSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, c.policySynced, c.urSynced, c.npolicySynced, c.nsSynced) {
|
||||
c.log.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
@ -179,7 +163,7 @@ func (c *Controller) processNextWorkItem() bool {
|
|||
}
|
||||
|
||||
defer c.queue.Done(key)
|
||||
err := c.syncGenerateRequest(key.(string))
|
||||
err := c.syncUpdateRequest(key.(string))
|
||||
c.handleErr(err, key)
|
||||
return true
|
||||
}
|
||||
|
@ -193,53 +177,48 @@ func (c *Controller) handleErr(err error, key interface{}) {
|
|||
|
||||
if apierrors.IsNotFound(err) {
|
||||
c.queue.Forget(key)
|
||||
logger.V(4).Info("Dropping generate request from the queue", "key", key, "error", err.Error())
|
||||
logger.V(4).Info("Dropping update request from the queue", "key", key, "error", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if c.queue.NumRequeues(key) < maxRetries {
|
||||
logger.V(3).Info("retrying generate request", "key", key, "error", err.Error())
|
||||
logger.V(3).Info("retrying update request", "key", key, "error", err.Error())
|
||||
c.queue.AddRateLimited(key)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Error(err, "failed to process generate request", "key", key)
|
||||
logger.Error(err, "failed to process update request", "key", key)
|
||||
c.queue.Forget(key)
|
||||
}
|
||||
|
||||
func (c *Controller) syncGenerateRequest(key string) error {
|
||||
func (c *Controller) syncUpdateRequest(key string) error {
|
||||
logger := c.log
|
||||
var err error
|
||||
startTime := time.Now()
|
||||
logger.V(4).Info("started sync", "key", key, "startTime", startTime)
|
||||
defer func() {
|
||||
logger.V(4).Info("completed sync generate request", "key", key, "processingTime", time.Since(startTime).String())
|
||||
logger.V(4).Info("completed sync update request", "key", key, "processingTime", time.Since(startTime).String())
|
||||
}()
|
||||
|
||||
_, grName, err := cache.SplitMetaNamespaceKey(key)
|
||||
_, urName, err := cache.SplitMetaNamespaceKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gr, err := c.urLister.Get(grName)
|
||||
ur, err := c.urLister.Get(urName)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
logger.Error(err, "failed to fetch generate request", "key", key)
|
||||
logger.Error(err, "failed to fetch update request", "key", key)
|
||||
return err
|
||||
}
|
||||
|
||||
return c.ProcessUR(gr)
|
||||
return c.ProcessUR(ur)
|
||||
}
|
||||
|
||||
// EnqueueGenerateRequestFromWebhook - enqueueing generate requests from webhook
|
||||
func (c *Controller) EnqueueGenerateRequestFromWebhook(gr *kyverno.GenerateRequest) {
|
||||
c.enqueueGenerateRequest(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) enqueueGenerateRequest(obj interface{}) {
|
||||
func (c *Controller) enqueueUpdateRequest(obj interface{}) {
|
||||
key, err := cache.MetaNamespaceKeyFunc(obj)
|
||||
if err != nil {
|
||||
c.log.Error(err, "failed to extract name")
|
||||
|
@ -277,79 +256,22 @@ func (c *Controller) updatePolicy(old, cur interface{}) {
|
|||
|
||||
logger.V(4).Info("updating policy", "name", oldP.Name)
|
||||
|
||||
grs, err := c.urLister.GetUpdateRequestsForClusterPolicy(curP.Name)
|
||||
urs, err := c.urLister.GetUpdateRequestsForClusterPolicy(curP.Name)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to generate request for policy", "name", curP.Name)
|
||||
logger.Error(err, "failed to update request for policy", "name", curP.Name)
|
||||
return
|
||||
}
|
||||
|
||||
// re-evaluate the GR as the policy was updated
|
||||
for _, gr := range grs {
|
||||
gr.Spec.Context.AdmissionRequestInfo.Operation = admissionv1.Update
|
||||
c.enqueueGenerateRequest(gr)
|
||||
// re-evaluate the UR as the policy was updated
|
||||
for _, ur := range urs {
|
||||
ur.Spec.Context.AdmissionRequestInfo.Operation = admissionv1.Update
|
||||
c.enqueueUpdateRequest(ur)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) addGR(obj interface{}) {
|
||||
gr := obj.(*kyverno.GenerateRequest)
|
||||
c.enqueueGenerateRequest(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) updateGR(old, cur interface{}) {
|
||||
oldGr := old.(*kyverno.GenerateRequest)
|
||||
curGr := cur.(*kyverno.GenerateRequest)
|
||||
if oldGr.ResourceVersion == curGr.ResourceVersion {
|
||||
// Periodic resync will send update events for all known Namespace.
|
||||
// Two different versions of the same replica set will always have different RVs.
|
||||
return
|
||||
}
|
||||
// only process the ones that are in "Pending"/"Completed" state
|
||||
// if the Generate Request fails due to incorrect policy, it will be requeued during policy update
|
||||
if curGr.Status.State != kyverno.Pending {
|
||||
return
|
||||
}
|
||||
c.enqueueGenerateRequest(curGr)
|
||||
}
|
||||
|
||||
func (c *Controller) deleteGR(obj interface{}) {
|
||||
logger := c.log
|
||||
gr, ok := obj.(*kyverno.GenerateRequest)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
logger.Info("Couldn't get object from tombstone", "obj", obj)
|
||||
return
|
||||
}
|
||||
gr, ok = tombstone.Obj.(*kyverno.GenerateRequest)
|
||||
if !ok {
|
||||
logger.Info("tombstone contained object that is not a Generate Request CR", "obj", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
continue
|
||||
}
|
||||
|
||||
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.V(3).Info("deleting update request", "name", gr.Name)
|
||||
|
||||
// sync Handler will remove it from the queue
|
||||
c.enqueueGenerateRequest(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) addUR(obj interface{}) {
|
||||
ur := obj.(*urkyverno.UpdateRequest)
|
||||
c.enqueueGenerateRequest(ur)
|
||||
c.enqueueUpdateRequest(ur)
|
||||
}
|
||||
|
||||
func (c *Controller) updateUR(old, cur interface{}) {
|
||||
|
@ -361,31 +283,31 @@ func (c *Controller) updateUR(old, cur interface{}) {
|
|||
return
|
||||
}
|
||||
// only process the ones that are in "Pending"/"Completed" state
|
||||
// if the Generate Request fails due to incorrect policy, it will be requeued during policy update
|
||||
// if the UPDATE Request fails due to incorrect policy, it will be requeued during policy update
|
||||
if curUr.Status.State != urkyverno.Pending {
|
||||
return
|
||||
}
|
||||
c.enqueueGenerateRequest(curUr)
|
||||
c.enqueueUpdateRequest(curUr)
|
||||
}
|
||||
|
||||
func (c *Controller) deleteUR(obj interface{}) {
|
||||
logger := c.log
|
||||
gr, ok := obj.(*urkyverno.UpdateRequest)
|
||||
ur, ok := obj.(*urkyverno.UpdateRequest)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
logger.Info("Couldn't get object from tombstone", "obj", obj)
|
||||
return
|
||||
}
|
||||
gr, ok = tombstone.Obj.(*urkyverno.UpdateRequest)
|
||||
ur, ok = tombstone.Obj.(*urkyverno.UpdateRequest)
|
||||
if !ok {
|
||||
logger.Info("tombstone contained object that is not a Generate Request CR", "obj", obj)
|
||||
logger.Info("tombstone contained object that is not a Update Request CR", "obj", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if gr.Spec.GetRequestType() == urkyverno.Generate {
|
||||
for _, resource := range gr.Status.GeneratedResources {
|
||||
if ur.Spec.GetRequestType() == urkyverno.Generate {
|
||||
for _, resource := range ur.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)
|
||||
|
@ -399,9 +321,9 @@ func (c *Controller) deleteUR(obj interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
logger.V(3).Info("deleting update request", "name", gr.Name)
|
||||
logger.V(3).Info("deleting update request", "name", ur.Name)
|
||||
}
|
||||
|
||||
// sync Handler will remove it from the queue
|
||||
c.enqueueGenerateRequest(gr)
|
||||
c.enqueueUpdateRequest(ur)
|
||||
}
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
package backwardcompatibility
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
// AddLabels - adds labels to all the existing generate requests
|
||||
func AddLabels(client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer) {
|
||||
// Get all the GR's that are existing
|
||||
// Extract and Update all of them with the with the labels
|
||||
grList, err := grInformer.Lister().List(labels.NewSelector())
|
||||
if err != nil {
|
||||
log.Log.Error(err, "failed to get generate request list")
|
||||
return
|
||||
}
|
||||
|
||||
for _, gr := range grList {
|
||||
|
||||
grLabels := gr.Labels
|
||||
if len(grLabels) == 0 {
|
||||
grLabels = make(map[string]string)
|
||||
}
|
||||
grLabels[urkyverno.URGeneratePolicyLabel] = gr.Spec.Policy
|
||||
grLabels["generate.kyverno.io/resource-name"] = gr.Spec.Resource.Name
|
||||
grLabels["generate.kyverno.io/resource-kind"] = gr.Spec.Resource.Kind
|
||||
grLabels["generate.kyverno.io/resource-namespace"] = gr.Spec.Resource.Namespace
|
||||
|
||||
gr.SetLabels(grLabels)
|
||||
|
||||
_, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Update(context.TODO(), gr, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Log.V(4).Info(fmt.Sprintf("failed to update the GR %v. error: %v", gr.Name, err))
|
||||
for n := 0; n <= 3; n++ {
|
||||
log.Log.V(4).Info(fmt.Sprintf("retrying to get GR %v", gr.Name))
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
errInGettingGR := addLabelForGR(gr.Name, gr.Namespace, client, grInformer)
|
||||
if errInGettingGR != nil {
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addLabelForGR(name string, namespace string, client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer) error {
|
||||
gr, err := grInformer.Lister().GenerateRequests(namespace).Get(name)
|
||||
if err != nil {
|
||||
log.Log.Error(err, fmt.Sprintf("failed to update the GR %v", name))
|
||||
return err
|
||||
}
|
||||
|
||||
grLabels := gr.Labels
|
||||
if len(grLabels) == 0 {
|
||||
grLabels = make(map[string]string)
|
||||
}
|
||||
grLabels[urkyverno.URGeneratePolicyLabel] = gr.Spec.Policy
|
||||
grLabels["generate.kyverno.io/resource-name"] = gr.Spec.Resource.Name
|
||||
grLabels["generate.kyverno.io/resource-kind"] = gr.Spec.Resource.Kind
|
||||
grLabels["generate.kyverno.io/resource-namespace"] = gr.Spec.Resource.Namespace
|
||||
|
||||
gr.SetLabels(grLabels)
|
||||
|
||||
_, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Update(context.TODO(), gr, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Log.Error(err, fmt.Sprintf("failed to update the GR %v", gr.Name))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddCloneLabel - add label to the source resource about the new clone
|
||||
func AddCloneLabel(client *dclient.Client, pInformer kyvernoinformer.ClusterPolicyInformer) {
|
||||
// Get all the Generate Policies which has clone
|
||||
// Get the resource with Kind, NameSpace, Name
|
||||
// Add Policy name if label not found
|
||||
policies, err := pInformer.Lister().List(labels.NewSelector())
|
||||
if err != nil {
|
||||
log.Log.Error(err, "failed to get policies")
|
||||
return
|
||||
}
|
||||
|
||||
for _, policy := range policies {
|
||||
for _, rule := range autogen.ComputeRules(policy) {
|
||||
if rule.HasGenerate() {
|
||||
clone := rule.Generation.Clone
|
||||
if clone.Name != "" {
|
||||
namespace := clone.Namespace
|
||||
name := clone.Name
|
||||
kind := rule.Generation.Kind
|
||||
|
||||
obj, err := client.GetResource("", kind, namespace, name)
|
||||
if err != nil {
|
||||
log.Log.Error(err, fmt.Sprintf("source not found name:%v namespace:%v kind:%v", name, namespace, kind))
|
||||
continue
|
||||
}
|
||||
updateSource := true
|
||||
|
||||
// add label
|
||||
label := obj.GetLabels()
|
||||
if len(label) == 0 {
|
||||
label = make(map[string]string)
|
||||
label["generate.kyverno.io/clone-policy-name"] = policy.GetName()
|
||||
} else {
|
||||
if label["generate.kyverno.io/clone-policy-name"] != "" {
|
||||
policyNames := label["generate.kyverno.io/clone-policy-name"]
|
||||
if !strings.Contains(policyNames, policy.GetName()) {
|
||||
policyNames = policyNames + "," + policy.GetName()
|
||||
label["generate.kyverno.io/clone-policy-name"] = policyNames
|
||||
} else {
|
||||
updateSource = false
|
||||
}
|
||||
} else {
|
||||
label["generate.kyverno.io/clone-policy-name"] = policy.GetName()
|
||||
}
|
||||
}
|
||||
|
||||
if updateSource {
|
||||
log.Log.V(4).Info("updating existing clone source")
|
||||
obj.SetLabels(label)
|
||||
_, err = client.UpdateResource(obj.GetAPIVersion(), kind, namespace, obj, false)
|
||||
if err != nil {
|
||||
log.Log.Error(err, fmt.Sprintf("failed to update source name:%v namespace:%v kind:%v\n", obj.GetName(), obj.GetNamespace(), obj.GetKind()))
|
||||
return
|
||||
}
|
||||
log.Log.V(4).Info(fmt.Sprintf("updated source name:%v namespace:%v kind:%v\n", obj.GetName(), obj.GetNamespace(), obj.GetKind()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,9 +70,6 @@ type PolicyController struct {
|
|||
// npLister can list/get namespace policy from the shared informer's store
|
||||
npLister kyvernolister.PolicyLister
|
||||
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestLister
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urkyvernolister.UpdateRequestLister
|
||||
|
||||
|
@ -88,9 +85,6 @@ type PolicyController struct {
|
|||
// nsListerSynced returns true if the namespace store has been synced at least once
|
||||
nsListerSynced cache.InformerSynced
|
||||
|
||||
// grListerSynced returns true if the generate request store has been synced at least once
|
||||
grListerSynced cache.InformerSynced
|
||||
|
||||
// urListerSynced returns true if the update request store has been synced at least once
|
||||
urListerSynced cache.InformerSynced
|
||||
|
||||
|
@ -119,7 +113,6 @@ func NewPolicyController(
|
|||
client *client.Client,
|
||||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
npInformer kyvernoinformer.PolicyInformer,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urkyvernoinformer.UpdateRequestInformer,
|
||||
configHandler config.Interface,
|
||||
eventGen event.Interface,
|
||||
|
@ -160,14 +153,12 @@ func NewPolicyController(
|
|||
pc.npLister = npInformer.Lister()
|
||||
|
||||
pc.nsLister = namespaces.Lister()
|
||||
pc.grLister = grInformer.Lister()
|
||||
pc.urLister = urInformer.Lister()
|
||||
|
||||
pc.pListerSynced = pInformer.Informer().HasSynced
|
||||
pc.npListerSynced = npInformer.Informer().HasSynced
|
||||
|
||||
pc.nsListerSynced = namespaces.Informer().HasSynced
|
||||
pc.grListerSynced = grInformer.Informer().HasSynced
|
||||
pc.urListerSynced = urInformer.Informer().HasSynced
|
||||
|
||||
// resource manager
|
||||
|
@ -431,7 +422,7 @@ func (pc *PolicyController) Run(workers int, reconcileCh <-chan bool, stopCh <-c
|
|||
logger.Info("starting")
|
||||
defer logger.Info("shutting down")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.npListerSynced, pc.nsListerSynced, pc.grListerSynced, pc.urListerSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.npListerSynced, pc.nsListerSynced, pc.urListerSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package webhookconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
@ -198,17 +199,19 @@ func (wrc *Register) Check() error {
|
|||
// Remove removes all webhook configurations
|
||||
func (wrc *Register) Remove(cleanUp chan<- struct{}) {
|
||||
defer close(cleanUp)
|
||||
|
||||
// delete Lease object to let init container do the cleanup
|
||||
err := wrc.kubeClient.CoordinationV1().Leases(config.KyvernoNamespace).Delete(context.TODO(), "kyvernopre-lock", metav1.DeleteOptions{})
|
||||
if err != nil && errorsapi.IsNotFound(err) {
|
||||
wrc.log.WithName("cleanup").Error(err, "failed to clean up Lease lock")
|
||||
}
|
||||
|
||||
if !wrc.cleanupKyvernoResource() {
|
||||
return
|
||||
}
|
||||
|
||||
wrc.removeWebhookConfigurations()
|
||||
wrc.removeSecrets()
|
||||
err := wrc.client.DeleteResource("coordination.k8s.io/v1", "Lease", config.KyvernoNamespace, "kyvernopre-lock", false)
|
||||
if err != nil && errorsapi.IsNotFound(err) {
|
||||
wrc.log.WithName("cleanup").Error(err, "failed to clean up Lease lock")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// UpdateWebhookConfigurations updates resource webhook configurations dynamically
|
||||
|
@ -272,7 +275,7 @@ func (wrc *Register) ValidateWebhookConfigurations(namespace, name string) error
|
|||
return json.Unmarshal([]byte(webhooks), &webhookCfgs)
|
||||
}
|
||||
|
||||
// cleanupKyvernoResource returns true if Kyverno lease is terminating
|
||||
// cleanupKyvernoResource returns true if Kyverno is terminating
|
||||
func (wrc *Register) cleanupKyvernoResource() bool {
|
||||
logger := wrc.log.WithName("cleanupKyvernoResource")
|
||||
deploy, err := wrc.client.GetResource("", "Deployment", config.KyvernoNamespace, config.KyvernoDeploymentName)
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
backoff "github.com/cenkalti/backoff"
|
||||
"github.com/gardener/controller-manager-library/pkg/logger"
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenerateRequests provides interface to manage generate requests
|
||||
type GenerateRequests interface {
|
||||
Apply(gr kyverno.GenerateRequestSpec, action admissionv1.Operation) error
|
||||
}
|
||||
|
||||
// GeneratorChannel ...
|
||||
type GeneratorChannel struct {
|
||||
spec urkyverno.UpdateRequestSpec
|
||||
action admissionv1.Operation
|
||||
}
|
||||
|
||||
// Generator defines the implementation to mange generate request resource
|
||||
type Generator struct {
|
||||
// channel to receive request
|
||||
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
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urkyvernolister.UpdateRequestNamespaceLister
|
||||
urSynced cache.InformerSynced
|
||||
}
|
||||
|
||||
// NewGenerator returns a new instance of Generate-Request resource generator
|
||||
func NewGenerator(client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer, urInformer urkyvernoinformer.UpdateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
|
||||
gen := &Generator{
|
||||
client: client,
|
||||
stopCh: stopCh,
|
||||
log: log,
|
||||
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
|
||||
grSynced: grInformer.Informer().HasSynced,
|
||||
urLister: urInformer.Lister().UpdateRequests(config.KyvernoNamespace),
|
||||
urSynced: urInformer.Informer().HasSynced,
|
||||
}
|
||||
return gen
|
||||
}
|
||||
|
||||
// Apply creates generate request resource (blocking call if channel is full)
|
||||
func (g *Generator) Apply(gr urkyverno.UpdateRequestSpec, action admissionv1.Operation) error {
|
||||
logger := g.log
|
||||
logger.V(4).Info("creating Generate Request", "request", gr)
|
||||
|
||||
// Update to channel
|
||||
message := GeneratorChannel{
|
||||
action: action,
|
||||
spec: gr,
|
||||
}
|
||||
go g.processApply(message)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Generator) processApply(m GeneratorChannel) {
|
||||
if err := g.generate(m.spec, m.action); err != nil {
|
||||
logger.Error(err, "failed to generate request CR")
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) generate(grSpec urkyverno.UpdateRequestSpec, action admissionv1.Operation) error {
|
||||
// create/update a generate request
|
||||
|
||||
if err := retryApplyResource(g.client, grSpec, g.log, action, g.grLister, g.urLister); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// -> receiving channel to take requests to create request
|
||||
// use worker pattern to read and create the CR resource
|
||||
|
||||
func retryApplyResource(client *kyvernoclient.Clientset, grSpec urkyverno.UpdateRequestSpec,
|
||||
log logr.Logger, action admissionv1.Operation, grLister kyvernolister.GenerateRequestNamespaceLister,
|
||||
urLister urkyvernolister.UpdateRequestNamespaceLister) error {
|
||||
|
||||
var i int
|
||||
var err error
|
||||
|
||||
_, policyName, err := cache.SplitMetaNamespaceKey(grSpec.Policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
applyResource := func() error {
|
||||
gr := urkyverno.UpdateRequest{
|
||||
Spec: grSpec,
|
||||
}
|
||||
|
||||
gr.SetNamespace(config.KyvernoNamespace)
|
||||
// Initial state "Pending"
|
||||
// generate requests created in kyverno namespace
|
||||
isExist := false
|
||||
if action == admissionv1.Create || action == admissionv1.Update {
|
||||
log.V(4).Info("querying all generate requests")
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: policyName,
|
||||
"generate.kyverno.io/resource-name": grSpec.Resource.Name,
|
||||
"generate.kyverno.io/resource-kind": grSpec.Resource.Kind,
|
||||
"generate.kyverno.io/resource-namespace": grSpec.Resource.Namespace,
|
||||
}))
|
||||
grList, err := urLister.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 _, v := range grList {
|
||||
|
||||
grLabels := gr.Labels
|
||||
if len(grLabels) == 0 {
|
||||
grLabels = make(map[string]string)
|
||||
}
|
||||
grLabels["resources-update"] = "true"
|
||||
gr.SetLabels(grLabels)
|
||||
v.Spec.Context = gr.Spec.Context
|
||||
v.Spec.Policy = gr.Spec.Policy
|
||||
v.Spec.Resource = gr.Spec.Resource
|
||||
|
||||
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), v, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
new.Status.State = urkyverno.Pending
|
||||
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
|
||||
logger.Error(err, "failed to set UpdateRequest state to Pending")
|
||||
}
|
||||
|
||||
isExist = true
|
||||
}
|
||||
|
||||
if !isExist {
|
||||
gr.SetGenerateName("gr-")
|
||||
gr.SetLabels(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: policyName,
|
||||
"generate.kyverno.io/resource-name": grSpec.Resource.Name,
|
||||
"generate.kyverno.io/resource-kind": grSpec.Resource.Kind,
|
||||
"generate.kyverno.io/resource-namespace": grSpec.Resource.Namespace,
|
||||
})
|
||||
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), &gr, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
new.Status.State = urkyverno.Pending
|
||||
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
|
||||
logger.Error(err, "failed to set UpdateRequest state to Pending")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
log.V(4).Info("retrying update generate request CR", "retryCount", i, "name", gr.GetGenerateName(), "namespace", gr.GetNamespace())
|
||||
i++
|
||||
return err
|
||||
}
|
||||
|
||||
exbackoff := &backoff.ExponentialBackOff{
|
||||
InitialInterval: 500 * time.Millisecond,
|
||||
RandomizationFactor: 0.5,
|
||||
Multiplier: 1.5,
|
||||
MaxInterval: time.Second,
|
||||
MaxElapsedTime: 3 * time.Second,
|
||||
Clock: backoff.SystemClock,
|
||||
}
|
||||
|
||||
exbackoff.Reset()
|
||||
err = backoff.Retry(applyResource, exbackoff)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -75,10 +75,10 @@ func (ws *WebhookServer) handleGenerate(
|
|||
go ws.registerPolicyExecutionDurationMetricGenerate(logger, string(request.Operation), policy, *engineResponse)
|
||||
}
|
||||
|
||||
if failedResponse := applyGenerateRequest(request, urkyverno.Generate, ws.grGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
if failedResponse := applyUpdateRequest(request, urkyverno.Generate, ws.urGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
// report failure event
|
||||
for _, failedGR := range failedResponse {
|
||||
events := failedEvents(fmt.Errorf("failed to create Generate Request: %v", failedGR.err), failedGR.gr, policyContext.NewResource)
|
||||
for _, failedUR := range failedResponse {
|
||||
events := failedEvents(fmt.Errorf("failed to create Update Request: %v", failedUR.err), failedUR.ur, policyContext.NewResource)
|
||||
ws.eventGen.Add(events...)
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (ws *WebhookServer) handleUpdateGenerateSourceResource(resLabels map[string
|
|||
_, err := ws.kyvernoClient.KyvernoV1().ClusterPolicies().Get(contextdefault.TODO(), policyName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not found") {
|
||||
logger.V(4).Info("skipping update of generate request as policy is deleted")
|
||||
logger.V(4).Info("skipping update of update request as policy is deleted")
|
||||
} else {
|
||||
logger.Error(err, "failed to get generate policy", "Name", policyName)
|
||||
}
|
||||
|
@ -135,46 +135,46 @@ func (ws *WebhookServer) handleUpdateGenerateSourceResource(resLabels map[string
|
|||
urkyverno.URGeneratePolicyLabel: policyName,
|
||||
}))
|
||||
|
||||
grList, err := ws.urLister.List(selector)
|
||||
urList, err := ws.urLister.List(selector)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request for the resource", "label", urkyverno.URGeneratePolicyLabel)
|
||||
logger.Error(err, "failed to get update request for the resource", "label", urkyverno.URGeneratePolicyLabel)
|
||||
return
|
||||
}
|
||||
|
||||
for _, gr := range grList {
|
||||
ws.updateAnnotationInGR(gr, logger)
|
||||
for _, ur := range urList {
|
||||
ws.updateAnnotationInUR(ur, logger)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// updateAnnotationInGR - function used to update GR annotation
|
||||
// updating GR will trigger reprocessing of GR and recreation/updation of generated resource
|
||||
func (ws *WebhookServer) updateAnnotationInGR(gr *urkyverno.UpdateRequest, logger logr.Logger) {
|
||||
grAnnotations := gr.Annotations
|
||||
if len(grAnnotations) == 0 {
|
||||
grAnnotations = make(map[string]string)
|
||||
// updateAnnotationInUR - function used to update UR annotation
|
||||
// updating UR will trigger reprocessing of UR and recreation/updation of generated resource
|
||||
func (ws *WebhookServer) updateAnnotationInUR(ur *urkyverno.UpdateRequest, logger logr.Logger) {
|
||||
urAnnotations := ur.Annotations
|
||||
if len(urAnnotations) == 0 {
|
||||
urAnnotations = make(map[string]string)
|
||||
}
|
||||
ws.mu.Lock()
|
||||
grAnnotations["generate.kyverno.io/updation-time"] = time.Now().String()
|
||||
gr.SetAnnotations(grAnnotations)
|
||||
urAnnotations["generate.kyverno.io/updation-time"] = time.Now().String()
|
||||
ur.SetAnnotations(urAnnotations)
|
||||
ws.mu.Unlock()
|
||||
|
||||
patch := jsonutils.NewPatch(
|
||||
"/metadata/annotations",
|
||||
"replace",
|
||||
gr.Annotations,
|
||||
ur.Annotations,
|
||||
)
|
||||
|
||||
new, err := gencommon.PatchGenerateRequest(gr, patch, ws.kyvernoClient)
|
||||
new, err := gencommon.PatchUpdateRequest(ur, patch, ws.kyvernoClient)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update generate request update-time annotations for the resource", "generate request", gr.Name)
|
||||
logger.Error(err, "failed to update update request update-time annotations for the resource", "update request", ur.Name)
|
||||
return
|
||||
}
|
||||
new.Status.State = urkyverno.Pending
|
||||
if _, err := ws.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(contextdefault.TODO(), new, metav1.UpdateOptions{}); err != nil {
|
||||
logger.Error(err, "failed to set UpdateRequest state to Pending", "update request", gr.Name)
|
||||
logger.Error(err, "failed to set UpdateRequest state to Pending", "update request", ur.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,13 +230,13 @@ func (ws *WebhookServer) handleUpdateGenerateTargetResource(request *admissionv1
|
|||
}
|
||||
|
||||
if enqueueBool {
|
||||
grName := resLabels["policy.kyverno.io/gr-name"]
|
||||
gr, err := ws.urLister.Get(grName)
|
||||
urName := resLabels["policy.kyverno.io/gr-name"]
|
||||
ur, err := ws.urLister.Get(urName)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request", "name", grName)
|
||||
logger.Error(err, "failed to get update request", "name", urName)
|
||||
return
|
||||
}
|
||||
ws.updateAnnotationInGR(gr, logger)
|
||||
ws.updateAnnotationInUR(ur, logger)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,22 +346,22 @@ func (ws *WebhookServer) handleDelete(request *admissionv1.AdmissionRequest) {
|
|||
|
||||
resLabels := resource.GetLabels()
|
||||
if resLabels["app.kubernetes.io/managed-by"] == "kyverno" && request.Operation == admissionv1.Delete {
|
||||
grName := resLabels["policy.kyverno.io/gr-name"]
|
||||
gr, err := ws.urLister.Get(grName)
|
||||
urName := resLabels["policy.kyverno.io/gr-name"]
|
||||
ur, err := ws.urLister.Get(urName)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request", "name", grName)
|
||||
logger.Error(err, "failed to get update request", "name", urName)
|
||||
return
|
||||
}
|
||||
|
||||
if gr.Spec.Type == urkyverno.Mutate {
|
||||
if ur.Spec.Type == urkyverno.Mutate {
|
||||
return
|
||||
}
|
||||
ws.updateAnnotationInGR(gr, logger)
|
||||
ws.updateAnnotationInUR(ur, logger)
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse *response.EngineResponse) {
|
||||
logger.V(4).Info("querying all generate requests")
|
||||
logger.V(4).Info("querying all update requests")
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
urkyverno.URGeneratePolicyLabel: engineResponse.PolicyResponse.Policy.Name,
|
||||
"generate.kyverno.io/resource-name": engineResponse.PolicyResponse.Resource.Name,
|
||||
|
@ -369,22 +369,22 @@ func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse *response.E
|
|||
"generate.kyverno.io/resource-namespace": engineResponse.PolicyResponse.Resource.Namespace,
|
||||
}))
|
||||
|
||||
grList, err := ws.urLister.List(selector)
|
||||
urList, err := ws.urLister.List(selector)
|
||||
if err != nil {
|
||||
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)
|
||||
logger.Error(err, "failed to get update request for the resource", "kind", engineResponse.PolicyResponse.Resource.Kind, "name", engineResponse.PolicyResponse.Resource.Name, "namespace", engineResponse.PolicyResponse.Resource.Namespace)
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range grList {
|
||||
for _, v := range urList {
|
||||
err := ws.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update gr")
|
||||
logger.Error(err, "failed to update ur")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyGenerateRequest(request *admissionv1.AdmissionRequest, ruleType urkyverno.RequestType, gnGenerator updaterequest.Interface, userRequestInfo urkyverno.RequestInfo,
|
||||
action admissionv1.Operation, engineResponses ...*response.EngineResponse) (failedGenerateRequest []generateRequestResponse) {
|
||||
func applyUpdateRequest(request *admissionv1.AdmissionRequest, ruleType urkyverno.RequestType, grGenerator updaterequest.Interface, userRequestInfo urkyverno.RequestInfo,
|
||||
action admissionv1.Operation, engineResponses ...*response.EngineResponse) (failedUpdateRequest []updateRequestResponse) {
|
||||
|
||||
requestBytes, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
|
@ -396,9 +396,9 @@ func applyGenerateRequest(request *admissionv1.AdmissionRequest, ruleType urkyve
|
|||
}
|
||||
|
||||
for _, er := range engineResponses {
|
||||
gr := transform(admissionRequestInfo, userRequestInfo, er, ruleType)
|
||||
if err := gnGenerator.Apply(gr, action); err != nil {
|
||||
failedGenerateRequest = append(failedGenerateRequest, generateRequestResponse{gr: gr, err: err})
|
||||
ur := transform(admissionRequestInfo, userRequestInfo, er, ruleType)
|
||||
if err := grGenerator.Apply(ur, action); err != nil {
|
||||
failedUpdateRequest = append(failedUpdateRequest, updateRequestResponse{ur: ur, err: err})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,7 +413,7 @@ func transform(admissionRequestInfo urkyverno.AdmissionRequestInfoObject, userRe
|
|||
PolicyNameNamespaceKey = er.PolicyResponse.Policy.Name
|
||||
}
|
||||
|
||||
gr := urkyverno.UpdateRequestSpec{
|
||||
ur := urkyverno.UpdateRequestSpec{
|
||||
Type: ruleType,
|
||||
Policy: PolicyNameNamespaceKey,
|
||||
Resource: kyverno.ResourceSpec{
|
||||
|
@ -428,30 +428,22 @@ func transform(admissionRequestInfo urkyverno.AdmissionRequestInfoObject, userRe
|
|||
},
|
||||
}
|
||||
|
||||
return gr
|
||||
return ur
|
||||
}
|
||||
|
||||
type generateRequestResponse struct {
|
||||
gr urkyverno.UpdateRequestSpec
|
||||
type updateRequestResponse struct {
|
||||
ur urkyverno.UpdateRequestSpec
|
||||
err error
|
||||
}
|
||||
|
||||
func (resp generateRequestResponse) info() string {
|
||||
return strings.Join([]string{resp.gr.Resource.Kind, resp.gr.Resource.Namespace, resp.gr.Resource.Name}, "/")
|
||||
}
|
||||
|
||||
func (resp generateRequestResponse) error() string {
|
||||
return resp.err.Error()
|
||||
}
|
||||
|
||||
func failedEvents(err error, gr urkyverno.UpdateRequestSpec, resource unstructured.Unstructured) []event.Info {
|
||||
func failedEvents(err error, ur urkyverno.UpdateRequestSpec, resource unstructured.Unstructured) []event.Info {
|
||||
re := event.Info{}
|
||||
re.Kind = resource.GetKind()
|
||||
re.Namespace = resource.GetNamespace()
|
||||
re.Name = resource.GetName()
|
||||
re.Reason = event.PolicyFailed.String()
|
||||
re.Source = event.GeneratePolicyController
|
||||
re.Message = fmt.Sprintf("policy %s failed to apply: %v", gr.Policy, err)
|
||||
re.Message = fmt.Sprintf("policy %s failed to apply: %v", ur.Policy, err)
|
||||
|
||||
return []event.Info{re}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urlister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
|
@ -45,12 +44,6 @@ 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
|
||||
|
||||
// urLister can list/get update requests from the shared informer's store
|
||||
urLister urlister.UpdateRequestNamespaceLister
|
||||
|
||||
|
@ -105,8 +98,8 @@ type WebhookServer struct {
|
|||
// policy report generator
|
||||
prGenerator policyreport.GeneratorInterface
|
||||
|
||||
// generate request generator
|
||||
grGenerator webhookgenerate.Interface
|
||||
// update request generator
|
||||
urGenerator webhookgenerate.Interface
|
||||
|
||||
nsLister listerv1.NamespaceLister
|
||||
|
||||
|
@ -119,7 +112,7 @@ type WebhookServer struct {
|
|||
|
||||
openAPIController *openapi.Controller
|
||||
|
||||
grController *background.Controller
|
||||
urController *background.Controller
|
||||
|
||||
promConfig *metrics.PromConfig
|
||||
|
||||
|
@ -132,7 +125,6 @@ func NewWebhookServer(
|
|||
kyvernoClient *kyvernoclient.Clientset,
|
||||
client *client.Client,
|
||||
tlsPair *tlsutils.PemPair,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urinformer.UpdateRequestInformer,
|
||||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
rbInformer rbacinformer.RoleBindingInformer,
|
||||
|
@ -146,12 +138,12 @@ func NewWebhookServer(
|
|||
webhookMonitor *webhookconfig.Monitor,
|
||||
configHandler config.Interface,
|
||||
prGenerator policyreport.GeneratorInterface,
|
||||
grGenerator webhookgenerate.Interface,
|
||||
urGenerator webhookgenerate.Interface,
|
||||
auditHandler AuditHandler,
|
||||
cleanUp chan<- struct{},
|
||||
log logr.Logger,
|
||||
openAPIController *openapi.Controller,
|
||||
grc *background.Controller,
|
||||
urc *background.Controller,
|
||||
promConfig *metrics.PromConfig,
|
||||
) (*WebhookServer, error) {
|
||||
if tlsPair == nil {
|
||||
|
@ -164,8 +156,6 @@ func NewWebhookServer(
|
|||
ws := &WebhookServer{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
|
||||
grSynced: grInformer.Informer().HasSynced,
|
||||
urLister: urInformer.Lister().UpdateRequests(config.KyvernoNamespace),
|
||||
urSynced: urInformer.Informer().HasSynced,
|
||||
pSynced: pInformer.Informer().HasSynced,
|
||||
|
@ -186,8 +176,8 @@ func NewWebhookServer(
|
|||
cleanUp: cleanUp,
|
||||
webhookMonitor: webhookMonitor,
|
||||
prGenerator: prGenerator,
|
||||
grGenerator: grGenerator,
|
||||
grController: grc,
|
||||
urGenerator: urGenerator,
|
||||
urController: urc,
|
||||
auditHandler: auditHandler,
|
||||
log: log,
|
||||
openAPIController: openAPIController,
|
||||
|
@ -265,7 +255,7 @@ func (ws *WebhookServer) buildPolicyContext(request *admissionv1.AdmissionReques
|
|||
|
||||
// RunAsync TLS server in separate thread and returns control immediately
|
||||
func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
|
||||
if !cache.WaitForCacheSync(stopCh, ws.grSynced, ws.urSynced, ws.pSynced, ws.rbSynced, ws.crbSynced, ws.rSynced, ws.crSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, ws.urSynced, ws.pSynced, ws.rbSynced, ws.crbSynced, ws.rSynced, ws.crSynced) {
|
||||
ws.log.Info("failed to sync informer cache")
|
||||
}
|
||||
go func() {
|
||||
|
|
|
@ -58,9 +58,9 @@ func (ws *WebhookServer) handleMutateExisting(request *admissionv1.AdmissionRequ
|
|||
go ws.registerPolicyExecutionDurationMetricMutate(logger, string(request.Operation), policy, *engineResponse)
|
||||
}
|
||||
|
||||
if failedResponse := applyGenerateRequest(request, urkyverno.Mutate, ws.grGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
for _, failedGR := range failedResponse {
|
||||
events := failedEvents(fmt.Errorf("failed to create update request: %v", failedGR.err), failedGR.gr, policyContext.NewResource)
|
||||
if failedResponse := applyUpdateRequest(request, urkyverno.Mutate, ws.urGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
for _, failedUR := range failedResponse {
|
||||
events := failedEvents(fmt.Errorf("failed to create update request: %v", failedUR.err), failedUR.ur, policyContext.NewResource)
|
||||
ws.eventGen.Add(events...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,7 @@ import (
|
|||
"github.com/go-logr/logr"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
|
@ -21,7 +19,7 @@ import (
|
|||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenerateRequests provides interface to manage update requests
|
||||
// UpdateRequest provides interface to manage update requests
|
||||
type Interface interface {
|
||||
Apply(gr urkyverno.UpdateRequestSpec, action admissionv1.Operation) error
|
||||
}
|
||||
|
@ -37,22 +35,17 @@ 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
|
||||
|
||||
urLister urkyvernolister.UpdateRequestNamespaceLister
|
||||
urSynced cache.InformerSynced
|
||||
}
|
||||
|
||||
// NewGenerator returns a new instance of UpdateRequest resource generator
|
||||
func NewGenerator(client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer, urInformer urkyvernoinformer.UpdateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
|
||||
func NewGenerator(client *kyvernoclient.Clientset, urInformer urkyvernoinformer.UpdateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
|
||||
gen := &Generator{
|
||||
client: client,
|
||||
stopCh: stopCh,
|
||||
log: log,
|
||||
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
|
||||
grSynced: grInformer.Informer().HasSynced,
|
||||
urLister: urInformer.Lister().UpdateRequests(config.KyvernoNamespace),
|
||||
urSynced: urInformer.Informer().HasSynced,
|
||||
}
|
||||
|
@ -60,13 +53,13 @@ func NewGenerator(client *kyvernoclient.Clientset, grInformer kyvernoinformer.Ge
|
|||
}
|
||||
|
||||
// Apply creates update request resource
|
||||
func (g *Generator) Apply(gr urkyverno.UpdateRequestSpec, action admissionv1.Operation) error {
|
||||
func (g *Generator) Apply(ur urkyverno.UpdateRequestSpec, action admissionv1.Operation) error {
|
||||
logger := g.log
|
||||
logger.V(4).Info("reconcile Update Request", "request", gr)
|
||||
logger.V(4).Info("reconcile Update Request", "request", ur)
|
||||
|
||||
message := info{
|
||||
action: action,
|
||||
spec: gr,
|
||||
spec: ur,
|
||||
}
|
||||
go g.processApply(message)
|
||||
return nil
|
||||
|
@ -82,7 +75,7 @@ func (g *Generator) Run(workers int, stopCh <-chan struct{}) {
|
|||
logger.V(4).Info("shutting down")
|
||||
}()
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, g.grSynced, g.urSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, g.urSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ func Test_Mutate_Existing(t *testing.T) {
|
|||
for _, test := range mutateExistingTests {
|
||||
By(fmt.Sprintf("\nStart Mutate Existing Tests: %s", test.TestDescription))
|
||||
|
||||
By("======Cleaning up resources======")
|
||||
By("\nCleaning up resources")
|
||||
By("Deleting Cluster Policies...")
|
||||
e2eClient.CleanClusterPolicies(policyGVR)
|
||||
|
||||
|
@ -363,7 +363,7 @@ func Test_Mutate_Existing(t *testing.T) {
|
|||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("======Done cleaning up resources======")
|
||||
By("Done cleaning up resources\n")
|
||||
|
||||
By(fmt.Sprintf("Creating target Namespace: %s...", test.TargetNamespace))
|
||||
_, err = e2eClient.CreateClusteredResourceYaml(namespaceGVR, newNamespaceYaml(test.TargetNamespace))
|
||||
|
@ -575,7 +575,7 @@ func Test_Mutate_Existing(t *testing.T) {
|
|||
By(err.Error())
|
||||
}
|
||||
|
||||
By("Done")
|
||||
By("Done\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue