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

fix: TODOs in cli (#8333)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-09-11 17:24:10 +02:00 committed by GitHub
parent aeabe7048d
commit 30598c64d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 64 additions and 94 deletions

View file

@ -447,12 +447,15 @@ func printSkippedAndInvalidPolicies(skipInvalidPolicies SkippedInvalidPolicies)
} }
func printReport(engineResponses []engineapi.EngineResponse, auditWarn bool) { func printReport(engineResponses []engineapi.EngineResponse, auditWarn bool) {
clustered, namespaced := report.ComputePolicyReports(auditWarn, engineResponses...) clustered, namespaced, err := report.ComputePolicyReports(auditWarn, engineResponses...)
if err != nil {
fmt.Println("Error: failed to compute policy reports")
}
if len(clustered) > 0 || len(namespaced) > 0 { if len(clustered) > 0 || len(namespaced) > 0 {
fmt.Println(divider) fmt.Println(divider)
fmt.Println("POLICY REPORT:") fmt.Println("POLICY REPORT:")
fmt.Println(divider) fmt.Println(divider)
report := report.MergeClusterReports(clustered, namespaced) report := report.MergeClusterReports(clustered)
yamlReport, _ := yaml.Marshal(report) yamlReport, _ := yaml.Marshal(report)
fmt.Println(string(yamlReport)) fmt.Println(string(yamlReport))
} else { } else {

View file

@ -317,10 +317,10 @@ func Test_Apply(t *testing.T) {
_, _, _, responses, err := tc.config.applyCommandHelper() _, _, _, responses, err := tc.config.applyCommandHelper()
assert.NilError(t, err, desc) assert.NilError(t, err, desc)
clustered, _ := report.ComputePolicyReports(tc.config.AuditWarn, responses...) clustered, _, _ := report.ComputePolicyReports(tc.config.AuditWarn, responses...)
assert.Assert(t, len(clustered) > 0, "policy reports should not be empty: %s", desc) assert.Assert(t, len(clustered) > 0, "policy reports should not be empty: %s", desc)
combined := []policyreportv1alpha2.ClusterPolicyReport{ combined := []policyreportv1alpha2.ClusterPolicyReport{
report.MergeClusterReports(clustered, nil), report.MergeClusterReports(clustered),
} }
assert.Equal(t, len(combined), len(tc.expectedPolicyReports)) assert.Equal(t, len(combined), len(tc.expectedPolicyReports))
for i, resp := range combined { for i, resp := range combined {

View file

@ -179,7 +179,10 @@ func checkResult(test testapi.TestResults, fs billy.Filesystem, resoucePath stri
return false, "Generated resource didn't match the generated resource in the test result", "Resource diff" return false, "Generated resource didn't match the generated resource in the test result", "Resource diff"
} }
} }
result := report.ComputePolicyReportResult(false, response, rule) result, err := report.ComputePolicyReportResult(false, response, rule)
if err != nil {
return false, err.Error(), "Error"
}
if result.Result != expected { if result.Result != expected {
return false, result.Message, fmt.Sprintf("Want %s, got %s", expected, result.Result) return false, result.Message, fmt.Sprintf("Want %s, got %s", expected, result.Result)
} }

View file

@ -185,9 +185,7 @@ func TestTable_Rows(t *testing.T) {
}, },
Message: "message2", Message: "message2",
}}, }},
}, }}
// TODO: Add test cases.
}
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
tr := &Table{ tr := &Table{

View file

@ -28,7 +28,7 @@ func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov
} }
pols = append(pols, p...) pols = append(pols, p...)
vaps = append(vaps, v...) vaps = append(vaps, v...)
} else if fs != nil /* && source.IsGit(path) */ { // TODO source.IsGit(path) } else if fs != nil {
p, v, err := gitLoad(fs, filepath.Join(resourcePath, path)) p, v, err := gitLoad(fs, filepath.Join(resourcePath, path))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View file

@ -8,17 +8,20 @@ import (
reportutils "github.com/kyverno/kyverno/pkg/utils/report" reportutils "github.com/kyverno/kyverno/pkg/utils/report"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
) )
func ComputePolicyReportResult(auditWarn bool, engineResponse engineapi.EngineResponse, ruleResponse engineapi.RuleResponse) policyreportv1alpha2.PolicyReportResult { func ComputePolicyReportResult(auditWarn bool, engineResponse engineapi.EngineResponse, ruleResponse engineapi.RuleResponse) (policyreportv1alpha2.PolicyReportResult, error) {
policy := engineResponse.Policy() policy := engineResponse.Policy()
policyName := policy.GetName() policyName, err := cache.MetaNamespaceKeyFunc(policy.MetaObject())
if err != nil {
return policyreportv1alpha2.PolicyReportResult{}, err
}
audit := engineResponse.GetValidationFailureAction().Audit() audit := engineResponse.GetValidationFailureAction().Audit()
scored := annotations.Scored(policy.GetAnnotations()) scored := annotations.Scored(policy.GetAnnotations())
category := annotations.Category(policy.GetAnnotations()) category := annotations.Category(policy.GetAnnotations())
severity := annotations.Severity(policy.GetAnnotations()) severity := annotations.Severity(policy.GetAnnotations())
result := policyreportv1alpha2.PolicyReportResult{ result := policyreportv1alpha2.PolicyReportResult{
// TODO policy name looks wrong, it should consider the namespace too
Policy: policyName, Policy: policyName,
Resources: []corev1.ObjectReference{ Resources: []corev1.ObjectReference{
{ {
@ -54,10 +57,10 @@ func ComputePolicyReportResult(auditWarn bool, engineResponse engineapi.EngineRe
result.Message = ruleResponse.Message() result.Message = ruleResponse.Message()
result.Source = kyverno.ValueKyvernoApp result.Source = kyverno.ValueKyvernoApp
result.Timestamp = metav1.Timestamp{Seconds: ruleResponse.Stats().Timestamp()} result.Timestamp = metav1.Timestamp{Seconds: ruleResponse.Stats().Timestamp()}
return result return result, nil
} }
func ComputePolicyReportResultsPerPolicy(auditWarn bool, engineResponses ...engineapi.EngineResponse) map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult { func ComputePolicyReportResultsPerPolicy(auditWarn bool, engineResponses ...engineapi.EngineResponse) (map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult, error) {
results := map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult{} results := map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult{}
for _, engineResponse := range engineResponses { for _, engineResponse := range engineResponses {
if len(engineResponse.PolicyResponse.Rules) == 0 { if len(engineResponse.PolicyResponse.Rules) == 0 {
@ -69,20 +72,26 @@ func ComputePolicyReportResultsPerPolicy(auditWarn bool, engineResponses ...engi
// if ruleResponse.RuleType() != engineapi.Validation && ruleResponse.RuleType() != engineapi.ImageVerify { // if ruleResponse.RuleType() != engineapi.Validation && ruleResponse.RuleType() != engineapi.ImageVerify {
// continue // continue
// } // }
result := ComputePolicyReportResult(auditWarn, engineResponse, ruleResponse) result, err := ComputePolicyReportResult(auditWarn, engineResponse, ruleResponse)
if err != nil {
return nil, err
}
results[policy] = append(results[policy], result) results[policy] = append(results[policy], result)
} }
} }
if len(results) == 0 { if len(results) == 0 {
return nil return nil, nil
} }
return results return results, nil
} }
func ComputePolicyReports(auditWarn bool, engineResponses ...engineapi.EngineResponse) ([]policyreportv1alpha2.ClusterPolicyReport, []policyreportv1alpha2.PolicyReport) { func ComputePolicyReports(auditWarn bool, engineResponses ...engineapi.EngineResponse) ([]policyreportv1alpha2.ClusterPolicyReport, []policyreportv1alpha2.PolicyReport, error) {
var clustered []policyreportv1alpha2.ClusterPolicyReport var clustered []policyreportv1alpha2.ClusterPolicyReport
var namespaced []policyreportv1alpha2.PolicyReport var namespaced []policyreportv1alpha2.PolicyReport
perPolicyResults := ComputePolicyReportResultsPerPolicy(auditWarn, engineResponses...) perPolicyResults, err := ComputePolicyReportResultsPerPolicy(auditWarn, engineResponses...)
if err != nil {
return nil, nil, err
}
for policy, results := range perPolicyResults { for policy, results := range perPolicyResults {
if policy.GetNamespace() == "" { if policy.GetNamespace() == "" {
report := policyreportv1alpha2.ClusterPolicyReport{ report := policyreportv1alpha2.ClusterPolicyReport{
@ -109,21 +118,14 @@ func ComputePolicyReports(auditWarn bool, engineResponses ...engineapi.EngineRes
namespaced = append(namespaced, report) namespaced = append(namespaced, report)
} }
} }
return clustered, namespaced return clustered, namespaced, nil
} }
func MergeClusterReports(clustered []policyreportv1alpha2.ClusterPolicyReport, namespaced []policyreportv1alpha2.PolicyReport) policyreportv1alpha2.ClusterPolicyReport { func MergeClusterReports(clustered []policyreportv1alpha2.ClusterPolicyReport) policyreportv1alpha2.ClusterPolicyReport {
var results []policyreportv1alpha2.PolicyReportResult var results []policyreportv1alpha2.PolicyReportResult
for _, report := range clustered { for _, report := range clustered {
results = append(results, report.Results...) results = append(results, report.Results...)
} }
// TODO why this ?
for _, report := range namespaced {
if report.GetNamespace() != "" {
continue
}
results = append(results, report.Results...)
}
return policyreportv1alpha2.ClusterPolicyReport{ return policyreportv1alpha2.ClusterPolicyReport{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
Kind: "ClusterPolicyReport", Kind: "ClusterPolicyReport",

View file

@ -34,7 +34,8 @@ func TestComputeClusterPolicyReports(t *testing.T) {
"validation rule 'pods-require-limits' passed.", "validation rule 'pods-require-limits' passed.",
), ),
) )
clustered, namespaced := ComputePolicyReports(false, er) clustered, namespaced, err := ComputePolicyReports(false, er)
assert.NilError(t, err)
assert.Equal(t, len(clustered), 1) assert.Equal(t, len(clustered), 1)
assert.Equal(t, len(namespaced), 0) assert.Equal(t, len(namespaced), 0)
{ {
@ -68,7 +69,8 @@ func TestComputePolicyReports(t *testing.T) {
"validation rule 'pods-require-limits' passed.", "validation rule 'pods-require-limits' passed.",
), ),
) )
clustered, namespaced := ComputePolicyReports(false, er) clustered, namespaced, err := ComputePolicyReports(false, er)
assert.NilError(t, err)
assert.Equal(t, len(clustered), 0) assert.Equal(t, len(clustered), 0)
assert.Equal(t, len(namespaced), 1) assert.Equal(t, len(namespaced), 1)
{ {
@ -102,7 +104,8 @@ func TestComputePolicyReportResultsPerPolicyOld(t *testing.T) {
"validation rule 'pods-require-limits' passed.", "validation rule 'pods-require-limits' passed.",
), ),
) )
results := ComputePolicyReportResultsPerPolicy(false, er) results, err := ComputePolicyReportResultsPerPolicy(false, er)
assert.NilError(t, err)
for _, result := range results { for _, result := range results {
assert.Equal(t, len(result), 2) assert.Equal(t, len(result), 2)
for _, r := range result { for _, r := range result {
@ -146,73 +149,18 @@ func TestMergeClusterReport(t *testing.T) {
}, },
}, },
}} }}
namespaced := []policyreportv1alpha2.PolicyReport{{
TypeMeta: metav1.TypeMeta{
Kind: "PolicyReport",
APIVersion: report.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "ns-polr-1",
Namespace: "ns-polr",
},
Results: []policyreportv1alpha2.PolicyReportResult{
{
Policy: "ns-polr-1",
Result: report.StatusPass,
Resources: make([]corev1.ObjectReference, 10),
},
},
}, {
TypeMeta: metav1.TypeMeta{
Kind: "PolicyReport",
APIVersion: report.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "ns-polr-2",
},
Results: []policyreportv1alpha2.PolicyReportResult{
{
Policy: "ns-polr-2",
Result: report.StatusPass,
Resources: make([]corev1.ObjectReference, 5),
},
},
}, {
TypeMeta: metav1.TypeMeta{
Kind: "PolicyReport",
APIVersion: report.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "polr-3",
},
Results: []policyreportv1alpha2.PolicyReportResult{
{
Policy: "polr-3",
Result: report.StatusPass,
Resources: make([]corev1.ObjectReference, 1),
},
},
}}
expectedResults := []policyreportv1alpha2.PolicyReportResult{{ expectedResults := []policyreportv1alpha2.PolicyReportResult{{
Policy: "cpolr-4", Policy: "cpolr-4",
Result: report.StatusFail, Result: report.StatusFail,
}, { }, {
Policy: "cpolr-5", Policy: "cpolr-5",
Result: report.StatusFail, Result: report.StatusFail,
}, {
Policy: "ns-polr-2",
Result: report.StatusPass,
Resources: make([]corev1.ObjectReference, 5),
}, {
Policy: "polr-3",
Result: report.StatusPass,
Resources: make([]corev1.ObjectReference, 1),
}} }}
cpolr := MergeClusterReports(clustered, namespaced) cpolr := MergeClusterReports(clustered)
assert.Equal(t, cpolr.APIVersion, report.SchemeGroupVersion.String()) assert.Equal(t, cpolr.APIVersion, report.SchemeGroupVersion.String())
assert.Equal(t, cpolr.Kind, "ClusterPolicyReport") assert.Equal(t, cpolr.Kind, "ClusterPolicyReport")
assert.DeepEqual(t, cpolr.Results, expectedResults) assert.DeepEqual(t, cpolr.Results, expectedResults)
assert.Equal(t, cpolr.Summary.Pass, 2) assert.Equal(t, cpolr.Summary.Pass, 0)
assert.Equal(t, cpolr.Summary.Fail, 2) assert.Equal(t, cpolr.Summary.Fail, 2)
} }
@ -326,7 +274,8 @@ func TestComputePolicyReportResult(t *testing.T) {
}} }}
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got := ComputePolicyReportResult(tt.auditWarn, tt.engineResponse, tt.ruleResponse) got, err := ComputePolicyReportResult(tt.auditWarn, tt.engineResponse, tt.ruleResponse)
assert.NilError(t, err)
got.Timestamp = metav1.Timestamp{} got.Timestamp = metav1.Timestamp{}
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ComputePolicyReportResult() = %v, want %v", got, tt.want) t.Errorf("ComputePolicyReportResult() = %v, want %v", got, tt.want)
@ -351,7 +300,9 @@ func TestComputePolicyReportResultsPerPolicy(t *testing.T) {
}} }}
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := ComputePolicyReportResultsPerPolicy(tt.auditWarn, tt.engineResponses...); !reflect.DeepEqual(got, tt.want) { got, err := ComputePolicyReportResultsPerPolicy(tt.auditWarn, tt.engineResponses...)
assert.NilError(t, err)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ComputePolicyReportResultsPerPolicy() = %v, want %v", got, tt.want) t.Errorf("ComputePolicyReportResultsPerPolicy() = %v, want %v", got, tt.want)
} }
}) })

