Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions go/api/config/crd/bases/kagent.dev_agents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3574,6 +3574,57 @@ spec:
- name
type: object
type: array
envFrom:
description: |-
EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
on the agent container. Values defined in Env with a duplicate key take precedence.
items:
description: EnvFromSource represents the source of a set
of ConfigMaps or Secrets
properties:
configMapRef:
description: The ConfigMap to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap must
be defined
type: boolean
type: object
x-kubernetes-map-type: atomic
prefix:
description: |-
Optional text to prepend to the name of each environment variable.
May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret must be
defined
type: boolean
type: object
x-kubernetes-map-type: atomic
type: object
type: array
extraContainers:
description: |-
ExtraContainers is a list of additional containers to run alongside the main agent container.
Expand Down Expand Up @@ -8919,6 +8970,57 @@ spec:
- name
type: object
type: array
envFrom:
description: |-
EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
on the agent container. Values defined in Env with a duplicate key take precedence.
items:
description: EnvFromSource represents the source of a set
of ConfigMaps or Secrets
properties:
configMapRef:
description: The ConfigMap to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap must
be defined
type: boolean
type: object
x-kubernetes-map-type: atomic
prefix:
description: |-
Optional text to prepend to the name of each environment variable.
May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret must be
defined
type: boolean
type: object
x-kubernetes-map-type: atomic
type: object
type: array
extraContainers:
description: |-
ExtraContainers is a list of additional containers to run alongside the main agent container.
Expand Down
102 changes: 102 additions & 0 deletions go/api/config/crd/bases/kagent.dev_sandboxagents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,57 @@ spec:
- name
type: object
type: array
envFrom:
description: |-
EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
on the agent container. Values defined in Env with a duplicate key take precedence.
items:
description: EnvFromSource represents the source of a set
of ConfigMaps or Secrets
properties:
configMapRef:
description: The ConfigMap to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap must
be defined
type: boolean
type: object
x-kubernetes-map-type: atomic
prefix:
description: |-
Optional text to prepend to the name of each environment variable.
May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret must be
defined
type: boolean
type: object
x-kubernetes-map-type: atomic
type: object
type: array
extraContainers:
description: |-
ExtraContainers is a list of additional containers to run alongside the main agent container.
Expand Down Expand Up @@ -6576,6 +6627,57 @@ spec:
- name
type: object
type: array
envFrom:
description: |-
EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
on the agent container. Values defined in Env with a duplicate key take precedence.
items:
description: EnvFromSource represents the source of a set
of ConfigMaps or Secrets
properties:
configMapRef:
description: The ConfigMap to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap must
be defined
type: boolean
type: object
x-kubernetes-map-type: atomic
prefix:
description: |-
Optional text to prepend to the name of each environment variable.
May consist of any printable ASCII characters except '='.
type: string
secretRef:
description: The Secret to select from
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret must be
defined
type: boolean
type: object
x-kubernetes-map-type: atomic
type: object
type: array
extraContainers:
description: |-
ExtraContainers is a list of additional containers to run alongside the main agent container.
Expand Down
4 changes: 4 additions & 0 deletions go/api/v1alpha2/agent_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ type SharedDeploymentSpec struct {
// Env are additional environment variables set on the agent container.
// +optional
Env []corev1.EnvVar `json:"env,omitempty"`
// EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
// on the agent container. Values defined in Env with a duplicate key take precedence.
// +optional
EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"`
Comment on lines +458 to +459

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? Env above already has ValueFrom support

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These solve different problems. env + valueFrom binds a single ConfigMap/Secret key to a single env var, so every key has to be listed explicitly. envFrom imports all keys from a ConfigMap/Secret at once, using each key as the variable name.

The use case is a ConfigMap/Secret whose key set isn't fixed (populated from an external system, like external secret operator), where enumerating keys in the spec isn't practical. Same reason upstream PodSpec exposes both.

// +optional
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
// +optional
Expand Down
7 changes: 7 additions & 0 deletions go/api/v1alpha2/zz_generated.deepcopy.go

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

3 changes: 3 additions & 0 deletions go/core/internal/controller/translator/agent/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type resolvedDeployment struct {
Labels map[string]string
Annotations map[string]string
Env []corev1.EnvVar
EnvFrom []corev1.EnvFromSource
Resources corev1.ResourceRequirements
Tolerations []corev1.Toleration
Affinity *corev1.Affinity
Expand Down Expand Up @@ -254,6 +255,7 @@ func resolveInlineDeployment(agent v1alpha2.AgentObject, mdd *modelDeploymentDat
Labels: getDefaultLabels(agent.GetName(), spec.Labels),
Annotations: maps.Clone(spec.Annotations),
Env: append(slices.Clone(spec.Env), mdd.EnvVars...),
EnvFrom: slices.Clone(spec.EnvFrom),
Resources: getDefaultResources(spec.Resources), // Set default resources if not specified
Tolerations: slices.Clone(spec.Tolerations),
Affinity: spec.Affinity,
Expand Down Expand Up @@ -338,6 +340,7 @@ func resolveByoDeployment(agent v1alpha2.AgentObject) (*resolvedDeployment, erro
Labels: getDefaultLabels(agent.GetName(), spec.Labels),
Annotations: maps.Clone(spec.Annotations),
Env: slices.Clone(spec.Env),
EnvFrom: slices.Clone(spec.EnvFrom),
Resources: getDefaultResources(spec.Resources), // Set default resources if not specified
Tolerations: slices.Clone(spec.Tolerations),
Affinity: spec.Affinity,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package agent

import (
"reflect"
"testing"

"github.com/kagent-dev/kagent/go/api/v1alpha2"
Expand Down Expand Up @@ -29,6 +30,60 @@ func TestResolveByoDeployment_NilReplicasPreserved(t *testing.T) {
}
}

func TestResolveByoDeployment_EnvFromPropagated(t *testing.T) {
envFrom := []corev1.EnvFromSource{
{SecretRef: &corev1.SecretEnvSource{LocalObjectReference: corev1.LocalObjectReference{Name: "my-secret"}}},
{ConfigMapRef: &corev1.ConfigMapEnvSource{LocalObjectReference: corev1.LocalObjectReference{Name: "my-config"}}},
}
agent := &v1alpha2.Agent{
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
Spec: v1alpha2.AgentSpec{
Type: v1alpha2.AgentType_BYO,
BYO: &v1alpha2.BYOAgentSpec{
Deployment: &v1alpha2.ByoDeploymentSpec{
Image: "my-image:latest",
SharedDeploymentSpec: v1alpha2.SharedDeploymentSpec{
EnvFrom: envFrom,
},
},
},
},
}
dep, err := resolveByoDeployment(agent)
if err != nil {
t.Fatalf("resolveByoDeployment() error = %v", err)
}
if !reflect.DeepEqual(dep.EnvFrom, envFrom) {
t.Errorf("EnvFrom = %v, want %v", dep.EnvFrom, envFrom)
}
}

func TestResolveInlineDeployment_EnvFromPropagated(t *testing.T) {
envFrom := []corev1.EnvFromSource{
{SecretRef: &corev1.SecretEnvSource{LocalObjectReference: corev1.LocalObjectReference{Name: "my-secret"}}},
}
agent := &v1alpha2.Agent{
ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "default"},
Spec: v1alpha2.AgentSpec{
Type: v1alpha2.AgentType_Declarative,
Declarative: &v1alpha2.DeclarativeAgentSpec{
Deployment: &v1alpha2.DeclarativeDeploymentSpec{
SharedDeploymentSpec: v1alpha2.SharedDeploymentSpec{
EnvFrom: envFrom,
},
},
},
},
}
dep, err := resolveInlineDeployment(agent, &modelDeploymentData{})
if err != nil {
t.Fatalf("resolveInlineDeployment() error = %v", err)
}
if !reflect.DeepEqual(dep.EnvFrom, envFrom) {
t.Errorf("EnvFrom = %v, want %v", dep.EnvFrom, envFrom)
}
}

func TestValidateExtraContainers(t *testing.T) {
t.Parallel()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type configHashInput struct {
type podRuntimeInputs struct {
initContainers []corev1.Container
envVars []corev1.EnvVar
envFrom []corev1.EnvFromSource
volumes []corev1.Volume
volumeMounts []corev1.VolumeMount
securityContext *corev1.SecurityContext
Expand Down Expand Up @@ -327,6 +328,7 @@ func buildPodRuntime(
return &podRuntimeInputs{
initContainers: initContainers,
envVars: envVars,
envFrom: manifestCtx.deployment.EnvFrom,
volumes: volumes,
volumeMounts: volumeMounts,
securityContext: buildContainerSecurityContext(manifestCtx.deployment.SecurityContext, needCodeExecIsolation),
Expand Down Expand Up @@ -538,6 +540,7 @@ func buildPodTemplate(
Ports: []corev1.ContainerPort{{Name: "http", ContainerPort: dep.Port}},
Resources: dep.Resources,
Env: runtimeInputs.envVars,
EnvFrom: runtimeInputs.envFrom,
ReadinessProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Expand Down
Loading
Loading