diff --git a/cmd/initContainer/main.go b/cmd/initContainer/main.go index 63cc67aba9..aaf6ee8fce 100644 --- a/cmd/initContainer/main.go +++ b/cmd/initContainer/main.go @@ -10,15 +10,16 @@ import ( "sync" "time" - kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned" "github.com/kyverno/kyverno/pkg/config" client "github.com/kyverno/kyverno/pkg/dclient" "github.com/kyverno/kyverno/pkg/leaderelection" + "github.com/kyverno/kyverno/pkg/policyreport" "github.com/kyverno/kyverno/pkg/signal" "github.com/kyverno/kyverno/pkg/utils" coord "k8s.io/api/coordination/v1" "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/klog/v2" "k8s.io/klog/v2/klogr" "sigs.k8s.io/controller-runtime/pkg/log" @@ -29,6 +30,16 @@ var ( setupLog = log.Log.WithName("setup") clientRateLimitQPS float64 clientRateLimitBurst int + + updateLabelSelector = &v1.LabelSelector{ + MatchExpressions: []v1.LabelSelectorRequirement{ + { + Key: policyreport.LabelSelectorKey, + Operator: v1.LabelSelectorOpDoesNotExist, + Values: []string{}, + }, + }, + } ) const ( @@ -70,17 +81,6 @@ func main() { os.Exit(1) } - pclientConfig, err := config.CreateClientConfig(kubeconfig, clientRateLimitQPS, clientRateLimitBurst, log.Log) - if err != nil { - setupLog.Error(err, "Failed to build client config") - os.Exit(1) - } - pclient, err := kyvernoclient.NewForConfig(pclientConfig) - if err != nil { - setupLog.Error(err, "Failed to create client") - os.Exit(1) - } - // Exit for unsupported version of kubernetes cluster if !utils.HigherThanKubernetesVersion(client, log.Log, 1, 16, 0) { os.Exit(1) @@ -111,6 +111,9 @@ func main() { cancel() }() + addPolicyReportSelectorLabel(client) + addClusterPolicyReportSelectorLabel(client) + done := make(chan struct{}) defer close(done) failure := false @@ -130,8 +133,8 @@ func main() { in := gen(done, stopCh, requests...) // process requests // processing routine count : 2 - p1 := process(client, pclient, done, stopCh, in) - p2 := process(client, pclient, done, stopCh, in) + p1 := process(client, done, stopCh, in) + p2 := process(client, done, stopCh, in) // merge results from processing routines for err := range merge(done, stopCh, p1, p2) { if err != nil { @@ -166,10 +169,10 @@ func main() { le.Run(ctx) } -func executeRequest(client *client.Client, pclient *kyvernoclient.Clientset, req request) error { +func executeRequest(client *client.Client, req request) error { switch req.kind { case policyReportKind: - return removePolicyReport(client, pclient, req.kind) + return removePolicyReport(client, req.kind) case clusterPolicyReportKind: return removeClusterPolicyReport(client, req.kind) case reportChangeRequestKind: @@ -217,14 +220,14 @@ func gen(done <-chan struct{}, stopCh <-chan struct{}, requests ...request) <-ch } // processes the requests -func process(client *client.Client, pclient *kyvernoclient.Clientset, done <-chan struct{}, stopCh <-chan struct{}, requests <-chan request) <-chan error { +func process(client *client.Client, 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, pclient, req): + case out <- executeRequest(client, req): case <-done: logger.Info("done") return @@ -274,7 +277,7 @@ func merge(done <-chan struct{}, stopCh <-chan struct{}, processes ...<-chan err func removeClusterPolicyReport(client *client.Client, kind string) error { logger := log.Log.WithName("removeClusterPolicyReport") - cpolrs, err := client.ListResource("", kind, "", nil) + cpolrs, err := client.ListResource("", kind, "", policyreport.LabelSelector) if err != nil { logger.Error(err, "failed to list clusterPolicyReport") return nil @@ -286,26 +289,54 @@ func removeClusterPolicyReport(client *client.Client, kind string) error { return nil } -func removePolicyReport(client *client.Client, pclient *kyvernoclient.Clientset, kind string) error { +func removePolicyReport(client *client.Client, kind string) error { logger := log.Log.WithName("removePolicyReport") - namespaces, err := client.ListResource("", "Namespace", "", nil) + polrs, err := client.ListResource("", kind, v1.NamespaceAll, policyreport.LabelSelector) if err != nil { - logger.Error(err, "failed to list namespaces") - return err + logger.Error(err, "failed to list policyReport") + return nil } - for _, ns := range namespaces.Items { - logger.Info("Removing policy reports", "namespace", ns.GetName()) - err := pclient.Wgpolicyk8sV1alpha2().PolicyReports(ns.GetName()).DeleteCollection(context.TODO(), v1.DeleteOptions{}, v1.ListOptions{}) - if err != nil { - logger.Error(err, "Failed to delete policy reports", "namespace", ns.GetName()) - } + for _, polr := range polrs.Items { + deleteResource(client, polr.GetAPIVersion(), polr.GetKind(), polr.GetNamespace(), polr.GetName()) } return nil } +func addClusterPolicyReportSelectorLabel(client *client.Client) { + logger := log.Log.WithName("addClusterPolicyReportSelectorLabel") + + cpolrs, err := client.ListResource("", clusterPolicyReportKind, "", updateLabelSelector) + if err != nil { + logger.Error(err, "failed to list clusterPolicyReport") + return + } + + for _, cpolr := range cpolrs.Items { + if cpolr.GetName() == policyreport.GeneratePolicyReportName("") { + addSelectorLabel(client, cpolr.GetAPIVersion(), cpolr.GetKind(), "", cpolr.GetName()) + } + } +} + +func addPolicyReportSelectorLabel(client *client.Client) { + logger := log.Log.WithName("addPolicyReportSelectorLabel") + + polrs, err := client.ListResource("", policyReportKind, v1.NamespaceAll, updateLabelSelector) + if err != nil { + logger.Error(err, "failed to list policyReport") + return + } + + for _, polr := range polrs.Items { + if polr.GetName() == policyreport.GeneratePolicyReportName(polr.GetNamespace()) { + addSelectorLabel(client, polr.GetAPIVersion(), polr.GetKind(), polr.GetNamespace(), polr.GetName()) + } + } +} + func removeReportChangeRequest(client *client.Client, kind string) error { logger := log.Log.WithName("removeReportChangeRequest") @@ -369,3 +400,27 @@ func deleteResource(client *client.Client, apiversion, kind, ns, name string) { log.Log.Info("successfully cleaned up resource", "kind", kind, "name", name) } + +func addSelectorLabel(client *client.Client, apiversion, kind, ns, name string) { + res, err := client.GetResource(apiversion, kind, ns, name) + if err != nil && !errors.IsNotFound(err) { + log.Log.Error(err, "failed to get resource", "kind", kind, "name", name) + return + } + + l, err := v1.LabelSelectorAsMap(policyreport.LabelSelector) + if err != nil { + log.Log.Error(err, "failed to convert labels", "labels", policyreport.LabelSelector) + return + } + + res.SetLabels(labels.Merge(res.GetLabels(), l)) + + _, err = client.UpdateResource(apiversion, kind, ns, res, false) + if err != nil { + log.Log.Error(err, "failed to update resource", "kind", kind, "name", name) + return + } + + log.Log.Info("successfully updated resource labels", "kind", kind, "name", name) +} diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go index cbf4de60f3..51c88488fd 100755 --- a/cmd/kyverno/main.go +++ b/cmd/kyverno/main.go @@ -214,7 +214,6 @@ func main() { ) prgen, err := policyreport.NewReportGenerator( - kubeClient, pclient, client, pInformer.Wgpolicyk8s().V1alpha2().ClusterPolicyReports(), diff --git a/pkg/policy/report.go b/pkg/policy/report.go index 33f4d3d135..46f6e985ab 100644 --- a/pkg/policy/report.go +++ b/pkg/policy/report.go @@ -100,9 +100,14 @@ func cleanupReportChangeRequests(pclient *kyvernoclient.Clientset, rcrLister cha } func eraseResultsEntries(pclient *kyvernoclient.Clientset, reportLister policyreportlister.PolicyReportLister, clusterReportLister policyreportlister.ClusterPolicyReportLister) error { + selector, err := metav1.LabelSelectorAsSelector(policyreport.LabelSelector) + if err != nil { + return fmt.Errorf("failed to erase results entries %v", err) + } + var errors []string - if polrs, err := reportLister.List(labels.Everything()); err != nil { + if polrs, err := reportLister.List(selector); err != nil { errors = append(errors, err.Error()) } else { for _, polr := range polrs { @@ -114,7 +119,7 @@ func eraseResultsEntries(pclient *kyvernoclient.Clientset, reportLister policyre } } - if cpolrs, err := clusterReportLister.List(labels.Everything()); err != nil { + if cpolrs, err := clusterReportLister.List(selector); err != nil { errors = append(errors, err.Error()) } else { for _, cpolr := range cpolrs { diff --git a/pkg/policyreport/builder.go b/pkg/policyreport/builder.go index 495a642bb8..fd8139d5e2 100755 --- a/pkg/policyreport/builder.go +++ b/pkg/policyreport/builder.go @@ -40,7 +40,7 @@ const ( SourceValue = "Kyverno" ) -func generatePolicyReportName(ns string) string { +func GeneratePolicyReportName(ns string) string { if ns == "" { return clusterpolicyreport } diff --git a/pkg/policyreport/reportcontroller.go b/pkg/policyreport/reportcontroller.go index aae1905857..76cf83492c 100644 --- a/pkg/policyreport/reportcontroller.go +++ b/pkg/policyreport/reportcontroller.go @@ -19,7 +19,6 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" informers "k8s.io/client-go/informers/core/v1" - "k8s.io/client-go/kubernetes" listerv1 "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -37,8 +36,17 @@ import ( const ( prWorkQueueName = "policy-report-controller" clusterpolicyreport = "clusterpolicyreport" + + LabelSelectorKey = "managed-by" + LabelSelectorValue = "kyverno" ) +var LabelSelector = &metav1.LabelSelector{ + MatchLabels: map[string]string{ + LabelSelectorKey: LabelSelectorValue, + }, +} + // ReportGenerator creates policy report type ReportGenerator struct { pclient *kyvernoclient.Clientset @@ -75,7 +83,6 @@ type ReportGenerator struct { // NewReportGenerator returns a new instance of policy report generator func NewReportGenerator( - kubeClient kubernetes.Interface, pclient *kyvernoclient.Clientset, dclient *dclient.Client, clusterReportInformer policyreportinformer.ClusterPolicyReportInformer, @@ -372,7 +379,7 @@ func (g *ReportGenerator) createReportIfNotPresent(namespace string, new *unstru return nil, nil } - report, err = g.reportLister.PolicyReports(namespace).Get(generatePolicyReportName(namespace)) + report, err = g.reportLister.PolicyReports(namespace).Get(GeneratePolicyReportName(namespace)) if err != nil { if apierrors.IsNotFound(err) && new != nil { if _, err := g.dclient.CreateResource(new.GetAPIVersion(), new.GetKind(), new.GetNamespace(), new, false); err != nil { @@ -387,7 +394,7 @@ func (g *ReportGenerator) createReportIfNotPresent(namespace string, new *unstru return nil, fmt.Errorf("unable to get policyReport: %v", err) } } else { - report, err = g.clusterReportLister.Get(generatePolicyReportName(namespace)) + report, err = g.clusterReportLister.Get(GeneratePolicyReportName(namespace)) if err != nil { if apierrors.IsNotFound(err) { if new != nil { @@ -465,9 +472,10 @@ func (g *ReportGenerator) removeFromPolicyReport(policyName, ruleName string) er return fmt.Errorf("unable to list namespace %v", err) } + selector, err := metav1.LabelSelectorAsSelector(LabelSelector) policyReports := []*report.PolicyReport{} for _, ns := range namespaces.Items { - reports, err := g.reportLister.PolicyReports(ns.GetName()).List(labels.Everything()) + reports, err := g.reportLister.PolicyReports(ns.GetName()).List(selector) if err != nil { return fmt.Errorf("unable to list policyReport for namespace %s %v", ns.GetName(), err) } @@ -601,14 +609,15 @@ func mergeRequests(ns *v1.Namespace, requestsGeneral interface{}) (*unstructured func setReport(reportUnstructured *unstructured.Unstructured, ns *v1.Namespace) { reportUnstructured.SetAPIVersion(report.SchemeGroupVersion.String()) + reportUnstructured.SetLabels(LabelSelector.MatchLabels) if ns == nil { - reportUnstructured.SetName(generatePolicyReportName("")) + reportUnstructured.SetName(GeneratePolicyReportName("")) reportUnstructured.SetKind("ClusterPolicyReport") return } - reportUnstructured.SetName(generatePolicyReportName(ns.GetName())) + reportUnstructured.SetName(GeneratePolicyReportName(ns.GetName())) reportUnstructured.SetNamespace(ns.GetName()) reportUnstructured.SetKind("PolicyReport")