1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00
kyverno/pkg/engine/loadtargets.go
Charles-Edouard Brétéché 5aaf2d8770
chore: make kyverno api import aliases consistent (#3939)
Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
2022-05-17 13:12:43 +02:00

111 lines
3.5 KiB
Go

package engine
import (
"fmt"
"github.com/go-logr/logr"
"github.com/kyverno/go-wildcard"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
engineUtils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/engine/variables"
stringutils "github.com/kyverno/kyverno/pkg/utils/string"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func loadTargets(targets []kyvernov1.ResourceSpec, ctx *PolicyContext, logger logr.Logger) ([]unstructured.Unstructured, error) {
targetObjects := []unstructured.Unstructured{}
var errors []error
for i := range targets {
spec, err := resolveSpec(i, targets[i], ctx, logger)
if err != nil {
errors = append(errors, err)
continue
}
objs, err := getTargets(spec, ctx, logger)
if err != nil {
errors = append(errors, err)
continue
}
targetObjects = append(targetObjects, objs...)
}
return targetObjects, engineUtils.CombineErrors(errors)
}
func resolveSpec(i int, target kyvernov1.ResourceSpec, ctx *PolicyContext, logger logr.Logger) (kyvernov1.ResourceSpec, error) {
kind, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Kind)
if err != nil {
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].Kind %s: %v", i, target.Kind, err)
}
apiversion, err := variables.SubstituteAll(logger, ctx.JSONContext, target.APIVersion)
if err != nil {
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].APIVersion %s: %v", i, target.APIVersion, err)
}
namespace, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Namespace)
if err != nil {
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].Namespace %s: %v", i, target.Namespace, err)
}
name, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Name)
if err != nil {
return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].Name %s: %v", i, target.Name, err)
}
return kyvernov1.ResourceSpec{
APIVersion: apiversion.(string),
Kind: kind.(string),
Namespace: namespace.(string),
Name: name.(string),
}, nil
}
func getTargets(target kyvernov1.ResourceSpec, ctx *PolicyContext, logger logr.Logger) ([]unstructured.Unstructured, error) {
var targetObjects []unstructured.Unstructured
namespace := target.Namespace
name := target.Name
if namespace != "" && name != "" &&
!stringutils.ContainsWildcard(namespace) && !stringutils.ContainsWildcard(name) {
obj, err := ctx.Client.GetResource(target.APIVersion, target.Kind, namespace, name)
if err != nil {
return nil, fmt.Errorf("failed to get target %s/%s %s/%s : %v", target.APIVersion, target.Kind, namespace, name, err)
}
return []unstructured.Unstructured{*obj}, nil
}
// list all targets if wildcard is specified
objList, err := ctx.Client.ListResource(target.APIVersion, target.Kind, "", nil)
if err != nil {
return nil, err
}
for i := range objList.Items {
obj := objList.Items[i].DeepCopy()
if match(namespace, name, obj.GetNamespace(), obj.GetName()) {
targetObjects = append(targetObjects, *obj)
}
}
return targetObjects, nil
}
func match(namespacePattern, namePattern, namespace, name string) bool {
if namespacePattern == "" && namePattern == "" {
return true
} else if namespacePattern == "" {
if wildcard.Match(namePattern, name) {
return true
}
} else if wildcard.Match(namespacePattern, namespace) {
if namePattern == "" || wildcard.Match(namePattern, name) {
return true
}
}
return false
}