Files
capsule/pkg/template/fast.go
Oliver Bähler a6b830b1af feat: add ruleset api(#1844)
* fix(controller): decode old object for delete requests

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: modernize golang

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: modernize golang

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: modernize golang

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* fix(config): remove usergroups default

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* fix(config): remove usergroups default

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* sec(ghsa-2ww6-hf35-mfjm): intercept namespace subresource

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* feat(api): add rulestatus api

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* chore: conflicts

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* feat(api): add rulestatus api

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* feat(api): add rulestatus api

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* feat(api): add rulestatus api

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* feat(api): add rulestatus api

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* feat(api): add rulestatus api

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

* feat(api): add rulestatus api

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

---------

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>
2026-01-27 14:28:48 +01:00

113 lines
2.5 KiB
Go

// Copyright 2020-2026 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0
package template
import (
"fmt"
"io"
"slices"
"strings"
"github.com/valyala/fasttemplate"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// RequiresFastTemplate evaluates if given string requires templating.
func RequiresFastTemplate(
template string,
) bool {
return strings.Contains(template, "{{") && strings.Contains(template, "}}")
}
// FastTemplate applies templating to the provided string.
func FastTemplate(
template string,
templateContext map[string]string,
) string {
if !RequiresFastTemplate(template) {
return template
}
t := fasttemplate.New(template, "{{", "}}")
return t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
key := strings.TrimSpace(tag)
if v, ok := templateContext[key]; ok {
return w.Write([]byte(v))
}
return 0, nil
})
}
// FastTemplateMap applies templating to all values in the provided map in place.
func FastTemplateMap(
m map[string]string,
templateContext map[string]string,
) map[string]string {
if len(m) == 0 {
return map[string]string{}
}
out := make(map[string]string, len(m))
for k, v := range m {
out[FastTemplate(k, templateContext)] = FastTemplate(v, templateContext)
}
return out
}
// FastTemplateMap evaluates if given LabelSelector requires templating.
func SelectorRequiresTemplating(sel *metav1.LabelSelector) bool {
if sel == nil {
return false
}
for k, v := range sel.MatchLabels {
if RequiresFastTemplate(k) || RequiresFastTemplate(v) {
return true
}
}
for _, expr := range sel.MatchExpressions {
if RequiresFastTemplate(expr.Key) {
return true
}
if slices.ContainsFunc(expr.Values, RequiresFastTemplate) {
return true
}
}
return false
}
// FastTemplateMap templates a Labelselector (all keys and values).
func FastTemplateLabelSelector(
in *metav1.LabelSelector,
templateContext map[string]string,
) (*metav1.LabelSelector, error) {
if in == nil {
return nil, nil
}
out := in.DeepCopy()
out.MatchLabels = FastTemplateMap(in.MatchLabels, templateContext)
for i := range out.MatchExpressions {
out.MatchExpressions[i].Key = FastTemplate(out.MatchExpressions[i].Key, templateContext)
for j := range out.MatchExpressions[i].Values {
out.MatchExpressions[i].Values[j] = FastTemplate(out.MatchExpressions[i].Values[j], templateContext)
}
}
if _, err := metav1.LabelSelectorAsSelector(out); err != nil {
return nil, fmt.Errorf("templated label selector is invalid: %w", err)
}
return out, nil
}