mirror of
https://github.com/kyverno/policy-reporter.git
synced 2024-12-14 11:57:32 +00:00
Update Event process logic (#162)
* Update Event process logic Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>
This commit is contained in:
parent
b6150c30c4
commit
0509aeb75e
66 changed files with 859 additions and 843 deletions
|
@ -3,6 +3,8 @@
|
|||
# 2.9.4
|
||||
* Policy Reporter
|
||||
* Add [AWS Kinesis](https://aws.amazon.com/kinesis) compatible target
|
||||
* Add new Helm value `profiling.enabled` to enable pprof profiling, disabled by default
|
||||
* Improved Informer handling
|
||||
|
||||
# 2.9.3
|
||||
* Policy Reporter
|
||||
|
|
|
@ -59,6 +59,7 @@ spec:
|
|||
- --dbfile=/sqlite/database.db
|
||||
- --metrics-enabled={{ or .Values.metrics.enabled .Values.monitoring.enabled }}
|
||||
- --rest-enabled={{ or .Values.rest.enabled .Values.ui.enabled }}
|
||||
- --profile={{ .Values.profiling.enabled }}
|
||||
ports:
|
||||
- name: {{ .Values.port.name }}
|
||||
containerPort: {{ .Values.port.number }}
|
||||
|
|
|
@ -109,6 +109,9 @@ metrics:
|
|||
# status:
|
||||
# exclude: ["pass", "skip"]
|
||||
|
||||
profiling:
|
||||
enabled: false
|
||||
|
||||
# Filter PolicyReport resources to process
|
||||
reportFilter:
|
||||
namespaces:
|
||||
|
|
20
cmd/run.go
20
cmd/run.go
|
@ -1,8 +1,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"log"
|
||||
|
||||
|
@ -34,8 +32,6 @@ func newRunCMD() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
resolver := config.NewResolver(c, k8sConfig)
|
||||
|
||||
client, err := resolver.PolicyReportClient()
|
||||
|
@ -43,12 +39,12 @@ func newRunCMD() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
server := resolver.APIServer(client.HasSynced)
|
||||
|
||||
resolver.RegisterSendResultListener()
|
||||
|
||||
g := &errgroup.Group{}
|
||||
|
||||
server := resolver.APIServer(client.GetFoundResources())
|
||||
|
||||
if c.REST.Enabled {
|
||||
db, err := resolver.Database()
|
||||
if err != nil {
|
||||
|
@ -79,13 +75,13 @@ func newRunCMD() *cobra.Command {
|
|||
|
||||
g.Go(server.Start)
|
||||
|
||||
g.Go(func() error {
|
||||
eventChan := client.WatchPolicyReports(ctx)
|
||||
stop := make(chan struct{})
|
||||
defer close(stop)
|
||||
|
||||
resolver.EventPublisher().Publish(eventChan)
|
||||
|
||||
return errors.New("event publisher stoped")
|
||||
})
|
||||
err = client.Run(stop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return g.Wait()
|
||||
},
|
||||
|
|
35
go.mod
35
go.mod
|
@ -3,19 +3,20 @@ module github.com/kyverno/policy-reporter
|
|||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.44.27
|
||||
github.com/aws/aws-sdk-go v1.44.39
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/kyverno/kyverno v1.7.0
|
||||
github.com/kyverno/kyverno v1.7.1
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
github.com/minio/pkg v1.1.24
|
||||
github.com/minio/pkg v1.1.26
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/prometheus/client_golang v1.12.2
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/spf13/cobra v1.4.0
|
||||
github.com/segmentio/fasthash v1.0.3
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/viper v1.12.0
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f
|
||||
k8s.io/apimachinery v0.24.1
|
||||
k8s.io/client-go v0.24.1
|
||||
k8s.io/apimachinery v0.24.2
|
||||
k8s.io/client-go v0.24.2
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -23,6 +24,7 @@ require (
|
|||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
|
@ -45,14 +47,14 @@ require (
|
|||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/spf13/afero v1.8.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
|
@ -60,28 +62,27 @@ require (
|
|||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/klog/v2 v2.60.1 // indirect
|
||||
k8s.io/klog/v2 v2.70.0 // indirect
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/emicklei/go-restful v2.15.0+incompatible // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||
github.com/google/gnostic v0.6.9 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/prometheus/common v0.34.0 // indirect
|
||||
github.com/prometheus/common v0.35.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.0 // indirect
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 // indirect
|
||||
golang.org/x/net v0.0.0-20220621193019-9d032be2e588 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect
|
||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
k8s.io/api v0.24.1
|
||||
k8s.io/apiextensions-apiserver v0.24.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6 // indirect
|
||||
k8s.io/api v0.24.2
|
||||
k8s.io/apiextensions-apiserver v0.24.2 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220621154418-c39d0f63fac8 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.12.1 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect
|
||||
)
|
||||
|
|
79
go.sum
79
go.sum
|
@ -68,8 +68,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
|
|||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/aws/aws-sdk-go v1.44.27 h1:8CMspeZSrewnbvAwgl8qo5R7orDLwQnTGBf/OKPiHxI=
|
||||
github.com/aws/aws-sdk-go v1.44.27/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.44.39 h1:pMxYLqnuDidT0ZTDAhYC66fb3W3Yc+oShmfzEL4fTDI=
|
||||
github.com/aws/aws-sdk-go v1.44.39/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
|
@ -107,6 +107,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
|||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -121,8 +122,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
|||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.15.0+incompatible h1:8KpYO/Xl/ZudZs5RNOEhWMBY4hmzlZhhRd9cu+jrZP4=
|
||||
github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
|
||||
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
|
@ -337,8 +338,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kyverno/go-wildcard v1.0.4 h1:uoIWLnywcLED/nXeNVDj4U7OvNW1O3N4+emC5gK90ug=
|
||||
github.com/kyverno/go-wildcard v1.0.4/go.mod h1:sZkBvzy+au8C1uiqOH+SdN4psOL+0nhfWgsZzzJKwbs=
|
||||
github.com/kyverno/kyverno v1.7.0 h1:gp+t1ThTAMmXF1jcEie+ZHvLnOuwwRS6Upq5KzS52z4=
|
||||
github.com/kyverno/kyverno v1.7.0/go.mod h1:4twhW8CcubmLZ7lQF4+1pYXYTn0GJIiBUyHxsdl86mM=
|
||||
github.com/kyverno/kyverno v1.7.1 h1:YykyefFmlET8uYrQvOw+/Ki//9RmERcz8BwNPhQabZ8=
|
||||
github.com/kyverno/kyverno v1.7.1/go.mod h1:4twhW8CcubmLZ7lQF4+1pYXYTn0GJIiBUyHxsdl86mM=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
|
@ -355,8 +356,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
|
|||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/pkg v1.1.24 h1:a2RCb6LgsCi9DvrripuvlFQRCNb5Hp1HIssnsUqLoZY=
|
||||
github.com/minio/pkg v1.1.24/go.mod h1:z9PfmEI804KFkF6eY4LoGe8IDVvTCsYGVuaf58Dr0WI=
|
||||
github.com/minio/pkg v1.1.26 h1:a8x4sHNBxCiHEkxZ/0EBTLqvV3nMtM2G/A6lXNfXN3U=
|
||||
github.com/minio/pkg v1.1.26/go.mod h1:z9PfmEI804KFkF6eY4LoGe8IDVvTCsYGVuaf58Dr0WI=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
|
@ -403,8 +404,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK
|
|||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||
github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw=
|
||||
github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -435,8 +436,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
|||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.34.0 h1:RBmGO9d/FVjqHT0yUGQwBJhkwKV+wPCn7KGpvfab0uE=
|
||||
github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE=
|
||||
github.com/prometheus/common v0.35.0 h1:Eyr+Pw2VymWejHqCugNaQXkAi6KayVNxaHeu6khmFBE=
|
||||
github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
|
@ -453,6 +454,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
|||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
|
||||
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
@ -473,8 +476,9 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
|
|||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
|
||||
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
|
||||
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
|
@ -493,8 +497,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs=
|
||||
github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo=
|
||||
|
@ -649,8 +653,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
|
||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220621193019-9d032be2e588 h1:9ubFuySsnAJYGyJrZ3koiEv8FyqofCBdz3G9Mbf2YFc=
|
||||
golang.org/x/net v0.0.0-20220621193019-9d032be2e588/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -665,8 +669,8 @@ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ
|
|||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 h1:zwrSfklXn0gxyLRX/aR+q6cgHbV/ItVyzbPlbA+dkAw=
|
||||
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb h1:8tDJ3aechhddbdPAxpycgXHJRMLpk/Ab+aa4OgdN5/g=
|
||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -747,8 +751,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM=
|
||||
|
@ -768,8 +772,8 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
|
||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -992,26 +996,27 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY=
|
||||
k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ=
|
||||
k8s.io/apiextensions-apiserver v0.24.1 h1:5yBh9+ueTq/kfnHQZa0MAo6uNcPrtxPMpNQgorBaKS0=
|
||||
k8s.io/apiextensions-apiserver v0.24.1/go.mod h1:A6MHfaLDGfjOc/We2nM7uewD5Oa/FnEbZ6cD7g2ca4Q=
|
||||
k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I=
|
||||
k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
|
||||
k8s.io/apiserver v0.24.1/go.mod h1:dQWNMx15S8NqJMp0gpYfssyvhYnkilc1LpExd/dkLh0=
|
||||
k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E=
|
||||
k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8=
|
||||
k8s.io/code-generator v0.24.1/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=
|
||||
k8s.io/component-base v0.24.1/go.mod h1:DW5vQGYVCog8WYpNob3PMmmsY8A3L9QZNg4j/dV3s38=
|
||||
k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI=
|
||||
k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg=
|
||||
k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k=
|
||||
k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ=
|
||||
k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM=
|
||||
k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
|
||||
k8s.io/apiserver v0.24.2/go.mod h1:pSuKzr3zV+L+MWqsEo0kHHYwCo77AT5qXbFXP2jbvFI=
|
||||
k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA=
|
||||
k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=
|
||||
k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=
|
||||
k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM=
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
|
||||
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/klog/v2 v2.70.0 h1:GMmmjoFOrNepPN0ZeGCzvD2Gh5IKRwdFx8W5PBxVTQU=
|
||||
k8s.io/klog/v2 v2.70.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
|
||||
k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6 h1:nBQrWPlrNIiw0BsX6a6MKr1itkm0ZS0Nl97kNLitFfI=
|
||||
k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6/go.mod h1:daOouuuwd9JXpv1L7Y34iV3yf6nxzipkKMWWlqlvK9M=
|
||||
k8s.io/kube-openapi v0.0.0-20220621154418-c39d0f63fac8 h1:30P0UV8MQgg4f1khIUT09xHmpI5B5Wg0Vg6JNkUqsQ0=
|
||||
k8s.io/kube-openapi v0.0.0-20220621154418-c39d0f63fac8/go.mod h1:PNbiP2hKArDh8cgJZTDL6Ss/z3wsbga8yjj/7VMB+I4=
|
||||
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
|
|
|
@ -147,7 +147,7 @@ spec:
|
|||
fsGroup: 1234
|
||||
containers:
|
||||
- name: policy-reporter
|
||||
image: "ghcr.io/kyverno/policy-reporter:2.6.1"
|
||||
image: "ghcr.io/kyverno/policy-reporter:2.6.2"
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
|
|
|
@ -259,7 +259,7 @@ spec:
|
|||
fsGroup: 1234
|
||||
containers:
|
||||
- name: policy-reporter
|
||||
image: "ghcr.io/kyverno/policy-reporter:2.6.1"
|
||||
image: "ghcr.io/kyverno/policy-reporter:2.6.2"
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
|
|
|
@ -85,7 +85,7 @@ spec:
|
|||
automountServiceAccountToken: true
|
||||
containers:
|
||||
- name: policy-reporter
|
||||
image: "ghcr.io/kyverno/policy-reporter:2.6.1"
|
||||
image: "ghcr.io/kyverno/policy-reporter:2.6.2"
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
|
|
|
@ -2,20 +2,17 @@ package api
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HealthzHandler for the Halthz REST API
|
||||
func HealthzHandler(found map[string]string) http.HandlerFunc {
|
||||
func HealthzHandler(synced func() bool) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
if len(found) == 0 {
|
||||
if !synced() {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
|
||||
log.Println("[WARNING] - Healthz Check: No policyreport.wgpolicyk8s.io and clusterpolicyreport.wgpolicyk8s.io crds are found")
|
||||
|
||||
fmt.Fprint(w, `{ "error": "No PolicyReport CRDs found" }`)
|
||||
fmt.Fprint(w, `{ "error": "Informers not in sync" }`)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -28,8 +25,17 @@ func HealthzHandler(found map[string]string) http.HandlerFunc {
|
|||
}
|
||||
|
||||
// ReadyHandler for the Halthz REST API
|
||||
func ReadyHandler() http.HandlerFunc {
|
||||
func ReadyHandler(synced func() bool) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
if !synced() {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
|
||||
fmt.Fprint(w, `{ "error": "Informers not in sync" }`)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, "{}")
|
||||
|
|
|
@ -16,7 +16,7 @@ func Test_HealthzAPI(t *testing.T) {
|
|||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := api.HealthzHandler(map[string]string{"wgpolicyk8s.io/v1alpha2": "wgpolicyk8s.io/v1alpha2"})
|
||||
handler := api.HealthzHandler(func() bool { return true })
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
|
@ -24,15 +24,14 @@ func Test_HealthzAPI(t *testing.T) {
|
|||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Unavailable Respose", func(t *testing.T) {
|
||||
t.Run("Unavailable Response", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/healthz", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := api.HealthzHandler(map[string]string{})
|
||||
handler := api.HealthzHandler(func() bool { return false })
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
|
@ -43,14 +42,14 @@ func Test_HealthzAPI(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_ReadyAPI(t *testing.T) {
|
||||
t.Run("Success Respose", func(t *testing.T) {
|
||||
t.Run("Success Response", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/ready", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := api.ReadyHandler()
|
||||
handler := api.ReadyHandler(func() bool { return true })
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
|
@ -58,4 +57,19 @@ func Test_ReadyAPI(t *testing.T) {
|
|||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
})
|
||||
t.Run("Unavailable Response", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "/ready", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler := api.ReadyHandler(func() bool { return false })
|
||||
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if status := rr.Code; status != http.StatusServiceUnavailable {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusServiceUnavailable)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -32,12 +32,12 @@ type httpServer struct {
|
|||
http http.Server
|
||||
mux *http.ServeMux
|
||||
targets []target.Client
|
||||
foundResources map[string]string
|
||||
synced func() bool
|
||||
}
|
||||
|
||||
func (s *httpServer) RegisterLifecycleHandler() {
|
||||
s.mux.HandleFunc("/healthz", HealthzHandler(s.foundResources))
|
||||
s.mux.HandleFunc("/ready", ReadyHandler())
|
||||
s.mux.HandleFunc("/healthz", HealthzHandler(s.synced))
|
||||
s.mux.HandleFunc("/ready", ReadyHandler(s.synced))
|
||||
}
|
||||
|
||||
func (s *httpServer) RegisterV1Handler(finder v1.PolicyReportFinder) {
|
||||
|
@ -84,13 +84,13 @@ func (s *httpServer) Shutdown(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// NewServer constructor for a new API Server
|
||||
func NewServer(targets []target.Client, port int, foundResources map[string]string) Server {
|
||||
func NewServer(targets []target.Client, port int, synced func() bool) Server {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
s := &httpServer{
|
||||
targets: targets,
|
||||
synced: synced,
|
||||
mux: mux,
|
||||
foundResources: foundResources,
|
||||
http: http.Server{
|
||||
Addr: fmt.Sprintf(":%d", port),
|
||||
Handler: mux,
|
||||
|
|
|
@ -20,7 +20,7 @@ func Test_NewServer(t *testing.T) {
|
|||
|
||||
port := int(rnd * 10000)
|
||||
|
||||
server := api.NewServer(make([]target.Client, 0), port, make(map[string]string))
|
||||
server := api.NewServer(make([]target.Client, 0), port, func() bool { return true })
|
||||
|
||||
server.RegisterMetricsHandler()
|
||||
server.RegisterV1Handler(nil)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/loki"
|
||||
)
|
||||
|
||||
var result1 = &report.Result{
|
||||
var result1 = report.Result{
|
||||
ID: "123",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -25,7 +25,7 @@ var result1 = &report.Result{
|
|||
Severity: report.High,
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -34,7 +34,7 @@ var result1 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var result2 = &report.Result{
|
||||
var result2 = report.Result{
|
||||
ID: "124",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -44,7 +44,7 @@ var result2 = &report.Result{
|
|||
Category: "Best Practices",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Name: "nginx",
|
||||
|
@ -53,7 +53,7 @@ var result2 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var cresult1 = &report.Result{
|
||||
var cresult1 = report.Result{
|
||||
ID: "125",
|
||||
Message: "validation error: The label `test` is required. Rule check-for-labels-on-namespace",
|
||||
Policy: "require-ns-labels",
|
||||
|
@ -64,7 +64,7 @@ var cresult1 = &report.Result{
|
|||
Severity: report.Medium,
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Namespace",
|
||||
Name: "test",
|
||||
|
@ -72,7 +72,7 @@ var cresult1 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var cresult2 = &report.Result{
|
||||
var cresult2 = report.Result{
|
||||
ID: "126",
|
||||
Message: "validation error: The label `test` is required. Rule check-for-labels-on-namespace",
|
||||
Policy: "require-ns-labels",
|
||||
|
@ -83,7 +83,7 @@ var cresult2 = &report.Result{
|
|||
Severity: report.High,
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Namespace",
|
||||
Name: "dev",
|
||||
|
@ -91,26 +91,20 @@ var cresult2 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var preport = &report.PolicyReport{
|
||||
var preport = report.PolicyReport{
|
||||
ID: report.GeneratePolicyReportID("polr-test", "test"),
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
result2.GetIdentifier(): result2,
|
||||
},
|
||||
Summary: &report.Summary{Fail: 1},
|
||||
Results: []report.Result{result1, result2},
|
||||
Summary: report.Summary{Fail: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
var creport = &report.PolicyReport{
|
||||
var creport = report.PolicyReport{
|
||||
ID: report.GeneratePolicyReportID("cpolr", ""),
|
||||
Name: "cpolr",
|
||||
Results: map[string]*report.Result{
|
||||
cresult1.GetIdentifier(): cresult1,
|
||||
cresult2.GetIdentifier(): cresult2,
|
||||
},
|
||||
Summary: &report.Summary{},
|
||||
Results: []report.Result{cresult1, cresult2},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
|
|
|
@ -46,11 +46,11 @@ type Resolver struct {
|
|||
}
|
||||
|
||||
// APIServer resolver method
|
||||
func (r *Resolver) APIServer(foundResources map[string]string) api.Server {
|
||||
func (r *Resolver) APIServer(synced func() bool) api.Server {
|
||||
return api.NewServer(
|
||||
r.TargetClients(),
|
||||
r.config.API.Port,
|
||||
foundResources,
|
||||
synced,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -386,7 +386,7 @@ func (r *Resolver) PolicyReportClient() (report.PolicyReportClient, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
r.policyReportClient = kubernetes.NewPolicyReportClient(client, r.Mapper(), 5*time.Second, r.ReportFilter())
|
||||
r.policyReportClient = kubernetes.NewPolicyReportClient(client, r.Mapper(), r.ReportFilter(), r.EventPublisher())
|
||||
|
||||
return r.policyReportClient, nil
|
||||
}
|
||||
|
|
|
@ -84,6 +84,16 @@ var testConfig = &config.Config{
|
|||
Prefix: "prefix",
|
||||
Channels: []config.S3{{}},
|
||||
},
|
||||
Kinesis: config.Kinesis{
|
||||
AccessKeyID: "AccessKey",
|
||||
SecretAccessKey: "SecretAccessKey",
|
||||
StreamName: "policy-reporter",
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
Endpoint: "https://yds.serverless.yandexcloud.net",
|
||||
Region: "ru-central1",
|
||||
Channels: []config.Kinesis{{}},
|
||||
},
|
||||
}
|
||||
|
||||
func Test_ResolveTarget(t *testing.T) {
|
||||
|
@ -132,13 +142,19 @@ func Test_ResolveTarget(t *testing.T) {
|
|||
t.Errorf("Expected 2 Client, got %d clients", len(clients))
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis", func(t *testing.T) {
|
||||
clients := resolver.KinesisClients()
|
||||
if len(clients) != 2 {
|
||||
t.Errorf("Expected 2 Client, got %d clients", len(clients))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ResolveTargets(t *testing.T) {
|
||||
resolver := config.NewResolver(testConfig, nil)
|
||||
|
||||
clients := resolver.TargetClients()
|
||||
if count := len(clients); count != 15 {
|
||||
if count := len(clients); count != 17 {
|
||||
t.Errorf("Expected 15 Clients, got %d", count)
|
||||
}
|
||||
}
|
||||
|
@ -221,6 +237,15 @@ func Test_ResolveTargetWithoutHost(t *testing.T) {
|
|||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
},
|
||||
Kinesis: config.Kinesis{
|
||||
Endpoint: "",
|
||||
Region: "",
|
||||
AccessKeyID: "",
|
||||
SecretAccessKey: "",
|
||||
StreamName: "",
|
||||
SkipExisting: true,
|
||||
MinimumPriority: "debug",
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("Loki", func(t *testing.T) {
|
||||
|
@ -281,15 +306,6 @@ func Test_ResolveTargetWithoutHost(t *testing.T) {
|
|||
t.Error("Expected Client to be nil if no accessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.AccessKey", func(t *testing.T) {
|
||||
config2.S3.Endpoint = "https://storage.yandexcloud.net"
|
||||
|
||||
resolver := config.NewResolver(config2, nil)
|
||||
|
||||
if len(resolver.S3Clients()) != 0 {
|
||||
t.Error("Expected Client to be nil if no accessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.SecretAccessKey", func(t *testing.T) {
|
||||
config2.S3.AccessKeyID = "access"
|
||||
|
||||
|
@ -317,6 +333,49 @@ func Test_ResolveTargetWithoutHost(t *testing.T) {
|
|||
t.Error("Expected Client to be nil if no bucket is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.Endoint", func(t *testing.T) {
|
||||
resolver := config.NewResolver(config2, nil)
|
||||
|
||||
if len(resolver.KinesisClients()) != 0 {
|
||||
t.Error("Expected Client to be nil if no endpoint is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.AccessKey", func(t *testing.T) {
|
||||
config2.Kinesis.Endpoint = "https://yds.serverless.yandexcloud.net"
|
||||
|
||||
resolver := config.NewResolver(config2, nil)
|
||||
|
||||
if len(resolver.KinesisClients()) != 0 {
|
||||
t.Error("Expected Client to be nil if no accessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.SecretAccessKey", func(t *testing.T) {
|
||||
config2.Kinesis.AccessKeyID = "access"
|
||||
|
||||
resolver := config.NewResolver(config2, nil)
|
||||
|
||||
if len(resolver.KinesisClients()) != 0 {
|
||||
t.Error("Expected Client to be nil if no secretAccessKey is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.Region", func(t *testing.T) {
|
||||
config2.Kinesis.SecretAccessKey = "secret"
|
||||
|
||||
resolver := config.NewResolver(config2, nil)
|
||||
|
||||
if len(resolver.KinesisClients()) != 0 {
|
||||
t.Error("Expected Client to be nil if no region is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Kinesis.StreamName", func(t *testing.T) {
|
||||
config2.Kinesis.Region = "ru-central1"
|
||||
|
||||
resolver := config.NewResolver(config2, nil)
|
||||
|
||||
if len(resolver.KinesisClients()) != 0 {
|
||||
t.Error("Expected Client to be nil if no bucket is configured")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ResolvePolicyClient(t *testing.T) {
|
||||
|
@ -352,7 +411,7 @@ func Test_ResolvePolicyStore(t *testing.T) {
|
|||
func Test_ResolveAPIServer(t *testing.T) {
|
||||
resolver := config.NewResolver(&config.Config{}, &rest.Config{})
|
||||
|
||||
server := resolver.APIServer(make(map[string]string))
|
||||
server := resolver.APIServer(func() bool { return true })
|
||||
if server == nil {
|
||||
t.Error("Error: Should return API Server")
|
||||
}
|
||||
|
|
|
@ -9,13 +9,12 @@ import (
|
|||
|
||||
type Debouncer interface {
|
||||
Add(e report.LifecycleEvent)
|
||||
ReportGroups() *report.Group
|
||||
}
|
||||
|
||||
type debouncer struct {
|
||||
waitDuration time.Duration
|
||||
events map[string]report.LifecycleEvent
|
||||
channel *report.Group
|
||||
publisher report.EventPublisher
|
||||
mutx *sync.Mutex
|
||||
}
|
||||
|
||||
|
@ -27,14 +26,8 @@ func (d *debouncer) Add(event report.LifecycleEvent) {
|
|||
d.mutx.Unlock()
|
||||
}
|
||||
|
||||
if event.Type == report.Added {
|
||||
d.channel.Register(event.NewPolicyReport.ID)
|
||||
d.channel.AddEvent(event)
|
||||
return
|
||||
}
|
||||
|
||||
if event.Type == report.Deleted {
|
||||
d.channel.AddEvent(event)
|
||||
if event.Type == report.Added || event.Type == report.Deleted {
|
||||
d.publisher.Publish(event)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -48,7 +41,7 @@ func (d *debouncer) Add(event report.LifecycleEvent) {
|
|||
|
||||
d.mutx.Lock()
|
||||
if event, ok := d.events[event.NewPolicyReport.GetIdentifier()]; ok {
|
||||
d.channel.AddEvent(event)
|
||||
d.publisher.Publish(event)
|
||||
delete(d.events, event.NewPolicyReport.GetIdentifier())
|
||||
}
|
||||
d.mutx.Unlock()
|
||||
|
@ -66,18 +59,14 @@ func (d *debouncer) Add(event report.LifecycleEvent) {
|
|||
return
|
||||
}
|
||||
|
||||
d.channel.AddEvent(event)
|
||||
d.publisher.Publish(event)
|
||||
}
|
||||
|
||||
func (d *debouncer) ReportGroups() *report.Group {
|
||||
return d.channel
|
||||
}
|
||||
|
||||
func NewDebouncer(waitDuration time.Duration) Debouncer {
|
||||
func NewDebouncer(waitDuration time.Duration, publisher report.EventPublisher) Debouncer {
|
||||
return &debouncer{
|
||||
waitDuration: waitDuration,
|
||||
events: make(map[string]report.LifecycleEvent),
|
||||
mutx: new(sync.Mutex),
|
||||
channel: report.NewGroup(),
|
||||
publisher: publisher,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,23 +11,17 @@ import (
|
|||
|
||||
func Test_Debouncer(t *testing.T) {
|
||||
t.Run("Skip Empty Update", func(t *testing.T) {
|
||||
debouncer := kubernetes.NewDebouncer(200 * time.Millisecond)
|
||||
|
||||
counter := 0
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
go func() {
|
||||
group := debouncer.ReportGroups()
|
||||
reportID := <-group.ChannelAdded()
|
||||
eventChan, _ := group.Listen(reportID)
|
||||
|
||||
for event := range eventChan {
|
||||
publisher := report.NewEventPublisher()
|
||||
publisher.RegisterListener(func(event report.LifecycleEvent) {
|
||||
counter++
|
||||
wg.Done()
|
||||
if len(event.NewPolicyReport.Results) == 0 {
|
||||
t.Error("Expected to skip the empty modify event")
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
debouncer := kubernetes.NewDebouncer(200*time.Millisecond, publisher)
|
||||
|
||||
debouncer.Add(report.LifecycleEvent{
|
||||
Type: report.Added,
|
||||
|
@ -48,6 +42,8 @@ func Test_Debouncer(t *testing.T) {
|
|||
|
||||
wg.Wait()
|
||||
|
||||
debouncer.ReportGroups().CloseAll()
|
||||
if counter != 2 {
|
||||
t.Error("Expected to skip the empty modify event")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -118,6 +118,50 @@ var policyReportCRD = &v1alpha2.PolicyReport{
|
|||
},
|
||||
}
|
||||
|
||||
var multiResourcePolicyReportCRD = &v1alpha2.PolicyReport{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "policy-report",
|
||||
Namespace: "test",
|
||||
},
|
||||
Summary: v1alpha2.PolicyReportSummary{
|
||||
Pass: 1,
|
||||
Skip: 2,
|
||||
Warn: 3,
|
||||
Fail: 4,
|
||||
Error: 5,
|
||||
},
|
||||
Results: []v1alpha2.PolicyReportResult{
|
||||
{
|
||||
Message: "message",
|
||||
Result: v1alpha2.StatusFail,
|
||||
Scored: true,
|
||||
Policy: "required-label",
|
||||
Rule: "app-label-required",
|
||||
Timestamp: v1.Timestamp{Seconds: 1614093000},
|
||||
Source: "test",
|
||||
Category: "test",
|
||||
Severity: v1alpha2.SeverityHigh,
|
||||
Resources: []corev1.ObjectReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
Namespace: "test",
|
||||
UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx2",
|
||||
Namespace: "test",
|
||||
UID: "dfd57c50-f30c-4729-b63f-b1954d8988d2",
|
||||
},
|
||||
},
|
||||
Properties: map[string]string{"version": "1.2.0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var minPolicyReportCRD = &v1alpha2.PolicyReport{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "policy-report",
|
||||
|
@ -212,6 +256,67 @@ var clusterPolicyReportCRD = &v1alpha2.ClusterPolicyReport{
|
|||
},
|
||||
}
|
||||
|
||||
var minClusterPolicyReportCRD = &v1alpha2.ClusterPolicyReport{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "cluster-policy-report",
|
||||
},
|
||||
Summary: v1alpha2.PolicyReportSummary{
|
||||
Fail: 4,
|
||||
},
|
||||
Results: []v1alpha2.PolicyReportResult{
|
||||
{
|
||||
Message: "message",
|
||||
Result: v1alpha2.StatusFail,
|
||||
Scored: true,
|
||||
Policy: "cluster-policy",
|
||||
Rule: "cluster-role",
|
||||
Timestamp: v1.Timestamp{Seconds: 1614093000},
|
||||
Source: "test",
|
||||
Category: "test",
|
||||
Severity: v1alpha2.SeverityHigh,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var multiResourceClusterPolicyReportCRD = &v1alpha2.ClusterPolicyReport{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "cluster-policy-report",
|
||||
},
|
||||
Summary: v1alpha2.PolicyReportSummary{
|
||||
Fail: 4,
|
||||
},
|
||||
Results: []v1alpha2.PolicyReportResult{
|
||||
{
|
||||
Message: "message",
|
||||
Result: v1alpha2.StatusFail,
|
||||
Scored: true,
|
||||
Policy: "cluster-required-label",
|
||||
Rule: "ns-label-required",
|
||||
Timestamp: v1.Timestamp{Seconds: 1614093000},
|
||||
Source: "test",
|
||||
Category: "test",
|
||||
Severity: v1alpha2.SeverityHigh,
|
||||
Resources: []corev1.ObjectReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "Namespace",
|
||||
Name: "policy-reporter",
|
||||
Namespace: "test",
|
||||
UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1",
|
||||
},
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "Namespace",
|
||||
Name: "policy-reporter-check",
|
||||
Namespace: "test",
|
||||
UID: "dfd57c50-f30c-4729-b63f-b1954d8988d1",
|
||||
},
|
||||
},
|
||||
Properties: map[string]string{"version": "1.2.0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var result1ID string = report.GeneratePolicyReportResultID(
|
||||
string(policyReportCRD.Results[0].Resources[0].UID),
|
||||
policyReportCRD.Results[0].Resources[0].Name,
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/report"
|
||||
|
||||
"github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
|
@ -14,28 +15,32 @@ const ResultIDKey = "resultID"
|
|||
// Mapper converts maps into report structs
|
||||
type Mapper interface {
|
||||
// MapPolicyReport maps a v1alpha2.PolicyReport into a PolicyReport
|
||||
MapPolicyReport(*v1alpha2.PolicyReport) *report.PolicyReport
|
||||
MapPolicyReport(*v1alpha2.PolicyReport) report.PolicyReport
|
||||
// MapClusterPolicyReport maps a v1alpha2.ClusterPolicyReport into a PolicyReport
|
||||
MapClusterPolicyReport(*v1alpha2.ClusterPolicyReport) *report.PolicyReport
|
||||
MapClusterPolicyReport(*v1alpha2.ClusterPolicyReport) report.PolicyReport
|
||||
}
|
||||
|
||||
type mapper struct {
|
||||
priorityMap map[string]string
|
||||
}
|
||||
|
||||
func (m *mapper) MapPolicyReport(preport *v1alpha2.PolicyReport) *report.PolicyReport {
|
||||
r := &report.PolicyReport{
|
||||
func (m *mapper) MapPolicyReport(preport *v1alpha2.PolicyReport) report.PolicyReport {
|
||||
r := report.PolicyReport{
|
||||
Name: preport.Name,
|
||||
Namespace: preport.Namespace,
|
||||
Summary: m.mapSummary(preport.Summary),
|
||||
Results: make(map[string]*report.Result),
|
||||
Results: make([]report.Result, 0),
|
||||
CreationTimestamp: preport.CreationTimestamp.Time,
|
||||
}
|
||||
|
||||
for _, resultItem := range preport.Results {
|
||||
results := m.mapResult(resultItem.DeepCopy())
|
||||
for _, result := range results {
|
||||
r.Results[result.GetIdentifier()] = result
|
||||
for _, result := range preport.Results {
|
||||
if len(result.Resources) == 0 {
|
||||
r.Results = append(r.Results, m.mapResult(result, report.Resource{}))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, res := range result.Resources {
|
||||
r.Results = append(r.Results, m.mapResult(result, mapResource(res)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,18 +49,22 @@ func (m *mapper) MapPolicyReport(preport *v1alpha2.PolicyReport) *report.PolicyR
|
|||
return r
|
||||
}
|
||||
|
||||
func (m *mapper) MapClusterPolicyReport(creport *v1alpha2.ClusterPolicyReport) *report.PolicyReport {
|
||||
r := &report.PolicyReport{
|
||||
func (m *mapper) MapClusterPolicyReport(creport *v1alpha2.ClusterPolicyReport) report.PolicyReport {
|
||||
r := report.PolicyReport{
|
||||
Name: creport.Name,
|
||||
Summary: m.mapSummary(creport.Summary),
|
||||
Results: make(map[string]*report.Result),
|
||||
Results: make([]report.Result, 0),
|
||||
CreationTimestamp: creport.CreationTimestamp.Time,
|
||||
}
|
||||
|
||||
for _, resultItem := range creport.Results {
|
||||
results := m.mapResult(resultItem.DeepCopy())
|
||||
for _, result := range results {
|
||||
r.Results[result.GetIdentifier()] = result
|
||||
for _, result := range creport.Results {
|
||||
if len(result.Resources) == 0 {
|
||||
r.Results = append(r.Results, m.mapResult(result, report.Resource{}))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, res := range result.Resources {
|
||||
r.Results = append(r.Results, m.mapResult(result, mapResource(res)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,8 +77,8 @@ func (m *mapper) SetPriorityMap(priorityMap map[string]string) {
|
|||
m.priorityMap = priorityMap
|
||||
}
|
||||
|
||||
func (m *mapper) mapSummary(sum v1alpha2.PolicyReportSummary) *report.Summary {
|
||||
summary := &report.Summary{}
|
||||
func (m *mapper) mapSummary(sum v1alpha2.PolicyReportSummary) report.Summary {
|
||||
summary := report.Summary{}
|
||||
summary.Pass = sum.Pass
|
||||
summary.Skip = sum.Skip
|
||||
summary.Warn = sum.Warn
|
||||
|
@ -79,72 +88,14 @@ func (m *mapper) mapSummary(sum v1alpha2.PolicyReportSummary) *report.Summary {
|
|||
return summary
|
||||
}
|
||||
|
||||
func (m *mapper) mapResult(result *v1alpha2.PolicyReportResult) []*report.Result {
|
||||
var resources []*report.Resource
|
||||
|
||||
for _, res := range result.Resources {
|
||||
r := &report.Resource{
|
||||
func mapResource(res corev1.ObjectReference) report.Resource {
|
||||
return report.Resource{
|
||||
Namespace: res.Namespace,
|
||||
APIVersion: res.APIVersion,
|
||||
Kind: res.Kind,
|
||||
Name: res.Name,
|
||||
UID: string(res.UID),
|
||||
}
|
||||
|
||||
resources = append(resources, r)
|
||||
}
|
||||
|
||||
var results []*report.Result
|
||||
|
||||
factory := func(res *report.Resource) *report.Result {
|
||||
status := string(result.Result)
|
||||
|
||||
r := &report.Result{
|
||||
Policy: result.Policy,
|
||||
Status: string(result.Result),
|
||||
Priority: report.PriorityFromStatus(status),
|
||||
Resource: res,
|
||||
Properties: make(map[string]string),
|
||||
Scored: result.Scored,
|
||||
Severity: string(result.Severity),
|
||||
Message: result.Message,
|
||||
Rule: result.Rule,
|
||||
Category: result.Category,
|
||||
Source: result.Source,
|
||||
Timestamp: convertTimestamp(result.Timestamp),
|
||||
}
|
||||
|
||||
if r.Status == report.Fail {
|
||||
r.Priority = m.resolvePriority(r.Policy, r.Severity)
|
||||
}
|
||||
|
||||
if id, ok := result.Properties[ResultIDKey]; ok {
|
||||
r.ID = id
|
||||
delete(result.Properties, ResultIDKey)
|
||||
}
|
||||
|
||||
for property, value := range result.Properties {
|
||||
if len(value) > 0 {
|
||||
r.Properties[property] = value
|
||||
}
|
||||
}
|
||||
|
||||
if r.ID == "" {
|
||||
r.ID = report.GeneratePolicyReportResultID(r.Resource.UID, r.Resource.Name, r.Policy, r.Rule, r.Status, r.Message)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
for _, resource := range resources {
|
||||
results = append(results, factory(resource))
|
||||
}
|
||||
|
||||
if len(results) == 0 {
|
||||
results = append(results, factory(&report.Resource{}))
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
func convertTimestamp(timestamp v1.Timestamp) time.Time {
|
||||
|
@ -171,6 +122,48 @@ func (m *mapper) resolvePriority(policy string, severity report.Severity) report
|
|||
return report.Priority(report.WarningPriority)
|
||||
}
|
||||
|
||||
func (m *mapper) mapResult(result v1alpha2.PolicyReportResult, res report.Resource) report.Result {
|
||||
status := string(result.Result)
|
||||
|
||||
r := report.Result{
|
||||
Policy: result.Policy,
|
||||
Status: string(result.Result),
|
||||
Priority: report.PriorityFromStatus(status),
|
||||
Resource: res,
|
||||
Properties: make(map[string]string),
|
||||
Scored: result.Scored,
|
||||
Severity: string(result.Severity),
|
||||
Message: result.Message,
|
||||
Rule: result.Rule,
|
||||
Category: result.Category,
|
||||
Source: result.Source,
|
||||
Timestamp: convertTimestamp(result.Timestamp),
|
||||
}
|
||||
|
||||
if r.Status == report.Fail {
|
||||
r.Priority = m.resolvePriority(r.Policy, r.Severity)
|
||||
}
|
||||
|
||||
if id, ok := result.Properties[ResultIDKey]; ok {
|
||||
r.ID = id
|
||||
}
|
||||
|
||||
for property, value := range result.Properties {
|
||||
if property == ResultIDKey {
|
||||
continue
|
||||
}
|
||||
if value != "" {
|
||||
r.Properties[property] = value
|
||||
}
|
||||
}
|
||||
|
||||
if r.ID == "" {
|
||||
r.ID = report.GeneratePolicyReportResultID(r.Resource.UID, r.Resource.Name, r.Policy, r.Rule, r.Status, r.Message)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// NewMapper creates an new Mapper instance
|
||||
func NewMapper(priorities map[string]string) Mapper {
|
||||
m := &mapper{}
|
||||
|
|
|
@ -34,8 +34,8 @@ func Test_MapPolicyReport(t *testing.T) {
|
|||
t.Errorf("Unexpected Summary.Error value %d (expected 5)", preport.Summary.Error)
|
||||
}
|
||||
|
||||
result1, ok := preport.Results[result1ID]
|
||||
if !ok {
|
||||
result1 := preport.GetResult(result1ID)
|
||||
if result1.ID == "" {
|
||||
t.Error("Expected result not found")
|
||||
}
|
||||
|
||||
|
@ -90,8 +90,8 @@ func Test_MapPolicyReport(t *testing.T) {
|
|||
t.Errorf("Expected Resource.Namespace 'dfd57c50-f30c-4729-b63f-b1954d8988d1' (acutal %s)", resource.UID)
|
||||
}
|
||||
|
||||
result2, ok := preport.Results[result2ID]
|
||||
if !ok {
|
||||
result2 := preport.GetResult(result2ID)
|
||||
if result1.ID == "" {
|
||||
t.Error("Expected result not found")
|
||||
}
|
||||
|
||||
|
@ -140,8 +140,8 @@ func Test_MapClusterPolicyReport(t *testing.T) {
|
|||
t.Errorf("Unexpected Summary.Error value %d (expected 5)", preport.Summary.Error)
|
||||
}
|
||||
|
||||
result1, ok := preport.Results[cresult1ID]
|
||||
if !ok {
|
||||
result1 := preport.GetResult(cresult1ID)
|
||||
if result1.ID == "" {
|
||||
t.Error("Expected result not found")
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,11 @@ func Test_MapClusterPolicyReport(t *testing.T) {
|
|||
if resource.UID != "dfd57c50-f30c-4729-b63f-b1954d8988d1" {
|
||||
t.Errorf("Expected Resource.Namespace 'dfd57c50-f30c-4729-b63f-b1954d8988d1' (acutal %s)", resource.UID)
|
||||
}
|
||||
|
||||
report2 := mapper.MapClusterPolicyReport(minClusterPolicyReportCRD)
|
||||
if len(report2.Results) != 1 || report2.Results[0].HasResource() {
|
||||
t.Error("Expected one result withour resource")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ResultIDPropertyMapping(t *testing.T) {
|
||||
|
@ -196,9 +201,9 @@ func Test_ResultIDPropertyMapping(t *testing.T) {
|
|||
|
||||
preport := mapper.MapPolicyReport(enforceReportCRD)
|
||||
|
||||
result := preport.Results[result3ID]
|
||||
result := preport.GetResult(result3ID)
|
||||
|
||||
if result == nil {
|
||||
if result.ID == "" {
|
||||
t.Errorf("Expected ResultID was mapped from property Key %s", kubernetes.ResultIDKey)
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +214,7 @@ func Test_PriorityMap(t *testing.T) {
|
|||
|
||||
preport := mapper.MapPolicyReport(policyReportCRD)
|
||||
|
||||
result := preport.Results[result1ID]
|
||||
result := preport.GetResult(result1ID)
|
||||
|
||||
if result.Priority != report.DebugPriority {
|
||||
t.Errorf("Expected Policy '%d' (acutal %d)", report.DebugPriority, result.Priority)
|
||||
|
@ -221,8 +226,7 @@ func Test_PriorityMap(t *testing.T) {
|
|||
|
||||
preport := mapper.MapPolicyReport(policyReportCRD)
|
||||
|
||||
result := preport.Results[result1ID]
|
||||
|
||||
result := preport.GetResult(result1ID)
|
||||
if result.Priority != report.DebugPriority {
|
||||
t.Errorf("Expected Priority '%d' (acutal %d)", report.DebugPriority, result.Priority)
|
||||
}
|
||||
|
@ -233,7 +237,7 @@ func Test_PriorityMap(t *testing.T) {
|
|||
|
||||
preport := mapper.MapPolicyReport(policyReportCRD)
|
||||
|
||||
result := preport.Results[result2ID]
|
||||
result := preport.GetResult(result2ID)
|
||||
|
||||
if result.Priority != report.WarningPriority {
|
||||
t.Errorf("Expected Policy '%d' (acutal %d)", report.WarningPriority, result.Priority)
|
||||
|
@ -246,7 +250,30 @@ func Test_MapCustomResultID(t *testing.T) {
|
|||
|
||||
r := mapper.MapPolicyReport(enforceReportCRD)
|
||||
|
||||
if _, ok := r.Results["123456"]; !ok {
|
||||
result := r.GetResult("123456")
|
||||
if result.ID == "" {
|
||||
t.Errorf("Expected resultID used as result.ID")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MapMultipleResourcesPolicyReport(t *testing.T) {
|
||||
mapper := kubernetes.NewMapper(make(map[string]string))
|
||||
|
||||
r := mapper.MapPolicyReport(multiResourcePolicyReportCRD)
|
||||
|
||||
results := r.ResultList()
|
||||
if len(results) != 2 {
|
||||
t.Errorf("Expected one result per resource")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MapMultipleResourcesClusterPolicyReport(t *testing.T) {
|
||||
mapper := kubernetes.NewMapper(make(map[string]string))
|
||||
|
||||
r := mapper.MapClusterPolicyReport(multiResourceClusterPolicyReportCRD)
|
||||
|
||||
results := r.ResultList()
|
||||
if len(results) != 2 {
|
||||
t.Errorf("Expected one result per resource")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -17,63 +16,50 @@ import (
|
|||
|
||||
type k8sPolicyReportClient struct {
|
||||
debouncer Debouncer
|
||||
client versioned.Interface
|
||||
found map[string]string
|
||||
fatcory externalversions.SharedInformerFactory
|
||||
v1alpha2 v1alpha2.Interface
|
||||
synced bool
|
||||
mapper Mapper
|
||||
mx *sync.Mutex
|
||||
restartWatchOnFailure time.Duration
|
||||
reportFilter report.Filter
|
||||
}
|
||||
|
||||
func (k *k8sPolicyReportClient) GetFoundResources() map[string]string {
|
||||
return k.found
|
||||
func (k *k8sPolicyReportClient) HasSynced() bool {
|
||||
return k.synced
|
||||
}
|
||||
|
||||
func (k *k8sPolicyReportClient) WatchPolicyReports(ctx context.Context) *report.Group {
|
||||
factory := externalversions.NewSharedInformerFactory(k.client, 0).Wgpolicyk8s().V1alpha2()
|
||||
func (k *k8sPolicyReportClient) Run(stopper chan struct{}) error {
|
||||
var cpolrInformer cache.SharedIndexInformer
|
||||
|
||||
go func(f v1alpha2.Interface) {
|
||||
informer := factory.PolicyReports().Informer()
|
||||
|
||||
for {
|
||||
k.watchPolicyReport(ctx, informer, "policyreport.wgpolicyk8s.io")
|
||||
time.Sleep(k.restartWatchOnFailure)
|
||||
}
|
||||
}(factory)
|
||||
polrInformer := k.configurePolicyReport()
|
||||
|
||||
if !k.reportFilter.DisableClusterReports() {
|
||||
informer := factory.ClusterPolicyReports().Informer()
|
||||
|
||||
go func(f v1alpha2.Interface) {
|
||||
for {
|
||||
k.watchClusterPolicyReport(ctx, informer, "clusterpolicyreport.wgpolicyk8s.io")
|
||||
time.Sleep(k.restartWatchOnFailure)
|
||||
}
|
||||
}(factory)
|
||||
cpolrInformer = k.configureClusterPolicyReport()
|
||||
}
|
||||
|
||||
for {
|
||||
if !k.reportFilter.DisableClusterReports() && len(k.found) == 2 {
|
||||
break
|
||||
} else if k.reportFilter.DisableClusterReports() && len(k.found) == 1 {
|
||||
break
|
||||
}
|
||||
k.fatcory.Start(stopper)
|
||||
|
||||
if !cache.WaitForCacheSync(stopper, polrInformer.HasSynced) {
|
||||
return fmt.Errorf("failed to sync policy reports")
|
||||
}
|
||||
|
||||
return k.debouncer.ReportGroups()
|
||||
if cpolrInformer != nil && !cache.WaitForCacheSync(stopper, cpolrInformer.HasSynced) {
|
||||
return fmt.Errorf("failed to sync cluster policy reports")
|
||||
}
|
||||
|
||||
k.synced = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *k8sPolicyReportClient) watchPolicyReport(ctx context.Context, informer cache.SharedIndexInformer, crd string) {
|
||||
ctx = k.addErrorWatchHandler(ctx, informer, crd)
|
||||
|
||||
go k.handleCRDRegistration(ctx, informer, crd)
|
||||
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
func (k *k8sPolicyReportClient) configurePolicyReport() cache.SharedIndexInformer {
|
||||
polrInformer := k.v1alpha2.PolicyReports().Informer()
|
||||
polrInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
if item, ok := obj.(*pr.PolicyReport); ok {
|
||||
preport := k.mapper.MapPolicyReport(item)
|
||||
if k.reportFilter.AllowReport(preport) {
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: &report.PolicyReport{}, Type: report.Added})
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: report.PolicyReport{}, Type: report.Added})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -81,7 +67,7 @@ func (k *k8sPolicyReportClient) watchPolicyReport(ctx context.Context, informer
|
|||
if item, ok := obj.(*pr.PolicyReport); ok {
|
||||
preport := k.mapper.MapPolicyReport(item)
|
||||
if k.reportFilter.AllowReport(preport) {
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: &report.PolicyReport{}, Type: report.Deleted})
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: report.PolicyReport{}, Type: report.Deleted})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -89,7 +75,7 @@ func (k *k8sPolicyReportClient) watchPolicyReport(ctx context.Context, informer
|
|||
if item, ok := newObj.(*pr.PolicyReport); ok {
|
||||
preport := k.mapper.MapPolicyReport(item)
|
||||
|
||||
var oreport *report.PolicyReport
|
||||
var oreport report.PolicyReport
|
||||
if oldItem, ok := oldObj.(*pr.PolicyReport); ok {
|
||||
oreport = k.mapper.MapPolicyReport(oldItem)
|
||||
}
|
||||
|
@ -101,20 +87,21 @@ func (k *k8sPolicyReportClient) watchPolicyReport(ctx context.Context, informer
|
|||
},
|
||||
})
|
||||
|
||||
informer.Run(ctx.Done())
|
||||
polrInformer.SetWatchErrorHandler(func(_ *cache.Reflector, _ error) {
|
||||
k.synced = false
|
||||
})
|
||||
|
||||
return polrInformer
|
||||
}
|
||||
|
||||
func (k *k8sPolicyReportClient) watchClusterPolicyReport(ctx context.Context, informer cache.SharedIndexInformer, crd string) {
|
||||
ctx = k.addErrorWatchHandler(ctx, informer, crd)
|
||||
|
||||
go k.handleCRDRegistration(ctx, informer, crd)
|
||||
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
func (k *k8sPolicyReportClient) configureClusterPolicyReport() cache.SharedIndexInformer {
|
||||
cpolrInformer := k.v1alpha2.ClusterPolicyReports().Informer()
|
||||
cpolrInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
if item, ok := obj.(*pr.ClusterPolicyReport); ok {
|
||||
preport := k.mapper.MapClusterPolicyReport(item)
|
||||
if k.reportFilter.AllowReport(preport) {
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: &report.PolicyReport{}, Type: report.Added})
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: report.PolicyReport{}, Type: report.Added})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -122,7 +109,7 @@ func (k *k8sPolicyReportClient) watchClusterPolicyReport(ctx context.Context, in
|
|||
if item, ok := obj.(*pr.ClusterPolicyReport); ok {
|
||||
preport := k.mapper.MapClusterPolicyReport(item)
|
||||
if k.reportFilter.AllowReport(preport) {
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: &report.PolicyReport{}, Type: report.Deleted})
|
||||
k.debouncer.Add(report.LifecycleEvent{NewPolicyReport: preport, OldPolicyReport: report.PolicyReport{}, Type: report.Deleted})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -130,7 +117,7 @@ func (k *k8sPolicyReportClient) watchClusterPolicyReport(ctx context.Context, in
|
|||
if item, ok := newObj.(*pr.ClusterPolicyReport); ok {
|
||||
preport := k.mapper.MapClusterPolicyReport(item)
|
||||
|
||||
var oreport *report.PolicyReport
|
||||
var oreport report.PolicyReport
|
||||
if oldItem, ok := oldObj.(*pr.ClusterPolicyReport); ok {
|
||||
oreport = k.mapper.MapClusterPolicyReport(oldItem)
|
||||
}
|
||||
|
@ -142,53 +129,24 @@ func (k *k8sPolicyReportClient) watchClusterPolicyReport(ctx context.Context, in
|
|||
},
|
||||
})
|
||||
|
||||
informer.Run(ctx.Done())
|
||||
}
|
||||
|
||||
func (k *k8sPolicyReportClient) handleCRDRegistration(ctx context.Context, informer cache.SharedIndexInformer, crd string) {
|
||||
ticker := time.NewTicker(k.restartWatchOnFailure)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
if informer.HasSynced() {
|
||||
k.mx.Lock()
|
||||
k.found[crd] = crd
|
||||
k.mx.Unlock()
|
||||
|
||||
log.Printf("[INFO] Resource registered: %s\n", crd)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (k *k8sPolicyReportClient) addErrorWatchHandler(ctx context.Context, informer cache.SharedIndexInformer, crd string) context.Context {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
informer.SetWatchErrorHandler(func(c *cache.Reflector, err error) {
|
||||
k.mx.Lock()
|
||||
delete(k.found, crd)
|
||||
k.mx.Unlock()
|
||||
cancel()
|
||||
|
||||
log.Printf("[WARNING] Resource registration failed: %s\n", crd)
|
||||
cpolrInformer.SetWatchErrorHandler(func(_ *cache.Reflector, _ error) {
|
||||
k.synced = false
|
||||
})
|
||||
|
||||
return ctx
|
||||
return cpolrInformer
|
||||
}
|
||||
|
||||
// NewPolicyReportAdapter new Adapter for Policy Report Kubernetes API
|
||||
func NewPolicyReportClient(client versioned.Interface, mapper Mapper, restartWatchOnFailure time.Duration, reportFilter report.Filter) report.PolicyReportClient {
|
||||
func NewPolicyReportClient(client versioned.Interface, mapper Mapper, reportFilter report.Filter, publisher report.EventPublisher) report.PolicyReportClient {
|
||||
fatcory := externalversions.NewSharedInformerFactory(client, time.Hour)
|
||||
v1alpha2 := fatcory.Wgpolicyk8s().V1alpha2()
|
||||
|
||||
return &k8sPolicyReportClient{
|
||||
client: client,
|
||||
fatcory: fatcory,
|
||||
v1alpha2: v1alpha2,
|
||||
mapper: mapper,
|
||||
mx: &sync.Mutex{},
|
||||
found: make(map[string]string),
|
||||
debouncer: NewDebouncer(time.Minute),
|
||||
restartWatchOnFailure: restartWatchOnFailure,
|
||||
debouncer: NewDebouncer(time.Minute, publisher),
|
||||
reportFilter: reportFilter,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package kubernetes_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -17,29 +16,26 @@ var filter = report.NewFilter(false, make([]string, 0), make([]string, 0))
|
|||
|
||||
func Test_PolicyReportWatcher(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
kclient, rclient, _ := NewFakeCilent()
|
||||
client := kubernetes.NewPolicyReportClient(kclient, NewMapper(), 100*time.Millisecond, filter)
|
||||
|
||||
group := client.WatchPolicyReports(ctx)
|
||||
store := newStore(3)
|
||||
stop := make(chan struct{})
|
||||
defer close(stop)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(3)
|
||||
|
||||
go func() {
|
||||
reportID := <-group.ChannelAdded()
|
||||
eventChan, err := group.Listen(reportID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for event := range eventChan {
|
||||
fmt.Printf("%v\n", event.Type)
|
||||
store := newStore(3)
|
||||
publisher := report.NewEventPublisher()
|
||||
publisher.RegisterListener(func(event report.LifecycleEvent) {
|
||||
store.Add(event)
|
||||
wg.Done()
|
||||
})
|
||||
|
||||
kclient, rclient, _ := NewFakeCilent()
|
||||
client := kubernetes.NewPolicyReportClient(kclient, NewMapper(), filter, publisher)
|
||||
|
||||
err := client.Run(stop)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
rclient.Create(ctx, policyReportCRD, metav1.CreateOptions{})
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
@ -55,28 +51,25 @@ func Test_PolicyReportWatcher(t *testing.T) {
|
|||
}
|
||||
func Test_ClusterPolicyReportWatcher(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
kclient, _, rclient := NewFakeCilent()
|
||||
client := kubernetes.NewPolicyReportClient(kclient, NewMapper(), 100*time.Millisecond, filter)
|
||||
|
||||
group := client.WatchPolicyReports(ctx)
|
||||
store := newStore(3)
|
||||
|
||||
stop := make(chan struct{})
|
||||
defer close(stop)
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(3)
|
||||
|
||||
go func() {
|
||||
reportID := <-group.ChannelAdded()
|
||||
eventChan, err := group.Listen(reportID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for event := range eventChan {
|
||||
store := newStore(3)
|
||||
publisher := report.NewEventPublisher()
|
||||
publisher.RegisterListener(func(event report.LifecycleEvent) {
|
||||
store.Add(event)
|
||||
wg.Done()
|
||||
})
|
||||
|
||||
kclient, _, rclient := NewFakeCilent()
|
||||
client := kubernetes.NewPolicyReportClient(kclient, NewMapper(), filter, publisher)
|
||||
|
||||
err := client.Run(stop)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
rclient.Create(ctx, clusterPolicyReportCRD, metav1.CreateOptions{})
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
@ -91,32 +84,19 @@ func Test_ClusterPolicyReportWatcher(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_GetFoundResources(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
func Test_HasSynced(t *testing.T) {
|
||||
stop := make(chan struct{})
|
||||
defer close(stop)
|
||||
|
||||
kclient, _, _ := NewFakeCilent()
|
||||
client := kubernetes.NewPolicyReportClient(kclient, NewMapper(), 100*time.Millisecond, filter)
|
||||
client := kubernetes.NewPolicyReportClient(kclient, NewMapper(), filter, report.NewEventPublisher())
|
||||
|
||||
client.WatchPolicyReports(ctx)
|
||||
err := client.Run(stop)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
if len(client.GetFoundResources()) != 2 {
|
||||
t.Errorf("Should find PolicyReport and ClusterPolicyReport Resource")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetFoundResourcesWihDisabledClusterReports(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
kclient, _, _ := NewFakeCilent()
|
||||
client := kubernetes.NewPolicyReportClient(kclient, NewMapper(), 100*time.Millisecond, report.NewFilter(true, make([]string, 0), make([]string, 0)))
|
||||
|
||||
client.WatchPolicyReports(ctx)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
if len(client.GetFoundResources()) != 1 {
|
||||
t.Errorf("Should find only PolicyReport Resource")
|
||||
if client.HasSynced() != true {
|
||||
t.Errorf("Should synced")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/report"
|
||||
)
|
||||
|
||||
var result1 = &report.Result{
|
||||
var result1 = report.Result{
|
||||
ID: "123",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -17,7 +17,7 @@ var result1 = &report.Result{
|
|||
Severity: report.High,
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -26,7 +26,7 @@ var result1 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var result2 = &report.Result{
|
||||
var result2 = report.Result{
|
||||
ID: "124",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -36,7 +36,7 @@ var result2 = &report.Result{
|
|||
Category: "Best Practices",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Name: "nginx",
|
||||
|
@ -45,31 +45,26 @@ var result2 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var preport1 = &report.PolicyReport{
|
||||
var preport1 = report.PolicyReport{
|
||||
ID: report.GeneratePolicyReportID("polr-test", "test"),
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
},
|
||||
Summary: &report.Summary{Fail: 1},
|
||||
Results: []report.Result{result1},
|
||||
Summary: report.Summary{Fail: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
var preport2 = &report.PolicyReport{
|
||||
var preport2 = report.PolicyReport{
|
||||
ID: report.GeneratePolicyReportID("polr-test", "test"),
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
result2.GetIdentifier(): result2,
|
||||
},
|
||||
Summary: &report.Summary{Fail: 1, Pass: 1},
|
||||
Results: []report.Result{result1, result2},
|
||||
Summary: report.Summary{Fail: 1, Pass: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
var creport = &report.PolicyReport{
|
||||
var creport = report.PolicyReport{
|
||||
Name: "cpolr-test",
|
||||
Summary: &report.Summary{},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ func CreateClusterPolicyReportMetricsListener(filter *Filter) report.PolicyRepor
|
|||
prometheus.Register(clusterPolicyGauge)
|
||||
prometheus.Register(clusterRuleGauge)
|
||||
|
||||
var newReport *report.PolicyReport
|
||||
var oldReport *report.PolicyReport
|
||||
var newReport report.PolicyReport
|
||||
var oldReport report.PolicyReport
|
||||
|
||||
return func(event report.LifecycleEvent) {
|
||||
newReport = event.NewPolicyReport
|
||||
|
@ -70,7 +70,7 @@ func CreateClusterPolicyReportMetricsListener(filter *Filter) report.PolicyRepor
|
|||
}
|
||||
}
|
||||
|
||||
func generateClusterResultLabels(newReport *report.PolicyReport, result *report.Result) prometheus.Labels {
|
||||
func generateClusterResultLabels(newReport report.PolicyReport, result report.Result) prometheus.Labels {
|
||||
labels := prometheus.Labels{
|
||||
"rule": result.Rule,
|
||||
"policy": result.Policy,
|
||||
|
@ -91,7 +91,7 @@ func generateClusterResultLabels(newReport *report.PolicyReport, result *report.
|
|||
return labels
|
||||
}
|
||||
|
||||
func resetClusterPolicyGauge(newReport *report.PolicyReport) {
|
||||
func resetClusterPolicyGauge(newReport report.PolicyReport) {
|
||||
clusterPolicyGauge.
|
||||
WithLabelValues(newReport.Name, "Pass").
|
||||
Set(0)
|
||||
|
|
|
@ -13,37 +13,30 @@ import (
|
|||
|
||||
var creport = &report.PolicyReport{
|
||||
Name: "cpolr-test",
|
||||
Results: make(map[string]*report.Result),
|
||||
Summary: &report.Summary{},
|
||||
Results: make([]report.Result, 0),
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
func Test_ClusterPolicyReportMetricGeneration(t *testing.T) {
|
||||
report1 := &report.PolicyReport{
|
||||
report1 := report.PolicyReport{
|
||||
Name: "cpolr-test",
|
||||
Summary: &report.Summary{Pass: 1, Fail: 1},
|
||||
Summary: report.Summary{Pass: 1, Fail: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
result2.GetIdentifier(): result2,
|
||||
result3.GetIdentifier(): result3,
|
||||
},
|
||||
Results: []report.Result{result1, result2, result3},
|
||||
}
|
||||
|
||||
report2 := &report.PolicyReport{
|
||||
report2 := report.PolicyReport{
|
||||
Name: "cpolr-test",
|
||||
Summary: &report.Summary{Pass: 0, Fail: 1},
|
||||
Summary: report.Summary{Pass: 0, Fail: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
result3.GetIdentifier(): result3,
|
||||
},
|
||||
Results: []report.Result{result1, result3},
|
||||
}
|
||||
|
||||
handler := metrics.CreateClusterPolicyReportMetricsListener(&metrics.Filter{Policy: metrics.Rules{Exclude: []string{"disallow-policy"}}})
|
||||
|
||||
t.Run("Added Metric", func(t *testing.T) {
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
|
@ -88,7 +81,7 @@ func Test_ClusterPolicyReportMetricGeneration(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Modified Metric", func(t *testing.T) {
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: report2, OldPolicyReport: report1})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
|
@ -134,9 +127,9 @@ func Test_ClusterPolicyReportMetricGeneration(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Deleted Metric", func(t *testing.T) {
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: report2, OldPolicyReport: report1})
|
||||
handler(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: report2, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: report2, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
|
@ -183,7 +176,7 @@ func testClusterSummaryMetricLabels(
|
|||
return nil
|
||||
}
|
||||
|
||||
func testClusterResultMetricLabels(metric *ioprometheusclient.Metric, result *report.Result) error {
|
||||
func testClusterResultMetricLabels(metric *ioprometheusclient.Metric, result report.Result) error {
|
||||
if name := *metric.Label[0].Name; name != "category" {
|
||||
return fmt.Errorf("unexpected Category Label: %s", name)
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ type Filter struct {
|
|||
Severity Rules
|
||||
}
|
||||
|
||||
func (f *Filter) Validate(result *report.Result) bool {
|
||||
if result.Resource != nil &&
|
||||
func (f *Filter) Validate(result report.Result) bool {
|
||||
if result.HasResource() &&
|
||||
result.Resource.Namespace != "" &&
|
||||
!validateRules(result.Resource.Namespace, f.Namespace) {
|
||||
return false
|
||||
|
|
|
@ -22,8 +22,8 @@ func CreatePolicyReportMetricsListener(filter *Filter) report.PolicyReportListen
|
|||
prometheus.Register(policyGauge)
|
||||
prometheus.Register(ruleGauge)
|
||||
|
||||
var newReport *report.PolicyReport
|
||||
var oldReport *report.PolicyReport
|
||||
var newReport report.PolicyReport
|
||||
var oldReport report.PolicyReport
|
||||
|
||||
return func(event report.LifecycleEvent) {
|
||||
newReport = event.NewPolicyReport
|
||||
|
@ -70,7 +70,7 @@ func CreatePolicyReportMetricsListener(filter *Filter) report.PolicyReportListen
|
|||
}
|
||||
}
|
||||
|
||||
func generateResultLabels(report *report.PolicyReport, result *report.Result) prometheus.Labels {
|
||||
func generateResultLabels(report report.PolicyReport, result report.Result) prometheus.Labels {
|
||||
labels := prometheus.Labels{
|
||||
"namespace": report.Namespace,
|
||||
"rule": result.Rule,
|
||||
|
@ -92,7 +92,7 @@ func generateResultLabels(report *report.PolicyReport, result *report.Result) pr
|
|||
return labels
|
||||
}
|
||||
|
||||
func resetPolicyGauge(newReport *report.PolicyReport) {
|
||||
func resetPolicyGauge(newReport report.PolicyReport) {
|
||||
policyGauge.WithLabelValues(newReport.Namespace, newReport.Name, "Pass").Set(0)
|
||||
policyGauge.WithLabelValues(newReport.Namespace, newReport.Name, "Fail").Set(0)
|
||||
policyGauge.WithLabelValues(newReport.Namespace, newReport.Name, "Warn").Set(0)
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
ioprometheusclient "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
var result1 = &report.Result{
|
||||
var result1 = report.Result{
|
||||
ID: "1",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -21,7 +21,7 @@ var result1 = &report.Result{
|
|||
Severity: report.High,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -31,7 +31,7 @@ var result1 = &report.Result{
|
|||
Source: "Kyverno",
|
||||
}
|
||||
|
||||
var result2 = &report.Result{
|
||||
var result2 = report.Result{
|
||||
ID: "2",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "check-requests-and-limits-required",
|
||||
|
@ -40,7 +40,7 @@ var result2 = &report.Result{
|
|||
Status: report.Pass,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -50,7 +50,7 @@ var result2 = &report.Result{
|
|||
Source: "Kyverno",
|
||||
}
|
||||
|
||||
var result3 = &report.Result{
|
||||
var result3 = report.Result{
|
||||
ID: "3",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "disallow-policy",
|
||||
|
@ -59,7 +59,7 @@ var result3 = &report.Result{
|
|||
Status: report.Pass,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -69,45 +69,38 @@ var result3 = &report.Result{
|
|||
Source: "Kyverno",
|
||||
}
|
||||
|
||||
var preport = &report.PolicyReport{
|
||||
var preport = report.PolicyReport{
|
||||
ID: "1",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: make(map[string]*report.Result),
|
||||
Summary: &report.Summary{},
|
||||
Results: make([]report.Result, 0),
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
func Test_PolicyReportMetricGeneration(t *testing.T) {
|
||||
report1 := &report.PolicyReport{
|
||||
report1 := report.PolicyReport{
|
||||
ID: "1",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Summary: &report.Summary{Pass: 2, Fail: 1},
|
||||
Summary: report.Summary{Pass: 2, Fail: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
result2.GetIdentifier(): result2,
|
||||
result3.GetIdentifier(): result3,
|
||||
},
|
||||
Results: []report.Result{result1, result2, result3},
|
||||
}
|
||||
|
||||
report2 := &report.PolicyReport{
|
||||
report2 := report.PolicyReport{
|
||||
ID: "1",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Summary: &report.Summary{Pass: 0, Fail: 1},
|
||||
Summary: report.Summary{Pass: 0, Fail: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
result3.GetIdentifier(): result3,
|
||||
},
|
||||
Results: []report.Result{result1, result3},
|
||||
}
|
||||
|
||||
handler := metrics.CreatePolicyReportMetricsListener(&metrics.Filter{Policy: metrics.Rules{Exclude: []string{"disallow-policy"}}})
|
||||
|
||||
t.Run("Added Metric", func(t *testing.T) {
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
|
@ -152,7 +145,7 @@ func Test_PolicyReportMetricGeneration(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Modified Metric", func(t *testing.T) {
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: report2, OldPolicyReport: report1})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
|
@ -198,9 +191,9 @@ func Test_PolicyReportMetricGeneration(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Deleted Metric", func(t *testing.T) {
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Added, NewPolicyReport: report1, OldPolicyReport: report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: report2, OldPolicyReport: report1})
|
||||
handler(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: report2, OldPolicyReport: &report.PolicyReport{}})
|
||||
handler(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: report2, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
|
@ -221,7 +214,7 @@ func Test_PolicyReportMetricGeneration(t *testing.T) {
|
|||
|
||||
func testSummaryMetricLabels(
|
||||
metric *ioprometheusclient.Metric,
|
||||
preport *report.PolicyReport,
|
||||
preport report.PolicyReport,
|
||||
status string,
|
||||
gauge float64,
|
||||
) error {
|
||||
|
@ -253,7 +246,7 @@ func testSummaryMetricLabels(
|
|||
return nil
|
||||
}
|
||||
|
||||
func testResultMetricLabels(metric *ioprometheusclient.Metric, result *report.Result) error {
|
||||
func testResultMetricLabels(metric *ioprometheusclient.Metric, result report.Result) error {
|
||||
if name := *metric.Label[0].Name; name != "category" {
|
||||
return fmt.Errorf("unexpected Name Label: %s", name)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func Test_MetricsListener(t *testing.T) {
|
|||
slistener := listener.NewMetricsListener(&metrics.Filter{})
|
||||
|
||||
t.Run("Add ClusterPolicyReport Metric", func(t *testing.T) {
|
||||
slistener(report.LifecycleEvent{Type: report.Added, NewPolicyReport: creport, OldPolicyReport: &report.PolicyReport{}})
|
||||
slistener(report.LifecycleEvent{Type: report.Added, NewPolicyReport: creport, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
|
@ -28,7 +28,7 @@ func Test_MetricsListener(t *testing.T) {
|
|||
}
|
||||
})
|
||||
t.Run("Add PolicyReport Metric", func(t *testing.T) {
|
||||
slistener(report.LifecycleEvent{Type: report.Added, NewPolicyReport: preport1, OldPolicyReport: &report.PolicyReport{}})
|
||||
slistener(report.LifecycleEvent{Type: report.Added, NewPolicyReport: preport1, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
metricFam, err := prometheus.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
|
|
|
@ -21,8 +21,8 @@ func (l *ResultListener) RegisterListener(listener report.PolicyReportResultList
|
|||
|
||||
func (l *ResultListener) Listen(event report.LifecycleEvent) {
|
||||
if len(event.OldPolicyReport.Results) > 0 {
|
||||
for id := range event.OldPolicyReport.Results {
|
||||
l.cache.Add(id)
|
||||
for _, result := range event.OldPolicyReport.Results {
|
||||
l.cache.Add(result.ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ func (l *ResultListener) Listen(event report.LifecycleEvent) {
|
|||
wg.Add(len(l.listener))
|
||||
|
||||
for _, cb := range l.listener {
|
||||
go func(callback report.PolicyReportResultListener, result *report.Result) {
|
||||
go func(callback report.PolicyReportResultListener, result report.Result) {
|
||||
callback(result, preExisted)
|
||||
wg.Done()
|
||||
}(cb, r)
|
||||
|
|
|
@ -11,10 +11,10 @@ import (
|
|||
|
||||
func Test_ResultListener(t *testing.T) {
|
||||
t.Run("Publish Result", func(t *testing.T) {
|
||||
var called *report.Result
|
||||
var called report.Result
|
||||
|
||||
slistener := listener.NewResultListener(true, cache.New(0, 5*time.Minute), time.Now())
|
||||
slistener.RegisterListener(func(r *report.Result, b bool) {
|
||||
slistener.RegisterListener(func(r report.Result, b bool) {
|
||||
called = r
|
||||
})
|
||||
|
||||
|
@ -29,7 +29,7 @@ func Test_ResultListener(t *testing.T) {
|
|||
var called bool
|
||||
|
||||
slistener := listener.NewResultListener(true, cache.New(0, 5*time.Minute), time.Now())
|
||||
slistener.RegisterListener(func(r *report.Result, b bool) {
|
||||
slistener.RegisterListener(func(r report.Result, b bool) {
|
||||
called = true
|
||||
})
|
||||
|
||||
|
@ -44,7 +44,7 @@ func Test_ResultListener(t *testing.T) {
|
|||
var called bool
|
||||
|
||||
slistener := listener.NewResultListener(true, cache.New(0, 5*time.Minute), time.Now())
|
||||
slistener.RegisterListener(func(r *report.Result, b bool) {
|
||||
slistener.RegisterListener(func(r report.Result, b bool) {
|
||||
called = true
|
||||
})
|
||||
|
||||
|
@ -62,7 +62,7 @@ func Test_ResultListener(t *testing.T) {
|
|||
rcache.Add(result2.ID)
|
||||
|
||||
slistener := listener.NewResultListener(true, rcache, time.Now())
|
||||
slistener.RegisterListener(func(r *report.Result, b bool) {
|
||||
slistener.RegisterListener(func(r report.Result, b bool) {
|
||||
called = true
|
||||
})
|
||||
|
||||
|
@ -80,7 +80,7 @@ func Test_ResultListener(t *testing.T) {
|
|||
rcache.Add(result2.ID)
|
||||
|
||||
slistener := listener.NewResultListener(true, rcache, time.Now())
|
||||
slistener.RegisterListener(func(r *report.Result, b bool) {
|
||||
slistener.RegisterListener(func(r report.Result, b bool) {
|
||||
called = true
|
||||
})
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
)
|
||||
|
||||
func NewSendResultListener(clients []target.Client) report.PolicyReportResultListener {
|
||||
return func(r *report.Result, e bool) {
|
||||
return func(r report.Result, e bool) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(len(clients))
|
||||
|
||||
for _, t := range clients {
|
||||
go func(target target.Client, result *report.Result, preExisted bool) {
|
||||
go func(target target.Client, result report.Result, preExisted bool) {
|
||||
defer wg.Done()
|
||||
|
||||
if (preExisted && target.SkipExistingOnStartup()) || !target.Validate(result) {
|
||||
|
|
|
@ -14,7 +14,7 @@ type client struct {
|
|||
validated bool
|
||||
}
|
||||
|
||||
func (c *client) Send(result *report.Result) {
|
||||
func (c *client) Send(result report.Result) {
|
||||
c.Called = true
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ func (c *client) SkipExistingOnStartup() bool {
|
|||
return c.skipExistingOnStartup
|
||||
}
|
||||
|
||||
func (c client) Validate(result *report.Result) bool {
|
||||
func (c client) Validate(result report.Result) bool {
|
||||
return c.validated
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ func Test_StoreListener(t *testing.T) {
|
|||
|
||||
t.Run("Save New Report", func(t *testing.T) {
|
||||
slistener := listener.NewStoreListener(store)
|
||||
slistener(report.LifecycleEvent{Type: report.Added, NewPolicyReport: preport1, OldPolicyReport: &report.PolicyReport{}})
|
||||
slistener(report.LifecycleEvent{Type: report.Added, NewPolicyReport: preport1, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
if _, ok := store.Get(preport1.ID); !ok {
|
||||
t.Error("Expected Report to be stored")
|
||||
|
@ -28,7 +28,7 @@ func Test_StoreListener(t *testing.T) {
|
|||
})
|
||||
t.Run("Remove Deleted Report", func(t *testing.T) {
|
||||
slistener := listener.NewStoreListener(store)
|
||||
slistener(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: preport2, OldPolicyReport: &report.PolicyReport{}})
|
||||
slistener(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: preport2, OldPolicyReport: report.PolicyReport{}})
|
||||
|
||||
if _, ok := store.Get(preport2.ID); ok {
|
||||
t.Error("Expected Report to be removed")
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
package report
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// PolicyReportListener is called whenever a new PolicyReport comes in
|
||||
type PolicyReportListener = func(LifecycleEvent)
|
||||
|
||||
// PolicyReportResultListener is called whenever a new PolicyResult comes in
|
||||
type PolicyReportResultListener = func(*Result, bool)
|
||||
type PolicyReportResultListener = func(Result, bool)
|
||||
|
||||
// PolicyReportClient watches for PolicyReport Events and executes registered callback
|
||||
type PolicyReportClient interface {
|
||||
// WatchPolicyReports starts to watch for PolicyReport LifecycleEvent events
|
||||
WatchPolicyReports(ctx context.Context) *Group
|
||||
// GetFoundResources as Map of Names
|
||||
GetFoundResources() map[string]string
|
||||
Run(stopper chan struct{}) error
|
||||
// HasSynced the configured PolicyReport
|
||||
HasSynced() bool
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import "github.com/minio/pkg/wildcard"
|
|||
|
||||
type Filter interface {
|
||||
DisableClusterReports() bool
|
||||
AllowReport(report *PolicyReport) bool
|
||||
AllowReport(report PolicyReport) bool
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
|
@ -17,7 +17,7 @@ func (f *filter) DisableClusterReports() bool {
|
|||
return f.disbaleClusterReports
|
||||
}
|
||||
|
||||
func (f *filter) AllowReport(report *PolicyReport) bool {
|
||||
func (f *filter) AllowReport(report PolicyReport) bool {
|
||||
if report.Namespace == "" {
|
||||
return true
|
||||
} else if len(f.includeNamespaces) > 0 {
|
||||
|
|
|
@ -2,9 +2,10 @@ package report
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/segmentio/fasthash/fnv1a"
|
||||
)
|
||||
|
||||
// Event Enum
|
||||
|
@ -33,8 +34,8 @@ const (
|
|||
// LifecycleEvent of PolicyReports
|
||||
type LifecycleEvent struct {
|
||||
Type Event
|
||||
NewPolicyReport *PolicyReport
|
||||
OldPolicyReport *PolicyReport
|
||||
NewPolicyReport PolicyReport
|
||||
OldPolicyReport PolicyReport
|
||||
}
|
||||
|
||||
// Status Enum defined for PolicyReport
|
||||
|
@ -173,15 +174,15 @@ type Result struct {
|
|||
Message string
|
||||
Policy string
|
||||
Rule string
|
||||
Priority Priority
|
||||
Status Status
|
||||
Severity Severity `json:",omitempty"`
|
||||
Category string `json:",omitempty"`
|
||||
Source string `json:",omitempty"`
|
||||
Scored bool
|
||||
Timestamp time.Time
|
||||
Resource *Resource
|
||||
Properties map[string]string
|
||||
Resource Resource
|
||||
Priority Priority
|
||||
Scored bool
|
||||
}
|
||||
|
||||
// GetIdentifier returns a global unique Result identifier
|
||||
|
@ -191,10 +192,6 @@ func (r Result) GetIdentifier() string {
|
|||
|
||||
// HasResource checks if the result has an valid Resource
|
||||
func (r Result) HasResource() bool {
|
||||
if r.Resource == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return r.Resource.UID != "" || r.Resource.Name != ""
|
||||
}
|
||||
|
||||
|
@ -212,8 +209,8 @@ type PolicyReport struct {
|
|||
ID string
|
||||
Name string
|
||||
Namespace string
|
||||
Results map[string]*Result
|
||||
Summary *Summary
|
||||
Results []Result
|
||||
Summary Summary
|
||||
CreationTimestamp time.Time
|
||||
}
|
||||
|
||||
|
@ -224,19 +221,29 @@ func (pr PolicyReport) GetIdentifier() string {
|
|||
|
||||
// HasResult returns if the Report has an Rusult with the given ID
|
||||
func (pr PolicyReport) HasResult(id string) bool {
|
||||
_, ok := pr.Results[id]
|
||||
for _, r := range pr.Results {
|
||||
if r.ID == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return ok
|
||||
return false
|
||||
}
|
||||
|
||||
// GetResult returns if the Report has an Rusult with the given ID
|
||||
func (pr PolicyReport) GetResult(id string) Result {
|
||||
for _, r := range pr.Results {
|
||||
if r.ID == id {
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
return Result{}
|
||||
}
|
||||
|
||||
// ResultList returns all results as slice
|
||||
func (pr PolicyReport) ResultList() []*Result {
|
||||
list := make([]*Result, 0, len(pr.Results))
|
||||
for _, v := range pr.Results {
|
||||
list = append(list, v)
|
||||
}
|
||||
|
||||
return list
|
||||
func (pr PolicyReport) ResultList() []Result {
|
||||
return pr.Results
|
||||
}
|
||||
|
||||
// GetType returns the Type of the Report
|
||||
|
@ -249,8 +256,8 @@ func (pr PolicyReport) GetType() ResourceType {
|
|||
}
|
||||
|
||||
// GetNewResults filters already existing Results from the old PolicyReport and returns only the diff with new Results
|
||||
func (pr PolicyReport) GetNewResults(or *PolicyReport) []*Result {
|
||||
diff := make([]*Result, 0)
|
||||
func (pr PolicyReport) GetNewResults(or PolicyReport) []Result {
|
||||
diff := make([]Result, 0)
|
||||
|
||||
for _, r := range pr.Results {
|
||||
if or.HasResult(r.GetIdentifier()) {
|
||||
|
@ -264,28 +271,26 @@ func (pr PolicyReport) GetNewResults(or *PolicyReport) []*Result {
|
|||
}
|
||||
|
||||
func GeneratePolicyReportID(name, namespace string) string {
|
||||
id := name
|
||||
h1 := fnv1a.Init64
|
||||
h1 = fnv1a.AddString64(h1, name)
|
||||
|
||||
if namespace != "" {
|
||||
id = fmt.Sprintf("%s__%s", namespace, name)
|
||||
h1 = fnv1a.AddString64(h1, namespace)
|
||||
}
|
||||
|
||||
h := sha1.New()
|
||||
|
||||
h.Write([]byte(id))
|
||||
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
return strconv.FormatUint(h1, 10)
|
||||
}
|
||||
|
||||
func GeneratePolicyReportResultID(uid, name, policy, rule, status, suffix string) string {
|
||||
h1 := fnv1a.Init64
|
||||
h1 = fnv1a.AddString64(h1, name)
|
||||
h1 = fnv1a.AddString64(h1, policy)
|
||||
h1 = fnv1a.AddString64(h1, rule)
|
||||
h1 = fnv1a.AddString64(h1, status)
|
||||
h1 = fnv1a.AddString64(h1, suffix)
|
||||
if uid != "" {
|
||||
suffix = "__" + uid
|
||||
h1 = fnv1a.AddString64(h1, uid)
|
||||
}
|
||||
|
||||
id := fmt.Sprintf("%s_%s__%s__%s%s", name, policy, rule, status, suffix)
|
||||
|
||||
h := sha1.New()
|
||||
h.Write([]byte(id))
|
||||
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
return strconv.FormatUint(h1, 10)
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/report"
|
||||
)
|
||||
|
||||
var result1 = &report.Result{
|
||||
ID: "c6215d837642824766ec511357140bf02636b5d8",
|
||||
var result1 = report.Result{
|
||||
ID: "8804968580595351199",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -17,7 +17,7 @@ var result1 = &report.Result{
|
|||
Category: "resources",
|
||||
Severity: report.High,
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -26,7 +26,7 @@ var result1 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var result2 = &report.Result{
|
||||
var result2 = report.Result{
|
||||
ID: "2",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -35,7 +35,7 @@ var result2 = &report.Result{
|
|||
Status: report.Fail,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -44,20 +44,20 @@ var result2 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var preport = &report.PolicyReport{
|
||||
ID: "24cfa233af033d104cd6ce0ff9a5a875c71a5844",
|
||||
var preport = report.PolicyReport{
|
||||
ID: "7605991845421273693",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: make(map[string]*report.Result),
|
||||
Summary: &report.Summary{},
|
||||
Results: make([]report.Result, 0),
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
var creport = &report.PolicyReport{
|
||||
ID: "57e1551475e17740bacc3640d2412b1a6aad6a93",
|
||||
var creport = report.PolicyReport{
|
||||
ID: "1241710096395975500",
|
||||
Name: "cpolr-test",
|
||||
Results: make(map[string]*report.Result),
|
||||
Summary: &report.Summary{},
|
||||
Results: make([]report.Result, 0),
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
|
@ -71,21 +71,21 @@ func Test_PolicyReport(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Check PolicyReport.GetNewResults", func(t *testing.T) {
|
||||
preport1 := &report.PolicyReport{
|
||||
preport1 := report.PolicyReport{
|
||||
ID: "24cfa233af033d104cd6ce0ff9a5a875c71a5844",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Summary: &report.Summary{},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{result1.GetIdentifier(): result1},
|
||||
Results: []report.Result{result1},
|
||||
}
|
||||
preport2 := &report.PolicyReport{
|
||||
preport2 := report.PolicyReport{
|
||||
ID: "24cfa233af033d104cd6ce0ff9a5a875c71a5844",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Summary: &report.Summary{},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{result1.GetIdentifier(): result1, result2.GetIdentifier(): result2},
|
||||
Results: []report.Result{result1, result2},
|
||||
}
|
||||
|
||||
diff := preport2.GetNewResults(preport1)
|
||||
|
@ -98,9 +98,9 @@ func Test_PolicyReport(t *testing.T) {
|
|||
creport2 := &report.PolicyReport{
|
||||
ID: "57e1551475e17740bacc3640d2412b1a6aad6a93",
|
||||
Name: "cpolr-test",
|
||||
Summary: &report.Summary{},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{result1.GetIdentifier(): result1, result2.GetIdentifier(): result2},
|
||||
Results: []report.Result{result1, result2},
|
||||
}
|
||||
|
||||
list := creport2.ResultList()
|
||||
|
@ -109,7 +109,23 @@ func Test_PolicyReport(t *testing.T) {
|
|||
t.Errorf("Expected len of PolicyReport.ResultList() to be 2 (actual: %d)", len(list))
|
||||
}
|
||||
})
|
||||
t.Run("Check PolicyReport.GetResult", func(t *testing.T) {
|
||||
preport := report.PolicyReport{
|
||||
ID: "24cfa233af033d104cd6ce0ff9a5a875c71a5844",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: []report.Result{result1},
|
||||
}
|
||||
|
||||
if result := preport.GetResult("8804968580595351199"); result.ID != "8804968580595351199" {
|
||||
t.Error("Expected PolicyReport.GetResult() returns a given Result by ID")
|
||||
}
|
||||
if result := preport.GetResult("123"); result.ID != "" {
|
||||
t.Error("Expected PolicyReport.GetResult() returns an empty Result for an unknown ID")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ClusterPolicyReport(t *testing.T) {
|
||||
|
@ -127,20 +143,20 @@ func Test_ClusterPolicyReport(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Check ClusterPolicyReport.GetNewResults", func(t *testing.T) {
|
||||
creport1 := &report.PolicyReport{
|
||||
creport1 := report.PolicyReport{
|
||||
ID: "57e1551475e17740bacc3640d2412b1a6aad6a93",
|
||||
Name: "cpolr-test",
|
||||
Summary: &report.Summary{},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{result1.GetIdentifier(): result1},
|
||||
Results: []report.Result{result1},
|
||||
}
|
||||
|
||||
creport2 := &report.PolicyReport{
|
||||
ID: "57e1551475e17740bacc3640d2412b1a6aad6a93",
|
||||
Name: "cpolr-test",
|
||||
Summary: &report.Summary{},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
Results: map[string]*report.Result{result1.GetIdentifier(): result1, result2.GetIdentifier(): result2},
|
||||
Results: []report.Result{result1, result2},
|
||||
}
|
||||
|
||||
diff := creport2.GetNewResults(creport1)
|
||||
|
@ -170,7 +186,6 @@ func Test_Result(t *testing.T) {
|
|||
t.Errorf("Expected result.HasResource() to be false without a Resource (actual: %v)", result1.HasResource())
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func Test_MarshalPriority(t *testing.T) {
|
||||
|
@ -250,3 +265,20 @@ func Test_Priorities(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Events(t *testing.T) {
|
||||
t.Run("Event.String", func(t *testing.T) {
|
||||
if report.Added.String() != "add" {
|
||||
t.Errorf("Unexpected type conversion, expected %s go %s", "add", report.Added.String())
|
||||
}
|
||||
if report.Updated.String() != "update" {
|
||||
t.Errorf("Unexpected type conversion, expected %s go %s", "update", report.Updated.String())
|
||||
}
|
||||
if report.Deleted.String() != "delete" {
|
||||
t.Errorf("Unexpected type conversion, expected %s go %s", "delete", report.Deleted.String())
|
||||
}
|
||||
if report.Event(4).String() != "unknown" {
|
||||
t.Errorf("Unexpected type conversion, expected %s go %s", "unknown", report.Event(4).String())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,91 +1,16 @@
|
|||
package report
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Group struct {
|
||||
reportsChan chan string
|
||||
eventGroups map[string]chan LifecycleEvent
|
||||
}
|
||||
|
||||
func (g *Group) Register(reportID string) {
|
||||
g.eventGroups[reportID] = make(chan LifecycleEvent)
|
||||
g.reportsChan <- reportID
|
||||
}
|
||||
|
||||
func (g *Group) ChannelAdded() <-chan string {
|
||||
return g.reportsChan
|
||||
}
|
||||
|
||||
func (g *Group) AddEvent(event LifecycleEvent) {
|
||||
if channel, ok := g.eventGroups[event.NewPolicyReport.ID]; ok {
|
||||
channel <- event
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Group) Listen(reportID string) (<-chan LifecycleEvent, error) {
|
||||
if channel, ok := g.eventGroups[reportID]; ok {
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("channel for ReportID %s not found", reportID)
|
||||
}
|
||||
|
||||
func (g *Group) ListenWithRetry(reportID string, retry int) (<-chan LifecycleEvent, error) {
|
||||
var count int
|
||||
var err error
|
||||
for count <= retry {
|
||||
channel, err := g.Listen(reportID)
|
||||
if err == nil {
|
||||
return channel, nil
|
||||
}
|
||||
count++
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (g *Group) Close(reportID string) error {
|
||||
if channel, ok := g.eventGroups[reportID]; ok {
|
||||
close(channel)
|
||||
delete(g.eventGroups, reportID)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("channel for ReportID %s not found", reportID)
|
||||
}
|
||||
|
||||
func (g *Group) CloseRegisterChannel() {
|
||||
close(g.reportsChan)
|
||||
}
|
||||
|
||||
func (g *Group) CloseAll() {
|
||||
for reportID, channel := range g.eventGroups {
|
||||
close(channel)
|
||||
delete(g.eventGroups, reportID)
|
||||
}
|
||||
|
||||
close(g.reportsChan)
|
||||
}
|
||||
|
||||
func NewGroup() *Group {
|
||||
return &Group{
|
||||
reportsChan: make(chan string),
|
||||
eventGroups: make(map[string]chan LifecycleEvent),
|
||||
}
|
||||
}
|
||||
|
||||
type EventPublisher interface {
|
||||
// RegisterListener register Handlers called on each PolicyReport watch.Event
|
||||
RegisterListener(PolicyReportListener)
|
||||
// GetListener returns a list of all registered Listeners
|
||||
GetListener() []PolicyReportListener
|
||||
// Publish events to the registered listeners
|
||||
Publish(reportChannels *Group)
|
||||
// Process LifecycleEvent with all registered listeners
|
||||
Publish(event LifecycleEvent)
|
||||
}
|
||||
|
||||
type lifecycleEventPublisher struct {
|
||||
|
@ -102,33 +27,18 @@ func (p *lifecycleEventPublisher) GetListener() []PolicyReportListener {
|
|||
return p.listeners
|
||||
}
|
||||
|
||||
func (p *lifecycleEventPublisher) Publish(reportChannels *Group) {
|
||||
for channelName := range reportChannels.ChannelAdded() {
|
||||
go func(cName string) {
|
||||
channel, err := reportChannels.ListenWithRetry(cName, 3)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
|
||||
for event := range channel {
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(p.listenerCount)
|
||||
|
||||
func (p *lifecycleEventPublisher) Publish(event LifecycleEvent) {
|
||||
g := sync.WaitGroup{}
|
||||
g.Add(len(p.listeners))
|
||||
for _, listener := range p.listeners {
|
||||
go func(li PolicyReportListener, ev LifecycleEvent) {
|
||||
li(ev)
|
||||
wg.Done()
|
||||
|
||||
g.Done()
|
||||
}(listener, event)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if event.Type == Deleted {
|
||||
reportChannels.Close(cName)
|
||||
}
|
||||
}
|
||||
}(channelName)
|
||||
}
|
||||
g.Wait()
|
||||
}
|
||||
|
||||
func NewEventPublisher() EventPublisher {
|
||||
|
|
|
@ -19,17 +19,7 @@ func Test_PublishLifecycleEvents(t *testing.T) {
|
|||
wg.Done()
|
||||
})
|
||||
|
||||
groups := report.NewGroup()
|
||||
|
||||
go func() {
|
||||
groups.Register("UID")
|
||||
|
||||
groups.AddEvent(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: &report.PolicyReport{ID: "UID"}, OldPolicyReport: &report.PolicyReport{ID: "UID"}})
|
||||
|
||||
groups.CloseAll()
|
||||
}()
|
||||
|
||||
publisher.Publish(groups)
|
||||
publisher.Publish(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: report.PolicyReport{ID: "UID"}, OldPolicyReport: report.PolicyReport{ID: "UID"}})
|
||||
|
||||
wg.Wait()
|
||||
|
||||
|
@ -50,27 +40,14 @@ func Test_PublishDeleteLifecycleEvents(t *testing.T) {
|
|||
wg.Done()
|
||||
})
|
||||
|
||||
groups := report.NewGroup()
|
||||
|
||||
go func() {
|
||||
groups.Register("UID")
|
||||
|
||||
groups.AddEvent(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: &report.PolicyReport{ID: "UID"}, OldPolicyReport: &report.PolicyReport{ID: "UID"}})
|
||||
groups.AddEvent(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: &report.PolicyReport{ID: "UID"}})
|
||||
|
||||
groups.CloseRegisterChannel()
|
||||
}()
|
||||
|
||||
publisher.Publish(groups)
|
||||
publisher.Publish(report.LifecycleEvent{Type: report.Updated, NewPolicyReport: report.PolicyReport{ID: "UID"}, OldPolicyReport: report.PolicyReport{ID: "UID"}})
|
||||
publisher.Publish(report.LifecycleEvent{Type: report.Deleted, NewPolicyReport: report.PolicyReport{ID: "UID"}})
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if event.Type != report.Deleted {
|
||||
t.Error("Expected Event to be published to the listener")
|
||||
}
|
||||
if _, err := groups.Listen("UID"); err == nil {
|
||||
t.Error("Expected report to be deleted")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetReisteredListeners(t *testing.T) {
|
||||
|
@ -81,12 +58,3 @@ func Test_GetReisteredListeners(t *testing.T) {
|
|||
t.Error("Expected to get one registered listener back")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ListenUknownChannel(t *testing.T) {
|
||||
reportChannel := report.NewGroup()
|
||||
_, err := reportChannel.Listen("test")
|
||||
|
||||
if err == nil {
|
||||
t.Error("Expected to get a not found error")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ type PolicyReportStore interface {
|
|||
// CreateSchemas for PolicyReports and PolicyReportResults
|
||||
CreateSchemas() error
|
||||
// Get an PolicyReport by Type and ID
|
||||
Get(id string) (*PolicyReport, bool)
|
||||
Get(id string) (PolicyReport, bool)
|
||||
// Add a PolicyReport to the Store
|
||||
Add(r *PolicyReport) error
|
||||
Add(r PolicyReport) error
|
||||
// Add a PolicyReport to the Store
|
||||
Update(r *PolicyReport) error
|
||||
Update(r PolicyReport) error
|
||||
// Remove a PolicyReport with the given Type and ID from the Store
|
||||
Remove(id string) error
|
||||
// CleanUp removes all items in the store
|
||||
|
@ -19,7 +19,7 @@ type PolicyReportStore interface {
|
|||
|
||||
// PolicyReportStore caches the latest version of an PolicyReport
|
||||
type policyReportStore struct {
|
||||
store map[string]map[string]*PolicyReport
|
||||
store map[string]map[string]PolicyReport
|
||||
rwm *sync.RWMutex
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ func (s *policyReportStore) CreateSchemas() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *policyReportStore) Get(id string) (*PolicyReport, bool) {
|
||||
func (s *policyReportStore) Get(id string) (PolicyReport, bool) {
|
||||
s.rwm.RLock()
|
||||
r, ok := s.store[PolicyReportType][id]
|
||||
s.rwm.RUnlock()
|
||||
|
@ -42,7 +42,7 @@ func (s *policyReportStore) Get(id string) (*PolicyReport, bool) {
|
|||
return r, ok
|
||||
}
|
||||
|
||||
func (s *policyReportStore) Add(r *PolicyReport) error {
|
||||
func (s *policyReportStore) Add(r PolicyReport) error {
|
||||
s.rwm.Lock()
|
||||
s.store[r.GetType()][r.GetIdentifier()] = r
|
||||
s.rwm.Unlock()
|
||||
|
@ -50,7 +50,7 @@ func (s *policyReportStore) Add(r *PolicyReport) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *policyReportStore) Update(r *PolicyReport) error {
|
||||
func (s *policyReportStore) Update(r PolicyReport) error {
|
||||
s.rwm.Lock()
|
||||
s.store[r.GetType()][r.GetIdentifier()] = r
|
||||
s.rwm.Unlock()
|
||||
|
@ -70,7 +70,7 @@ func (s *policyReportStore) Remove(id string) error {
|
|||
|
||||
func (s *policyReportStore) CleanUp() error {
|
||||
s.rwm.Lock()
|
||||
s.store = map[ResourceType]map[string]*PolicyReport{
|
||||
s.store = map[ResourceType]map[string]PolicyReport{
|
||||
PolicyReportType: {},
|
||||
ClusterPolicyReportType: {},
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ func (s *policyReportStore) CleanUp() error {
|
|||
// NewPolicyReportStore construct a PolicyReportStore
|
||||
func NewPolicyReportStore() PolicyReportStore {
|
||||
return &policyReportStore{
|
||||
store: map[ResourceType]map[string]*PolicyReport{
|
||||
store: map[ResourceType]map[string]PolicyReport{
|
||||
PolicyReportType: {},
|
||||
ClusterPolicyReportType: {},
|
||||
},
|
||||
|
|
|
@ -25,12 +25,12 @@ func Test_PolicyReportStore(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Update/Get", func(t *testing.T) {
|
||||
ureport := &report.PolicyReport{
|
||||
ID: "24cfa233af033d104cd6ce0ff9a5a875c71a5844",
|
||||
ureport := report.PolicyReport{
|
||||
ID: "7605991845421273693",
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: make(map[string]*report.Result),
|
||||
Summary: &report.Summary{Skip: 1},
|
||||
Results: make([]report.Result, 0),
|
||||
Summary: report.Summary{Skip: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
|
|
|
@ -81,9 +81,9 @@ func (s *policyReportStore) CreateSchemas() error {
|
|||
}
|
||||
|
||||
// Get an PolicyReport by Type and ID
|
||||
func (s *policyReportStore) Get(id string) (*report.PolicyReport, bool) {
|
||||
func (s *policyReportStore) Get(id string) (report.PolicyReport, bool) {
|
||||
var created int64
|
||||
r := &report.PolicyReport{Summary: &report.Summary{}}
|
||||
r := report.PolicyReport{Summary: report.Summary{}}
|
||||
|
||||
row := s.db.QueryRow("SELECT namespace, name, pass, skip, warn, fail, error, created FROM policy_report WHERE id=$1", id)
|
||||
err := row.Scan(&r.Namespace, &r.Name, &r.Summary.Pass, &r.Summary.Skip, &r.Summary.Warn, &r.Summary.Fail, &r.Summary.Error, &created)
|
||||
|
@ -108,7 +108,7 @@ func (s *policyReportStore) Get(id string) (*report.PolicyReport, bool) {
|
|||
}
|
||||
|
||||
// Add a PolicyReport to the Store
|
||||
func (s *policyReportStore) Add(r *report.PolicyReport) error {
|
||||
func (s *policyReportStore) Add(r report.PolicyReport) error {
|
||||
stmt, err := s.db.Prepare("INSERT INTO policy_report(id, type, namespace, name, pass, skip, warn, fail, error, created) values(?,?,?,?,?,?,?,?,?,?)")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -123,7 +123,7 @@ func (s *policyReportStore) Add(r *report.PolicyReport) error {
|
|||
return s.persistResults(r)
|
||||
}
|
||||
|
||||
func (s *policyReportStore) Update(r *report.PolicyReport) error {
|
||||
func (s *policyReportStore) Update(r report.PolicyReport) error {
|
||||
stmt, err := s.db.Prepare("UPDATE policy_report SET pass=?, skip=?, warn=?, fail=?, error=?, created=? WHERE id=?")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -755,12 +755,15 @@ func (s *policyReportStore) CountClusterResults(filter api.Filter) (int, error)
|
|||
return count, nil
|
||||
}
|
||||
|
||||
func (s *policyReportStore) persistResults(report *report.PolicyReport) error {
|
||||
func (s *policyReportStore) persistResults(report report.PolicyReport) error {
|
||||
var vals []interface{}
|
||||
var sqlStr string
|
||||
|
||||
bulks := chunkSlice(report.ResultList(), 50)
|
||||
|
||||
for _, list := range bulks {
|
||||
sqlStr := resultInsertBaseSQL
|
||||
vals := make([]interface{}, 0, len(list)*18)
|
||||
sqlStr = resultInsertBaseSQL
|
||||
vals = make([]interface{}, 0, len(list)*18)
|
||||
|
||||
for _, result := range list {
|
||||
sqlStr += "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?),"
|
||||
|
@ -810,8 +813,8 @@ func (s *policyReportStore) persistResults(report *report.PolicyReport) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *policyReportStore) fetchResults(reportID string) (map[string]*report.Result, error) {
|
||||
results := make(map[string]*report.Result)
|
||||
func (s *policyReportStore) fetchResults(reportID string) ([]report.Result, error) {
|
||||
results := make([]report.Result, 0)
|
||||
|
||||
rows, err := s.db.Query(`
|
||||
SELECT
|
||||
|
@ -844,8 +847,8 @@ func (s *policyReportStore) fetchResults(reportID string) (map[string]*report.Re
|
|||
var timestamp int64
|
||||
|
||||
for rows.Next() {
|
||||
result := &report.Result{
|
||||
Resource: &report.Resource{},
|
||||
result := report.Result{
|
||||
Resource: report.Resource{},
|
||||
}
|
||||
|
||||
err = rows.Scan(
|
||||
|
@ -878,7 +881,7 @@ func (s *policyReportStore) fetchResults(reportID string) (map[string]*report.Re
|
|||
|
||||
result.Timestamp = time.Unix(timestamp, 0)
|
||||
|
||||
results[result.GetIdentifier()] = result
|
||||
results = append(results, result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
|
@ -1019,8 +1022,8 @@ func NewDatabase(dbFile string) (*sql.DB, error) {
|
|||
return sql.Open("sqlite3", dbFile)
|
||||
}
|
||||
|
||||
func chunkSlice(slice []*report.Result, chunkSize int) [][]*report.Result {
|
||||
var chunks [][]*report.Result
|
||||
func chunkSlice(slice []report.Result, chunkSize int) [][]report.Result {
|
||||
var chunks [][]report.Result
|
||||
for i := 0; i < len(slice); i += chunkSize {
|
||||
end := i + chunkSize
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
var pagination = v1.Pagination{Page: 1, Offset: 20, Direction: "ASC", SortBy: []string{"resource_name"}}
|
||||
|
||||
var result1 = &report.Result{
|
||||
var result1 = report.Result{
|
||||
ID: "123",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -22,7 +22,7 @@ var result1 = &report.Result{
|
|||
Severity: report.High,
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -31,7 +31,7 @@ var result1 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var result2 = &report.Result{
|
||||
var result2 = report.Result{
|
||||
ID: "124",
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
|
@ -41,7 +41,7 @@ var result2 = &report.Result{
|
|||
Category: "Best Practices",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Name: "nginx",
|
||||
|
@ -50,7 +50,7 @@ var result2 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var cresult1 = &report.Result{
|
||||
var cresult1 = report.Result{
|
||||
ID: "125",
|
||||
Message: "validation error: The label `test` is required. Rule check-for-labels-on-namespace",
|
||||
Policy: "require-ns-labels",
|
||||
|
@ -61,7 +61,7 @@ var cresult1 = &report.Result{
|
|||
Severity: report.Medium,
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Namespace",
|
||||
Name: "test",
|
||||
|
@ -69,7 +69,7 @@ var cresult1 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var cresult2 = &report.Result{
|
||||
var cresult2 = report.Result{
|
||||
ID: "126",
|
||||
Message: "validation error: The label `test` is required. Rule check-for-labels-on-namespace",
|
||||
Policy: "require-ns-labels",
|
||||
|
@ -80,7 +80,7 @@ var cresult2 = &report.Result{
|
|||
Severity: report.High,
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Namespace",
|
||||
Name: "dev",
|
||||
|
@ -88,37 +88,29 @@ var cresult2 = &report.Result{
|
|||
},
|
||||
}
|
||||
|
||||
var preport = &report.PolicyReport{
|
||||
var preport = report.PolicyReport{
|
||||
ID: report.GeneratePolicyReportID("polr-test", "test"),
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
},
|
||||
Summary: &report.Summary{Fail: 1},
|
||||
Results: []report.Result{result1},
|
||||
Summary: report.Summary{Fail: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
var ureport = &report.PolicyReport{
|
||||
var ureport = report.PolicyReport{
|
||||
ID: report.GeneratePolicyReportID("polr-test", "test"),
|
||||
Name: "polr-test",
|
||||
Namespace: "test",
|
||||
Results: map[string]*report.Result{
|
||||
result1.GetIdentifier(): result1,
|
||||
result2.GetIdentifier(): result2,
|
||||
},
|
||||
Summary: &report.Summary{Fail: 1, Pass: 1},
|
||||
Results: []report.Result{result1, result2},
|
||||
Summary: report.Summary{Fail: 1, Pass: 1},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
var creport = &report.PolicyReport{
|
||||
var creport = report.PolicyReport{
|
||||
ID: report.GeneratePolicyReportID("cpolr", ""),
|
||||
Name: "cpolr",
|
||||
Results: map[string]*report.Result{
|
||||
cresult1.GetIdentifier(): cresult1,
|
||||
cresult2.GetIdentifier(): cresult2,
|
||||
},
|
||||
Summary: &report.Summary{},
|
||||
Results: []report.Result{cresult1, cresult2},
|
||||
Summary: report.Summary{},
|
||||
CreationTimestamp: time.Now(),
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,13 @@ import (
|
|||
// Client for a provided Target
|
||||
type Client interface {
|
||||
// Send the given Result to the configured Target
|
||||
Send(result *report.Result)
|
||||
Send(result report.Result)
|
||||
// SkipExistingOnStartup skips already existing PolicyReportResults on startup
|
||||
SkipExistingOnStartup() bool
|
||||
// Name is a unique identifier for each Target
|
||||
Name() string
|
||||
// Validate is a result should send
|
||||
Validate(result *report.Result) bool
|
||||
Validate(result report.Result) bool
|
||||
// MinimumPriority for a triggered Result to send to this target
|
||||
MinimumPriority() string
|
||||
// Sources of the Results which should send to this target, empty means all sources
|
||||
|
@ -36,7 +36,7 @@ type Filter struct {
|
|||
Sources []string
|
||||
}
|
||||
|
||||
func (f *Filter) Validate(result *report.Result) bool {
|
||||
func (f *Filter) Validate(result report.Result) bool {
|
||||
if len(f.Sources) > 0 && !contains(result.Source, f.Sources) {
|
||||
return false
|
||||
}
|
||||
|
@ -60,8 +60,8 @@ func (f *Filter) Validate(result *report.Result) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (f *Filter) validateNamespaceRules(result *report.Result) bool {
|
||||
if result.Resource != nil && len(f.Namespace.Include) > 0 {
|
||||
func (f *Filter) validateNamespaceRules(result report.Result) bool {
|
||||
if result.HasResource() && len(f.Namespace.Include) > 0 {
|
||||
for _, ns := range f.Namespace.Include {
|
||||
if wildcard.Match(ns, result.Resource.Namespace) {
|
||||
return true
|
||||
|
@ -69,7 +69,7 @@ func (f *Filter) validateNamespaceRules(result *report.Result) bool {
|
|||
}
|
||||
|
||||
return false
|
||||
} else if result.Resource != nil && len(f.Namespace.Exclude) > 0 {
|
||||
} else if result.HasResource() && len(f.Namespace.Exclude) > 0 {
|
||||
for _, ns := range f.Namespace.Exclude {
|
||||
if wildcard.Match(ns, result.Resource.Namespace) {
|
||||
return false
|
||||
|
@ -80,7 +80,7 @@ func (f *Filter) validateNamespaceRules(result *report.Result) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (f *Filter) validatePolicyRules(result *report.Result) bool {
|
||||
func (f *Filter) validatePolicyRules(result report.Result) bool {
|
||||
if len(f.Policy.Include) > 0 {
|
||||
for _, ns := range f.Policy.Include {
|
||||
if wildcard.Match(ns, result.Policy) {
|
||||
|
@ -100,7 +100,7 @@ func (f *Filter) validatePolicyRules(result *report.Result) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (f *Filter) validatePriorityRules(result *report.Result) bool {
|
||||
func (f *Filter) validatePriorityRules(result report.Result) bool {
|
||||
if len(f.Priority.Include) > 0 {
|
||||
return contains(result.Priority.String(), f.Priority.Include)
|
||||
} else if len(f.Priority.Exclude) > 0 && contains(result.Priority.String(), f.Priority.Exclude) {
|
||||
|
@ -128,7 +128,7 @@ func (c *BaseClient) Sources() []string {
|
|||
return c.filter.Sources
|
||||
}
|
||||
|
||||
func (c *BaseClient) Validate(result *report.Result) bool {
|
||||
func (c *BaseClient) Validate(result report.Result) bool {
|
||||
return c.filter.Validate(result)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target"
|
||||
)
|
||||
|
||||
var result = &report.Result{
|
||||
var result = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -17,7 +17,7 @@ var result = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
|
|
@ -34,7 +34,7 @@ var colors = map[report.Priority]string{
|
|||
report.ErrorPriority: "15158332",
|
||||
}
|
||||
|
||||
func newPayload(result *report.Result) payload {
|
||||
func newPayload(result report.Result) payload {
|
||||
color := colors[result.Priority]
|
||||
|
||||
embedFields := make([]embedField, 0)
|
||||
|
@ -89,7 +89,7 @@ type client struct {
|
|||
client http.Client
|
||||
}
|
||||
|
||||
func (d *client) Send(result *report.Result) {
|
||||
func (d *client) Send(result report.Result) {
|
||||
req, err := http.CreateJSONRequest(d.Name(), "POST", d.webhook, newPayload(result))
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/discord"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -21,7 +21,7 @@ var completeResult = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -31,7 +31,7 @@ var completeResult = &report.Result{
|
|||
Properties: map[string]string{"version": "1.2.0"},
|
||||
}
|
||||
|
||||
var minimalResult = &report.Result{
|
||||
var minimalResult = report.Result{
|
||||
Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "app-label-requirement",
|
||||
Priority: report.CriticalPriority,
|
||||
|
|
|
@ -27,7 +27,7 @@ type client struct {
|
|||
client http.Client
|
||||
}
|
||||
|
||||
func (e *client) Send(result *report.Result) {
|
||||
func (e *client) Send(result report.Result) {
|
||||
var host string
|
||||
switch e.rotation {
|
||||
case None:
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/elasticsearch"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -21,7 +21,7 @@ var completeResult = &report.Result{
|
|||
Category: "resources",
|
||||
Source: "Kyverno",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
|
|
@ -49,7 +49,7 @@ func ProcessHTTPResponse(target string, resp *http.Response, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
func NewJSONResult(r *report.Result) Result {
|
||||
func NewJSONResult(r report.Result) Result {
|
||||
return Result{
|
||||
Message: r.Message,
|
||||
Policy: r.Policy,
|
||||
|
|
|
@ -17,7 +17,7 @@ type client struct {
|
|||
kinesis helper.AWSClient
|
||||
}
|
||||
|
||||
func (c *client) Send(result *report.Result) {
|
||||
func (c *client) Send(result report.Result) {
|
||||
body := new(bytes.Buffer)
|
||||
|
||||
if err := json.NewEncoder(body).Encode(result); err != nil {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/kinesis"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -19,7 +19,7 @@ var completeResult = &report.Result{
|
|||
Severity: report.High,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
|
|
@ -23,7 +23,7 @@ type entry struct {
|
|||
Line string `json:"line"`
|
||||
}
|
||||
|
||||
func newLokiPayload(result *report.Result, customLabels map[string]string) payload {
|
||||
func newLokiPayload(result report.Result, customLabels map[string]string) payload {
|
||||
timestamp := time.Now()
|
||||
if !result.Timestamp.IsZero() {
|
||||
timestamp = result.Timestamp
|
||||
|
@ -85,7 +85,7 @@ type client struct {
|
|||
customLabels map[string]string
|
||||
}
|
||||
|
||||
func (l *client) Send(result *report.Result) {
|
||||
func (l *client) Send(result report.Result) {
|
||||
req, err := http.CreateJSONRequest(l.Name(), "POST", l.host, newLokiPayload(result, l.customLabels))
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/loki"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -24,7 +24,7 @@ var completeResult = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -34,7 +34,7 @@ var completeResult = &report.Result{
|
|||
Properties: map[string]string{"version": "1.2.0"},
|
||||
}
|
||||
|
||||
var minimalResult = &report.Result{
|
||||
var minimalResult = report.Result{
|
||||
Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "app-label-requirement",
|
||||
Priority: report.WarningPriority,
|
||||
|
|
|
@ -18,7 +18,7 @@ type client struct {
|
|||
prefix string
|
||||
}
|
||||
|
||||
func (c *client) Send(result *report.Result) {
|
||||
func (c *client) Send(result report.Result) {
|
||||
body := new(bytes.Buffer)
|
||||
|
||||
if err := json.NewEncoder(body).Encode(result); err != nil {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/s3"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -19,7 +19,7 @@ var completeResult = &report.Result{
|
|||
Severity: report.High,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
|
|
@ -48,7 +48,7 @@ var colors = map[report.Priority]string{
|
|||
report.ErrorPriority: "#e20b0b",
|
||||
}
|
||||
|
||||
func (s *client) newPayload(result *report.Result) payload {
|
||||
func (s *client) newPayload(result report.Result) payload {
|
||||
p := payload{
|
||||
Attachments: make([]attachment, 0, 1),
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ func (s *client) newPayload(result *report.Result) payload {
|
|||
return p
|
||||
}
|
||||
|
||||
func (s *client) Send(result *report.Result) {
|
||||
func (s *client) Send(result report.Result) {
|
||||
req, err := http.CreateJSONRequest(s.Name(), "POST", s.webhook, s.newPayload(result))
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/slack"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -21,7 +21,7 @@ var completeResult = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -31,7 +31,7 @@ var completeResult = &report.Result{
|
|||
Properties: map[string]string{"version": "1.2.0"},
|
||||
}
|
||||
|
||||
var enforceResult = &report.Result{
|
||||
var enforceResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "check-for-requests-and-limits",
|
||||
|
@ -42,7 +42,7 @@ var enforceResult = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "",
|
||||
Kind: "Pod",
|
||||
Name: "nginx",
|
||||
|
@ -52,7 +52,7 @@ var enforceResult = &report.Result{
|
|||
Properties: map[string]string{"version": "1.2.0"},
|
||||
}
|
||||
|
||||
var incompleteResult = &report.Result{
|
||||
var incompleteResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "check-for-requests-and-limits",
|
||||
|
@ -63,7 +63,7 @@ var incompleteResult = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Name: "nginx",
|
||||
|
@ -73,7 +73,7 @@ var incompleteResult = &report.Result{
|
|||
Properties: map[string]string{"version": "1.2.0"},
|
||||
}
|
||||
|
||||
var incompleteResult2 = &report.Result{
|
||||
var incompleteResult2 = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "check-for-requests-and-limits",
|
||||
|
@ -84,7 +84,7 @@ var incompleteResult2 = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "",
|
||||
Kind: "Pod",
|
||||
Name: "nginx",
|
||||
|
@ -94,7 +94,7 @@ var incompleteResult2 = &report.Result{
|
|||
Properties: map[string]string{"version": "1.2.0"},
|
||||
}
|
||||
|
||||
var minimalResult = &report.Result{
|
||||
var minimalResult = report.Result{
|
||||
Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "app-label-requirement",
|
||||
Priority: report.WarningPriority,
|
||||
|
|
|
@ -37,7 +37,7 @@ var colors = map[report.Priority]string{
|
|||
report.ErrorPriority: "e20b0b",
|
||||
}
|
||||
|
||||
func newPayload(result *report.Result) payload {
|
||||
func newPayload(result report.Result) payload {
|
||||
facts := make([]fact, 0)
|
||||
|
||||
facts = append(facts, fact{"Policy", result.Policy})
|
||||
|
@ -103,7 +103,7 @@ type client struct {
|
|||
client http.Client
|
||||
}
|
||||
|
||||
func (s *client) Send(result *report.Result) {
|
||||
func (s *client) Send(result report.Result) {
|
||||
req, err := http.CreateJSONRequest(s.Name(), "POST", s.webhook, newPayload(result))
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/teams"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -22,7 +22,7 @@ var completeResult = &report.Result{
|
|||
Category: "resources",
|
||||
Scored: true,
|
||||
Source: "Kyverno",
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
@ -32,7 +32,7 @@ var completeResult = &report.Result{
|
|||
Properties: map[string]string{"version": "1.2.0"},
|
||||
}
|
||||
|
||||
var minimalErrorResult = &report.Result{
|
||||
var minimalErrorResult = report.Result{
|
||||
Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "app-label-requirement",
|
||||
Priority: report.ErrorPriority,
|
||||
|
@ -40,7 +40,7 @@ var minimalErrorResult = &report.Result{
|
|||
Scored: true,
|
||||
}
|
||||
|
||||
var minimalResult = &report.Result{
|
||||
var minimalResult = report.Result{
|
||||
Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "app-label-requirement",
|
||||
Priority: report.CriticalPriority,
|
||||
|
@ -48,7 +48,7 @@ var minimalResult = &report.Result{
|
|||
Scored: true,
|
||||
}
|
||||
|
||||
var minimalInfoResult = &report.Result{
|
||||
var minimalInfoResult = report.Result{
|
||||
Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "app-label-requirement",
|
||||
Priority: report.InfoPriority,
|
||||
|
@ -56,7 +56,7 @@ var minimalInfoResult = &report.Result{
|
|||
Scored: true,
|
||||
}
|
||||
|
||||
var minimalDebugResult = &report.Result{
|
||||
var minimalDebugResult = report.Result{
|
||||
Message: "validation error: label required. Rule app-label-required failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "app-label-requirement",
|
||||
Priority: report.DebugPriority,
|
||||
|
|
|
@ -12,7 +12,7 @@ type client struct {
|
|||
client http.Client
|
||||
}
|
||||
|
||||
func (e *client) Send(result *report.Result) {
|
||||
func (e *client) Send(result report.Result) {
|
||||
req, err := http.CreateJSONRequest(e.Name(), "POST", e.host, http.NewJSONResult(result))
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/ui"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -18,7 +18,7 @@ var completeResult = &report.Result{
|
|||
Severity: report.High,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
|
|
@ -13,7 +13,7 @@ type client struct {
|
|||
client http.Client
|
||||
}
|
||||
|
||||
func (e *client) Send(result *report.Result) {
|
||||
func (e *client) Send(result report.Result) {
|
||||
req, err := http.CreateJSONRequest(e.Name(), "POST", e.host, http.NewJSONResult(result))
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/webhook"
|
||||
)
|
||||
|
||||
var completeResult = &report.Result{
|
||||
var completeResult = report.Result{
|
||||
Message: "validation error: requests and limits required. Rule autogen-check-for-requests-and-limits failed at path /spec/template/spec/containers/0/resources/requests/",
|
||||
Policy: "require-requests-and-limits-required",
|
||||
Rule: "autogen-check-for-requests-and-limits",
|
||||
|
@ -20,7 +20,7 @@ var completeResult = &report.Result{
|
|||
Severity: report.High,
|
||||
Category: "resources",
|
||||
Scored: true,
|
||||
Resource: &report.Resource{
|
||||
Resource: report.Resource{
|
||||
APIVersion: "v1",
|
||||
Kind: "Deployment",
|
||||
Name: "nginx",
|
||||
|
|
Loading…
Reference in a new issue