diff --git a/pkg/apis/jenkins/v1alpha2/jenkins_types.go b/pkg/apis/jenkins/v1alpha2/jenkins_types.go index a428c1f5..afddc89a 100644 --- a/pkg/apis/jenkins/v1alpha2/jenkins_types.go +++ b/pkg/apis/jenkins/v1alpha2/jenkins_types.go @@ -321,6 +321,10 @@ type JenkinsStatus struct { // BackupDoneBeforePodDeletion tells if backup before pod deletion has been made // +optional BackupDoneBeforePodDeletion bool `json:"backupDoneBeforePodDeletion,omitempty"` + + // UserAndPasswordHash is a SHA256 hash made from user and password + // +optional + UserAndPasswordHash string `json:"userAndPasswordHash,omitempty"` } // BuildStatus defines type of Jenkins build job status diff --git a/pkg/controller/jenkins/configuration/base/reconcile.go b/pkg/controller/jenkins/configuration/base/reconcile.go index 6cb35c6f..5e62a7af 100644 --- a/pkg/controller/jenkins/configuration/base/reconcile.go +++ b/pkg/controller/jenkins/configuration/base/reconcile.go @@ -2,6 +2,8 @@ package base import ( "context" + "crypto/sha256" + "encoding/base64" "fmt" "reflect" "strings" @@ -377,6 +379,11 @@ func (r *ReconcileJenkinsBaseConfiguration) getJenkinsMasterPod(meta metav1.Obje } func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.ObjectMeta) (reconcile.Result, error) { + userAndPasswordHash, err := r.calculateUserAndPasswordHash() + if err != nil { + return reconcile.Result{}, err + } + // Check if this Pod already exists currentJenkinsMasterPod, err := r.getJenkinsMasterPod(meta) if err != nil && errors.IsNotFound(err) { @@ -388,13 +395,14 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O } now := metav1.Now() r.jenkins.Status = v1alpha2.JenkinsStatus{ - ProvisionStartTime: &now, - LastBackup: r.jenkins.Status.LastBackup, - PendingBackup: r.jenkins.Status.LastBackup, + ProvisionStartTime: &now, + LastBackup: r.jenkins.Status.LastBackup, + PendingBackup: r.jenkins.Status.LastBackup, + UserAndPasswordHash: userAndPasswordHash, } - err = r.updateResource(r.jenkins) + err = r.k8sClient.Update(context.TODO(), r.jenkins) if err != nil { - return reconcile.Result{}, err // don't wrap error + return reconcile.Result{Requeue: true}, err } return reconcile.Result{}, nil } else if err != nil && !errors.IsNotFound(err) { @@ -419,18 +427,36 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O } return reconcile.Result{Requeue: true}, nil } - if currentJenkinsMasterPod != nil && r.isRecreatePodNeeded(*currentJenkinsMasterPod) { + if currentJenkinsMasterPod != nil && r.isRecreatePodNeeded(*currentJenkinsMasterPod, userAndPasswordHash) { return reconcile.Result{Requeue: true}, r.restartJenkinsMasterPod(meta) } return reconcile.Result{}, nil } +func (r *ReconcileJenkinsBaseConfiguration) calculateUserAndPasswordHash() (string, error) { + credentialsSecret := &corev1.Secret{} + err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.jenkins), Namespace: r.jenkins.ObjectMeta.Namespace}, credentialsSecret) + if err != nil { + return "", stackerr.WithStack(err) + } + + hash := sha256.New() + hash.Write(credentialsSecret.Data[resources.OperatorCredentialsSecretUserNameKey]) + hash.Write(credentialsSecret.Data[resources.OperatorCredentialsSecretPasswordKey]) + return base64.StdEncoding.EncodeToString(hash.Sum(nil)), nil +} + func isPodTerminating(pod corev1.Pod) bool { return pod.ObjectMeta.DeletionTimestamp != nil } -func (r *ReconcileJenkinsBaseConfiguration) isRecreatePodNeeded(currentJenkinsMasterPod corev1.Pod) bool { +func (r *ReconcileJenkinsBaseConfiguration) isRecreatePodNeeded(currentJenkinsMasterPod corev1.Pod, userAndPasswordHash string) bool { + if userAndPasswordHash != r.jenkins.Status.UserAndPasswordHash { + r.logger.Info("User or password have changed, recreating pod") + return true + } + if r.jenkins.Spec.Restore.RecoveryOnce != 0 && r.jenkins.Status.RestoredBackup != 0 { r.logger.Info(fmt.Sprintf("spec.restore.recoveryOnce is set, recreating pod")) return true diff --git a/pkg/controller/jenkins/jenkins_controller.go b/pkg/controller/jenkins/jenkins_controller.go index 6849e143..9cefa4e2 100644 --- a/pkg/controller/jenkins/jenkins_controller.go +++ b/pkg/controller/jenkins/jenkins_controller.go @@ -93,6 +93,14 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { return errors.WithStack(err) } + err = c.Watch(&source.Kind{Type: &corev1.Secret{TypeMeta: metav1.TypeMeta{APIVersion: "core/v1", Kind: "Secret"}}}, &handler.EnqueueRequestForOwner{ + IsController: true, + OwnerType: &v1alpha2.Jenkins{}, + }) + if err != nil { + return errors.WithStack(err) + } + jenkinsHandler := &enqueueRequestForJenkins{} err = c.Watch(&source.Kind{Type: &corev1.Secret{TypeMeta: metav1.TypeMeta{APIVersion: "core/v1", Kind: "Secret"}}}, jenkinsHandler) if err != nil {