View file

@ -2,6 +2,8 @@ package variables
import ( import (
"strings" "strings"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/log"
) )
func parse(vars ...string) map[string]string { func parse(vars ...string) map[string]string {
@ -10,21 +12,21 @@ func parse(vars ...string) map[string]string {
variable = strings.TrimSpace(variable) variable = strings.TrimSpace(variable)
kvs := strings.Split(variable, "=") kvs := strings.Split(variable, "=")
if len(kvs) != 2 { if len(kvs) != 2 {
// TODO warning log.Log.Info("ignored variable", "variable", variable)
continue continue
} }
key := strings.TrimSpace(kvs[0]) key := strings.TrimSpace(kvs[0])
value := strings.TrimSpace(kvs[1]) value := strings.TrimSpace(kvs[1])
if len(value) == 0 || len(key) == 0 { if len(value) == 0 || len(key) == 0 {
// TODO log log.Log.Info("ignored variable", "variable", variable)
continue continue
} }
if strings.Contains(key, "request.object.") { if strings.Contains(key, "request.object.") {
// TODO log log.Log.Info("ignored variable (contains `request.object.`)", "variable", variable)
continue continue
} }
if result[key] != "" { if result[key] != "" {
// TODO log log.Log.Info("ignored variable (duplicated)", "variable", variable)
continue continue
} }
result[key] = value result[key] = value

View file

@ -3,6 +3,7 @@ package api
import ( import (
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"k8s.io/api/admissionregistration/v1alpha1" "k8s.io/api/admissionregistration/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
// PolicyType represents the type of a policy // PolicyType represents the type of a policy
@ -34,6 +35,8 @@ type GenericPolicy interface {
GetAnnotations() map[string]string GetAnnotations() map[string]string
// IsNamespaced indicates if the policy is namespace scoped // IsNamespaced indicates if the policy is namespace scoped
IsNamespaced() bool IsNamespaced() bool
// MetaObject provides an object compatible with metav1.Object
MetaObject() metav1.Object
} }
type KyvernoPolicy struct { type KyvernoPolicy struct {
@ -72,6 +75,10 @@ func (p *KyvernoPolicy) IsNamespaced() bool {
return p.policy.IsNamespaced() return p.policy.IsNamespaced()
} }
func (p *KyvernoPolicy) MetaObject() metav1.Object {
return p.policy
}
func NewKyvernoPolicy(pol kyvernov1.PolicyInterface) GenericPolicy { func NewKyvernoPolicy(pol kyvernov1.PolicyInterface) GenericPolicy {
return &KyvernoPolicy{ return &KyvernoPolicy{
policy: pol, policy: pol,
@ -114,6 +121,10 @@ func (p *ValidatingAdmissionPolicy) IsNamespaced() bool {
return false return false
} }
func (p *ValidatingAdmissionPolicy) MetaObject() metav1.Object {
return &p.policy
}
func NewValidatingAdmissionPolicy(pol v1alpha1.ValidatingAdmissionPolicy) GenericPolicy { func NewValidatingAdmissionPolicy(pol v1alpha1.ValidatingAdmissionPolicy) GenericPolicy {
return &ValidatingAdmissionPolicy{ return &ValidatingAdmissionPolicy{
policy: pol, policy: pol,