package response import ( "fmt" "time" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) //EngineResponse engine response to the action type EngineResponse struct { // Resource patched with the engine action changes PatchedResource unstructured.Unstructured // Policy Response PolicyResponse PolicyResponse } //PolicyResponse policy application response type PolicyResponse struct { // policy name Policy string `json:"policy"` // resource details Resource ResourceSpec `json:"resource"` // policy statistics PolicyStats `json:",inline"` // rule response Rules []RuleResponse `json:"rules"` // ValidationFailureAction: audit(default if not set),enforce ValidationFailureAction string } //ResourceSpec resource action applied on type ResourceSpec struct { //TODO: support ApiVersion Kind string `json:"kind"` APIVersion string `json:"apiVersion"` Namespace string `json:"namespace"` 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 ProcessingTime time.Duration `json:"processingTime"` // Count of rules that were applied successfully RulesAppliedCount int `json:"rulesAppliedCount"` } //RuleResponse details for each rule applicatino type RuleResponse struct { // rule name specified in policy Name string `json:"name"` // rule type (Mutation,Generation,Validation) for Kyverno Policy Type string `json:"type"` // message response from the rule application Message string `json:"message"` // JSON patches, for mutation rules Patches [][]byte `json:"patches,omitempty"` // success/fail Success bool `json:"success"` // statistics RuleStats `json:",inline"` // PathNotPresent indicates whether referenced path in variable substitution exist PathNotPresent bool `json:"pathNotPresent"` } //ToString ... func (rr RuleResponse) ToString() string { return fmt.Sprintf("rule %s (%s): %v", rr.Name, rr.Type, rr.Message) } //RuleStats stores the statisctis for the single rule application type RuleStats struct { // time required to appliy the rule on the resource ProcessingTime time.Duration `json:"processingTime"` } //IsSuccesful checks if any rule has failed or not func (er EngineResponse) IsSuccesful() bool { for _, r := range er.PolicyResponse.Rules { if !r.Success { return false } } return true } //GetPatches returns all the patches joined func (er EngineResponse) GetPatches() [][]byte { var patches [][]byte for _, r := range er.PolicyResponse.Rules { if r.Patches != nil { patches = append(patches, r.Patches...) } } // join patches return patches } //GetFailedRules returns failed rules func (er EngineResponse) GetFailedRules() []string { return er.getRules(false) } //GetSuccessRules returns success rules func (er EngineResponse) GetSuccessRules() []string { return er.getRules(true) } func (er EngineResponse) getRules(success bool) []string { var rules []string for _, r := range er.PolicyResponse.Rules { if r.Success == success { rules = append(rules, r.Name) } } return rules } // IsPathNotPresent checks if the referenced path(in variable substitution) exist func (er EngineResponse) IsPathNotPresent() bool { for _, r := range er.PolicyResponse.Rules { if r.PathNotPresent { return true } } return false }