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

Merge branch 'master' into 544_documentation

# Conflicts:
#	pkg/engine/overlay_test.go
This commit is contained in:
Shuting Zhao 2019-12-27 13:04:07 -08:00
commit 340dee24bc
16 changed files with 308 additions and 131 deletions

View file

@ -7,6 +7,7 @@ import (
"flag"
"os"
"sync"
"time"
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/config"
@ -41,7 +42,7 @@ func main() {
// DYNAMIC CLIENT
// - client for all registered resources
client, err := client.NewClient(clientConfig)
client, err := client.NewClient(clientConfig, 10*time.Second, stopCh)
if err != nil {
glog.Fatalf("Error creating client: %v\n", err)
}

View file

@ -60,12 +60,13 @@ func main() {
// DYNAMIC CLIENT
// - client for all registered resources
client, err := dclient.NewClient(clientConfig)
// - invalidate local cache of registered resource every 10 seconds
client, err := dclient.NewClient(clientConfig, 10*time.Second, stopCh)
if err != nil {
glog.Fatalf("Error creating client: %v\n", err)
}
// CRD CHECK
// - verify if the CRD for Policy & PolicyViolation are avialalbe
// - verify if the CRD for Policy & PolicyViolation are available
if !utils.CRDInstalled(client.DiscoveryClient) {
glog.Fatalf("Required CRDs unavailable")
}

View file

@ -36,7 +36,7 @@ type Client struct {
}
//NewClient creates new instance of client
func NewClient(config *rest.Config) (*Client, error) {
func NewClient(config *rest.Config, resync time.Duration, stopCh <-chan struct{}) (*Client, error) {
dclient, err := dynamic.NewForConfig(config)
if err != nil {
return nil, err
@ -52,6 +52,13 @@ func NewClient(config *rest.Config) (*Client, error) {
}
// Set discovery client
discoveryClient := ServerPreferredResources{memory.NewMemCacheClient(kclient.Discovery())}
// client will invalidate registered resources cache every x seconds,
// As there is no way to identify if the registered resource is available or not
// we will be invalidating the local cache, so the next request get a fresh cache
// If a resource is removed then and cache is not invalidate yet, we will not detect the removal
// but the re-sync shall re-evaluate
go discoveryClient.Poll(resync, stopCh)
client.SetDiscovery(discoveryClient)
return &client, nil
}
@ -266,6 +273,25 @@ type ServerPreferredResources struct {
cachedClient discovery.CachedDiscoveryInterface
}
//Poll will keep invalidate the local cache
func (c ServerPreferredResources) Poll(resync time.Duration, stopCh <-chan struct{}) {
// start a ticker
ticker := time.NewTicker(resync)
defer func() { ticker.Stop() }()
glog.Infof("Starting registered resources sync: every %d seconds", resync)
for {
select {
case <-stopCh:
glog.Info("Stopping registered resources sync")
return
case <-ticker.C:
// set cache as stale
glog.V(6).Info("invalidating local client cache for registered resources")
c.cachedClient.Invalidate()
}
}
}
//GetGVRFromKind get the Group Version Resource from kind
// if kind is not found in first attempt we invalidate the cache,
// the retry will then fetch the new registered resources and check again

View file

@ -281,7 +281,7 @@ func applyOverlayToArrayOfMaps(resource, overlay []interface{}, path string) ([]
if len(anchors) > 0 {
// If we have anchors - choose corresponding resource element and mutate it
patches, err := applyOverlayWithAnchors(resource, overlayElement, anchors, path)
patches, err := applyOverlayWithAnchors(resource, overlayElement, path)
if err != nil {
return nil, err
}
@ -312,21 +312,17 @@ func applyOverlayToArrayOfMaps(resource, overlay []interface{}, path string) ([]
return appliedPatches, nil
}
func applyOverlayWithAnchors(resource []interface{}, overlay interface{}, anchors map[string]interface{}, path string) ([][]byte, error) {
func applyOverlayWithAnchors(resource []interface{}, overlay interface{}, path string) ([][]byte, error) {
var appliedPatches [][]byte
for i, resourceElement := range resource {
typedResource := resourceElement.(map[string]interface{})
currentPath := path + strconv.Itoa(i) + "/"
// currentPath example: /spec/template/spec/containers/3/
if !skipArrayObject(typedResource, anchors) {
patches, err := applyOverlay(resourceElement, overlay, currentPath)
if err != nil {
return nil, err
}
appliedPatches = append(appliedPatches, patches...)
patches, err := applyOverlay(resourceElement, overlay, currentPath)
if err != nil {
return nil, err
}
appliedPatches = append(appliedPatches, patches...)
}
return appliedPatches, nil

View file

@ -1071,3 +1071,88 @@ func Test_wrapBoolean(t *testing.T) {
assert.Assert(t, testcase.expected == out)
}
}
func TestApplyOverlay_ConditionOnArray(t *testing.T) {
resourceRaw := []byte(`
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "myapp-pod",
"labels": {
"app": "myapp",
"dedicated": "spark"
}
},
"spec": {
"containers": [
{
"name": "myapp-container",
"image": "busybox",
"command": [
"sh",
"-c",
"echo Hello Kubernetes! && sleep 3600"
]
}
],
"affinity": {
"nodeAffinity": {
"a": {
"b": [
{
"matchExpressions": [
{
"key": "dedicated",
"operator": "NotIn",
"values": [
"spark"
]
}
]
}
]
}
}
}
}
}
`)
overlayRaw := []byte(`
{
"spec": {
"affinity": {
"nodeAffinity": {
"a": {
"b": [
{
"matchExpressions": [
{
"(key)": "dedicated",
"operator": "In",
"(values)": [
"spark"
]
}
]
}
]
}
}
}
}
}
`)
var resource, overlay interface{}
assert.NilError(t, json.Unmarshal(resourceRaw, &resource))
assert.NilError(t, json.Unmarshal(overlayRaw, &overlay))
expectedPatches := []byte(`[
{ "op": "replace", "path": "/spec/affinity/nodeAffinity/a/b/0/matchExpressions/0/operator", "value":"In" }
]`)
p, err := applyOverlay(resource, overlay, "/")
assert.NilError(t, err)
assert.Assert(t, string(JoinPatches(p)) == string(expectedPatches))
}

View file

@ -7,8 +7,8 @@ import (
"strings"
"github.com/golang/glog"
"github.com/minio/minio/pkg/wildcard"
apiresource "k8s.io/apimachinery/pkg/api/resource"
)
// Operator is string alias that represents selection operators enum
@ -32,6 +32,14 @@ const (
const relativePrefix Operator = "./"
const referenceSign Operator = "$()"
type quantity int
const (
equal quantity = 0
lessThan quantity = -1
greaterThan quantity = 1
)
// ValidateValueWithPattern validates value with operators and wildcards
func ValidateValueWithPattern(value, pattern interface{}) bool {
switch typedPattern := pattern.(type) {
@ -187,7 +195,7 @@ func validateValueWithStringPattern(value interface{}, pattern string) bool {
return validateString(value, str, operator)
}
return validateNumberWithStr(value, number, str, operator)
return validateNumberWithStr(value, pattern, operator)
}
// Handler for string values
@ -212,53 +220,50 @@ func validateString(value interface{}, pattern string, operator Operator) bool {
return false
}
// validateNumberWithStr applies wildcard to suffix and operator to numerical part
func validateNumberWithStr(value interface{}, patternNumber, patternStr string, operator Operator) bool {
// pattern has suffix
if "" != patternStr {
typedValue, ok := value.(string)
if !ok {
glog.Warningf("Number must have suffix: %s", patternStr)
return false
}
valueNumber, valueStr := getNumberAndStringPartsFromPattern(typedValue)
if !wildcard.Match(patternStr, valueStr) {
glog.Warningf("Suffix %s has not passed wildcard check: %s", valueStr, patternStr)
return false
}
return validateNumber(valueNumber, patternNumber, operator)
// validateNumberWithStr compares quantity if pattern type is quantity
// or a wildcard match to pattern string
func validateNumberWithStr(value interface{}, pattern string, operator Operator) bool {
typedValue, err := convertToString(value)
if err != nil {
glog.Warning(err)
return false
}
return validateNumber(value, patternNumber, operator)
patternQuan, err := apiresource.ParseQuantity(pattern)
// 1. nil error - quantity comparison
if err == nil {
valueQuan, err := apiresource.ParseQuantity(typedValue)
if err != nil {
glog.Warningf("Invalid quantity in resource %s, err: %v\n", typedValue, err)
return false
}
return compareQuantity(valueQuan, patternQuan, operator)
}
// 2. wildcard match
if !wildcard.Match(pattern, typedValue) {
glog.Warningf("Value '%s' has not passed wildcard check: %s", typedValue, pattern)
return false
}
return true
}
// validateNumber compares two numbers with operator
func validateNumber(value, pattern interface{}, operator Operator) bool {
floatPattern, err := convertToFloat(pattern)
if err != nil {
return false
}
floatValue, err := convertToFloat(value)
if err != nil {
return false
}
func compareQuantity(value, pattern apiresource.Quantity, operator Operator) bool {
result := value.Cmp(pattern)
switch operator {
case Equal:
return floatValue == floatPattern
return result == int(equal)
case NotEqual:
return floatValue != floatPattern
return result != int(equal)
case More:
return floatValue > floatPattern
case MoreEqual:
return floatValue >= floatPattern
return result == int(greaterThan)
case Less:
return floatValue < floatPattern
return result == int(lessThan)
case MoreEqual:
return (result == int(equal)) || (result == int(greaterThan))
case LessEqual:
return floatValue <= floatPattern
return (result == int(equal)) || (result == int(lessThan))
}
return false

View file

@ -152,6 +152,10 @@ func TestValidateValueWithPattern_StringsLogicalOr(t *testing.T) {
assert.Assert(t, ValidateValueWithPattern(value, pattern))
}
func TestValidateValueWithPattern_EqualTwoFloats(t *testing.T) {
assert.Assert(t, ValidateValueWithPattern(7.0, 7.000))
}
func TestValidateValueWithNilPattern_NullPatternStringValue(t *testing.T) {
assert.Assert(t, !validateValueWithNilPattern("value"))
}
@ -242,32 +246,36 @@ func TestGetNumberAndStringPartsFromPattern_Empty(t *testing.T) {
assert.Equal(t, str, "")
}
func TestValidateNumber_EqualTwoFloats(t *testing.T) {
assert.Assert(t, validateNumber(7.0, 7.000, Equal))
func TestValidateNumberWithStr_LessFloatAndInt(t *testing.T) {
assert.Assert(t, validateNumberWithStr(7.00001, "7.000001", More))
assert.Assert(t, validateNumberWithStr(7.00001, "7", NotEqual))
assert.Assert(t, validateNumberWithStr(7.0000, "7", Equal))
assert.Assert(t, !validateNumberWithStr(6.000000001, "6", Less))
}
func TestValidateNumber_LessFloatAndInt(t *testing.T) {
assert.Assert(t, validateNumber(7, 7.00001, Less))
assert.Assert(t, validateNumber(7, 7.00001, NotEqual))
assert.Assert(t, !validateNumber(7, 7.0000, NotEqual))
assert.Assert(t, !validateNumber(6, 6.000000001, More))
func TestValidateQuantity_InvalidQuantity(t *testing.T) {
assert.Assert(t, !validateNumberWithStr("1024Gi", "", Equal))
assert.Assert(t, !validateNumberWithStr("gii", "1024Gi", Equal))
}
func TestValidateNumberWithStr_Equal(t *testing.T) {
assert.Assert(t, validateNumberWithStr("1024Gi", "1024", "Gi", Equal))
func TestValidateQuantity_Equal(t *testing.T) {
assert.Assert(t, validateNumberWithStr("1024Gi", "1024Gi", Equal))
assert.Assert(t, validateNumberWithStr("1024Mi", "1Gi", Equal))
assert.Assert(t, validateNumberWithStr("0.2", "200m", Equal))
assert.Assert(t, validateNumberWithStr("500", "500", Equal))
assert.Assert(t, !validateNumberWithStr("2048", "1024", Equal))
assert.Assert(t, validateNumberWithStr(1024, "1024", Equal))
}
func TestValidateNumberWithStr_More(t *testing.T) {
assert.Assert(t, !validateNumberWithStr("512Gi", "1024", "Gi", More))
}
func TestValidateNumberWithStr_MoreAndWildCard(t *testing.T) {
assert.Assert(t, validateNumberWithStr("2048Gi", "1024", "G?", More))
}
func TestValidateNumberWithStr_NoStr(t *testing.T) {
assert.Assert(t, validateNumberWithStr(2048, "1024", "", More))
func TestValidateQuantity_Operation(t *testing.T) {
assert.Assert(t, validateNumberWithStr("1Gi", "1000Mi", More))
assert.Assert(t, validateNumberWithStr("1G", "1Gi", Less))
assert.Assert(t, validateNumberWithStr("500m", "0.5", MoreEqual))
assert.Assert(t, validateNumberWithStr("1", "500m", MoreEqual))
assert.Assert(t, validateNumberWithStr("0.5", ".5", LessEqual))
assert.Assert(t, validateNumberWithStr("0.2", ".5", LessEqual))
assert.Assert(t, validateNumberWithStr("0.2", ".5", NotEqual))
}
func TestGetOperatorFromStringPattern_OneChar(t *testing.T) {

View file

@ -38,6 +38,11 @@ type ResourceSpec struct {
Name string `json:"name"`
}
//GetKey returns the key
func (rs ResourceSpec) GetKey() string {
return rs.Kind + "/" + rs.Namespace + "/" + rs.Name
}
//PolicyStats stores statistics for the single policy application
type PolicyStats struct {
// time required to process the policy rules on a resource

View file

@ -318,25 +318,19 @@ func removeAnchor(key string) string {
return key
}
// convertToFloat converts string and any other value to float64
func convertToFloat(value interface{}) (float64, error) {
// convertToString converts value to string
func convertToString(value interface{}) (string, error) {
switch typed := value.(type) {
case string:
var err error
floatValue, err := strconv.ParseFloat(typed, 64)
if err != nil {
return 0, err
}
return floatValue, nil
return string(typed), nil
case float64:
return typed, nil
return fmt.Sprintf("%f", typed), nil
case int64:
return float64(typed), nil
return strconv.FormatInt(typed, 10), nil
case int:
return float64(typed), nil
return strconv.Itoa(typed), nil
default:
return 0, fmt.Errorf("Could not convert %T to float64", value)
return "", fmt.Errorf("Could not convert %T to string", value)
}
}

View file

@ -26,8 +26,14 @@ type Generator struct {
pLister kyvernolister.ClusterPolicyLister
// returns true if the cluster policy store has been synced at least once
pSynced cache.InformerSynced
// queue to store event generation requests
queue workqueue.RateLimitingInterface
recorder record.EventRecorder
// events generated at policy controller
policyCtrRecorder record.EventRecorder
// events generated at admission control
admissionCtrRecorder record.EventRecorder
// events generated at namespaced policy controller to process 'generate' rule
genPolicyRecorder record.EventRecorder
}
//Interface to generate event
@ -39,17 +45,19 @@ type Interface interface {
func NewEventGenerator(client *client.Client, pInformer kyvernoinformer.ClusterPolicyInformer) *Generator {
gen := Generator{
client: client,
pLister: pInformer.Lister(),
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), eventWorkQueueName),
pSynced: pInformer.Informer().HasSynced,
recorder: initRecorder(client),
}
client: client,
pLister: pInformer.Lister(),
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), eventWorkQueueName),
pSynced: pInformer.Informer().HasSynced,
policyCtrRecorder: initRecorder(client, PolicyController),
admissionCtrRecorder: initRecorder(client, AdmissionController),
genPolicyRecorder: initRecorder(client, GeneratePolicyController),
}
return &gen
}
func initRecorder(client *client.Client) record.EventRecorder {
func initRecorder(client *client.Client, eventSource Source) record.EventRecorder {
// Initliaze Event Broadcaster
err := scheme.AddToScheme(scheme.Scheme)
if err != nil {
@ -68,7 +76,7 @@ func initRecorder(client *client.Client) record.EventRecorder {
Interface: eventInterface})
recorder := eventBroadcaster.NewRecorder(
scheme.Scheme,
v1.EventSource{Component: eventSource})
v1.EventSource{Component: eventSource.String()})
return recorder
}
@ -113,7 +121,7 @@ func (gen *Generator) handleErr(err error, key interface{}) {
}
// This controller retries if something goes wrong. After that, it stops trying.
if gen.queue.NumRequeues(key) < workQueueRetryLimit {
glog.Warningf("Error syncing events %v: %v", key, err)
glog.Warningf("Error syncing events %v(re-queuing request, the resource might not have been created yet): %v", key, err)
// Re-enqueue the key rate limited. Based on the rate limiter on the
// queue and the re-enqueue history, the key will be processed later again.
gen.queue.AddRateLimited(key)
@ -159,47 +167,45 @@ func (gen *Generator) syncHandler(key Info) error {
//TODO: policy is clustered resource so wont need namespace
robj, err = gen.pLister.Get(key.Name)
if err != nil {
glog.Errorf("Error creating event: unable to get policy %s, will retry ", key.Name)
glog.V(4).Infof("Error creating event: unable to get policy %s, will retry ", key.Name)
return err
}
default:
robj, err = gen.client.GetResource(key.Kind, key.Namespace, key.Name)
if err != nil {
glog.Errorf("Error creating event: unable to get resource %s, %s, will retry ", key.Kind, key.Namespace+"/"+key.Name)
glog.V(4).Infof("Error creating event: unable to get resource %s, %s, will retry ", key.Kind, key.Namespace+"/"+key.Name)
return err
}
}
// set the event type based on reason
eventType := v1.EventTypeWarning
if key.Reason == PolicyApplied.String() {
gen.recorder.Event(robj, v1.EventTypeNormal, key.Reason, key.Message)
} else {
gen.recorder.Event(robj, v1.EventTypeWarning, key.Reason, key.Message)
eventType = v1.EventTypeNormal
}
// based on the source of event generation, use different event recorders
switch key.Source {
case AdmissionController:
gen.admissionCtrRecorder.Event(robj, eventType, key.Reason, key.Message)
case PolicyController:
gen.policyCtrRecorder.Event(robj, eventType, key.Reason, key.Message)
case GeneratePolicyController:
gen.genPolicyRecorder.Event(robj, eventType, key.Reason, key.Message)
default:
glog.Info("info.source not defined for the event generator request")
}
return nil
}
//TODO: check if we need this ?
//NewEvent returns a new event
func NewEvent(rkind string, rnamespace string, rname string, reason Reason, message MsgKey, args ...interface{}) *Info {
msgText, err := getEventMsg(message, args...)
if err != nil {
glog.Error(err)
}
return &Info{
Kind: rkind,
Name: rname,
Namespace: rnamespace,
Reason: reason.String(),
Message: msgText,
}
}
func NewEventNew(
//NewEvent builds a event creation request
func NewEvent(
rkind,
rapiVersion,
rnamespace,
rname,
reason string,
source Source,
message MsgKey,
args ...interface{}) Info {
msgText, err := getEventMsg(message, args...)
@ -211,6 +217,7 @@ func NewEventNew(
Name: rname,
Namespace: rnamespace,
Reason: reason,
Source: source,
Message: msgText,
}
}

21
pkg/event/source.go Normal file
View file

@ -0,0 +1,21 @@
package event
//Source of event generation
type Source int
const (
// AdmissionController : event generated in admission-control webhook
AdmissionController Source = iota
// PolicyController : event generated in policy-controller
PolicyController
// GeneratePolicyController : event generated in generate policyController
GeneratePolicyController
)
func (s Source) String() string {
return [...]string{
"admission-controller",
"policy-controller",
"generate-policy-controller",
}[s]
}

View file

@ -1,8 +1,6 @@
package event
const eventSource = "policy-controller"
const eventWorkQueueName = "policy-controller-events"
const eventWorkQueueName = "kyverno-events"
const eventWorkerThreadCount = 1
@ -15,4 +13,5 @@ type Info struct {
Namespace string
Reason string
Message string
Source Source
}

View file

@ -89,6 +89,7 @@ func generateEventsPerEr(er engine.EngineResponse) []event.Info {
e.Namespace = "" // event generate on namespace resource
e.Name = er.PolicyResponse.Resource.Name
e.Reason = "Failure"
e.Source = event.GeneratePolicyController
e.Message = fmt.Sprintf("policy '%s' (%s) rule '%s' not satisfied. %v", er.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message)
eventInfos = append(eventInfos, e)
}
@ -102,6 +103,7 @@ func generateEventsPerEr(er engine.EngineResponse) []event.Info {
e.Namespace = ""
e.Name = er.PolicyResponse.Policy
e.Reason = "Failure"
e.Source = event.GeneratePolicyController
e.Message = fmt.Sprintf("policy '%s' rules '%v' on resource '%s/%s/%s' not stasified", er.PolicyResponse.Policy, er.GetFailedRules(), er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name)
return eventInfos
}

View file

@ -1,8 +1,10 @@
package policy
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"time"
jsonpatch "github.com/evanphx/json-patch"
@ -108,7 +110,6 @@ func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse
if len(rule.Patches) == 0 {
continue
}
patch, err := jsonpatch.DecodePatch(utils.JoinPatches(rule.Patches))
if err != nil {
glog.V(4).Infof("unable to decode patch %s: %v", rule.Patches, err)
@ -121,12 +122,32 @@ func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse
glog.V(4).Infof("unable to apply patch %s: %v", rule.Patches, err)
return engine.EngineResponse{}, err
}
if !jsonpatch.Equal(patchedResource, rawResource) {
glog.V(4).Infof("policy %s rule %s condition not satisifed by existing resource", engineResponse.PolicyResponse.Policy, rule.Name)
engineResponse.PolicyResponse.Rules[index].Success = false
engineResponse.PolicyResponse.Rules[index].Message = fmt.Sprintf("rule not satisfied by existing resource.")
engineResponse.PolicyResponse.Rules[index].Message = fmt.Sprintf("mutation json patches not found at resource path %s", extractPatchPath(rule.Patches))
}
}
return engineResponse, nil
}
type jsonPatch struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value"`
}
func extractPatchPath(patches [][]byte) string {
var resultPath []string
// extract the patch path and value
for _, patch := range patches {
glog.V(4).Infof("expected json patch not found in resource: %s", string(patch))
var data jsonPatch
if err := json.Unmarshal(patch, &data); err != nil {
glog.V(4).Infof("Failed to decode the generated patch %v: Error %v", string(patch), err)
continue
}
resultPath = append(resultPath, data.Path)
}
return strings.Join(resultPath, ";")
}

View file

@ -109,6 +109,7 @@ func generateEventsPerEr(er engine.EngineResponse) []event.Info {
e.Namespace = er.PolicyResponse.Resource.Namespace
e.Name = er.PolicyResponse.Resource.Name
e.Reason = event.PolicyViolation.String()
e.Source = event.PolicyController
e.Message = fmt.Sprintf("policy '%s' (%s) rule '%s' not satisfied. %v", er.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message)
eventInfos = append(eventInfos, e)
}
@ -123,6 +124,7 @@ func generateEventsPerEr(er engine.EngineResponse) []event.Info {
e.Namespace = ""
e.Name = er.PolicyResponse.Policy
e.Reason = event.PolicyViolation.String()
e.Source = event.PolicyController
e.Message = fmt.Sprintf("policy '%s' rules '%v' not satisfied on resource '%s/%s/%s'", er.PolicyResponse.Policy, er.GetFailedRules(), er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name)
eventInfos = append(eventInfos, e)
return eventInfos

View file

@ -32,12 +32,13 @@ func generateEvents(engineResponses []engine.EngineResponse, onUpdate bool) []ev
var e event.Info
// UPDATE
// event on resource
e = event.NewEventNew(
e = event.NewEvent(
er.PolicyResponse.Resource.Kind,
er.PolicyResponse.Resource.APIVersion,
er.PolicyResponse.Resource.Namespace,
er.PolicyResponse.Resource.Name,
reason.String(),
event.AdmissionController,
event.FPolicyApplyBlockUpdate,
filedRulesStr,
er.PolicyResponse.Policy,
@ -46,14 +47,15 @@ func generateEvents(engineResponses []engine.EngineResponse, onUpdate bool) []ev
events = append(events, e)
// event on policy
e = event.NewEventNew(
e = event.NewEvent(
"ClusterPolicy",
kyverno.SchemeGroupVersion.String(),
"",
er.PolicyResponse.Policy,
reason.String(),
event.AdmissionController,
event.FPolicyBlockResourceUpdate,
er.PolicyResponse.Resource.Namespace+"/"+er.PolicyResponse.Resource.Name,
er.PolicyResponse.Resource.GetKey(),
filedRulesStr,
)
glog.V(4).Infof("UPDATE event on policy %s", er.PolicyResponse.Policy)
@ -62,14 +64,15 @@ func generateEvents(engineResponses []engine.EngineResponse, onUpdate bool) []ev
} else {
// CREATE
// event on policy
e := event.NewEventNew(
e := event.NewEvent(
"ClusterPolicy",
kyverno.SchemeGroupVersion.String(),
"",
er.PolicyResponse.Policy,
event.RequestBlocked.String(),
reason.String(),
event.AdmissionController,
event.FPolicyApplyBlockCreate,
er.PolicyResponse.Resource.Namespace+"/"+er.PolicyResponse.Resource.Name,
er.PolicyResponse.Resource.GetKey(),
filedRulesStr,
)
glog.V(4).Infof("CREATE event on policy %s", er.PolicyResponse.Policy)
@ -85,12 +88,13 @@ func generateEvents(engineResponses []engine.EngineResponse, onUpdate bool) []ev
successRules := er.GetSuccessRules()
successRulesStr := strings.Join(successRules, ";")
// event on resource
e := event.NewEventNew(
e := event.NewEvent(
er.PolicyResponse.Resource.Kind,
er.PolicyResponse.Resource.APIVersion,
er.PolicyResponse.Resource.Namespace,
er.PolicyResponse.Resource.Name,
event.PolicyApplied.String(),
event.AdmissionController,
event.SRulesApply,
successRulesStr,
er.PolicyResponse.Policy,