2019-06-25 18:16:02 -07:00
|
|
|
package info
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
2019-07-15 19:14:42 -07:00
|
|
|
|
|
|
|
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
2019-06-25 18:16:02 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
//PolicyInfo defines policy information
|
|
|
|
type PolicyInfo struct {
|
2019-06-26 18:04:50 -07:00
|
|
|
// Name is policy name
|
|
|
|
Name string
|
2019-06-26 18:16:06 -07:00
|
|
|
// RKind represents the resource kind
|
|
|
|
RKind string
|
|
|
|
// RName is resource name
|
|
|
|
RName string
|
2019-06-26 18:04:50 -07:00
|
|
|
// Namespace is the ns of resource
|
|
|
|
// empty on non-namespaced resources
|
2019-06-26 12:41:42 -07:00
|
|
|
RNamespace string
|
2019-07-15 19:14:42 -07:00
|
|
|
//TODO: add check/enum for types
|
2019-07-16 15:53:14 -07:00
|
|
|
ValidationFailureAction string // BlockChanges, ReportViolation
|
2019-08-13 11:32:12 -07:00
|
|
|
Rules []RuleInfo
|
2019-07-16 15:53:14 -07:00
|
|
|
success bool
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//NewPolicyInfo returns a new policy info
|
2019-08-09 16:55:43 -07:00
|
|
|
func NewPolicyInfo(policyName, rKind, rName, rNamespace, validationFailureAction string) PolicyInfo {
|
|
|
|
pi := PolicyInfo{
|
2019-07-16 15:53:14 -07:00
|
|
|
Name: policyName,
|
|
|
|
RKind: rKind,
|
|
|
|
RName: rName,
|
|
|
|
RNamespace: rNamespace,
|
|
|
|
success: true, // fail to be set explicity
|
|
|
|
ValidationFailureAction: validationFailureAction,
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
2019-08-09 16:55:43 -07:00
|
|
|
return pi
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//IsSuccessful checks if policy is succesful
|
|
|
|
// the policy is set to fail, if any of the rules have failed
|
|
|
|
func (pi *PolicyInfo) IsSuccessful() bool {
|
2019-07-19 20:30:55 -07:00
|
|
|
for _, r := range pi.Rules {
|
|
|
|
if !r.success {
|
|
|
|
pi.success = false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pi.success = true
|
|
|
|
return true
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
|
|
|
|
2019-07-15 15:55:53 -07:00
|
|
|
// SuccessfulRules returns list of successful rule names
|
|
|
|
func (pi *PolicyInfo) SuccessfulRules() []string {
|
|
|
|
var rules []string
|
|
|
|
for _, r := range pi.Rules {
|
|
|
|
if r.IsSuccessful() {
|
|
|
|
rules = append(rules, r.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rules
|
|
|
|
}
|
|
|
|
|
|
|
|
// FailedRules returns list of failed rule names
|
|
|
|
func (pi *PolicyInfo) FailedRules() []string {
|
|
|
|
var rules []string
|
|
|
|
for _, r := range pi.Rules {
|
|
|
|
if !r.IsSuccessful() {
|
|
|
|
rules = append(rules, r.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rules
|
|
|
|
}
|
|
|
|
|
2019-07-15 19:14:42 -07:00
|
|
|
//GetFailedRules returns the failed rules with rule type
|
|
|
|
func (pi *PolicyInfo) GetFailedRules() []v1alpha1.FailedRule {
|
|
|
|
var rules []v1alpha1.FailedRule
|
|
|
|
for _, r := range pi.Rules {
|
|
|
|
if !r.IsSuccessful() {
|
2019-07-19 15:10:40 -07:00
|
|
|
rules = append(rules, v1alpha1.FailedRule{Name: r.Name, Type: r.RuleType.String(), Error: r.GetErrorString()})
|
2019-07-15 19:14:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return rules
|
|
|
|
}
|
|
|
|
|
2019-06-25 18:16:02 -07:00
|
|
|
//ErrorRules returns error msgs from all rule
|
|
|
|
func (pi *PolicyInfo) ErrorRules() string {
|
|
|
|
errorMsgs := []string{}
|
2019-06-25 23:58:28 -07:00
|
|
|
for _, r := range pi.Rules {
|
2019-06-25 18:16:02 -07:00
|
|
|
if !r.IsSuccessful() {
|
2019-06-25 18:38:00 -07:00
|
|
|
errorMsgs = append(errorMsgs, r.ToString())
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return strings.Join(errorMsgs, ";")
|
|
|
|
}
|
|
|
|
|
2019-06-25 23:58:28 -07:00
|
|
|
type RuleType int
|
|
|
|
|
|
|
|
const (
|
|
|
|
Mutation RuleType = iota
|
|
|
|
Validation
|
|
|
|
Generation
|
2019-08-08 15:36:37 -07:00
|
|
|
All
|
2019-06-25 23:58:28 -07:00
|
|
|
)
|
|
|
|
|
2019-07-01 12:23:10 -07:00
|
|
|
func (ri RuleType) String() string {
|
|
|
|
return [...]string{
|
|
|
|
"Mutation",
|
|
|
|
"Validation",
|
|
|
|
"Generation",
|
2019-08-08 15:36:37 -07:00
|
|
|
"All",
|
2019-07-01 12:23:10 -07:00
|
|
|
}[ri]
|
|
|
|
}
|
|
|
|
|
2019-06-25 18:16:02 -07:00
|
|
|
//RuleInfo defines rule struct
|
|
|
|
type RuleInfo struct {
|
2019-06-25 23:58:28 -07:00
|
|
|
Name string
|
2019-08-09 11:08:02 -07:00
|
|
|
RuleType RuleType
|
2019-06-25 23:58:28 -07:00
|
|
|
Msgs []string
|
2019-07-25 16:20:22 -04:00
|
|
|
Changes string // this will store the mutation patch being applied by the rule
|
2019-06-25 23:58:28 -07:00
|
|
|
success bool
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
|
|
|
|
2019-06-25 18:38:00 -07:00
|
|
|
//ToString reule information
|
2019-07-19 15:10:40 -07:00
|
|
|
//TODO: check if this is needed
|
2019-06-25 18:38:00 -07:00
|
|
|
func (ri *RuleInfo) ToString() string {
|
|
|
|
str := "rulename: " + ri.Name
|
|
|
|
msgs := strings.Join(ri.Msgs, ";")
|
|
|
|
return strings.Join([]string{str, msgs}, ";")
|
|
|
|
}
|
|
|
|
|
2019-07-19 15:10:40 -07:00
|
|
|
//GetErrorString returns the error message for a rule
|
|
|
|
func (ri *RuleInfo) GetErrorString() string {
|
|
|
|
return strings.Join(ri.Msgs, ";")
|
|
|
|
}
|
|
|
|
|
2019-06-25 18:16:02 -07:00
|
|
|
//NewRuleInfo creates a new RuleInfo
|
2019-08-13 11:32:12 -07:00
|
|
|
func NewRuleInfo(ruleName string, ruleType RuleType) RuleInfo {
|
|
|
|
return RuleInfo{
|
2019-06-25 23:58:28 -07:00
|
|
|
Name: ruleName,
|
|
|
|
Msgs: []string{},
|
2019-06-26 12:19:11 -07:00
|
|
|
RuleType: ruleType,
|
2019-06-25 23:58:28 -07:00
|
|
|
success: true, // fail to be set explicity
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Fail set the rule as failed
|
|
|
|
func (ri *RuleInfo) Fail() {
|
|
|
|
ri.success = false
|
|
|
|
}
|
|
|
|
|
|
|
|
//IsSuccessful checks if rule is succesful
|
|
|
|
func (ri *RuleInfo) IsSuccessful() bool {
|
|
|
|
return ri.success
|
|
|
|
}
|
|
|
|
|
|
|
|
//Add add msg
|
|
|
|
func (ri *RuleInfo) Add(msg string) {
|
|
|
|
ri.Msgs = append(ri.Msgs, msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
//Addf add msg with args
|
|
|
|
func (ri *RuleInfo) Addf(msg string, args ...interface{}) {
|
|
|
|
ri.Msgs = append(ri.Msgs, fmt.Sprintf(msg, args...))
|
|
|
|
}
|
|
|
|
|
|
|
|
//RulesSuccesfuly check if the any rule has failed or not
|
2019-08-13 11:32:12 -07:00
|
|
|
func RulesSuccesfuly(rules []RuleInfo) bool {
|
2019-06-25 18:16:02 -07:00
|
|
|
for _, r := range rules {
|
|
|
|
if !r.success {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
//AddRuleInfos sets the rule information
|
2019-08-13 11:32:12 -07:00
|
|
|
func (pi *PolicyInfo) AddRuleInfos(rules []RuleInfo) {
|
2019-07-18 10:22:20 -07:00
|
|
|
if rules == nil {
|
|
|
|
return
|
|
|
|
}
|
2019-06-25 18:16:02 -07:00
|
|
|
if !RulesSuccesfuly(rules) {
|
|
|
|
pi.success = false
|
|
|
|
}
|
2019-06-26 15:31:18 -07:00
|
|
|
|
|
|
|
pi.Rules = append(pi.Rules, rules...)
|
2019-06-25 18:16:02 -07:00
|
|
|
}
|
2019-07-08 16:53:34 -07:00
|
|
|
|
|
|
|
//GetRuleNames gets the name of successful rules
|
|
|
|
func (pi *PolicyInfo) GetRuleNames(onSuccess bool) string {
|
|
|
|
var ruleNames []string
|
|
|
|
for _, rule := range pi.Rules {
|
|
|
|
if onSuccess {
|
|
|
|
if rule.IsSuccessful() {
|
|
|
|
ruleNames = append(ruleNames, rule.Name)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if !rule.IsSuccessful() {
|
|
|
|
ruleNames = append(ruleNames, rule.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return strings.Join(ruleNames, ",")
|
|
|
|
}
|
2019-07-25 13:14:55 -04:00
|
|
|
|
|
|
|
//ContainsRuleType checks if a policy info contains a rule type
|
|
|
|
func (pi *PolicyInfo) ContainsRuleType(ruleType RuleType) bool {
|
|
|
|
for _, r := range pi.Rules {
|
|
|
|
if r.RuleType == ruleType {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|