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
20 changes: 18 additions & 2 deletions controller/proposal/podspec_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ func (b *PodSpecBuilder) Build(

var volumes []corev1.Volume

volumes = append(volumes, corev1.Volume{
Name: "home",
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
})
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
Name: "home",
MountPath: "/home/agent",
})

container.Env = append(container.Env,
corev1.EnvVar{Name: "LIGHTSPEED_PROVIDER", Value: providerTypeString(llm.Spec.Type)},
corev1.EnvVar{Name: "LIGHTSPEED_MODEL", Value: agent.Spec.Model},
Expand Down Expand Up @@ -205,8 +214,15 @@ func (b *PodSpecBuilder) buildSkills(skills []agenticv1alpha1.SkillsSource) ([]c
},
},
}
workdirVol := corev1.Volume{
Name: "skills-workdir",
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
}

var mounts []corev1.VolumeMount
mounts := []corev1.VolumeMount{{
Name: "skills-workdir",
MountPath: "/app/skills/.agents",
}}
if len(s.Paths) > 0 {
baseMountPath := "/app/skills"
for _, p := range s.Paths {
Expand All @@ -221,7 +237,7 @@ func (b *PodSpecBuilder) buildSkills(skills []agenticv1alpha1.SkillsSource) ([]c
}
}

return []corev1.Volume{vol}, mounts
return []corev1.Volume{vol, workdirVol}, mounts
}

func (b *PodSpecBuilder) buildMCPServers(servers []agenticv1alpha1.MCPServerConfig) ([]corev1.Volume, []corev1.VolumeMount, []corev1.EnvVar, error) {
Expand Down
48 changes: 47 additions & 1 deletion controller/proposal/podspec_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ func TestPodSpecBuilder_Skills(t *testing.T) {
}

foundVolume := false
foundWorkdirVolume := false
for _, v := range podSpec.Volumes {
if v.Name == "skills" {
foundVolume = true
Expand All @@ -339,12 +340,34 @@ func TestPodSpecBuilder_Skills(t *testing.T) {
if v.Image.PullPolicy != corev1.PullAlways {
t.Errorf("skills pullPolicy = %v, want PullAlways", v.Image.PullPolicy)
}
break
}
if v.Name == "skills-workdir" {
foundWorkdirVolume = true
if v.EmptyDir == nil {
t.Fatal("skills-workdir volume should be emptyDir")
}
}
}
if !foundVolume {
t.Error("missing skills volume")
}
if !foundWorkdirVolume {
t.Error("missing skills-workdir volume")
}

container := podSpec.Containers[0]
foundWorkdirMount := false
for _, m := range container.VolumeMounts {
if m.Name == "skills-workdir" && m.MountPath == "/app/skills/.agents" {
foundWorkdirMount = true
if m.ReadOnly {
t.Error("skills-workdir mount should be writable")
}
}
}
if !foundWorkdirMount {
t.Error("missing skills-workdir mount at /app/skills/.agents")
}
}

func TestPodSpecBuilder_SkillsWithPaths(t *testing.T) {
Expand Down Expand Up @@ -372,6 +395,7 @@ func TestPodSpecBuilder_SkillsWithPaths(t *testing.T) {

foundSearch := false
foundAnalyze := false
foundWorkdirMount := false
for _, m := range container.VolumeMounts {
if m.Name == "skills" {
if m.MountPath == "/app/skills/search.md" && m.SubPath == "skills/search.md" {
Expand All @@ -384,13 +408,35 @@ func TestPodSpecBuilder_SkillsWithPaths(t *testing.T) {
t.Error("skills mount should be readOnly")
}
}
if m.Name == "skills-workdir" && m.MountPath == "/app/skills/.agents" {
foundWorkdirMount = true
if m.ReadOnly {
t.Error("skills-workdir mount should be writable")
}
}
}
if !foundSearch {
t.Error("missing search.md skill mount")
}
if !foundAnalyze {
t.Error("missing analyze.md skill mount")
}
if !foundWorkdirMount {
t.Error("missing skills-workdir mount at /app/skills/.agents")
}

foundWorkdirVolume := false
for _, v := range podSpec.Volumes {
if v.Name == "skills-workdir" {
foundWorkdirVolume = true
if v.EmptyDir == nil {
t.Fatal("skills-workdir volume should be emptyDir")
}
}
}
if !foundWorkdirVolume {
t.Error("missing skills-workdir volume")
}
}

func TestPodSpecBuilder_RequiredSecrets_EnvVar(t *testing.T) {
Expand Down
18 changes: 18 additions & 0 deletions controller/sandbox/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ func ensureSandboxTemplate(ctx context.Context, c client.Client, image, namespac
"type": "RuntimeDefault",
},
},
"volumeMounts": []any{
map[string]any{
"name": "home",
"mountPath": "/home/agent",
},
map[string]any{
"name": "skills-workdir",
"mountPath": "/app/skills/.agents",
},
},
},
},
"volumes": []any{
Expand All @@ -139,6 +149,14 @@ func ensureSandboxTemplate(ctx context.Context, c client.Client, image, namespac
"reference": "placeholder:latest",
},
},
map[string]any{
"name": "home",
"emptyDir": map[string]any{},
},
map[string]any{
"name": "skills-workdir",
"emptyDir": map[string]any{},
},
},
},
},
Expand Down
22 changes: 22 additions & 0 deletions controller/sandbox/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,37 @@ func TestEnsureBootstrapResources_CreatesResources(t *testing.T) {

volumes, _, _ := unstructured.NestedSlice(tmpl.Object, "spec", "podTemplate", "spec", "volumes")
foundSkills := false
foundWorkdirVolume := false
for _, v := range volumes {
vol := v.(map[string]any)
if vol["name"] == "skills" {
foundSkills = true
}
if vol["name"] == "skills-workdir" {
foundWorkdirVolume = true
if vol["emptyDir"] == nil {
t.Error("skills-workdir volume should be emptyDir")
}
}
}
if !foundSkills {
t.Error("SandboxTemplate missing skills volume")
}
if !foundWorkdirVolume {
t.Error("SandboxTemplate missing skills-workdir volume")
}

mounts, _, _ := unstructured.NestedSlice(container, "volumeMounts")
foundWorkdirMount := false
for _, m := range mounts {
mount := m.(map[string]any)
if mount["name"] == "skills-workdir" && mount["mountPath"] == "/app/skills/.agents" {
foundWorkdirMount = true
}
}
if !foundWorkdirMount {
t.Error("SandboxTemplate missing skills-workdir mount at /app/skills/.agents")
}

lbls := tmpl.GetLabels()
if lbls["app.kubernetes.io/managed-by"] != "lightspeed-operator" {
Expand Down
9 changes: 9 additions & 0 deletions test/agent/sandboxtemplate/sandboxtemplate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ spec:
readOnlyRootFilesystem: true
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: home
mountPath: /home/agent
- name: skills-workdir
mountPath: /app/skills/.agents
volumes:
- name: skills
image:
reference: placeholder:latest
- name: home
emptyDir: {}
- name: skills-workdir
emptyDir: {}