mirror of
https://github.com/kubevela/kubevela.git
synced 2026-05-20 16:23:24 +00:00
* Feat: add MapVariant operation and support for OneOf parameters with default variant Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: enhance string parameter output to include optional prefix in CUE generation Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: add ConditionalOrFieldRef for fallback handling and support inline array values Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: update CUE generation to support inline arrays with conditional wrapping Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: update CUE generation to support inline arrays with conditional wrapping Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: add support for compound optional fields and enhance array builder with guarded filtering Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: add comprehensive tests for ArrayBuilder functionality Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: implement field grouping in StatusBuilder for consolidated CUE output Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: enhance CUE decomposition to support condValues and improve filtering logic Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: add metadata labels to ComponentDefinition and update CUE generation Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: clean up comments and formatting in cuegen and param files Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: enhance CUE generation, trait definitions, and PatchContainer logic CUE Generation: - Simplify condition decomposition logic and rename GetDirective method - Add condition decomposition and lifting logic to improve generated CUE output - Refactor cueTypeForParamType to use a standalone cueTypeStr function for reusability Collections: - Enhance MapVariant operation to merge variant mappings and preserve non-matching items Trait Definitions: - Enhance TraitDefinition and PatchContainerConfig with new attributes (MultiContainerCheckField, MultiContainerErrMsg) - Update emission logic in TraitCUEGenerator for multi-container support PatchContainer: - Update error messages to use camelCase for consistency with KubeVela conventions Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: enhance test descriptions for clarity and accuracy in array_builder, collections, and status tests Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: enhance handling of optional fields in collections and improve test descriptions for clarity Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: improve ConditionalOrFieldRef tests for clarity and accuracy in handling primary and fallback fields Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: enhance test descriptions for clarity and accuracy in array_builder and expr tests Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Feat: improve formatting of test data in collections tests for better readability Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> --------- Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com>
546 lines
19 KiB
Go
546 lines
19 KiB
Go
/*
|
|
Copyright 2025 The KubeVela Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package defkit
|
|
|
|
// This file extends the fluent API with patterns commonly used in traits:
|
|
// - PatchContainerConfig: for traits that patch containers by name
|
|
// - LetBinding: for CUE let bindings (local variables)
|
|
// - ListComprehension: for CUE list comprehensions with conditional fields
|
|
// - ParamIsSet/ParamNotSet: convenience constructors for parameter existence conditions
|
|
|
|
// PatchFieldBuilder provides a fluent API for constructing PatchContainerField values.
|
|
// Use PatchField() to start building.
|
|
//
|
|
// Example:
|
|
//
|
|
// defkit.PatchField("exec").IsSet().Build()
|
|
// defkit.PatchField("initialDelaySeconds").Int().IsSet().Default("0").Build()
|
|
// defkit.PatchField("image").Strategy("retainKeys").Description("Specify the image").Build()
|
|
type PatchFieldBuilder struct {
|
|
paramName string
|
|
targetField string
|
|
patchStrategy string
|
|
condition string
|
|
paramType string
|
|
paramDefault string
|
|
description string
|
|
}
|
|
|
|
// PatchField starts building a PatchContainerField with the given parameter name.
|
|
// The TargetField defaults to the same as the parameter name.
|
|
func PatchField(name string) *PatchFieldBuilder {
|
|
return &PatchFieldBuilder{
|
|
paramName: name,
|
|
targetField: name,
|
|
}
|
|
}
|
|
|
|
// Target sets the container field to patch, if different from the parameter name.
|
|
func (b *PatchFieldBuilder) Target(t string) *PatchFieldBuilder {
|
|
b.targetField = t
|
|
return b
|
|
}
|
|
|
|
// Default sets an explicit default value for the parameter.
|
|
func (b *PatchFieldBuilder) Default(val string) *PatchFieldBuilder {
|
|
b.paramDefault = val
|
|
return b
|
|
}
|
|
|
|
// Type sets an explicit CUE type string (e.g., "string", "[...string]", "{...}").
|
|
func (b *PatchFieldBuilder) Type(t string) *PatchFieldBuilder {
|
|
b.paramType = t
|
|
return b
|
|
}
|
|
|
|
// Int is shorthand for Type("int").
|
|
func (b *PatchFieldBuilder) Int() *PatchFieldBuilder {
|
|
return b.Type("int")
|
|
}
|
|
|
|
// Bool is shorthand for Type("bool").
|
|
func (b *PatchFieldBuilder) Bool() *PatchFieldBuilder {
|
|
return b.Type("bool")
|
|
}
|
|
|
|
// Str is shorthand for Type("string").
|
|
func (b *PatchFieldBuilder) Str() *PatchFieldBuilder {
|
|
return b.Type("string")
|
|
}
|
|
|
|
// StringArray is shorthand for Type("[...string]").
|
|
func (b *PatchFieldBuilder) StringArray() *PatchFieldBuilder {
|
|
return b.Type("[...string]")
|
|
}
|
|
|
|
// Strategy sets the patch strategy (e.g., "replace", "retainKeys").
|
|
func (b *PatchFieldBuilder) Strategy(s string) *PatchFieldBuilder {
|
|
b.patchStrategy = s
|
|
return b
|
|
}
|
|
|
|
// --- Condition methods (following param.go / health_expr.go patterns) ---
|
|
|
|
// IsSet guards the field with an existence check (CUE: != _|_).
|
|
// Use this for optional fields that should only be patched when provided.
|
|
func (b *PatchFieldBuilder) IsSet() *PatchFieldBuilder {
|
|
b.condition = "!= _|_"
|
|
return b
|
|
}
|
|
|
|
// NotEmpty guards the field with a non-empty string check (CUE: != "").
|
|
// Use this for string fields that should only be patched when non-empty.
|
|
func (b *PatchFieldBuilder) NotEmpty() *PatchFieldBuilder {
|
|
b.condition = `!= ""`
|
|
return b
|
|
}
|
|
|
|
// Eq sets a condition that checks the field equals the given value.
|
|
func (b *PatchFieldBuilder) Eq(val string) *PatchFieldBuilder {
|
|
b.condition = "== " + val
|
|
return b
|
|
}
|
|
|
|
// Ne sets a condition that checks the field is not equal to the given value.
|
|
func (b *PatchFieldBuilder) Ne(val string) *PatchFieldBuilder {
|
|
b.condition = "!= " + val
|
|
return b
|
|
}
|
|
|
|
// Gt sets a condition that checks the field is greater than the given value.
|
|
func (b *PatchFieldBuilder) Gt(val string) *PatchFieldBuilder {
|
|
b.condition = "> " + val
|
|
return b
|
|
}
|
|
|
|
// Gte sets a condition that checks the field is greater than or equal to the given value.
|
|
func (b *PatchFieldBuilder) Gte(val string) *PatchFieldBuilder {
|
|
b.condition = ">= " + val
|
|
return b
|
|
}
|
|
|
|
// Lt sets a condition that checks the field is less than the given value.
|
|
func (b *PatchFieldBuilder) Lt(val string) *PatchFieldBuilder {
|
|
b.condition = "< " + val
|
|
return b
|
|
}
|
|
|
|
// Lte sets a condition that checks the field is less than or equal to the given value.
|
|
func (b *PatchFieldBuilder) Lte(val string) *PatchFieldBuilder {
|
|
b.condition = "<= " + val
|
|
return b
|
|
}
|
|
|
|
// RawCondition sets a raw CUE condition string.
|
|
// Use this as an escape hatch for non-standard conditions not covered by the typed API.
|
|
func (b *PatchFieldBuilder) RawCondition(c string) *PatchFieldBuilder {
|
|
b.condition = c
|
|
return b
|
|
}
|
|
|
|
// Description sets the +usage description for this field.
|
|
func (b *PatchFieldBuilder) Description(d string) *PatchFieldBuilder {
|
|
b.description = d
|
|
return b
|
|
}
|
|
|
|
// Build returns the constructed PatchContainerField.
|
|
func (b *PatchFieldBuilder) Build() PatchContainerField {
|
|
return PatchContainerField{
|
|
ParamName: b.paramName,
|
|
TargetField: b.targetField,
|
|
PatchStrategy: b.patchStrategy,
|
|
Condition: b.condition,
|
|
ParamType: b.paramType,
|
|
ParamDefault: b.paramDefault,
|
|
Description: b.description,
|
|
}
|
|
}
|
|
|
|
// PatchFields builds a slice of PatchContainerField from builders.
|
|
// This eliminates the need to call .Build() on each field individually.
|
|
//
|
|
// Example:
|
|
//
|
|
// Fields: defkit.PatchFields(
|
|
// defkit.PatchField("exec").IsSet(),
|
|
// defkit.PatchField("initialDelaySeconds").Int().IsSet().Default("0"),
|
|
// )
|
|
func PatchFields(builders ...*PatchFieldBuilder) []PatchContainerField {
|
|
fields := make([]PatchContainerField, len(builders))
|
|
for i, b := range builders {
|
|
fields[i] = b.Build()
|
|
}
|
|
return fields
|
|
}
|
|
|
|
// PatchContainerField defines a field to be patched in the container.
|
|
type PatchContainerField struct {
|
|
ParamName string // the parameter name (e.g., "command", "args")
|
|
TargetField string // the container field to patch (e.g., "command", "args")
|
|
PatchStrategy string // the patch strategy (e.g., "replace", "merge")
|
|
Condition string // optional CUE condition (e.g., "!= null")
|
|
ParamType string // explicit CUE type (e.g., "string", "[...string]", "{...}")
|
|
ParamDefault string // explicit default value (e.g., "0", "\"\"", "false")
|
|
Description string // optional +usage description (auto-generated if empty)
|
|
}
|
|
|
|
// PatchContainerGroup defines a group of fields under a common parent field.
|
|
// This generates CUE like:
|
|
//
|
|
// startupProbe: {
|
|
// if _params.exec != _|_ { exec: _params.exec }
|
|
// if _params.httpGet != _|_ { httpGet: _params.httpGet }
|
|
// }
|
|
type PatchContainerGroup struct {
|
|
TargetField string // the parent field name (e.g., "startupProbe", "securityContext")
|
|
Fields []PatchContainerField // fields within this group
|
|
SubGroups []PatchContainerGroup // nested groups (e.g., securityContext.capabilities)
|
|
}
|
|
|
|
// PatchContainerConfig configures the PatchContainer helper.
|
|
type PatchContainerConfig struct {
|
|
ContainerNameParam string // parameter for container name
|
|
DefaultToContextName bool // default container name to context.name
|
|
PatchFields []PatchContainerField // flat fields to patch directly on container
|
|
Groups []PatchContainerGroup // grouped fields (e.g., startupProbe: { ... })
|
|
AllowMultiple bool // if true, allow patching multiple containers
|
|
ContainersParam string // for multi-container mode, the array param name
|
|
ContainersDescription string // +usage description for the containers param (auto-generated if empty)
|
|
CustomParamsBlock string // custom CUE block for #PatchParams (for complex types)
|
|
MultiContainerParam string // alternate name for multi-container param (default: "probes" for probes, "containers" for others)
|
|
MultiContainerCheckField string // field name for multi-container error check (default: "containerName")
|
|
MultiContainerErrMsg string // custom error message for multi-container mode (default: "container name must be set for %s")
|
|
CustomPatchContainerBlock string // custom CUE block for PatchContainer body (for complex merge logic)
|
|
CustomPatchBlock string // custom CUE block for the patch: spec: template: spec: { ... } body
|
|
CustomParameterBlock string // custom CUE block for the parameter definition
|
|
PatchStrategy string // if set, emitted as // +patchStrategy=<value> before the patch block (e.g., "open")
|
|
ParamsTypeName string // custom name for the #PatchParams helper (default: "PatchParams")
|
|
NoDefaultDisjunction bool // if true, omit the * default marker on parameter disjunction
|
|
}
|
|
|
|
// --- Let Binding Support ---
|
|
|
|
// LetBinding represents a CUE let binding for local variables.
|
|
// This generates: let varName = expression
|
|
//
|
|
// Usage:
|
|
//
|
|
// tpl.AddLetBinding("resourceContent", defkit.Struct(...))
|
|
// tpl.AddLetBinding("_baseContainers", defkit.ContextOutput().Field("spec.template.spec.containers"))
|
|
type LetBinding struct {
|
|
name string
|
|
expr Value
|
|
}
|
|
|
|
// NewLetBinding creates a new let binding.
|
|
func NewLetBinding(name string, expr Value) *LetBinding {
|
|
return &LetBinding{name: name, expr: expr}
|
|
}
|
|
|
|
// Name returns the binding name.
|
|
func (l *LetBinding) Name() string { return l.name }
|
|
|
|
// Expr returns the bound expression.
|
|
func (l *LetBinding) Expr() Value { return l.expr }
|
|
|
|
// LetRef references a let binding by name.
|
|
// This generates: varName in CUE expressions.
|
|
type LetRef struct {
|
|
name string
|
|
}
|
|
|
|
func (l *LetRef) value() {}
|
|
func (l *LetRef) expr() {}
|
|
|
|
// LetVariable creates a reference to a let binding.
|
|
// Use this to reference a variable created with AddLetBinding.
|
|
//
|
|
// Example:
|
|
//
|
|
// tpl.AddLetBinding("resourceContent", defkit.Struct(...))
|
|
// // Later in template:
|
|
// defkit.LetVariable("resourceContent")
|
|
func LetVariable(name string) *LetRef {
|
|
return &LetRef{name: name}
|
|
}
|
|
|
|
// Name returns the variable name.
|
|
func (l *LetRef) Name() string { return l.name }
|
|
|
|
// --- List Comprehension with Conditionals ---
|
|
|
|
// ListComprehension represents a CUE list comprehension.
|
|
// This generates: [for v in source { ... if v.field != _|_ { field: v.field } }]
|
|
//
|
|
// Usage:
|
|
//
|
|
// defkit.ForEachIn(defkit.Param("constraints")).
|
|
// MapFields(defkit.FieldMap{
|
|
// "maxSkew": defkit.FieldRef("maxSkew"), // always included
|
|
// "minDomains": defkit.Optional("minDomains"), // only if set
|
|
// })
|
|
type ListComprehension struct {
|
|
source Value
|
|
filterCondition ListPredicate
|
|
mappings FieldMap
|
|
conditionalFields []string // fields that should only appear if set
|
|
}
|
|
|
|
func (l *ListComprehension) value() {}
|
|
func (l *ListComprehension) expr() {}
|
|
|
|
// ForEachIn creates a list comprehension from a source collection.
|
|
// This is the starting point for building list comprehensions.
|
|
//
|
|
// Example:
|
|
//
|
|
// defkit.ForEachIn(defkit.ParamRef("constraints")).
|
|
// MapFields(defkit.FieldMap{...})
|
|
func ForEachIn(source Value) *ListComprehension {
|
|
return &ListComprehension{
|
|
source: source,
|
|
conditionalFields: make([]string, 0),
|
|
}
|
|
}
|
|
|
|
// WithFilter adds a filter condition to the comprehension.
|
|
// Only items matching the filter will be included in the output.
|
|
func (l *ListComprehension) WithFilter(pred ListPredicate) *ListComprehension {
|
|
l.filterCondition = pred
|
|
return l
|
|
}
|
|
|
|
// MapFields sets the field mappings for each item in the comprehension.
|
|
// Use FieldRef for always-included fields and Optional for conditional fields.
|
|
func (l *ListComprehension) MapFields(mappings FieldMap) *ListComprehension {
|
|
l.mappings = mappings
|
|
return l
|
|
}
|
|
|
|
// WithOptionalFields marks additional fields that should only appear if set.
|
|
// This is an alternative to using Optional in the FieldMap.
|
|
func (l *ListComprehension) WithOptionalFields(fields ...string) *ListComprehension {
|
|
l.conditionalFields = append(l.conditionalFields, fields...)
|
|
return l
|
|
}
|
|
|
|
// Source returns the source value.
|
|
func (l *ListComprehension) Source() Value { return l.source }
|
|
|
|
// FilterCondition returns the filter condition.
|
|
func (l *ListComprehension) FilterCondition() ListPredicate { return l.filterCondition }
|
|
|
|
// Mappings returns the field mappings.
|
|
func (l *ListComprehension) Mappings() FieldMap { return l.mappings }
|
|
|
|
// ConditionalFields returns fields that should be conditionally included.
|
|
func (l *ListComprehension) ConditionalFields() []string { return l.conditionalFields }
|
|
|
|
// --- ListPredicate for List Comprehension Filters ---
|
|
|
|
// ListPredicate represents a condition used to filter list comprehension items.
|
|
// Unlike Predicate in collections.go (which is for runtime filtering),
|
|
// ListPredicate generates CUE conditional expressions.
|
|
type ListPredicate interface {
|
|
listPredicate()
|
|
}
|
|
|
|
// ListFieldExistsPredicate checks if a field exists (is not bottom) in list items.
|
|
type ListFieldExistsPredicate struct {
|
|
field string
|
|
}
|
|
|
|
func (p *ListFieldExistsPredicate) listPredicate() {}
|
|
|
|
// GetField returns the field name being checked.
|
|
func (p *ListFieldExistsPredicate) GetField() string { return p.field }
|
|
|
|
// ListFieldExists creates a predicate that checks if a field exists in list items.
|
|
// This generates CUE: if v.field != _|_
|
|
//
|
|
// Example:
|
|
//
|
|
// defkit.ForEachIn(source).
|
|
// WithFilter(defkit.ListFieldExists("optionalField"))
|
|
func ListFieldExists(field string) *ListFieldExistsPredicate {
|
|
return &ListFieldExistsPredicate{field: field}
|
|
}
|
|
|
|
// --- Template Extensions for Traits ---
|
|
|
|
// UsePatchContainer configures the template to use the PatchContainer pattern.
|
|
func (t *Template) UsePatchContainer(config PatchContainerConfig) *Template {
|
|
t.patchContainerConfig = &config
|
|
return t
|
|
}
|
|
|
|
// AddLetBinding adds a let binding to the template.
|
|
// Let bindings create local variables in the CUE template.
|
|
//
|
|
// Example:
|
|
//
|
|
// tpl.AddLetBinding("resourceContent", defkit.Struct(
|
|
// defkit.Field("cpu", defkit.ParamTypeString),
|
|
// defkit.Field("memory", defkit.ParamTypeString),
|
|
// ))
|
|
func (t *Template) AddLetBinding(name string, expr Value) *Template {
|
|
if t.letBindings == nil {
|
|
t.letBindings = make([]*LetBinding, 0)
|
|
}
|
|
t.letBindings = append(t.letBindings, NewLetBinding(name, expr))
|
|
return t
|
|
}
|
|
|
|
// GetLetBindings returns all let bindings.
|
|
func (t *Template) GetLetBindings() []*LetBinding {
|
|
return t.letBindings
|
|
}
|
|
|
|
// GetPatchContainerConfig returns the PatchContainer configuration.
|
|
func (t *Template) GetPatchContainerConfig() *PatchContainerConfig {
|
|
return t.patchContainerConfig
|
|
}
|
|
|
|
// SetRawPatchBlock sets a raw CUE block for the patch section.
|
|
// This allows traits to define complex patch structures directly in CUE.
|
|
func (t *Template) SetRawPatchBlock(block string) *Template {
|
|
t.rawPatchBlock = block
|
|
return t
|
|
}
|
|
|
|
// GetRawPatchBlock returns the raw patch block.
|
|
func (t *Template) GetRawPatchBlock() string {
|
|
return t.rawPatchBlock
|
|
}
|
|
|
|
// SetRawParameterBlock sets a raw CUE block for the parameter section.
|
|
// This allows traits to define complex parameter schemas directly in CUE.
|
|
func (t *Template) SetRawParameterBlock(block string) *Template {
|
|
t.rawParameterBlock = block
|
|
return t
|
|
}
|
|
|
|
// GetRawParameterBlock returns the raw parameter block.
|
|
func (t *Template) GetRawParameterBlock() string {
|
|
return t.rawParameterBlock
|
|
}
|
|
|
|
// SetRawOutputsBlock sets a raw CUE block for the outputs section.
|
|
// This allows traits to define K8s resources to create directly in CUE.
|
|
// Use this for traits that generate Services, Ingresses, HPAs, PVCs, etc.
|
|
func (t *Template) SetRawOutputsBlock(block string) *Template {
|
|
t.rawOutputsBlock = block
|
|
return t
|
|
}
|
|
|
|
// GetRawOutputsBlock returns the raw outputs block.
|
|
func (t *Template) GetRawOutputsBlock() string {
|
|
return t.rawOutputsBlock
|
|
}
|
|
|
|
// SetRawHeaderBlock sets a raw CUE block for let bindings and pre-output declarations.
|
|
// This allows traits to define local variables and helper expressions in CUE.
|
|
// Use this for let bindings, helper lists, and other declarations that come before outputs.
|
|
func (t *Template) SetRawHeaderBlock(block string) *Template {
|
|
t.rawHeaderBlock = block
|
|
return t
|
|
}
|
|
|
|
// GetRawHeaderBlock returns the raw header block.
|
|
func (t *Template) GetRawHeaderBlock() string {
|
|
return t.rawHeaderBlock
|
|
}
|
|
|
|
// ParamIsSet creates a condition that checks if a parameter is set.
|
|
// This generates CUE: parameter.name != _|_
|
|
//
|
|
// This is a convenience wrapper around IsSetCondition.
|
|
//
|
|
// Example:
|
|
//
|
|
// tpl.Patch().
|
|
// SetIf(defkit.ParamIsSet("replicas"), "spec.replicas", defkit.ParamRef("replicas"))
|
|
func ParamIsSet(name string) *IsSetCondition {
|
|
return &IsSetCondition{paramName: name}
|
|
}
|
|
|
|
// ParamNotSet creates a condition that checks if a parameter is NOT set.
|
|
// This generates CUE: parameter.name == _|_
|
|
//
|
|
// This is a convenience wrapper around NotCondition{inner: IsSetCondition}.
|
|
//
|
|
// Example:
|
|
//
|
|
// // Set default only if not explicitly specified
|
|
// tpl.Patch().
|
|
// SetIf(defkit.ParamNotSet("replicas"), "spec.replicas", defkit.Literal(1))
|
|
func ParamNotSet(name string) *NotCondition {
|
|
return &NotCondition{inner: &IsSetCondition{paramName: name}}
|
|
}
|
|
|
|
// --- ContextOutputExists condition ---
|
|
|
|
// ContextOutputExistsCondition checks if a path exists in context.output.
|
|
type ContextOutputExistsCondition struct {
|
|
baseCondition
|
|
path string
|
|
}
|
|
|
|
// Path returns the path being checked.
|
|
func (c *ContextOutputExistsCondition) Path() string { return c.path }
|
|
|
|
// ContextOutputExists creates a condition that checks if a path exists in context.output.
|
|
// This generates CUE: context.output.path != _|_
|
|
//
|
|
// Example:
|
|
//
|
|
// // Only patch if workload has spec.template (Deployment/StatefulSet)
|
|
// tpl.Patch().
|
|
// SetIf(defkit.ContextOutputExists("spec.template"), "spec.template.spec.replicas", defkit.ParamRef("replicas"))
|
|
func ContextOutputExists(path string) *ContextOutputExistsCondition {
|
|
return &ContextOutputExistsCondition{path: path}
|
|
}
|
|
|
|
// --- AllConditions compound condition ---
|
|
|
|
// AllConditionsCondition is a compound condition that requires all sub-conditions to be true.
|
|
type AllConditionsCondition struct {
|
|
baseCondition
|
|
conditions []Condition
|
|
}
|
|
|
|
// Conditions returns the list of sub-conditions.
|
|
func (a *AllConditionsCondition) Conditions() []Condition { return a.conditions }
|
|
|
|
// AllConditions creates a compound condition that requires all sub-conditions to be true.
|
|
// This generates CUE: if cond1 if cond2 if cond3 { ... }
|
|
//
|
|
// Example:
|
|
//
|
|
// // Apply only if cpu AND memory are set AND requests AND limits are NOT set
|
|
// tpl.Patch().
|
|
// SetIf(defkit.AllConditions(
|
|
// defkit.ParamIsSet("cpu"),
|
|
// defkit.ParamIsSet("memory"),
|
|
// defkit.ParamNotSet("requests"),
|
|
// defkit.ParamNotSet("limits"),
|
|
// ), "spec.resources", resourceStruct)
|
|
func AllConditions(conditions ...Condition) *AllConditionsCondition {
|
|
return &AllConditionsCondition{conditions: conditions}
|
|
}
|