changed app to use json config for pipeline steps

readme command line usage - to specify pipeline file name
readme updated to include reasoning behind the project

use native golang sqlite

RunScriptCommand named in functionMap
removed unused functions
removed unused functions
run script and pipeline example
renamed functions to drop the word script and add pipeline verb
This commit is contained in:
jon brookes 2025-07-09 13:19:43 +01:00 committed by jon brookes
parent bd7cee720a
commit 924954d0ff
49 changed files with 2059 additions and 101 deletions

158
app/app_test.go Normal file
View file

@ -0,0 +1,158 @@
package app
import (
"encoding/json"
"math/rand"
"os"
"os/exec"
"path/filepath"
"testing"
"headshed/infctl-cli/config"
)
func TestMain(m *testing.M) {
// Setup: Set TEST_ENV=true for all tests
err := os.Setenv("TEST_ENV", "true")
if err != nil {
panic("Failed to set TEST_ENV")
}
// Run all tests
code := m.Run()
// Teardown: Unset TEST_ENV after all tests
os.Unsetenv("TEST_ENV")
// Exit with the test result code
os.Exit(code)
}
func TestRunPipeline(t *testing.T) {
// Create a temporary directory for test assets
tempDir, err := os.MkdirTemp("", "smoke-test")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir) // Cleanup after test
// Create test scripts
scripts := map[string]string{
"good.sh": "#!/bin/bash\necho 'Good script executed'\nexit 0",
"warning.sh": "#!/bin/bash\necho 'Warning script executed'\nexit 0",
"error.sh": "#!/bin/bash\necho 'Error script executed'\nexit 1",
}
for name, content := range scripts {
scriptPath := filepath.Join(tempDir, name)
if err := os.WriteFile(scriptPath, []byte(content), 0755); err != nil {
t.Fatalf("Failed to create script %s: %v", name, err)
}
}
// Create a test JSON pipeline file
pipeline := []PipelineStep{
{Name: "Good Step", Function: "RunCommand", Params: []string{filepath.Join(tempDir, "good.sh")}, RetryCount: 0, ShouldAbort: false},
{Name: "Warning Step", Function: "RunCommand", Params: []string{filepath.Join(tempDir, "warning.sh")}, RetryCount: 0, ShouldAbort: false},
{Name: "Error Step", Function: "RunCommand", Params: []string{filepath.Join(tempDir, "error.sh")}, RetryCount: 0, ShouldAbort: true},
}
pipelineFile := filepath.Join(tempDir, "pipeline.json")
pipelineData, err := json.Marshal(pipeline)
if err != nil {
t.Fatalf("Failed to marshal pipeline: %v", err)
}
if err := os.WriteFile(pipelineFile, pipelineData, 0644); err != nil {
t.Fatalf("Failed to write pipeline file: %v", err)
}
// Set up AppState
app := &AppState{
Config: config.BaseConfig{
DeploymentFile: pipelineFile,
},
}
// Run the pipeline
err = app.runPipeline(pipeline)
if err == nil {
t.Errorf("Expected error due to 'Error Step', but got none")
}
}
func randomString(length int) string {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, length)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
return string(b)
}
func TestK3DNamespaceCreation(t *testing.T) {
// Check if k3d is installed
_, err := exec.LookPath("k3d")
if err != nil {
t.Fatal("k3d is not installed. Please install k3d to run this test.")
}
// Create a test cluster
clusterName := "test-" + randomString(6)
cmd := exec.Command("k3d", "cluster", "create", clusterName, "--servers", "1")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
t.Fatalf("Failed to create k3d cluster: %v", err)
}
defer func() {
// Clean up the test cluster
cmd := exec.Command("k3d", "cluster", "delete", clusterName)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
t.Errorf("Failed to delete k3d cluster: %v", err)
}
}()
// Create a temporary directory for the pipeline config
tempDir, err := os.MkdirTemp("", "k3d-test")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
// Create a test JSON pipeline file
pipeline := []PipelineStep{
{Name: "Ensure Namespace Exists", Function: "k8sNamespaceExists", Params: []string{"test-namespace"}, RetryCount: 0, ShouldAbort: true},
}
pipelineFile := filepath.Join(tempDir, "pipeline.json")
pipelineData, err := json.Marshal(pipeline)
if err != nil {
t.Fatalf("Failed to marshal pipeline: %v", err)
}
if err := os.WriteFile(pipelineFile, pipelineData, 0644); err != nil {
t.Fatalf("Failed to write pipeline file: %v", err)
}
// Set up AppState
app := &AppState{
Config: config.BaseConfig{
DeploymentFile: pipelineFile,
},
}
// Run the pipeline
err = app.runPipeline(pipeline)
if err != nil {
t.Fatalf("Pipeline execution failed: %v", err)
}
// Verify the namespace exists
cmd = exec.Command("kubectl", "get", "ns", "test-namespace")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
t.Fatalf("Namespace 'test-namespace' was not created: %v", err)
}
}