pkg/controller/jenkins_folder/jenkins_folder_controller.go (160 lines of code) (raw):

package jenkins import ( "context" "fmt" "reflect" "strings" "github.com/go-logr/logr" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" jenkinsApi "github.com/epam/edp-jenkins-operator/v2/pkg/apis/v2/v1" jenkinsClient "github.com/epam/edp-jenkins-operator/v2/pkg/client/jenkins" "github.com/epam/edp-jenkins-operator/v2/pkg/controller/helper" "github.com/epam/edp-jenkins-operator/v2/pkg/controller/jenkins_folder/chain" jfHandler "github.com/epam/edp-jenkins-operator/v2/pkg/controller/jenkins_folder/chain/handler" "github.com/epam/edp-jenkins-operator/v2/pkg/service/platform" "github.com/epam/edp-jenkins-operator/v2/pkg/util/finalizer" plutil "github.com/epam/edp-jenkins-operator/v2/pkg/util/platform" ) const jenkinsFolderJenkinsFinalizerName = "jenkinsfolder.jenkins.finalizer.name" func NewReconcileJenkinsFolder( k8sClient client.Client, scheme *runtime.Scheme, log logr.Logger, ps platform.PlatformService, ) *ReconcileJenkinsFolder { return &ReconcileJenkinsFolder{ client: k8sClient, scheme: scheme, platform: ps, log: log.WithName("jenkins-folder"), } } type ReconcileJenkinsFolder struct { client client.Client scheme *runtime.Scheme platform platform.PlatformService log logr.Logger } func (r *ReconcileJenkinsFolder) SetupWithManager(mgr ctrl.Manager) error { p := predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { oldObject, ok := e.ObjectOld.(*jenkinsApi.JenkinsFolder) if !ok { return false } newObject, ok := e.ObjectNew.(*jenkinsApi.JenkinsFolder) if !ok { return false } if !reflect.DeepEqual(oldObject.Spec, newObject.Spec) { return true } if newObject.DeletionTimestamp != nil { return true } return false }, } if err := ctrl.NewControllerManagedBy(mgr). For(&jenkinsApi.JenkinsFolder{}, builder.WithPredicates(p)). Complete(r); err != nil { return fmt.Errorf("failed to create new managed controller: %w", err) } return nil } func (r *ReconcileJenkinsFolder) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { log := r.log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) log.V(2).Info("Reconciling JenkinsFolder has been started") jenkinsFolder := &jenkinsApi.JenkinsFolder{} if err := r.client.Get(ctx, request.NamespacedName, jenkinsFolder); err != nil { if k8serrors.IsNotFound(err) { log.Info("instance not found") return reconcile.Result{}, nil } return reconcile.Result{}, fmt.Errorf("failed to Get JenkinsFolder: %w", err) } jc, err := r.initGoJenkinsClient(jenkinsFolder) if err != nil { return reconcile.Result{}, fmt.Errorf("failed to create gojenkins client: %w", err) } result, err := r.tryToDeleteJenkinsFolder(ctx, *jc, jenkinsFolder) if err != nil || result != nil { return *result, err } h, err := r.createChain(jenkinsFolder.Spec.Job != nil) if err != nil { return reconcile.Result{}, err } if err = h.ServeRequest(jenkinsFolder); err != nil { return reconcile.Result{}, fmt.Errorf("failed to ServeRequest: %w", err) } log.V(2).Info("Reconciling JenkinsFolder has been finished") return reconcile.Result{}, nil } func (r *ReconcileJenkinsFolder) createChain(flag bool) (jfHandler.JenkinsFolderHandler, error) { if flag { folderHandler, err := chain.CreateTriggerBuildProvisionChain(r.scheme, r.client) if err != nil { return nil, fmt.Errorf("failed to CreateTriggerBuildProvisionChain: %w", err) } return folderHandler, nil } folderHandler, err := chain.CreateCDPipelineFolderChain(r.scheme, r.client) if err != nil { return nil, fmt.Errorf("failed to CreateCDPipelineFolderChain: %w", err) } return folderHandler, nil } func (r *ReconcileJenkinsFolder) initGoJenkinsClient(jf *jenkinsApi.JenkinsFolder) (*jenkinsClient.JenkinsClient, error) { j, err := plutil.GetJenkinsInstanceOwner(r.client, jf.Name, jf.Namespace, jf.Spec.OwnerName, jf.GetOwnerReferences()) if err != nil { return nil, fmt.Errorf("failed to get owner jenkins for jenkins folder %v: %w", jf.Name, err) } r.log.Info("Jenkins instance has been received", "name", j.Name) jClient, err := jenkinsClient.InitGoJenkinsClient(j, r.platform) if err != nil { return nil, fmt.Errorf("failed to InitGoJenkinsClient: %w", err) } return jClient, nil } func (r *ReconcileJenkinsFolder) tryToDeleteJenkinsFolder( ctx context.Context, jc jenkinsClient.JenkinsClient, jenkinsFolder *jenkinsApi.JenkinsFolder, ) (*reconcile.Result, error) { if jenkinsFolder.GetDeletionTimestamp().IsZero() { if !finalizer.ContainsString(jenkinsFolder.ObjectMeta.Finalizers, jenkinsFolderJenkinsFinalizerName) { jenkinsFolder.ObjectMeta.Finalizers = append(jenkinsFolder.ObjectMeta.Finalizers, jenkinsFolderJenkinsFinalizerName) if err := r.client.Update(ctx, jenkinsFolder); err != nil { return &reconcile.Result{}, fmt.Errorf("failed to update JenkinsFolder: %w", err) } } return nil, nil } jenkinsFolderName := r.getJenkinsFolderName(jenkinsFolder) if _, err := jc.GoJenkins.DeleteJob(jenkinsFolderName); err != nil { if helper.JenkinsIsNotFoundErr(err) { return &reconcile.Result{}, fmt.Errorf("failed to delete JenkinsFolder: %w", err) } r.log.V(2).Info("404 code error when Jenkins job was deleted earlier during reconciliation", "jenkins folder", jenkinsFolder.Name) } jenkinsFolder.ObjectMeta.Finalizers = finalizer.RemoveString(jenkinsFolder.ObjectMeta.Finalizers, jenkinsFolderJenkinsFinalizerName) if err := r.client.Update(ctx, jenkinsFolder); err != nil { return &reconcile.Result{}, fmt.Errorf("failed to update JenkinsFolder: %w", err) } return &reconcile.Result{}, nil } func (*ReconcileJenkinsFolder) getJenkinsFolderName(jf *jenkinsApi.JenkinsFolder) string { if jf.Spec.Job == nil { return jf.Name } return strings.ReplaceAll(jf.Name, "-codebase", "") }