Kubernetes Operator for Tangled Spindles
15
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix volume mounts

+23 -43
+1 -1
config/manager/kustomization.yaml
··· 6 6 images: 7 7 - name: controller 8 8 newName: atcr.io/evan.jarrett.net/loom 9 - newTag: v0.0.1 9 + newTag: v0.0.2
+6 -2
config/manager/manager.yaml
··· 96 96 requests: 97 97 cpu: 10m 98 98 memory: 64Mi 99 - volumeMounts: [] 100 - volumes: [] 99 + volumeMounts: 100 + - name: spindle-logs 101 + mountPath: /tmp/spindle-logs 102 + volumes: 103 + - name: spindle-logs 104 + emptyDir: {} 101 105 serviceAccountName: controller-manager 102 106 terminationGracePeriodSeconds: 10
+4 -1
go.mod
··· 196 196 sigs.k8s.io/yaml v1.4.0 // indirect 197 197 ) 198 198 199 - // Use local tangled.org/core for development 199 + // Remote replace (for future when server supports @handle in Git URLs): 200 + // replace tangled.org/core => tangled.org/evan.jarrett.net/core v0.0.0-20251107232645-99c60f368227 201 + 202 + // Local replace for development (current workaround): 200 203 replace tangled.org/core => ../core
+5 -38
internal/controller/spindleset_controller.go
··· 375 375 currentStatus = "pending" 376 376 } 377 377 378 - // Report status changes to spindle DB 379 - if newJob && currentStatus == "pending" { 380 - logger.Info("Reporting pending status", "job", job.Name, "workflow", workflowName) 381 - if err := r.Spindle.DB().StatusPending(wid, r.Spindle.Notifier()); err != nil { 382 - logger.Error(err, "Failed to report pending status") 383 - } 378 + // Status reporting is handled by the spindle engine's StartWorkflows 379 + // The controller just needs to track jobs for cleanup 380 + if newJob { 384 381 r.watchedJobs.Store(jobKey, wid) 385 382 } 386 383 387 - if currentStatus == "running" { 388 - if newJob || !exists { 389 - logger.Info("Reporting running status", "job", job.Name, "workflow", workflowName) 390 - if err := r.Spindle.DB().StatusRunning(wid, r.Spindle.Notifier()); err != nil { 391 - logger.Error(err, "Failed to report running status") 392 - } 393 - r.watchedJobs.Store(jobKey, wid) 394 - } 395 - } 396 - 397 - if currentStatus == "succeeded" { 398 - logger.Info("Reporting success status", "job", job.Name, "workflow", workflowName) 399 - if err := r.Spindle.DB().StatusSuccess(wid, r.Spindle.Notifier()); err != nil { 400 - logger.Error(err, "Failed to report success status") 401 - } 402 - r.watchedJobs.Delete(jobKey) 403 - } 404 - 405 - if currentStatus == "failed" { 406 - logger.Info("Reporting failed status", "job", job.Name, "workflow", workflowName) 407 - // Try to get error message from Job conditions 408 - errorMsg := "Job failed" 409 - for _, cond := range job.Status.Conditions { 410 - if cond.Type == batchv1.JobFailed { 411 - errorMsg = cond.Message 412 - break 413 - } 414 - } 415 - exitCode := int64(1) 416 - if err := r.Spindle.DB().StatusFailed(wid, errorMsg, exitCode, r.Spindle.Notifier()); err != nil { 417 - logger.Error(err, "Failed to report failed status") 418 - } 384 + if currentStatus == "succeeded" || currentStatus == "failed" { 385 + logger.Info("Job completed", "job", job.Name, "workflow", workflowName, "status", currentStatus) 419 386 r.watchedJobs.Delete(jobKey) 420 387 } 421 388 }
+7 -1
pkg/jobbuilder/job_template.go
··· 2 2 3 3 import ( 4 4 "fmt" 5 + "strings" 5 6 6 7 batchv1 "k8s.io/api/batch/v1" 7 8 corev1 "k8s.io/api/core/v1" ··· 84 85 } 85 86 86 87 // Job name: spindle-{pipelineID}-{workflowName} (truncated if needed) 87 - jobName := fmt.Sprintf("spindle-%s-%s", config.PipelineID, config.WorkflowName) 88 + // Sanitize workflow name: remove file extensions and replace dots with hyphens 89 + workflowName := strings.TrimSuffix(config.WorkflowName, ".yaml") 90 + workflowName = strings.TrimSuffix(workflowName, ".yml") 91 + workflowName = strings.ReplaceAll(workflowName, ".", "-") 92 + 93 + jobName := fmt.Sprintf("spindle-%s-%s", config.PipelineID, workflowName) 88 94 if len(jobName) > 63 { 89 95 // Kubernetes names must be 63 chars or less 90 96 jobName = jobName[:63]