2023-03-27 10:09:46 +02:00
|
|
|
package utils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
|
|
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
2023-12-03 23:35:36 -08:00
|
|
|
"github.com/kyverno/kyverno/pkg/engine/jsonutils"
|
2023-03-27 10:09:46 +02:00
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
|
|
)
|
|
|
|
|
|
|
|
func EvaluateList(jmesPath string, ctx enginecontext.EvalInterface) ([]interface{}, error) {
|
|
|
|
i, err := ctx.Query(jmesPath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
l, ok := i.([]interface{})
|
|
|
|
if !ok {
|
|
|
|
return []interface{}{i}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return l, nil
|
|
|
|
}
|
|
|
|
|
2024-05-20 12:15:21 +05:30
|
|
|
// InvertElements inverts the order of elements for patchStrategicMerge policies
|
|
|
|
// as kustomize patch reverses the order of patch resources.
|
|
|
|
func InvertElements(elements []interface{}) []interface{} {
|
|
|
|
elementsCopy := make([]interface{}, len(elements))
|
|
|
|
for i := range elements {
|
|
|
|
elementsCopy[i] = elements[len(elements)-i-1]
|
2023-03-27 10:09:46 +02:00
|
|
|
}
|
2024-05-20 12:15:21 +05:30
|
|
|
return elementsCopy
|
2023-03-27 10:09:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func AddElementToContext(ctx engineapi.PolicyContext, element interface{}, index, nesting int, elementScope *bool) error {
|
2023-12-03 23:35:36 -08:00
|
|
|
data, err := jsonutils.DocumentToUntyped(element)
|
2023-03-27 10:09:46 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := ctx.JSONContext().AddElement(data, index, nesting); err != nil {
|
|
|
|
return fmt.Errorf("failed to add element (%v) to JSON context: %w", element, err)
|
|
|
|
}
|
|
|
|
dataMap, ok := data.(map[string]interface{})
|
|
|
|
// We set scoped to true by default if the data is a map
|
|
|
|
// otherwise we do not do element scoped foreach unless the user
|
|
|
|
// has explicitly set it to true
|
|
|
|
scoped := ok
|
|
|
|
|
|
|
|
// If the user has explicitly provided an element scope
|
|
|
|
// we check if data is a map or not. In case it is not a map and the user
|
|
|
|
// has set elementscoped to true, we throw an error.
|
|
|
|
// Otherwise we set the value to what is specified by the user.
|
|
|
|
if elementScope != nil {
|
|
|
|
if *elementScope && !ok {
|
|
|
|
return fmt.Errorf("cannot use elementScope=true foreach rules for elements that are not maps, expected type=map got type=%T", data)
|
|
|
|
}
|
|
|
|
scoped = *elementScope
|
|
|
|
}
|
|
|
|
if scoped {
|
|
|
|
u := unstructured.Unstructured{}
|
|
|
|
u.SetUnstructuredContent(dataMap)
|
|
|
|
ctx.SetElement(u)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|