diff --git a/controllers/codebasebranch/chain/factory/factory.go b/controllers/codebasebranch/chain/factory/factory.go index 0e9bfbbb..5cd90497 100644 --- a/controllers/codebasebranch/chain/factory/factory.go +++ b/controllers/codebasebranch/chain/factory/factory.go @@ -2,6 +2,7 @@ package factory import ( "strings" + "time" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -20,7 +21,7 @@ import ( var log = ctrl.Log.WithName("codebase_branch_factory") -func createJenkinsDefChain(c client.Client) handler.CodebaseBranchHandler { +func createJenkinsDefChain(requestRequeueDelay time.Duration, c client.Client) handler.CodebaseBranchHandler { log.Info("chain is selected", "type", "jenkins chain") return chain.CheckCommitHashExists{ @@ -30,7 +31,8 @@ func createJenkinsDefChain(c client.Client) handler.CodebaseBranchHandler { TriggerJob: trigger_job.TriggerJob{ Client: c, Service: &service.CodebaseBranchServiceProvider{ - Client: c, + TimeoutDuration: requestRequeueDelay, + Client: c, }, Next: put_codebase_image_stream.PutCodebaseImageStream{ Client: c, @@ -41,7 +43,7 @@ func createJenkinsDefChain(c client.Client) handler.CodebaseBranchHandler { } } -func createTektonDefChain(c client.Client) handler.CodebaseBranchHandler { +func createTektonDefChain(requestRequeueDelay time.Duration, c client.Client) handler.CodebaseBranchHandler { log.Info("chain is selected", "type", "tekton chain") return put_branch_in_git.PutBranchInGit{ @@ -52,12 +54,13 @@ func createTektonDefChain(c client.Client) handler.CodebaseBranchHandler { Next: &clean_tmp_directory.CleanTempDirectory{}, }, Service: &service.CodebaseBranchServiceProvider{ - Client: c, + TimeoutDuration: requestRequeueDelay, + Client: c, }, } } -func GetDeletionChain(ciType string, c client.Client) handler.CodebaseBranchHandler { +func GetDeletionChain(ciType string, requestRequeueDelay time.Duration, c client.Client) handler.CodebaseBranchHandler { if strings.EqualFold(ciType, util.CITekton) { return empty.MakeChain("no deletion chain for tekton", false) } @@ -66,16 +69,17 @@ func GetDeletionChain(ciType string, c client.Client) handler.CodebaseBranchHand TriggerJob: trigger_job.TriggerJob{ Client: c, Service: &service.CodebaseBranchServiceProvider{ - Client: c, + TimeoutDuration: requestRequeueDelay, + Client: c, }, }, } } -func GetChain(ciType string, c client.Client) handler.CodebaseBranchHandler { +func GetChain(ciType string, requestRequeueDelay time.Duration, c client.Client) handler.CodebaseBranchHandler { if strings.EqualFold(ciType, util.CITekton) { - return createTektonDefChain(c) + return createTektonDefChain(requestRequeueDelay, c) } - return createJenkinsDefChain(c) + return createJenkinsDefChain(requestRequeueDelay, c) } diff --git a/controllers/codebasebranch/codebasebranch_controller.go b/controllers/codebasebranch/codebasebranch_controller.go index 092c911e..5e1015eb 100644 --- a/controllers/codebasebranch/codebasebranch_controller.go +++ b/controllers/codebasebranch/codebasebranch_controller.go @@ -32,25 +32,27 @@ import ( "github.com/epam/edp-codebase-operator/v2/pkg/util" ) -func NewReconcileCodebaseBranch(c client.Client, scheme *runtime.Scheme, log logr.Logger) *ReconcileCodebaseBranch { +const ( + codebaseBranchOperatorFinalizerName = "codebase.branch.operator.finalizer.name" + errorStatus = "error" +) + +func NewReconcileCodebaseBranch(c client.Client, scheme *runtime.Scheme, log logr.Logger, ciRequestDelay time.Duration) *ReconcileCodebaseBranch { return &ReconcileCodebaseBranch{ - client: c, - scheme: scheme, - log: log.WithName("codebase-branch"), + ciRequestDelay: ciRequestDelay, + client: c, + scheme: scheme, + log: log.WithName("codebase-branch"), } } type ReconcileCodebaseBranch struct { - client client.Client - scheme *runtime.Scheme - log logr.Logger + ciRequestDelay time.Duration + client client.Client + scheme *runtime.Scheme + log logr.Logger } -const ( - codebaseBranchOperatorFinalizerName = "codebase.branch.operator.finalizer.name" - errorStatus = "error" -) - func (r *ReconcileCodebaseBranch) SetupWithManager(mgr ctrl.Manager, maxConcurrentReconciles int) error { p := predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { @@ -133,7 +135,7 @@ func (r *ReconcileCodebaseBranch) Reconcile(ctx context.Context, request reconci log.Error(err, "set labels failed") } - result, err := r.tryToDeleteCodebaseBranch(ctx, cb, factory.GetDeletionChain(c.Spec.CiTool, r.client)) + result, err := r.tryToDeleteCodebaseBranch(ctx, cb, factory.GetDeletionChain(c.Spec.CiTool, r.ciRequestDelay, r.client)) if err != nil { return reconcile.Result{}, fmt.Errorf("failed to remove codebasebranch %v: %w", cb.Name, err) } @@ -150,7 +152,7 @@ func (r *ReconcileCodebaseBranch) Reconcile(ctx context.Context, request reconci cb.Status.Build = &buildNumber } - cbChain := factory.GetChain(c.Spec.CiTool, r.client) + cbChain := factory.GetChain(c.Spec.CiTool, r.ciRequestDelay, r.client) if err := cbChain.ServeRequest(ctx, cb); err != nil { const defaultPostponeTime = 5 * time.Second diff --git a/controllers/codebasebranch/service/codebasebranch.go b/controllers/codebasebranch/service/codebasebranch.go index 324df54c..2fd24504 100644 --- a/controllers/codebasebranch/service/codebasebranch.go +++ b/controllers/codebasebranch/service/codebasebranch.go @@ -20,7 +20,6 @@ var log = ctrl.Log.WithName("codebase_branch_service") const ( jenkinsJobSuccessStatus = "blue" - defaultTimeoutDuration = 5 * time.Second defaultRetryCount = 50 ) @@ -35,7 +34,8 @@ type CodebaseBranchService interface { } type CodebaseBranchServiceProvider struct { - Client client.Client + TimeoutDuration time.Duration + Client client.Client } var ErrJobFailed = errors.New("deletion job failed") @@ -63,7 +63,7 @@ func (s *CodebaseBranchServiceProvider) TriggerDeletionJob(cb *codebaseApi.Codeb rj := fmt.Sprintf("%v/job/Delete-release-%v", cb.Spec.CodebaseName, cb.Spec.CodebaseName) - js, err := jc.GetJobStatus(rj, defaultTimeoutDuration, defaultRetryCount) + js, err := jc.GetJobStatus(rj, s.TimeoutDuration, defaultRetryCount) if err != nil { return fmt.Errorf("failed to get deletion job status: %w", err) } @@ -115,7 +115,7 @@ func (s *CodebaseBranchServiceProvider) TriggerReleaseJob(cb *codebaseApi.Codeba rj := fmt.Sprintf("%v/job/Create-release-%v", cb.Spec.CodebaseName, cb.Spec.CodebaseName) - js, err := jc.GetJobStatus(rj, defaultTimeoutDuration, defaultRetryCount) + js, err := jc.GetJobStatus(rj, s.TimeoutDuration, defaultRetryCount) if err != nil { return fmt.Errorf("failed to fetch Jenkins job status: %w", err) } diff --git a/main.go b/main.go index 527c48f2..6cb2c2ee 100644 --- a/main.go +++ b/main.go @@ -3,8 +3,10 @@ package main import ( "context" "flag" + "fmt" "os" "strconv" + "time" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. @@ -52,6 +54,8 @@ const ( codebaseOperatorLock = "edp-codebase-operator-lock" codebaseBranchMaxConcurrentReconcilesEnv = "CODEBASE_BRANCH_MAX_CONCURRENT_RECONCILES" logFailCtrlCreateMessage = "failed to create controller" + + defaultCIRequestDelay = 5 * time.Second ) func main() { @@ -141,7 +145,17 @@ func main() { os.Exit(1) } - cbCtrl := codebasebranch.NewReconcileCodebaseBranch(mgr.GetClient(), mgr.GetScheme(), ctrlLog) + ciRequestDelay, err := getCIRequestDelay("CI_REQUEST_DELAY_SEC") + if err != nil { + setupLog.Error(err, "failed to read CI Request Delay from env vars", "controller", "codebase-branch") + setupLog.Info("Using default CI Request Delay") + + ciRequestDelay = defaultCIRequestDelay + } + + setupLog.Info("Request delay set", "CI Request delay", ciRequestDelay) + + cbCtrl := codebasebranch.NewReconcileCodebaseBranch(mgr.GetClient(), mgr.GetScheme(), ctrlLog, ciRequestDelay) if err = cbCtrl.SetupWithManager(mgr, getMaxConcurrentReconciles(codebaseBranchMaxConcurrentReconcilesEnv)); err != nil { setupLog.Error(err, logFailCtrlCreateMessage, "controller", "codebase-branch") @@ -212,3 +226,17 @@ func getMaxConcurrentReconciles(envVar string) int { return int(n) } + +func getCIRequestDelay(envVar string) (time.Duration, error) { + value, exists := os.LookupEnv(envVar) + if !exists { + return defaultCIRequestDelay, nil + } + + intValue, err := strconv.Atoi(value) + if err != nil { + return 0, fmt.Errorf("failed to parse delay: %w", err) + } + + return time.Duration(intValue) * time.Second, nil +}