1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

Add SelectorLabel to (Cluster)PolicyReporter resources ()

Signed-off-by: Frank Jogeleit <frank.jogeleit@lovoo.com>

Co-authored-by: shuting <shutting06@gmail.com>
This commit is contained in:
Frank Jogeleit 2021-12-17 06:03:52 +01:00 committed by GitHub
parent f4614213e5
commit abb5bd2947
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 40 deletions
cmd
initContainer
kyverno
pkg

View file

@ -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)
}

View file

@ -214,7 +214,6 @@ func main() {
)
prgen, err := policyreport.NewReportGenerator(
kubeClient,
pclient,
client,
pInformer.Wgpolicyk8s().V1alpha2().ClusterPolicyReports(),

View file

@ -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 {

View file

@ -40,7 +40,7 @@ const (
SourceValue = "Kyverno"
)
func generatePolicyReportName(ns string) string {
func GeneratePolicyReportName(ns string) string {
if ns == "" {
return clusterpolicyreport
}

View file

@ -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")