mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
Add SelectorLabel to (Cluster)PolicyReporter resources (#2841)
Signed-off-by: Frank Jogeleit <frank.jogeleit@lovoo.com> Co-authored-by: shuting <shutting06@gmail.com>
This commit is contained in:
parent
f4614213e5
commit
abb5bd2947
5 changed files with 108 additions and 40 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -214,7 +214,6 @@ func main() {
|
|||
)
|
||||
|
||||
prgen, err := policyreport.NewReportGenerator(
|
||||
kubeClient,
|
||||
pclient,
|
||||
client,
|
||||
pInformer.Wgpolicyk8s().V1alpha2().ClusterPolicyReports(),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -40,7 +40,7 @@ const (
|
|||
SourceValue = "Kyverno"
|
||||
)
|
||||
|
||||
func generatePolicyReportName(ns string) string {
|
||||
func GeneratePolicyReportName(ns string) string {
|
||||
if ns == "" {
|
||||
return clusterpolicyreport
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue