Files
kubevela/pkg/definition/defkit/context_test.go
Jerrin Francis cf66f20cd9 Feat: introduce Mandatory() API and three-state CUE field markers in defkit (#7068)
* feat(defkit): introduce Mandatory() API and three-state CUE field markers

 Add a new .Mandatory() fluent method to all defkit param types and StructField,
 giving callers explicit control over all three CUE field presence semantics:

   field?: type   — optional, emitted by default (no method call)
   field: type    — non-optional; must have a value, defaults/merging can satisfy (.Mandatory())
   field!: type   — required in input; user must explicitly provide it (.Required())

 Previously, Required() emitted no marker (identical to a mandatory field), making
 it impossible to generate the CUE ! marker at all. Now Required() emits ! and
 Mandatory() emits no marker, matching their intuitive meanings.

 - Add `mandatory bool` field to baseParam and StructField
 - Add IsMandatory() accessor to baseParam, StructField, and Param interface
 - Add .Mandatory() builder method to all 10 concrete param types and StructField
 - Replace the `optional string` variable in cuegen.go with a typed `marker` variable
   backed by named constants (fieldMarkerOptional, fieldMarkerNone, fieldMarkerRequired)
 - Update IsOptional() to return !required && !mandatory
 - Update Optional() to clear mandatory instead of required
 - Update all tests to use .Mandatory() for non-optional fields

Signed-off-by: Jerrin Francis <jerrinfrancis7@gmail.com>

* fix(defkit): correct doc comments after Required/Mandatory semantic swap

  Fix misleading comments that still described the pre-swap behaviour.
  Mandatory() comments incorrectly referenced the "!" marker, and
  Required()/IsRequired() accessors had stale descriptions. Aligned
  all doc comments and field annotations with the actual semantics:
  Required → "!" marker, Mandatory → non-optional (no ? marker).

Signed-off-by: Jerrin Francis <jerrinfrancis7@gmail.com>

* feat(defkit): add BeMandatory matcher and fix BeOptional for three-state semantics

  BeOptional incorrectly returned true for mandatory params by checking
  !IsRequired(). Now uses IsOptional() which correctly excludes both
  required and mandatory params. Adds BeMandatory() matcher and updates
  paramAccessor interface with IsOptional/IsMandatory methods.

Signed-off-by: Jerrin Francis <jerrinfrancis7@gmail.com>

* fix(defkit): clear required flag in Optional() for all param types

  The previous commit only fixed StringParam.Optional(). Apply the same
  fix to Int, Bool, Float, Array, Map, Struct, StructField, Enum, OneOf,
  and StringKeyMap so that Optional() consistently resets both mandatory
  and required flags across all parameter types.

Signed-off-by: Jerrin Francis <jerrinfrancis7@gmail.com>

* fix(defkit): make Required() and Mandatory() mutually exclusive and fix missing optional markers in CUE generation

  Required() and Mandatory() only set their own flag without clearing
  the other, allowing both to be true simultaneously via chaining.
  Each method now clears the opposite flag so the last call wins,
  matching the reset semantics that Optional() already followed.

  Also fix CUE generation for int, bool, float, and enum params where
  the optional marker was dropped from format strings when a default
  value was present, causing those fields to always render without
  the field marker regardless of their optional/mandatory/required state.

Signed-off-by: Jerrin Francis <jerrinfrancis7@gmail.com>

* Empty commit to re-trigger e2e

Signed-off-by: Jerrin Francis <jerrinfrancis7@gmail.com>

---------

Signed-off-by: Jerrin Francis <jerrinfrancis7@gmail.com>
2026-03-12 16:39:34 +00:00

843 lines
24 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_test
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/oam-dev/kubevela/pkg/definition/defkit"
)
var _ = Describe("VelaContext", func() {
Context("VelaCtx", func() {
It("should create a context instance", func() {
vela := defkit.VelaCtx()
Expect(vela).NotTo(BeNil())
})
})
Context("Basic Context References", func() {
var vela *defkit.VelaContext
BeforeEach(func() {
vela = defkit.VelaCtx()
})
It("should return name reference", func() {
ref := vela.Name()
Expect(ref.Path()).To(Equal("context.name"))
})
It("should return namespace reference", func() {
ref := vela.Namespace()
Expect(ref.Path()).To(Equal("context.namespace"))
})
It("should return appName reference", func() {
ref := vela.AppName()
Expect(ref.Path()).To(Equal("context.appName"))
})
It("should return appRevision reference", func() {
ref := vela.AppRevision()
Expect(ref.Path()).To(Equal("context.appRevision"))
})
It("should return appRevisionNum reference", func() {
ref := vela.AppRevisionNum()
Expect(ref.Path()).To(Equal("context.appRevisionNum"))
})
})
Context("ClusterVersion", func() {
var vela *defkit.VelaContext
BeforeEach(func() {
vela = defkit.VelaCtx()
})
It("should return cluster version reference", func() {
ref := vela.ClusterVersion()
Expect(ref.Path()).To(Equal("context.clusterVersion"))
})
It("should return major version reference", func() {
ref := vela.ClusterVersion().Major()
Expect(ref.Path()).To(Equal("context.clusterVersion.major"))
})
It("should return minor version reference", func() {
ref := vela.ClusterVersion().Minor()
Expect(ref.Path()).To(Equal("context.clusterVersion.minor"))
})
It("should return patch version reference", func() {
ref := vela.ClusterVersion().Patch()
Expect(ref.Path()).To(Equal("context.clusterVersion.patch"))
})
It("should return gitVersion reference", func() {
ref := vela.ClusterVersion().GitVersion()
Expect(ref.Path()).To(Equal("context.clusterVersion.gitVersion"))
})
})
Context("Additional VelaContext Methods", func() {
var vela *defkit.VelaContext
BeforeEach(func() {
vela = defkit.VelaCtx()
})
It("should return revision reference", func() {
ref := vela.Revision()
Expect(ref.Path()).To(Equal("context.revision"))
})
It("should return output reference", func() {
ref := vela.Output()
Expect(ref.Path()).To(Equal("context.output"))
})
It("should return outputs reference with name", func() {
ref := vela.Outputs("service")
Expect(ref.Path()).To(Equal("context.outputs.service"))
})
It("should return outputs reference for configmap", func() {
ref := vela.Outputs("configmap")
Expect(ref.Path()).To(Equal("context.outputs.configmap"))
})
})
Context("ContextRef String Method", func() {
It("should return string representation for name", func() {
vela := defkit.VelaCtx()
ref := vela.Name()
Expect(ref.String()).To(Equal("$(context.name)"))
})
It("should return string representation for namespace", func() {
vela := defkit.VelaCtx()
ref := vela.Namespace()
Expect(ref.String()).To(Equal("$(context.namespace)"))
})
It("should return string representation for appName", func() {
vela := defkit.VelaCtx()
ref := vela.AppName()
Expect(ref.String()).To(Equal("$(context.appName)"))
})
It("should return string representation for revision", func() {
vela := defkit.VelaCtx()
ref := vela.Revision()
Expect(ref.String()).To(Equal("$(context.revision)"))
})
It("should return string representation for output", func() {
vela := defkit.VelaCtx()
ref := vela.Output()
Expect(ref.String()).To(Equal("$(context.output)"))
})
It("should return string representation for outputs", func() {
vela := defkit.VelaCtx()
ref := vela.Outputs("service")
Expect(ref.String()).To(Equal("$(context.outputs.service)"))
})
})
Context("Context in Expressions", func() {
It("should use context ref in comparison", func() {
vela := defkit.VelaCtx()
cond := defkit.Ge(vela.ClusterVersion().Minor(), defkit.Lit(21))
Expect(cond.Left()).To(Equal(vela.ClusterVersion().Minor()))
})
It("should use context ref in resource Set", func() {
vela := defkit.VelaCtx()
r := defkit.NewResource("v1", "ConfigMap").
Set("metadata.name", vela.Name()).
Set("metadata.namespace", vela.Namespace())
Expect(r.Ops()).To(HaveLen(2))
})
})
})
var _ = Describe("TestContext", func() {
Context("TestContextBuilder", func() {
It("should create test context with defaults", func() {
ctx := defkit.TestContext()
Expect(ctx.Name()).To(Equal("test-component"))
Expect(ctx.Namespace()).To(Equal("default"))
Expect(ctx.AppName()).To(Equal("test-app"))
})
It("should set custom name", func() {
ctx := defkit.TestContext().WithName("my-component")
Expect(ctx.Name()).To(Equal("my-component"))
})
It("should set custom namespace", func() {
ctx := defkit.TestContext().WithNamespace("production")
Expect(ctx.Namespace()).To(Equal("production"))
})
It("should set app name", func() {
ctx := defkit.TestContext().WithAppName("my-app")
Expect(ctx.AppName()).To(Equal("my-app"))
})
It("should set single parameter", func() {
ctx := defkit.TestContext().WithParam("replicas", 3)
Expect(ctx.Params()["replicas"]).To(Equal(3))
})
It("should set multiple parameters", func() {
ctx := defkit.TestContext().WithParams(map[string]any{
"image": "nginx:latest",
"replicas": 5,
"port": 8080,
})
Expect(ctx.Params()["image"]).To(Equal("nginx:latest"))
Expect(ctx.Params()["replicas"]).To(Equal(5))
Expect(ctx.Params()["port"]).To(Equal(8080))
})
It("should set cluster version", func() {
ctx := defkit.TestContext().WithClusterVersion(1, 30)
major, minor := ctx.ClusterVersion()
Expect(major).To(Equal(1))
Expect(minor).To(Equal(30))
})
It("should chain configuration methods", func() {
ctx := defkit.TestContext().
WithName("web").
WithNamespace("prod").
WithParam("image", "nginx").
WithParam("replicas", 3).
WithClusterVersion(1, 28)
Expect(ctx.Name()).To(Equal("web"))
Expect(ctx.Namespace()).To(Equal("prod"))
Expect(ctx.Params()["image"]).To(Equal("nginx"))
Expect(ctx.Params()["replicas"]).To(Equal(3))
major, minor := ctx.ClusterVersion()
Expect(major).To(Equal(1))
Expect(minor).To(Equal(28))
})
})
Context("Render", func() {
var (
image *defkit.StringParam
replicas *defkit.IntParam
port *defkit.IntParam
comp *defkit.ComponentDefinition
)
BeforeEach(func() {
image = defkit.String("image").Mandatory()
replicas = defkit.Int("replicas").Default(1)
port = defkit.Int("port").Default(80)
comp = defkit.NewComponent("webservice").
Description("Web service component").
Workload("apps/v1", "Deployment").
Params(image, replicas, port).
Template(func(tpl *defkit.Template) {
vela := defkit.VelaCtx()
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
Set("metadata.name", vela.Name()).
Set("spec.replicas", replicas).
Set("spec.template.spec.containers[0].image", image).
Set("spec.template.spec.containers[0].ports[0].containerPort", port),
)
tpl.Outputs("service",
defkit.NewResource("v1", "Service").
Set("metadata.name", vela.Name()).
Set("spec.ports[0].port", port),
)
})
})
It("should render component with parameter values", func() {
rendered := comp.Render(
defkit.TestContext().
WithName("my-web").
WithParam("image", "nginx:1.21").
WithParam("replicas", 3).
WithParam("port", 8080),
)
Expect(rendered.APIVersion()).To(Equal("apps/v1"))
Expect(rendered.Kind()).To(Equal("Deployment"))
Expect(rendered.Get("metadata.name")).To(Equal("my-web"))
Expect(rendered.Get("spec.replicas")).To(Equal(3))
Expect(rendered.Get("spec.template.spec.containers[0].image")).To(Equal("nginx:1.21"))
Expect(rendered.Get("spec.template.spec.containers[0].ports[0].containerPort")).To(Equal(8080))
})
It("should use default values when parameters not set", func() {
rendered := comp.Render(
defkit.TestContext().
WithName("default-web").
WithParam("image", "nginx:latest"),
)
Expect(rendered.Get("spec.replicas")).To(Equal(1))
Expect(rendered.Get("spec.template.spec.containers[0].ports[0].containerPort")).To(Equal(80))
})
It("should render all outputs", func() {
outputs := comp.RenderAll(
defkit.TestContext().
WithName("my-web").
WithParam("image", "nginx:latest").
WithParam("port", 9000),
)
Expect(outputs.Primary.Kind()).To(Equal("Deployment"))
Expect(outputs.Auxiliary).To(HaveKey("service"))
Expect(outputs.Auxiliary["service"].Kind()).To(Equal("Service"))
Expect(outputs.Auxiliary["service"].Get("spec.ports[0].port")).To(Equal(9000))
})
It("should resolve context references", func() {
rendered := comp.Render(
defkit.TestContext().
WithName("context-test").
WithNamespace("test-ns").
WithParam("image", "test"),
)
Expect(rendered.Get("metadata.name")).To(Equal("context-test"))
})
})
Context("SetIf with IsSet", func() {
It("should set field when parameter is set", func() {
cpu := defkit.String("cpu").Optional()
comp := defkit.NewComponent("test").
Params(cpu).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "Pod").
SetIf(cpu.IsSet(), "spec.resources.limits.cpu", cpu),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("cpu", "500m"),
)
Expect(rendered.Get("spec.resources.limits.cpu")).To(Equal("500m"))
})
It("should not set field when parameter is not set", func() {
cpu := defkit.String("cpu").Optional()
comp := defkit.NewComponent("test").
Params(cpu).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "Pod").
SetIf(cpu.IsSet(), "spec.resources.limits.cpu", cpu),
)
})
rendered := comp.Render(defkit.TestContext())
Expect(rendered.Get("spec.resources.limits.cpu")).To(BeNil())
})
})
Context("Literal values", func() {
It("should set literal string values", func() {
comp := defkit.NewComponent("test").
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
Set("data.key", defkit.Lit("literal-value")),
)
})
rendered := comp.Render(defkit.TestContext())
Expect(rendered.Get("data.key")).To(Equal("literal-value"))
})
It("should set literal int values", func() {
comp := defkit.NewComponent("test").
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
Set("spec.replicas", defkit.Lit(5)),
)
})
rendered := comp.Render(defkit.TestContext())
Expect(rendered.Get("spec.replicas")).To(Equal(5))
})
})
Context("Comparison conditions in Render", func() {
It("should evaluate greater-than condition", func() {
replicas := defkit.Int("replicas")
comp := defkit.NewComponent("test").
Params(replicas).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(defkit.Gt(replicas, defkit.Lit(1)), "spec.strategy.type", defkit.Lit("RollingUpdate")),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("replicas", 3),
)
Expect(rendered.Get("spec.strategy.type")).To(Equal("RollingUpdate"))
})
It("should evaluate less-than condition", func() {
replicas := defkit.Int("replicas")
comp := defkit.NewComponent("test").
Params(replicas).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(defkit.Lt(replicas, defkit.Lit(5)), "spec.minReplicas", replicas),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("replicas", 3),
)
Expect(rendered.Get("spec.minReplicas")).To(Equal(3))
})
It("should evaluate greater-than-or-equal condition", func() {
port := defkit.Int("port")
comp := defkit.NewComponent("test").
Params(port).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "Service").
SetIf(defkit.Ge(port, defkit.Lit(8080)), "spec.ports[0].port", port),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("port", 8080),
)
Expect(rendered.Get("spec.ports[0].port")).To(Equal(8080))
})
It("should evaluate less-than-or-equal condition", func() {
replicas := defkit.Int("replicas")
comp := defkit.NewComponent("test").
Params(replicas).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(defkit.Le(replicas, defkit.Lit(10)), "spec.replicas", replicas),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("replicas", 10),
)
Expect(rendered.Get("spec.replicas")).To(Equal(10))
})
It("should evaluate not-equal condition", func() {
env := defkit.String("env")
comp := defkit.NewComponent("test").
Params(env).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(defkit.Ne(env, defkit.Lit("prod")), "spec.debug", defkit.Lit(true)),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("env", "dev"),
)
Expect(rendered.Get("spec.debug")).To(Equal(true))
})
})
Context("Numeric value comparisons", func() {
It("should compare float values", func() {
threshold := defkit.Float("threshold")
comp := defkit.NewComponent("test").
Params(threshold).
Template(func(tpl *defkit.Template) {
cond := defkit.Gt(threshold, defkit.Lit(0.5))
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
SetIf(cond, "data.highThreshold", defkit.Lit("true")),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("threshold", 0.8),
)
Expect(rendered.Get("data.highThreshold")).To(Equal("true"))
})
It("should compare int values with different operators", func() {
priority := defkit.Int("priority")
comp := defkit.NewComponent("test").
Params(priority).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
SetIf(defkit.Ge(priority, defkit.Lit(1)), "data.low", defkit.Lit("yes")).
SetIf(defkit.Ge(priority, defkit.Lit(5)), "data.medium", defkit.Lit("yes")).
SetIf(defkit.Ge(priority, defkit.Lit(8)), "data.high", defkit.Lit("yes")),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("priority", 6),
)
Expect(rendered.Get("data.low")).To(Equal("yes"))
Expect(rendered.Get("data.medium")).To(Equal("yes"))
Expect(rendered.Get("data.high")).To(BeNil())
})
})
Context("Logical conditions in Render", func() {
It("should evaluate And condition", func() {
replicas := defkit.Int("replicas")
cpu := defkit.String("cpu")
comp := defkit.NewComponent("test").
Params(replicas, cpu).
Template(func(tpl *defkit.Template) {
cond := defkit.And(
defkit.Gt(replicas, defkit.Lit(1)),
cpu.IsSet(),
)
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(cond, "spec.resources.limits.cpu", cpu),
)
})
rendered := comp.Render(
defkit.TestContext().
WithParam("replicas", 3).
WithParam("cpu", "500m"),
)
Expect(rendered.Get("spec.resources.limits.cpu")).To(Equal("500m"))
})
It("should evaluate Or condition", func() {
debug := defkit.Bool("debug")
env := defkit.String("env")
comp := defkit.NewComponent("test").
Params(debug, env).
Template(func(tpl *defkit.Template) {
cond := defkit.Or(
defkit.Eq(debug, defkit.Lit(true)),
defkit.Eq(env, defkit.Lit("dev")),
)
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(cond, "spec.logging", defkit.Lit("verbose")),
)
})
rendered := comp.Render(
defkit.TestContext().
WithParam("debug", false).
WithParam("env", "dev"),
)
Expect(rendered.Get("spec.logging")).To(Equal("verbose"))
})
It("should evaluate Not condition", func() {
enabled := defkit.Bool("enabled")
comp := defkit.NewComponent("test").
Params(enabled).
Template(func(tpl *defkit.Template) {
cond := defkit.Not(defkit.Eq(enabled, defkit.Lit(true)))
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(cond, "spec.paused", defkit.Lit(true)),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("enabled", false),
)
Expect(rendered.Get("spec.paused")).To(Equal(true))
})
It("should evaluate nested And/Or conditions", func() {
replicas := defkit.Int("replicas")
cpu := defkit.String("cpu")
memory := defkit.String("memory")
comp := defkit.NewComponent("test").
Params(replicas, cpu, memory).
Template(func(tpl *defkit.Template) {
// (replicas > 1) AND (cpu set OR memory set)
cond := defkit.And(
defkit.Gt(replicas, defkit.Lit(1)),
defkit.Or(cpu.IsSet(), memory.IsSet()),
)
tpl.Output(
defkit.NewResource("apps/v1", "Deployment").
SetIf(cond, "spec.autoscaling", defkit.Lit(true)),
)
})
rendered := comp.Render(
defkit.TestContext().
WithParam("replicas", 3).
WithParam("memory", "512Mi"),
)
Expect(rendered.Get("spec.autoscaling")).To(Equal(true))
})
})
Context("If/EndIf blocks in Render", func() {
It("should evaluate If block when condition is true", func() {
enabled := defkit.Bool("enabled")
port := defkit.Int("port")
comp := defkit.NewComponent("test").
Params(enabled, port).
Template(func(tpl *defkit.Template) {
cond := defkit.Eq(enabled, defkit.Lit(true))
tpl.Output(
defkit.NewResource("v1", "Service").
Set("metadata.name", defkit.VelaCtx().Name()).
If(cond).
Set("spec.ports[0].port", port).
Set("spec.ports[0].protocol", defkit.Lit("TCP")).
EndIf(),
)
})
rendered := comp.Render(
defkit.TestContext().
WithName("my-svc").
WithParam("enabled", true).
WithParam("port", 8080),
)
Expect(rendered.Get("metadata.name")).To(Equal("my-svc"))
Expect(rendered.Get("spec.ports[0].port")).To(Equal(8080))
Expect(rendered.Get("spec.ports[0].protocol")).To(Equal("TCP"))
})
It("should skip If block when condition is false", func() {
enabled := defkit.Bool("enabled")
port := defkit.Int("port")
comp := defkit.NewComponent("test").
Params(enabled, port).
Template(func(tpl *defkit.Template) {
cond := defkit.Eq(enabled, defkit.Lit(true))
tpl.Output(
defkit.NewResource("v1", "Service").
Set("metadata.name", defkit.VelaCtx().Name()).
If(cond).
Set("spec.ports[0].port", port).
EndIf(),
)
})
rendered := comp.Render(
defkit.TestContext().
WithName("my-svc").
WithParam("enabled", false).
WithParam("port", 8080),
)
Expect(rendered.Get("metadata.name")).To(Equal("my-svc"))
Expect(rendered.Get("spec.ports[0].port")).To(BeNil())
})
})
Context("Array indexing in Render", func() {
It("should set values at array indices", func() {
ports := defkit.Array("ports")
comp := defkit.NewComponent("test").
Params(ports).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "Service").
Set("spec.ports[0].port", defkit.Lit(80)).
Set("spec.ports[0].name", defkit.Lit("http")).
Set("spec.ports[1].port", defkit.Lit(443)).
Set("spec.ports[1].name", defkit.Lit("https")),
)
})
rendered := comp.Render(defkit.TestContext())
Expect(rendered.Get("spec.ports[0].port")).To(Equal(80))
Expect(rendered.Get("spec.ports[0].name")).To(Equal("http"))
Expect(rendered.Get("spec.ports[1].port")).To(Equal(443))
Expect(rendered.Get("spec.ports[1].name")).To(Equal("https"))
})
})
Context("Context references in Render", func() {
It("should resolve appRevision context ref", func() {
comp := defkit.NewComponent("test").
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
Set("metadata.name", defkit.VelaCtx().Name()).
Set("metadata.labels.app", defkit.VelaCtx().AppName()).
Set("metadata.labels.revision", defkit.VelaCtx().AppRevision()),
)
})
rendered := comp.Render(
defkit.TestContext().
WithName("my-config").
WithAppName("my-app").
WithAppRevision("my-app-v1"),
)
Expect(rendered.Get("metadata.name")).To(Equal("my-config"))
Expect(rendered.Get("metadata.labels.app")).To(Equal("my-app"))
Expect(rendered.Get("metadata.labels.revision")).To(Equal("my-app-v1"))
})
It("should resolve namespace context ref", func() {
comp := defkit.NewComponent("test").
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
Set("metadata.namespace", defkit.VelaCtx().Namespace()),
)
})
rendered := comp.Render(
defkit.TestContext().WithNamespace("prod"),
)
Expect(rendered.Get("metadata.namespace")).To(Equal("prod"))
})
})
Context("Different numeric types in comparison", func() {
It("should compare int64 values", func() {
count := defkit.Int("count")
comp := defkit.NewComponent("test").
Params(count).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
SetIf(defkit.Gt(count, defkit.Lit(int64(100))), "data.large", defkit.Lit("true")),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("count", int64(150)),
)
Expect(rendered.Get("data.large")).To(Equal("true"))
})
It("should compare float32 values", func() {
ratio := defkit.Float("ratio")
comp := defkit.NewComponent("test").
Params(ratio).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
SetIf(defkit.Lt(ratio, defkit.Lit(float32(0.5))), "data.low", defkit.Lit("true")),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("ratio", float32(0.3)),
)
Expect(rendered.Get("data.low")).To(Equal("true"))
})
})
Context("Boolean parameter conditions", func() {
It("should evaluate boolean parameter directly", func() {
debug := defkit.Bool("debug")
comp := defkit.NewComponent("test").
Params(debug).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
SetIf(debug.IsTrue(), "data.debug", defkit.Lit("enabled")),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("debug", true),
)
Expect(rendered.Get("data.debug")).To(Equal("enabled"))
})
It("should evaluate boolean false condition", func() {
enabled := defkit.Bool("enabled")
comp := defkit.NewComponent("test").
Params(enabled).
Template(func(tpl *defkit.Template) {
tpl.Output(
defkit.NewResource("v1", "ConfigMap").
SetIf(enabled.IsFalse(), "data.disabled", defkit.Lit("true")),
)
})
rendered := comp.Render(
defkit.TestContext().WithParam("enabled", false),
)
Expect(rendered.Get("data.disabled")).To(Equal("true"))
})
})
})