Skip to content
Merged
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
33 changes: 27 additions & 6 deletions pkg/runtime/podman/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,24 @@ func findFreePorts(n int) ([]int, error) {
return ports, nil
}

// renderPodYAML renders the embedded pod YAML template with the given data.
func renderPodYAML(data podTemplateData) ([]byte, error) {
tmpl, err := template.New("pod").Parse(string(pods.OnecliPodYAML))
// loadPodYAMLTemplate returns the pod YAML template to use for rendering.
// If the user has placed a custom template at <storageDir>/config/onecli-pod.yaml
// that file is read and returned; otherwise the embedded default is returned.
func (p *podmanRuntime) loadPodYAMLTemplate() ([]byte, error) {
customPath := filepath.Join(p.storageDir, "config", "onecli-pod.yaml")
content, err := os.ReadFile(customPath)
if err == nil {
return content, nil
}
if !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to read custom pod template %s: %w", customPath, err)
}
return pods.OnecliPodYAML, nil
}

// renderPodYAML renders the given pod YAML template with the given data.
func renderPodYAML(tmplContent []byte, data podTemplateData) ([]byte, error) {
tmpl, err := template.New("pod").Parse(string(tmplContent))
if err != nil {
return nil, fmt.Errorf("failed to parse pod template: %w", err)
}
Expand Down Expand Up @@ -530,7 +545,7 @@ func (p *podmanRuntime) Create(ctx context.Context, params runtime.CreateParams)
return runtime.RuntimeInfo{}, fmt.Errorf("failed to create temp pod directory: %w", err)
}
tmpYAMLPath := filepath.Join(tmpPodDir, podYAMLFile)
if err := writePodYAMLFile(tmpYAMLPath, tmplData); err != nil {
if err := p.writePodYAMLFile(tmpYAMLPath, tmplData); err != nil {
return runtime.RuntimeInfo{}, err
}

Expand Down Expand Up @@ -790,8 +805,14 @@ func writeApprovalHandlerFiles(dir string) error {
}

// writePodYAMLFile renders and writes the pod YAML template to the given path.
func writePodYAMLFile(path string, data podTemplateData) error {
content, err := renderPodYAML(data)
// It uses a custom template from <storageDir>/config/onecli-pod.yaml when present,
// falling back to the embedded default.
func (p *podmanRuntime) writePodYAMLFile(path string, data podTemplateData) error {
tmplContent, err := p.loadPodYAMLTemplate()
if err != nil {
return err
}
content, err := renderPodYAML(tmplContent, data)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/runtime/podman/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/openkaiden/kdn/pkg/runtime"
"github.com/openkaiden/kdn/pkg/runtime/podman/config"
"github.com/openkaiden/kdn/pkg/runtime/podman/exec"
"github.com/openkaiden/kdn/pkg/runtime/podman/pods"
"github.com/openkaiden/kdn/pkg/steplogger"
)

Expand Down Expand Up @@ -2229,7 +2230,7 @@ func TestRenderPodYAML_Ports(t *testing.T) {
},
}

rendered, err := renderPodYAML(data)
rendered, err := renderPodYAML(pods.OnecliPodYAML, data)
if err != nil {
t.Fatalf("renderPodYAML() failed: %v", err)
}
Expand Down Expand Up @@ -2266,7 +2267,7 @@ func TestRenderPodYAML_Ports(t *testing.T) {
ApprovalHandlerDir: "/tmp/approval",
}

rendered, err := renderPodYAML(data)
rendered, err := renderPodYAML(pods.OnecliPodYAML, data)
if err != nil {
t.Fatalf("renderPodYAML() failed: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/runtime/podman/podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ func (p *podmanRuntime) podNamePath(containerID string) string {
}

// writePodFiles writes the per-workspace pod YAML and pod name file.
// The YAML is rendered from the embedded template using the supplied data.
// The YAML is rendered from the user-provided template (if present) or the embedded default.
func (p *podmanRuntime) writePodFiles(containerID string, data podTemplateData) error {
dir := p.podDir(containerID)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create pod directory: %w", err)
}

if err := writePodYAMLFile(p.podYAMLPath(containerID), data); err != nil {
if err := p.writePodYAMLFile(p.podYAMLPath(containerID), data); err != nil {
return err
}
if err := os.WriteFile(p.podNamePath(containerID), []byte(data.Name), 0644); err != nil {
Expand Down
48 changes: 46 additions & 2 deletions pkg/runtime/podman/podman_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
workspace "github.com/openkaiden/kdn-api/workspace-configuration/go"
"github.com/openkaiden/kdn/pkg/runtime/podman/config"
"github.com/openkaiden/kdn/pkg/runtime/podman/exec"
"github.com/openkaiden/kdn/pkg/runtime/podman/pods"
"github.com/openkaiden/kdn/pkg/system"
)

Expand Down Expand Up @@ -293,7 +294,7 @@ func TestRenderPodYAML(t *testing.T) {
ApprovalHandlerDir: "/tmp/approval-handler/my-project",
}

result, err := renderPodYAML(data)
result, err := renderPodYAML(pods.OnecliPodYAML, data)
if err != nil {
t.Fatalf("renderPodYAML() failed: %v", err)
}
Expand Down Expand Up @@ -350,7 +351,7 @@ func TestRenderPodYAML(t *testing.T) {
ApprovalHandlerDir: "/tmp/approval-handler/test",
}

result, err := renderPodYAML(data)
result, err := renderPodYAML(pods.OnecliPodYAML, data)
if err != nil {
t.Fatalf("renderPodYAML() failed: %v", err)
}
Expand All @@ -363,6 +364,49 @@ func TestRenderPodYAML(t *testing.T) {
})
}

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

t.Run("returns embedded template when no custom file exists", func(t *testing.T) {
t.Parallel()

storageDir := t.TempDir()
p := &podmanRuntime{storageDir: storageDir}

content, err := p.loadPodYAMLTemplate()
if err != nil {
t.Fatalf("loadPodYAMLTemplate() failed: %v", err)
}
if string(content) != string(pods.OnecliPodYAML) {
t.Error("Expected embedded template to be returned when no custom file exists")
}
})

t.Run("returns custom template when file exists in config dir", func(t *testing.T) {
t.Parallel()

storageDir := t.TempDir()
configDir := filepath.Join(storageDir, "config")
if err := os.MkdirAll(configDir, 0755); err != nil {
t.Fatalf("failed to create config dir: %v", err)
}
customTemplate := []byte("custom-pod-template: {{.Name}}")
if err := os.WriteFile(filepath.Join(configDir, "onecli-pod.yaml"), customTemplate, 0644); err != nil {
t.Fatalf("failed to write custom template: %v", err)
}

p := &podmanRuntime{storageDir: storageDir}

content, err := p.loadPodYAMLTemplate()
if err != nil {
t.Fatalf("loadPodYAMLTemplate() failed: %v", err)
}
if string(content) != string(customTemplate) {
t.Errorf("Expected custom template to be returned, got: %s", content)
}
})
}

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

Expand Down