Skip to content

Commit

Permalink
feat: EnvVarResourceSelector & some common types (#919)
Browse files Browse the repository at this point in the history
* feat: EnvVarResourceSelector & some common types

* chore: add missing fields to EnvVarResourceSelector
  • Loading branch information
adityathebe authored Jul 23, 2024
1 parent 7461204 commit 84792ed
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 0 deletions.
28 changes: 28 additions & 0 deletions types/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,37 @@ import (
"sort"
"strings"

"github.com/flanksource/commons/collections"
"github.com/flanksource/gomplate/v3"
"github.com/samber/lo"
"gorm.io/gorm"
)

type CelExpression string

func (t CelExpression) Eval(env map[string]any) (string, error) {
return gomplate.RunTemplate(env, gomplate.Template{Expression: string(t)})
}

type GoTemplate string

func (t GoTemplate) Run(env map[string]any) (string, error) {
return gomplate.RunTemplate(env, gomplate.Template{Template: string(t)})
}

// MatchExpression uses MatchItems
type MatchExpression string

func (t MatchExpression) Match(item string) bool {
return collections.MatchItems(item, string(t))
}

type MatchExpressions []MatchExpression

func (t MatchExpressions) Match(item string) bool {
return collections.MatchItems(item, lo.Map(t, func(x MatchExpression, _ int) string { return string(x) })...)
}

// asMap marshals the given struct into a map.
func asMap(t any, removeFields ...string) map[string]any {
m := make(map[string]any)
Expand Down
134 changes: 134 additions & 0 deletions types/envvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,137 @@ func (e *EnvVar) Scan(value any) error {
return fmt.Errorf("invalid value type: %T", value)
}
}

// +kubebuilder:object:generate=true
type ValueExpression struct {
Expr CelExpression `yaml:"expr,omitempty" json:"expr,omitempty"`

// Value is a static value
Value string `yaml:"value,omitempty" json:"value,omitempty"`
}

func (t ValueExpression) Empty() bool {
return t.Value == "" && t.Expr == ""
}

func (t ValueExpression) Eval(env map[string]any) (string, error) {
if t.Value != "" {
return t.Value, nil
}

return t.Expr.Eval(env)
}

// EnvVarResourceSelector is used to select a resource.
// At least one of the fields must be specified.
// +kubebuilder:object:generate=true
type EnvVarResourceSelector struct {
Agent ValueExpression `yaml:"agent,omitempty" json:"agent,omitempty"`
Scope string `yaml:"scope,omitempty" json:"scope,omitempty"`
Cache string `yaml:"cache,omitempty" json:"cache,omitempty"`
ID ValueExpression `yaml:"id,omitempty" json:"id,omitempty"`
Name ValueExpression `yaml:"name,omitempty" json:"name,omitempty"`
Namespace ValueExpression `yaml:"namespace,omitempty" json:"namespace,omitempty"`
Types []ValueExpression `yaml:"types,omitempty" json:"types,omitempty"`
Statuses []ValueExpression `yaml:"statuses,omitempty" json:"statuses,omitempty"`
TagSelector ValueExpression `yaml:"tagSelector,omitempty" json:"tagSelector,omitempty"`
LabelSelector ValueExpression `yaml:"labelSelector,omitempty" json:"labelSelector,omitempty"`
FieldSelector ValueExpression `json:"fieldSelector,omitempty" yaml:"fieldSelector,omitempty"`
}

func (t EnvVarResourceSelector) Empty() bool {
return t.Agent.Empty() && t.Scope == "" && t.Cache == "" && t.ID.Empty() &&
t.Name.Empty() && t.Namespace.Empty() && len(t.Types) == 0 && len(t.Statuses) == 0 &&
t.TagSelector.Empty() && t.LabelSelector.Empty() && t.FieldSelector.Empty()
}

func (t EnvVarResourceSelector) Hydrate(env map[string]any) (*ResourceSelector, error) {
rs := ResourceSelector{
Scope: t.Scope,
Cache: t.Cache,
}

if !t.Agent.Empty() {
agent, err := t.Agent.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate agent: %v", err)
}
rs.Agent = agent
}

if !t.ID.Empty() {
id, err := t.ID.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate id: %v", err)
}
rs.ID = id
}

if !t.Name.Empty() {
name, err := t.Name.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate name: %v", err)
}
rs.Name = name
}

if !t.Namespace.Empty() {
namespace, err := t.Namespace.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate namespace: %v", err)
}
rs.Namespace = namespace
}

if len(t.Types) > 0 {
rs.Types = make([]string, len(t.Types))
for i, typeExpr := range t.Types {
if !typeExpr.Empty() {
typeStr, err := typeExpr.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate type at index %d: %v", i, err)
}
rs.Types[i] = typeStr
}
}
}

if len(t.Statuses) > 0 {
rs.Statuses = make([]string, len(t.Statuses))
for i, statusExpr := range t.Statuses {
if !statusExpr.Empty() {
statusStr, err := statusExpr.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate status at index %d: %v", i, err)
}
rs.Statuses[i] = statusStr
}
}
}

if !t.TagSelector.Empty() {
tagSelector, err := t.TagSelector.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate tagSelector: %v", err)
}
rs.TagSelector = tagSelector
}

if !t.LabelSelector.Empty() {
labelSelector, err := t.LabelSelector.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate labelSelector: %v", err)
}
rs.LabelSelector = labelSelector
}

if !t.FieldSelector.Empty() {
fieldSelector, err := t.FieldSelector.Eval(env)
if err != nil {
return nil, fmt.Errorf("failed to evaluate fieldSelector: %v", err)
}
rs.FieldSelector = fieldSelector
}

return &rs, nil
}
47 changes: 47 additions & 0 deletions types/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 84792ed

Please sign in to comment.