mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
527 save commit
This commit is contained in:
parent
1026fc5236
commit
d32cd9363e
17 changed files with 445 additions and 330 deletions
|
@ -5,6 +5,8 @@ import (
|
|||
"flag"
|
||||
"time"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policyStatus"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/nirmata/kyverno/pkg/checker"
|
||||
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
|
@ -136,7 +138,7 @@ func main() {
|
|||
pInformer.Kyverno().V1().ClusterPolicies())
|
||||
|
||||
// Policy Status Handler - deals with all logic related to policy status
|
||||
statusSync := policy.NewStatusSync(
|
||||
statusSync := policyStatus.NewSync(
|
||||
pclient,
|
||||
stopCh,
|
||||
policyMetaStore)
|
||||
|
|
|
@ -4,8 +4,6 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policy"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
|
@ -13,6 +11,7 @@ import (
|
|||
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
|
||||
dclient "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"github.com/nirmata/kyverno/pkg/event"
|
||||
"github.com/nirmata/kyverno/pkg/policyStatus"
|
||||
"github.com/nirmata/kyverno/pkg/policyviolation"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
|
@ -70,7 +69,7 @@ func NewController(
|
|||
eventGen event.Interface,
|
||||
pvGenerator policyviolation.GeneratorInterface,
|
||||
dynamicInformer dynamicinformer.DynamicSharedInformerFactory,
|
||||
policyStatus *policy.StatSync,
|
||||
policyStatus *policyStatus.Sync,
|
||||
) *Controller {
|
||||
c := Controller{
|
||||
client: client,
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
"github.com/nirmata/kyverno/pkg/policy"
|
||||
"github.com/nirmata/kyverno/pkg/policyStatus"
|
||||
)
|
||||
|
||||
//StatusControlInterface provides interface to update status subresource
|
||||
|
@ -16,7 +16,7 @@ type StatusControlInterface interface {
|
|||
// StatusControl is default implementaation of GRStatusControlInterface
|
||||
type StatusControl struct {
|
||||
client kyvernoclient.Interface
|
||||
policyStatus *policy.StatSync
|
||||
policyStatus *policyStatus.Sync
|
||||
}
|
||||
|
||||
//Failed sets gr status.state to failed with message
|
||||
|
|
|
@ -1,308 +0,0 @@
|
|||
package policy
|
||||
|
||||
import (
|
||||
"log"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policystore"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
|
||||
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
)
|
||||
|
||||
type statusCache struct {
|
||||
mu sync.RWMutex
|
||||
data map[string]v1.PolicyStatus
|
||||
}
|
||||
|
||||
type StatSync struct {
|
||||
cache *statusCache
|
||||
stop <-chan struct{}
|
||||
client *versioned.Clientset
|
||||
policyStore *policystore.PolicyStore
|
||||
}
|
||||
|
||||
func NewStatusSync(
|
||||
client *versioned.Clientset,
|
||||
stopCh <-chan struct{},
|
||||
pMetaStore *policystore.PolicyStore,
|
||||
) *StatSync {
|
||||
return &StatSync{
|
||||
cache: &statusCache{
|
||||
mu: sync.RWMutex{},
|
||||
data: make(map[string]v1.PolicyStatus),
|
||||
},
|
||||
stop: stopCh,
|
||||
client: client,
|
||||
policyStore: pMetaStore,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StatSync) Run() {
|
||||
// update policy status every 10 seconds - waits for previous updateStatus to complete
|
||||
wait.Until(s.updateStats, 1*time.Second, s.stop)
|
||||
<-s.stop
|
||||
s.updateStats()
|
||||
}
|
||||
|
||||
func (s *StatSync) updateStats() {
|
||||
s.cache.mu.Lock()
|
||||
var nameToStatus = make(map[string]v1.PolicyStatus, len(s.cache.data))
|
||||
for k, v := range s.cache.data {
|
||||
nameToStatus[k] = v
|
||||
}
|
||||
s.cache.data = make(map[string]v1.PolicyStatus)
|
||||
s.cache.mu.Unlock()
|
||||
|
||||
for policyName, status := range nameToStatus {
|
||||
var policy = &v1.ClusterPolicy{}
|
||||
policy, err := s.policyStore.Get(policyName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
policy.Status = status
|
||||
_, err = s.client.KyvernoV1().ClusterPolicies().UpdateStatus(policy)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StatSync) UpdatePolicyStatusWithViolationCount(policyName string, violatedRules []v1.ViolatedRule) {
|
||||
s.cache.mu.Lock()
|
||||
status := s.cache.data[policyName]
|
||||
|
||||
var ruleNameToViolations = make(map[string]int)
|
||||
for _, rule := range violatedRules {
|
||||
ruleNameToViolations[rule.Name]++
|
||||
}
|
||||
|
||||
for i := range status.Rules {
|
||||
status.ViolationCount += ruleNameToViolations[status.Rules[i].Name]
|
||||
status.Rules[i].ViolationCount += ruleNameToViolations[status.Rules[i].Name]
|
||||
}
|
||||
|
||||
s.cache.data[policyName] = status
|
||||
s.cache.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *StatSync) UpdatePolicyStatusWithGeneratedResourceCount(generateRequest v1.GenerateRequest) {
|
||||
s.cache.mu.Lock()
|
||||
status := s.cache.data[generateRequest.Spec.Policy]
|
||||
|
||||
status.ResourcesGeneratedCount += len(generateRequest.Status.GeneratedResources)
|
||||
|
||||
s.cache.data[generateRequest.Spec.Policy] = status
|
||||
s.cache.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *StatSync) UpdateStatusWithMutateStats(resp response.EngineResponse) {
|
||||
if reflect.DeepEqual(response.EngineResponse{}, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
s.cache.mu.Lock()
|
||||
var policyStatus v1.PolicyStatus
|
||||
policyStatus, exist := s.cache.data[resp.PolicyResponse.Policy]
|
||||
if !exist {
|
||||
policy, _ := s.policyStore.Get(resp.PolicyResponse.Policy)
|
||||
if policy != nil {
|
||||
policyStatus = policy.Status
|
||||
}
|
||||
}
|
||||
|
||||
var nameToRule = make(map[string]v1.RuleStats, 0)
|
||||
for _, rule := range policyStatus.Rules {
|
||||
nameToRule[rule.Name] = rule
|
||||
}
|
||||
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
ruleStat := nameToRule[rule.Name]
|
||||
ruleStat.Name = rule.Name
|
||||
|
||||
averageOver := int64(ruleStat.AppliedCount + ruleStat.FailedCount)
|
||||
ruleStat.ExecutionTime = updateAverageTime(
|
||||
rule.ProcessingTime,
|
||||
ruleStat.ExecutionTime,
|
||||
averageOver).String()
|
||||
|
||||
if rule.Success {
|
||||
policyStatus.RulesAppliedCount++
|
||||
policyStatus.ResourcesMutatedCount++
|
||||
ruleStat.AppliedCount++
|
||||
ruleStat.ResourcesMutatedCount++
|
||||
} else {
|
||||
policyStatus.RulesFailedCount++
|
||||
ruleStat.FailedCount++
|
||||
}
|
||||
|
||||
nameToRule[rule.Name] = ruleStat
|
||||
}
|
||||
|
||||
var policyAverageExecutionTime time.Duration
|
||||
var ruleStats = make([]v1.RuleStats, 0, len(nameToRule))
|
||||
for _, ruleStat := range nameToRule {
|
||||
executionTime, err := time.ParseDuration(ruleStat.ExecutionTime)
|
||||
if err == nil {
|
||||
policyAverageExecutionTime += executionTime
|
||||
}
|
||||
ruleStats = append(ruleStats, ruleStat)
|
||||
}
|
||||
|
||||
sort.Slice(ruleStats, func(i, j int) bool {
|
||||
return ruleStats[i].Name < ruleStats[j].Name
|
||||
})
|
||||
|
||||
policyStatus.AvgExecutionTime = policyAverageExecutionTime.String()
|
||||
policyStatus.Rules = ruleStats
|
||||
|
||||
s.cache.data[resp.PolicyResponse.Policy] = policyStatus
|
||||
s.cache.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *StatSync) UpdateStatusWithValidateStats(resp response.EngineResponse) {
|
||||
if reflect.DeepEqual(response.EngineResponse{}, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
s.cache.mu.Lock()
|
||||
var policyStatus v1.PolicyStatus
|
||||
policyStatus, exist := s.cache.data[resp.PolicyResponse.Policy]
|
||||
if !exist {
|
||||
policy, _ := s.policyStore.Get(resp.PolicyResponse.Policy)
|
||||
if policy != nil {
|
||||
policyStatus = policy.Status
|
||||
}
|
||||
}
|
||||
|
||||
var nameToRule = make(map[string]v1.RuleStats, 0)
|
||||
for _, rule := range policyStatus.Rules {
|
||||
nameToRule[rule.Name] = rule
|
||||
}
|
||||
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
ruleStat := nameToRule[rule.Name]
|
||||
ruleStat.Name = rule.Name
|
||||
|
||||
averageOver := int64(ruleStat.AppliedCount + ruleStat.FailedCount)
|
||||
ruleStat.ExecutionTime = updateAverageTime(
|
||||
rule.ProcessingTime,
|
||||
ruleStat.ExecutionTime,
|
||||
averageOver).String()
|
||||
|
||||
if rule.Success {
|
||||
policyStatus.RulesAppliedCount++
|
||||
ruleStat.AppliedCount++
|
||||
} else {
|
||||
policyStatus.RulesFailedCount++
|
||||
ruleStat.FailedCount++
|
||||
if resp.PolicyResponse.ValidationFailureAction == "enforce" {
|
||||
policyStatus.ResourcesBlockedCount++
|
||||
ruleStat.ResourcesBlockedCount++
|
||||
}
|
||||
}
|
||||
|
||||
nameToRule[rule.Name] = ruleStat
|
||||
}
|
||||
|
||||
var policyAverageExecutionTime time.Duration
|
||||
var ruleStats = make([]v1.RuleStats, 0, len(nameToRule))
|
||||
for _, ruleStat := range nameToRule {
|
||||
executionTime, err := time.ParseDuration(ruleStat.ExecutionTime)
|
||||
if err == nil {
|
||||
policyAverageExecutionTime += executionTime
|
||||
}
|
||||
ruleStats = append(ruleStats, ruleStat)
|
||||
}
|
||||
|
||||
sort.Slice(ruleStats, func(i, j int) bool {
|
||||
return ruleStats[i].Name < ruleStats[j].Name
|
||||
})
|
||||
|
||||
policyStatus.AvgExecutionTime = policyAverageExecutionTime.String()
|
||||
policyStatus.Rules = ruleStats
|
||||
|
||||
s.cache.data[resp.PolicyResponse.Policy] = policyStatus
|
||||
s.cache.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *StatSync) UpdateStatusWithGenerateStats(resp response.EngineResponse) {
|
||||
if reflect.DeepEqual(response.EngineResponse{}, resp) {
|
||||
return
|
||||
}
|
||||
|
||||
s.cache.mu.Lock()
|
||||
var policyStatus v1.PolicyStatus
|
||||
policyStatus, exist := s.cache.data[resp.PolicyResponse.Policy]
|
||||
if !exist {
|
||||
policy, _ := s.policyStore.Get(resp.PolicyResponse.Policy)
|
||||
if policy != nil {
|
||||
policyStatus = policy.Status
|
||||
}
|
||||
}
|
||||
|
||||
var nameToRule = make(map[string]v1.RuleStats, 0)
|
||||
for _, rule := range policyStatus.Rules {
|
||||
nameToRule[rule.Name] = rule
|
||||
}
|
||||
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
ruleStat := nameToRule[rule.Name]
|
||||
ruleStat.Name = rule.Name
|
||||
|
||||
averageOver := int64(ruleStat.AppliedCount + ruleStat.FailedCount)
|
||||
ruleStat.ExecutionTime = updateAverageTime(
|
||||
rule.ProcessingTime,
|
||||
ruleStat.ExecutionTime,
|
||||
averageOver).String()
|
||||
|
||||
if rule.Success {
|
||||
policyStatus.RulesAppliedCount++
|
||||
ruleStat.AppliedCount++
|
||||
} else {
|
||||
policyStatus.RulesFailedCount++
|
||||
ruleStat.FailedCount++
|
||||
}
|
||||
|
||||
nameToRule[rule.Name] = ruleStat
|
||||
}
|
||||
|
||||
var policyAverageExecutionTime time.Duration
|
||||
var ruleStats = make([]v1.RuleStats, 0, len(nameToRule))
|
||||
for _, ruleStat := range nameToRule {
|
||||
executionTime, err := time.ParseDuration(ruleStat.ExecutionTime)
|
||||
if err == nil {
|
||||
policyAverageExecutionTime += executionTime
|
||||
}
|
||||
ruleStats = append(ruleStats, ruleStat)
|
||||
}
|
||||
|
||||
sort.Slice(ruleStats, func(i, j int) bool {
|
||||
return ruleStats[i].Name < ruleStats[j].Name
|
||||
})
|
||||
|
||||
policyStatus.AvgExecutionTime = policyAverageExecutionTime.String()
|
||||
policyStatus.Rules = ruleStats
|
||||
|
||||
s.cache.data[resp.PolicyResponse.Policy] = policyStatus
|
||||
s.cache.mu.Unlock()
|
||||
}
|
||||
|
||||
func updateAverageTime(newTime time.Duration, oldAverageTimeString string, averageOver int64) time.Duration {
|
||||
if averageOver == 0 {
|
||||
return newTime
|
||||
}
|
||||
oldAverageExecutionTime, _ := time.ParseDuration(oldAverageTimeString)
|
||||
numerator := (oldAverageExecutionTime.Nanoseconds() * averageOver) + newTime.Nanoseconds()
|
||||
denominator := averageOver + 1
|
||||
newAverageTimeInNanoSeconds := numerator / denominator
|
||||
return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond
|
||||
}
|
81
pkg/policyStatus/0_main.go
Normal file
81
pkg/policyStatus/0_main.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package policyStatus
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policystore"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
|
||||
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
)
|
||||
|
||||
type Sync struct {
|
||||
cache *cache
|
||||
listener chan statusUpdater
|
||||
stop <-chan struct{}
|
||||
client *versioned.Clientset
|
||||
policyStore *policystore.PolicyStore
|
||||
}
|
||||
|
||||
type cache struct {
|
||||
mutex sync.RWMutex
|
||||
data map[string]v1.PolicyStatus
|
||||
}
|
||||
|
||||
func NewSync(c *versioned.Clientset, sc <-chan struct{}, pms *policystore.PolicyStore) *Sync {
|
||||
return &Sync{
|
||||
cache: &cache{
|
||||
mutex: sync.RWMutex{},
|
||||
data: make(map[string]v1.PolicyStatus),
|
||||
},
|
||||
stop: sc,
|
||||
client: c,
|
||||
policyStore: pms,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Sync) Run() {
|
||||
wait.Until(s.updatePolicyStatus, 5*time.Second, s.stop)
|
||||
<-s.stop
|
||||
s.updatePolicyStatus()
|
||||
}
|
||||
|
||||
func (s *Sync) updateStatusCache() {
|
||||
for {
|
||||
select {
|
||||
case statusUpdater := <-s.listener:
|
||||
statusUpdater.updateStatus()
|
||||
case <-s.stop:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Sync) updatePolicyStatus() {
|
||||
s.cache.mutex.Lock()
|
||||
var nameToStatus = make(map[string]v1.PolicyStatus, len(s.cache.data))
|
||||
for k, v := range s.cache.data {
|
||||
nameToStatus[k] = v
|
||||
}
|
||||
s.cache.data = make(map[string]v1.PolicyStatus)
|
||||
s.cache.mutex.Unlock()
|
||||
|
||||
for policyName, status := range nameToStatus {
|
||||
var policy = &v1.ClusterPolicy{}
|
||||
policy, err := s.policyStore.Get(policyName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
policy.Status = status
|
||||
_, err = s.client.KyvernoV1().ClusterPolicies().UpdateStatus(policy)
|
||||
if err != nil {
|
||||
glog.V(4).Info(err)
|
||||
}
|
||||
}
|
||||
}
|
5
pkg/policyStatus/1_interface.go
Normal file
5
pkg/policyStatus/1_interface.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package policyStatus
|
||||
|
||||
type statusUpdater interface {
|
||||
updateStatus()
|
||||
}
|
14
pkg/policyStatus/2_functions.go
Normal file
14
pkg/policyStatus/2_functions.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package policyStatus
|
||||
|
||||
import "time"
|
||||
|
||||
func updateAverageTime(newTime time.Duration, oldAverageTimeString string, averageOver int64) time.Duration {
|
||||
if averageOver == 0 {
|
||||
return newTime
|
||||
}
|
||||
oldAverageExecutionTime, _ := time.ParseDuration(oldAverageTimeString)
|
||||
numerator := (oldAverageExecutionTime.Nanoseconds() * averageOver) + newTime.Nanoseconds()
|
||||
denominator := averageOver + 1
|
||||
newAverageTimeInNanoSeconds := numerator / denominator
|
||||
return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond
|
||||
}
|
84
pkg/policyStatus/generateCount.go
Normal file
84
pkg/policyStatus/generateCount.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
package policyStatus
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
)
|
||||
|
||||
type generateStats struct {
|
||||
s *Sync
|
||||
resp response.EngineResponse
|
||||
}
|
||||
|
||||
func (s *Sync) UpdateStatusWithGenerateStats(resp response.EngineResponse) {
|
||||
s.listener <- &generateStats{
|
||||
s: s,
|
||||
resp: resp,
|
||||
}
|
||||
}
|
||||
|
||||
func (gs *generateStats) updateStatus() {
|
||||
if reflect.DeepEqual(response.EngineResponse{}, gs.resp) {
|
||||
return
|
||||
}
|
||||
|
||||
gs.s.cache.mutex.Lock()
|
||||
var policyStatus v1.PolicyStatus
|
||||
policyStatus, exist := gs.s.cache.data[gs.resp.PolicyResponse.Policy]
|
||||
if !exist {
|
||||
policy, _ := gs.s.policyStore.Get(gs.resp.PolicyResponse.Policy)
|
||||
if policy != nil {
|
||||
policyStatus = policy.Status
|
||||
}
|
||||
}
|
||||
|
||||
var nameToRule = make(map[string]v1.RuleStats, 0)
|
||||
for _, rule := range policyStatus.Rules {
|
||||
nameToRule[rule.Name] = rule
|
||||
}
|
||||
|
||||
for _, rule := range gs.resp.PolicyResponse.Rules {
|
||||
ruleStat := nameToRule[rule.Name]
|
||||
ruleStat.Name = rule.Name
|
||||
|
||||
averageOver := int64(ruleStat.AppliedCount + ruleStat.FailedCount)
|
||||
ruleStat.ExecutionTime = updateAverageTime(
|
||||
rule.ProcessingTime,
|
||||
ruleStat.ExecutionTime,
|
||||
averageOver).String()
|
||||
|
||||
if rule.Success {
|
||||
policyStatus.RulesAppliedCount++
|
||||
ruleStat.AppliedCount++
|
||||
} else {
|
||||
policyStatus.RulesFailedCount++
|
||||
ruleStat.FailedCount++
|
||||
}
|
||||
|
||||
nameToRule[rule.Name] = ruleStat
|
||||
}
|
||||
|
||||
var policyAverageExecutionTime time.Duration
|
||||
var ruleStats = make([]v1.RuleStats, 0, len(nameToRule))
|
||||
for _, ruleStat := range nameToRule {
|
||||
executionTime, err := time.ParseDuration(ruleStat.ExecutionTime)
|
||||
if err == nil {
|
||||
policyAverageExecutionTime += executionTime
|
||||
}
|
||||
ruleStats = append(ruleStats, ruleStat)
|
||||
}
|
||||
|
||||
sort.Slice(ruleStats, func(i, j int) bool {
|
||||
return ruleStats[i].Name < ruleStats[j].Name
|
||||
})
|
||||
|
||||
policyStatus.AvgExecutionTime = policyAverageExecutionTime.String()
|
||||
policyStatus.Rules = ruleStats
|
||||
|
||||
gs.s.cache.data[gs.resp.PolicyResponse.Policy] = policyStatus
|
||||
gs.s.cache.mutex.Unlock()
|
||||
}
|
25
pkg/policyStatus/generatedResourceCount.go
Normal file
25
pkg/policyStatus/generatedResourceCount.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package policyStatus
|
||||
|
||||
import v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
|
||||
type generatedResourceCount struct {
|
||||
sync *Sync
|
||||
generateRequest v1.GenerateRequest
|
||||
}
|
||||
|
||||
func (s *Sync) UpdatePolicyStatusWithGeneratedResourceCount(generateRequest v1.GenerateRequest) {
|
||||
s.listener <- &generatedResourceCount{
|
||||
sync: s,
|
||||
generateRequest: generateRequest,
|
||||
}
|
||||
}
|
||||
|
||||
func (vc *generatedResourceCount) updateStatus() {
|
||||
vc.sync.cache.mutex.Lock()
|
||||
status := vc.sync.cache.data[vc.generateRequest.Spec.Policy]
|
||||
|
||||
status.ResourcesGeneratedCount += len(vc.generateRequest.Status.GeneratedResources)
|
||||
|
||||
vc.sync.cache.data[vc.generateRequest.Spec.Policy] = status
|
||||
vc.sync.cache.mutex.Unlock()
|
||||
}
|
87
pkg/policyStatus/mutateStats.go
Normal file
87
pkg/policyStatus/mutateStats.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package policyStatus
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
)
|
||||
|
||||
type mutateStats struct {
|
||||
s *Sync
|
||||
resp response.EngineResponse
|
||||
}
|
||||
|
||||
func (s *Sync) UpdateStatusWithMutateStats(resp response.EngineResponse) {
|
||||
s.listener <- &mutateStats{
|
||||
s: s,
|
||||
resp: resp,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (ms *mutateStats) updateStatus() {
|
||||
if reflect.DeepEqual(response.EngineResponse{}, ms.resp) {
|
||||
return
|
||||
}
|
||||
|
||||
ms.s.cache.mutex.Lock()
|
||||
var policyStatus v1.PolicyStatus
|
||||
policyStatus, exist := ms.s.cache.data[ms.resp.PolicyResponse.Policy]
|
||||
if !exist {
|
||||
policy, _ := ms.s.policyStore.Get(ms.resp.PolicyResponse.Policy)
|
||||
if policy != nil {
|
||||
policyStatus = policy.Status
|
||||
}
|
||||
}
|
||||
|
||||
var nameToRule = make(map[string]v1.RuleStats, 0)
|
||||
for _, rule := range policyStatus.Rules {
|
||||
nameToRule[rule.Name] = rule
|
||||
}
|
||||
|
||||
for _, rule := range ms.resp.PolicyResponse.Rules {
|
||||
ruleStat := nameToRule[rule.Name]
|
||||
ruleStat.Name = rule.Name
|
||||
|
||||
averageOver := int64(ruleStat.AppliedCount + ruleStat.FailedCount)
|
||||
ruleStat.ExecutionTime = updateAverageTime(
|
||||
rule.ProcessingTime,
|
||||
ruleStat.ExecutionTime,
|
||||
averageOver).String()
|
||||
|
||||
if rule.Success {
|
||||
policyStatus.RulesAppliedCount++
|
||||
policyStatus.ResourcesMutatedCount++
|
||||
ruleStat.AppliedCount++
|
||||
ruleStat.ResourcesMutatedCount++
|
||||
} else {
|
||||
policyStatus.RulesFailedCount++
|
||||
ruleStat.FailedCount++
|
||||
}
|
||||
|
||||
nameToRule[rule.Name] = ruleStat
|
||||
}
|
||||
|
||||
var policyAverageExecutionTime time.Duration
|
||||
var ruleStats = make([]v1.RuleStats, 0, len(nameToRule))
|
||||
for _, ruleStat := range nameToRule {
|
||||
executionTime, err := time.ParseDuration(ruleStat.ExecutionTime)
|
||||
if err == nil {
|
||||
policyAverageExecutionTime += executionTime
|
||||
}
|
||||
ruleStats = append(ruleStats, ruleStat)
|
||||
}
|
||||
|
||||
sort.Slice(ruleStats, func(i, j int) bool {
|
||||
return ruleStats[i].Name < ruleStats[j].Name
|
||||
})
|
||||
|
||||
policyStatus.AvgExecutionTime = policyAverageExecutionTime.String()
|
||||
policyStatus.Rules = ruleStats
|
||||
|
||||
ms.s.cache.data[ms.resp.PolicyResponse.Policy] = policyStatus
|
||||
ms.s.cache.mutex.Unlock()
|
||||
}
|
7
pkg/policyStatus/some_test.go
Normal file
7
pkg/policyStatus/some_test.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package policyStatus
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNewSync(t *testing.T) {
|
||||
|
||||
}
|
88
pkg/policyStatus/validateStats.go
Normal file
88
pkg/policyStatus/validateStats.go
Normal file
|
@ -0,0 +1,88 @@
|
|||
package policyStatus
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
)
|
||||
|
||||
type validateStats struct {
|
||||
s *Sync
|
||||
resp response.EngineResponse
|
||||
}
|
||||
|
||||
func (s *Sync) UpdateStatusWithValidateStats(resp response.EngineResponse) {
|
||||
s.listener <- &validateStats{
|
||||
s: s,
|
||||
resp: resp,
|
||||
}
|
||||
}
|
||||
|
||||
func (vs *validateStats) updateStatus() {
|
||||
if reflect.DeepEqual(response.EngineResponse{}, vs.resp) {
|
||||
return
|
||||
}
|
||||
|
||||
vs.s.cache.mutex.Lock()
|
||||
var policyStatus v1.PolicyStatus
|
||||
policyStatus, exist := vs.s.cache.data[vs.resp.PolicyResponse.Policy]
|
||||
if !exist {
|
||||
policy, _ := vs.s.policyStore.Get(vs.resp.PolicyResponse.Policy)
|
||||
if policy != nil {
|
||||
policyStatus = policy.Status
|
||||
}
|
||||
}
|
||||
|
||||
var nameToRule = make(map[string]v1.RuleStats, 0)
|
||||
for _, rule := range policyStatus.Rules {
|
||||
nameToRule[rule.Name] = rule
|
||||
}
|
||||
|
||||
for _, rule := range vs.resp.PolicyResponse.Rules {
|
||||
ruleStat := nameToRule[rule.Name]
|
||||
ruleStat.Name = rule.Name
|
||||
|
||||
averageOver := int64(ruleStat.AppliedCount + ruleStat.FailedCount)
|
||||
ruleStat.ExecutionTime = updateAverageTime(
|
||||
rule.ProcessingTime,
|
||||
ruleStat.ExecutionTime,
|
||||
averageOver).String()
|
||||
|
||||
if rule.Success {
|
||||
policyStatus.RulesAppliedCount++
|
||||
ruleStat.AppliedCount++
|
||||
} else {
|
||||
policyStatus.RulesFailedCount++
|
||||
ruleStat.FailedCount++
|
||||
if vs.resp.PolicyResponse.ValidationFailureAction == "enforce" {
|
||||
policyStatus.ResourcesBlockedCount++
|
||||
ruleStat.ResourcesBlockedCount++
|
||||
}
|
||||
}
|
||||
|
||||
nameToRule[rule.Name] = ruleStat
|
||||
}
|
||||
|
||||
var policyAverageExecutionTime time.Duration
|
||||
var ruleStats = make([]v1.RuleStats, 0, len(nameToRule))
|
||||
for _, ruleStat := range nameToRule {
|
||||
executionTime, err := time.ParseDuration(ruleStat.ExecutionTime)
|
||||
if err == nil {
|
||||
policyAverageExecutionTime += executionTime
|
||||
}
|
||||
ruleStats = append(ruleStats, ruleStat)
|
||||
}
|
||||
|
||||
sort.Slice(ruleStats, func(i, j int) bool {
|
||||
return ruleStats[i].Name < ruleStats[j].Name
|
||||
})
|
||||
|
||||
policyStatus.AvgExecutionTime = policyAverageExecutionTime.String()
|
||||
policyStatus.Rules = ruleStats
|
||||
|
||||
vs.s.cache.data[vs.resp.PolicyResponse.Policy] = policyStatus
|
||||
vs.s.cache.mutex.Unlock()
|
||||
}
|
35
pkg/policyStatus/violationCount.go
Normal file
35
pkg/policyStatus/violationCount.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package policyStatus
|
||||
|
||||
import v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
|
||||
type violationCount struct {
|
||||
sync *Sync
|
||||
policyName string
|
||||
violatedRules []v1.ViolatedRule
|
||||
}
|
||||
|
||||
func (s *Sync) UpdatePolicyStatusWithViolationCount(policyName string, violatedRules []v1.ViolatedRule) {
|
||||
s.listener <- &violationCount{
|
||||
sync: s,
|
||||
policyName: policyName,
|
||||
violatedRules: violatedRules,
|
||||
}
|
||||
}
|
||||
|
||||
func (vc *violationCount) updateStatus() {
|
||||
vc.sync.cache.mutex.Lock()
|
||||
status := vc.sync.cache.data[vc.policyName]
|
||||
|
||||
var ruleNameToViolations = make(map[string]int)
|
||||
for _, rule := range vc.violatedRules {
|
||||
ruleNameToViolations[rule.Name]++
|
||||
}
|
||||
|
||||
for i := range status.Rules {
|
||||
status.ViolationCount += ruleNameToViolations[status.Rules[i].Name]
|
||||
status.Rules[i].ViolationCount += ruleNameToViolations[status.Rules[i].Name]
|
||||
}
|
||||
|
||||
vc.sync.cache.data[vc.policyName] = status
|
||||
vc.sync.cache.mutex.Unlock()
|
||||
}
|
|
@ -4,13 +4,12 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policy"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1"
|
||||
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"github.com/nirmata/kyverno/pkg/policyStatus"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
|
@ -23,13 +22,13 @@ type clusterPV struct {
|
|||
// policy violation interface
|
||||
kyvernoInterface kyvernov1.KyvernoV1Interface
|
||||
// update policy stats with violationCount
|
||||
policyStatus *policy.StatSync
|
||||
policyStatus *policyStatus.Sync
|
||||
}
|
||||
|
||||
func newClusterPV(dclient *client.Client,
|
||||
cpvLister kyvernolister.ClusterPolicyViolationLister,
|
||||
kyvernoInterface kyvernov1.KyvernoV1Interface,
|
||||
policyStatus *policy.StatSync,
|
||||
policyStatus *policyStatus.Sync,
|
||||
) *clusterPV {
|
||||
cpv := clusterPV{
|
||||
dclient: dclient,
|
||||
|
|
|
@ -8,14 +8,13 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policy"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1"
|
||||
kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/policyStatus"
|
||||
|
||||
dclient "github.com/nirmata/kyverno/pkg/dclient"
|
||||
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -42,7 +41,7 @@ type Generator struct {
|
|||
nspvSynced cache.InformerSynced
|
||||
queue workqueue.RateLimitingInterface
|
||||
dataStore *dataStore
|
||||
policyStatus *policy.StatSync
|
||||
policyStatus *policyStatus.Sync
|
||||
}
|
||||
|
||||
//NewDataStore returns an instance of data store
|
||||
|
@ -107,7 +106,7 @@ func NewPVGenerator(client *kyvernoclient.Clientset,
|
|||
dclient *dclient.Client,
|
||||
pvInformer kyvernoinformer.ClusterPolicyViolationInformer,
|
||||
nspvInformer kyvernoinformer.PolicyViolationInformer,
|
||||
policyStatus *policy.StatSync) *Generator {
|
||||
policyStatus *policyStatus.Sync) *Generator {
|
||||
gen := Generator{
|
||||
kyvernoInterface: client.KyvernoV1(),
|
||||
dclient: dclient,
|
||||
|
|
|
@ -4,13 +4,12 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policy"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1"
|
||||
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"github.com/nirmata/kyverno/pkg/policyStatus"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
|
@ -23,13 +22,13 @@ type namespacedPV struct {
|
|||
// policy violation interface
|
||||
kyvernoInterface kyvernov1.KyvernoV1Interface
|
||||
// update policy status with violationCount
|
||||
policyStatus *policy.StatSync
|
||||
policyStatus *policyStatus.Sync
|
||||
}
|
||||
|
||||
func newNamespacedPV(dclient *client.Client,
|
||||
nspvLister kyvernolister.PolicyViolationLister,
|
||||
kyvernoInterface kyvernov1.KyvernoV1Interface,
|
||||
policyStatus *policy.StatSync,
|
||||
policyStatus *policyStatus.Sync,
|
||||
) *namespacedPV {
|
||||
nspv := namespacedPV{
|
||||
dclient: dclient,
|
||||
|
|
|
@ -10,8 +10,6 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/policy"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/nirmata/kyverno/pkg/checker"
|
||||
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
|
@ -20,6 +18,7 @@ import (
|
|||
"github.com/nirmata/kyverno/pkg/config"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"github.com/nirmata/kyverno/pkg/event"
|
||||
"github.com/nirmata/kyverno/pkg/policyStatus"
|
||||
"github.com/nirmata/kyverno/pkg/policystore"
|
||||
"github.com/nirmata/kyverno/pkg/policyviolation"
|
||||
tlsutils "github.com/nirmata/kyverno/pkg/tls"
|
||||
|
@ -56,7 +55,7 @@ type WebhookServer struct {
|
|||
// webhook registration client
|
||||
webhookRegistrationClient *webhookconfig.WebhookRegistrationClient
|
||||
// API to send policy stats for aggregation
|
||||
status *policy.StatSync
|
||||
status *policyStatus.Sync
|
||||
// helpers to validate against current loaded configuration
|
||||
configHandler config.Interface
|
||||
// channel for cleanup notification
|
||||
|
@ -83,7 +82,7 @@ func NewWebhookServer(
|
|||
crbInformer rbacinformer.ClusterRoleBindingInformer,
|
||||
eventGen event.Interface,
|
||||
webhookRegistrationClient *webhookconfig.WebhookRegistrationClient,
|
||||
statusSync *policy.StatSync,
|
||||
statusSync *policyStatus.Sync,
|
||||
configHandler config.Interface,
|
||||
pMetaStore policystore.LookupInterface,
|
||||
pvGenerator policyviolation.GeneratorInterface,
|
||||
|
|
Loading…
Add table
Reference in a new issue