mirror of
https://github.com/lukaszraczylo/jobs-manager-operator.git
synced 2026-07-08 06:34:25 +00:00
Multiple fixes (#29)
* Multiple fixes - add goreleaser to the build / release process - add kubectl plugin for job graphs visualization - add installation scripts - update dependencies * Update the release & CRD content. * Next set of improvements. Code Quality - Label constants: Added LabelWorkflowName, LabelGroupName, LabelJobName, LabelJobID in controllers/definitions.go - Removed commented debug code: Cleaned up dead code from multiple files - Removed unused dependencyTree field: Cleaned connPackage struct - Fixed snake_case variables: Changed to camelCase (runGroup, groupDep, runJob, jobDep, k8sJob) Kubernetes Best Practices - Finalizers: Implemented handleDeletion() and deleteChildJobs() for proper cleanup - Status enum validation: Added +kubebuilder:validation:Enum=pending;running;succeeded;failed;aborted - ImagePullPolicy default: Created getImagePullPolicy() helper that defaults to IfNotPresent - Resource limits support: Added Resources *corev1.ResourceRequirements to ManagedJobParameters Observability - Prometheus metrics: Created controllers/metrics.go with counters (jobs created/succeeded/failed), histogram (reconciliation duration), and gauge (active jobs) - Structured logging: Added logger field to connPackage, used context-based logging throughout Configuration - Leader election ID: Made configurable via --leader-election-id flag - Development mode: Made configurable via --dev-mode flag and LOG_LEVEL env var Performance - Dependency lookup optimization: Changed from O(n*m) to O(1) using lookup maps (jobDepMap, groupDepMap) - Reconciliation backoff: Added RequeueAfter: 30*time.Second when workflow is running Documentation & Testing - Godoc documentation: Added comprehensive comments to API types and controller - Unit tests: Added helpers_test.go with tests for all helper functions - Integration tests: Added managedjob_controller_test.go with Ginkgo/Gomega tests * Add the helm chart release. * Add reasonable test coverage.
This commit is contained in:
+59
-23
@@ -5,11 +5,11 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"raczylo.com/jobs-manager-operator/api/v1beta1"
|
||||
jobsmanagerv1beta1 "raczylo.com/jobs-manager-operator/api/v1beta1"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
func jobNameGenerator(name ...string) string {
|
||||
@@ -17,19 +17,37 @@ func jobNameGenerator(name ...string) string {
|
||||
return strings.ToLower(strings.Join(name, "-"))
|
||||
}
|
||||
|
||||
type jobStatusUpdate struct {
|
||||
Job *jobsmanagerv1beta1.ManagedJob
|
||||
PatchedResource string
|
||||
Status string
|
||||
type connPackage struct {
|
||||
r *ManagedJobReconciler
|
||||
ctx context.Context
|
||||
req ctrl.Request
|
||||
mtx sync.Mutex
|
||||
mj *jobsmanagerv1beta1.ManagedJob
|
||||
logger logr.Logger
|
||||
// jobDepMap maps job names to dependencies that reference them (for O(1) lookup)
|
||||
jobDepMap map[string][]*jobsmanagerv1beta1.ManagedJobDependencies
|
||||
// groupDepMap maps group names to dependencies that reference them (for O(1) lookup)
|
||||
groupDepMap map[string][]*jobsmanagerv1beta1.ManagedJobDependencies
|
||||
}
|
||||
|
||||
type connPackage struct {
|
||||
r *ManagedJobReconciler
|
||||
ctx context.Context
|
||||
req ctrl.Request
|
||||
mtx sync.Mutex
|
||||
mj *jobsmanagerv1beta1.ManagedJob
|
||||
dependencyTree Tree
|
||||
// buildDependencyMaps constructs lookup maps for efficient dependency status updates.
|
||||
// This converts O(n*m) lookups to O(1) by mapping job/group names to their dependents.
|
||||
func (cp *connPackage) buildDependencyMaps() {
|
||||
cp.jobDepMap = make(map[string][]*jobsmanagerv1beta1.ManagedJobDependencies)
|
||||
cp.groupDepMap = make(map[string][]*jobsmanagerv1beta1.ManagedJobDependencies)
|
||||
|
||||
for _, group := range cp.mj.Spec.Groups {
|
||||
// Map group dependencies
|
||||
for _, dep := range group.Dependencies {
|
||||
cp.groupDepMap[dep.Name] = append(cp.groupDepMap[dep.Name], dep)
|
||||
}
|
||||
// Map job dependencies
|
||||
for _, job := range group.Jobs {
|
||||
for _, dep := range job.Dependencies {
|
||||
cp.jobDepMap[dep.Name] = append(cp.jobDepMap[dep.Name], dep)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *connPackage) getOwnerReference() (metav1.OwnerReference, error) {
|
||||
@@ -40,7 +58,7 @@ func (cp *connPackage) getOwnerReference() (metav1.OwnerReference, error) {
|
||||
}
|
||||
t := true
|
||||
return metav1.OwnerReference{
|
||||
APIVersion: v1beta1.GroupVersion.String(),
|
||||
APIVersion: jobsmanagerv1beta1.GroupVersion.String(),
|
||||
Kind: "ManagedJob",
|
||||
Name: mj.Name,
|
||||
UID: mj.UID,
|
||||
@@ -50,15 +68,33 @@ func (cp *connPackage) getOwnerReference() (metav1.OwnerReference, error) {
|
||||
|
||||
func (cp *connPackage) updateCRDStatusDirectly() error {
|
||||
cp.mtx.Lock()
|
||||
err := cp.r.Update(cp.ctx, cp.mj)
|
||||
if err != nil {
|
||||
// log.Log.Info("Error", err.Error(), "more", "Unable to update ManagedJob status directly")
|
||||
defer cp.mtx.Unlock()
|
||||
|
||||
if err := cp.r.Update(cp.ctx, cp.mj); err != nil {
|
||||
cp.logger.Error(err, "Unable to update ManagedJob status directly")
|
||||
return err
|
||||
}
|
||||
// get updated ManagedJob
|
||||
err = cp.r.Client.Get(cp.ctx, cp.req.NamespacedName, cp.mj)
|
||||
if err != nil {
|
||||
log.Log.Error(err, "Unable to get updated ManagedJob")
|
||||
|
||||
if err := cp.r.Client.Get(cp.ctx, cp.req.NamespacedName, cp.mj); err != nil {
|
||||
cp.logger.Error(err, "Unable to get updated ManagedJob")
|
||||
return err
|
||||
}
|
||||
cp.mtx.Unlock()
|
||||
return err
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getImagePullPolicy returns the specified pull policy or IfNotPresent as default
|
||||
func getImagePullPolicy(policy string) corev1.PullPolicy {
|
||||
if policy == "" {
|
||||
return corev1.PullIfNotPresent
|
||||
}
|
||||
return corev1.PullPolicy(policy)
|
||||
}
|
||||
|
||||
// getResources returns the resource requirements or empty requirements if nil
|
||||
func getResources(resources *corev1.ResourceRequirements) corev1.ResourceRequirements {
|
||||
if resources == nil {
|
||||
return corev1.ResourceRequirements{}
|
||||
}
|
||||
return *resources
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user