Merge pull request #479 from SylwiaBrant/xmas-fix
Grand Christmas Patch
This commit is contained in:
		
						commit
						d6b10c6e0f
					
				
							
								
								
									
										4
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										4
									
								
								Makefile
								
								
								
								
							|  | @ -66,7 +66,7 @@ PACKAGES_FOR_UNIT_TESTS = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v | ||||||
| E2E_TEST_SELECTOR ?= .* | E2E_TEST_SELECTOR ?= .* | ||||||
| 
 | 
 | ||||||
| JENKINS_API_HOSTNAME := $(shell $(JENKINS_API_HOSTNAME_COMMAND) 2> /dev/null || echo "" ) | JENKINS_API_HOSTNAME := $(shell $(JENKINS_API_HOSTNAME_COMMAND) 2> /dev/null || echo "" ) | ||||||
| OPERATOR_ARGS ?= --jenkins-api-hostname=$(JENKINS_API_HOSTNAME) --jenkins-api-port=$(JENKINS_API_PORT) --jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) $(OPERATOR_EXTRA_ARGS) | OPERATOR_ARGS ?= --jenkins-api-hostname=$(JENKINS_API_HOSTNAME) --jenkins-api-port=$(JENKINS_API_PORT) --jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) --cluster-domain=$(CLUSTER_DOMAIN) $(OPERATOR_EXTRA_ARGS) | ||||||
| 
 | 
 | ||||||
| .DEFAULT_GOAL := help | .DEFAULT_GOAL := help | ||||||
| 
 | 
 | ||||||
|  | @ -422,7 +422,7 @@ endif | ||||||
| minikube-start: check-minikube ## Start minikube
 | minikube-start: check-minikube ## Start minikube
 | ||||||
| 	@echo "+ $@" | 	@echo "+ $@" | ||||||
| 	@minikube status && exit 0 || \
 | 	@minikube status && exit 0 || \
 | ||||||
| 	minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --vm-driver=$(MINIKUBE_DRIVER) --memory 4096 --cpus 3 | 	minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --dns-domain=$(CLUSTER_DOMAIN) --extra-config=kubelet.cluster-domain=$(CLUSTER_DOMAIN) --vm-driver=$(MINIKUBE_DRIVER) --memory 4096 --cpus 3 | ||||||
| 
 | 
 | ||||||
| .PHONY: crc-start | .PHONY: crc-start | ||||||
| crc-start: check-crc ## Start CodeReady Containers Kubernetes cluster
 | crc-start: check-crc ## Start CodeReady Containers Kubernetes cluster
 | ||||||
|  |  | ||||||
|  | @ -98,3 +98,30 @@ rules: | ||||||
|       - get |       - get | ||||||
|       - list |       - list | ||||||
|       - watch |       - watch | ||||||
|  |   - apiGroups: | ||||||
|  |       - "route.openshift.io" | ||||||
|  |     resources: | ||||||
|  |       - routes | ||||||
|  |     verbs: | ||||||
|  |       - get | ||||||
|  |       - list | ||||||
|  |       - watch | ||||||
|  |       - create | ||||||
|  |       - update | ||||||
|  |   - apiGroups: | ||||||
|  |       - "image.openshift.io" | ||||||
|  |     resources: | ||||||
|  |       - imagestreams | ||||||
|  |     verbs: | ||||||
|  |       - get | ||||||
|  |       - list | ||||||
|  |       - watch | ||||||
|  |   - apiGroups: | ||||||
|  |       - "build.openshift.io" | ||||||
|  |     resources: | ||||||
|  |       - builds | ||||||
|  |       - buildconfigs | ||||||
|  |     verbs: | ||||||
|  |       - get | ||||||
|  |       - list | ||||||
|  |       - watch | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ jenkins: | ||||||
|   # image is the name (and tag) of the Jenkins instance |   # image is the name (and tag) of the Jenkins instance | ||||||
|   # Default: jenkins/jenkins:lts |   # Default: jenkins/jenkins:lts | ||||||
|   # It's recommended to use LTS (tag: "lts") version |   # It's recommended to use LTS (tag: "lts") version | ||||||
|   image: jenkins/jenkins:lts |   image: jenkins/jenkins:2.249.3-lts-alpine | ||||||
| 
 | 
 | ||||||
|   # env contains jenkins container environment variables |   # env contains jenkins container environment variables | ||||||
|   env: [] |   env: [] | ||||||
|  | @ -63,34 +63,34 @@ jenkins: | ||||||
|   # |   # | ||||||
|   # basePlugins: |   # basePlugins: | ||||||
|   # - name: kubernetes |   # - name: kubernetes | ||||||
|   #   version: 1.18.3 |   #   version: 1.27.6 | ||||||
|   # - name: workflow-job |   # - name: workflow-job | ||||||
|   #   version: "2.34" |   #   version: "2.40" | ||||||
|   # - name: workflow-aggregator |   # - name: workflow-aggregator | ||||||
|   #   version: "2.6" |   #   version: "2.6" | ||||||
|   # - name: git |   # - name: git | ||||||
|   #   version: 3.12.0 |   #   version: 4.4.5 | ||||||
|   # - name: job-dsl |   # - name: job-dsl | ||||||
|   #   version: "1.76" |   #   version: "1.77" | ||||||
|   # - name: configuration-as-code |   # - name: configuration-as-code | ||||||
|   #   version: "1.29" |   #   version: "1.46" | ||||||
|   # - name: kubernetes-credentials-provider |   # - name: kubernetes-credentials-provider | ||||||
|   #   version: 0.12.1 |   #   version: 0.15 | ||||||
|   basePlugins: |   basePlugins: | ||||||
|     - name: kubernetes |     - name: kubernetes | ||||||
|       version: "1.25.2" |       version: "1.27.6" | ||||||
|     - name: workflow-job |     - name: workflow-job | ||||||
|       version: "2.39" |       version: "2.40" | ||||||
|     - name: workflow-aggregator |     - name: workflow-aggregator | ||||||
|       version: "2.6" |       version: "2.6" | ||||||
|     - name: git |     - name: git | ||||||
|       version: "4.2.2" |       version: "4.4.5" | ||||||
|     - name: job-dsl |     - name: job-dsl | ||||||
|       version: "1.77" |       version: "1.77" | ||||||
|     - name: configuration-as-code |     - name: configuration-as-code | ||||||
|       version: "1.38" |       version: "1.46" | ||||||
|     - name: kubernetes-credentials-provider |     - name: kubernetes-credentials-provider | ||||||
|       version: "0.13" |       version: "0.15" | ||||||
| 
 | 
 | ||||||
|   # plugins are plugins required by the user |   # plugins are plugins required by the user | ||||||
|   # You can define plugins here |   # You can define plugins here | ||||||
|  | @ -100,7 +100,7 @@ jenkins: | ||||||
|   # |   # | ||||||
|   # plugins: |   # plugins: | ||||||
|   # - name: simple-theme-plugin |   # - name: simple-theme-plugin | ||||||
|   #   version: 0.5.1 |   #   version: "0.6" | ||||||
|   plugins: [] |   plugins: [] | ||||||
| 
 | 
 | ||||||
|   # seedJobs is placeholder for jenkins seed jobs |   # seedJobs is placeholder for jenkins seed jobs | ||||||
|  | @ -159,7 +159,7 @@ jenkins: | ||||||
| 
 | 
 | ||||||
|     # image used by backup feature |     # image used by backup feature | ||||||
|     # By default using prebuilt backup PVC image by VirtusLab |     # By default using prebuilt backup PVC image by VirtusLab | ||||||
|     image: virtuslab/jenkins-operator-backup-pvc:v0.0.8 |     image: virtuslab/jenkins-operator-backup-pvc:v0.1.0 | ||||||
| 
 | 
 | ||||||
|     # containerName is backup container name |     # containerName is backup container name | ||||||
|     containerName: backup |     containerName: backup | ||||||
|  | @ -178,6 +178,9 @@ jenkins: | ||||||
|     restoreCommand: |     restoreCommand: | ||||||
|       - /home/user/bin/restore.sh |       - /home/user/bin/restore.sh | ||||||
| 
 | 
 | ||||||
|  |     getLatestAction: | ||||||
|  |       - /home/user/bin/get-latest.sh | ||||||
|  | 
 | ||||||
|     # pvc is Persistent Volume Claim Kubernetes resource |     # pvc is Persistent Volume Claim Kubernetes resource | ||||||
|     pvc: |     pvc: | ||||||
|       # enabled is enable/disable switch for PVC |       # enabled is enable/disable switch for PVC | ||||||
|  |  | ||||||
|  | @ -72,6 +72,7 @@ func main() { | ||||||
| 	port := pflag.Int("jenkins-api-port", 0, "The port on which Jenkins API is running. Note: If you want to use nodePort don't set this setting and --jenkins-api-use-nodeport must be true.") | 	port := pflag.Int("jenkins-api-port", 0, "The port on which Jenkins API is running. Note: If you want to use nodePort don't set this setting and --jenkins-api-use-nodeport must be true.") | ||||||
| 	useNodePort := pflag.Bool("jenkins-api-use-nodeport", false, "Connect to Jenkins API using the service nodePort instead of service port. If you want to set this as true - don't set --jenkins-api-port.") | 	useNodePort := pflag.Bool("jenkins-api-use-nodeport", false, "Connect to Jenkins API using the service nodePort instead of service port. If you want to set this as true - don't set --jenkins-api-port.") | ||||||
| 	debug := pflag.Bool("debug", false, "Set log level to debug") | 	debug := pflag.Bool("debug", false, "Set log level to debug") | ||||||
|  | 	kubernetesClusterDomain := pflag.String("cluster-domain", "cluster.local", "Use custom domain name instead of 'cluster.local'.") | ||||||
| 	pflag.Parse() | 	pflag.Parse() | ||||||
| 
 | 
 | ||||||
| 	log.SetupLogger(*debug) | 	log.SetupLogger(*debug) | ||||||
|  | @ -136,8 +137,13 @@ func main() { | ||||||
| 		fatal(errors.Wrap(err, "invalid command line parameters"), *debug) | 		fatal(errors.Wrap(err, "invalid command line parameters"), *debug) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// validate kubernetes cluster domain
 | ||||||
|  | 	if *kubernetesClusterDomain == "" { | ||||||
|  | 		fatal(errors.Wrap(err, "Kubernetes cluster domain can't be empty"), *debug) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// setup Jenkins controller
 | 	// setup Jenkins controller
 | ||||||
| 	if err := jenkins.Add(mgr, jenkinsAPIConnectionSettings, *clientSet, *cfg, &c); err != nil { | 	if err := jenkins.Add(mgr, jenkinsAPIConnectionSettings, *kubernetesClusterDomain, *clientSet, *cfg, &c); err != nil { | ||||||
| 		fatal(errors.Wrap(err, "failed to setup controllers"), *debug) | 		fatal(errors.Wrap(err, "failed to setup controllers"), *debug) | ||||||
| 	} | 	} | ||||||
| 	// setup JenkinsImage controller
 | 	// setup JenkinsImage controller
 | ||||||
|  |  | ||||||
|  | @ -12,3 +12,4 @@ ALL_IN_ONE_DEPLOY_FILE_PREFIX=all-in-one | ||||||
| GEN_CRD_API=gen-crd-api-reference-docs | GEN_CRD_API=gen-crd-api-reference-docs | ||||||
| IMAGE_PULL_MODE=local | IMAGE_PULL_MODE=local | ||||||
| HELM_VERSION=3.1.2 | HELM_VERSION=3.1.2 | ||||||
|  | CLUSTER_DOMAIN=cluster.local | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ spec: | ||||||
|   master: |   master: | ||||||
|     containers: |     containers: | ||||||
|     - name: jenkins-master |     - name: jenkins-master | ||||||
|       image: jenkins/jenkins:lts |       image: jenkins/jenkins:2.249.3-lts-alpine | ||||||
|       imagePullPolicy: Always |       imagePullPolicy: Always | ||||||
|       livenessProbe: |       livenessProbe: | ||||||
|         failureThreshold: 12 |         failureThreshold: 12 | ||||||
|  |  | ||||||
|  | @ -5,20 +5,20 @@ metadata: | ||||||
| spec: | spec: | ||||||
|   image: |   image: | ||||||
|     name: jenkins/jenkins |     name: jenkins/jenkins | ||||||
|     tag: lts |     tag: 2.249.3-lts-alpine | ||||||
|   plugins: |   plugins: | ||||||
|   - name: kubernetes |   - name: kubernetes | ||||||
|     version: "1.15.7" |     version: "1.27.6" | ||||||
|   - name: workflow-job |   - name: workflow-job | ||||||
|     version: "2.39" |     version: "2.40" | ||||||
|   - name: workflow-aggregator |   - name: workflow-aggregator | ||||||
|     version: "2.6" |     version: "2.6" | ||||||
|   - name: git |   - name: git | ||||||
|     version: "3.10.0" |     version: "4.4.5" | ||||||
|   - name: job-dsl |   - name: job-dsl | ||||||
|     version: "1.74" |     version: "1.77" | ||||||
|   - name: configuration-as-code |   - name: configuration-as-code | ||||||
|     version: "1.19" |     version: "1.46" | ||||||
|   - name: kubernetes-credentials-provider |   - name: kubernetes-credentials-provider | ||||||
|     version: "0.12.1" |     version: "0.15" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -626,6 +626,11 @@ type Restore struct { | ||||||
| 	// Action defines action which performs restore backup in restore container sidecar
 | 	// Action defines action which performs restore backup in restore container sidecar
 | ||||||
| 	Action Handler `json:"action"` | 	Action Handler `json:"action"` | ||||||
| 
 | 
 | ||||||
|  | 	// GetLatestAction defines action which returns the latest backup number. If there is no backup "-1" should be
 | ||||||
|  | 	// returned.
 | ||||||
|  | 	// +optional
 | ||||||
|  | 	GetLatestAction Handler `json:"getLatestAction"` | ||||||
|  | 
 | ||||||
| 	// RecoveryOnce if want to restore specific backup set this field and then Jenkins will be restarted and desired backup will be restored
 | 	// RecoveryOnce if want to restore specific backup set this field and then Jenkins will be restarted and desired backup will be restored
 | ||||||
| 	// +optional
 | 	// +optional
 | ||||||
| 	RecoveryOnce uint64 `json:"recoveryOnce,omitempty"` | 	RecoveryOnce uint64 `json:"recoveryOnce,omitempty"` | ||||||
|  |  | ||||||
|  | @ -677,6 +677,7 @@ func (in *Plugin) DeepCopy() *Plugin { | ||||||
| func (in *Restore) DeepCopyInto(out *Restore) { | func (in *Restore) DeepCopyInto(out *Restore) { | ||||||
| 	*out = *in | 	*out = *in | ||||||
| 	in.Action.DeepCopyInto(&out.Action) | 	in.Action.DeepCopyInto(&out.Action) | ||||||
|  | 	in.GetLatestAction.DeepCopyInto(&out.GetLatestAction) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ package backuprestore | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" | 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" | ||||||
|  | @ -12,6 +14,7 @@ import ( | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/log" | 	"github.com/jenkinsci/kubernetes-operator/pkg/log" | ||||||
| 
 | 
 | ||||||
| 	"github.com/go-logr/logr" | 	"github.com/go-logr/logr" | ||||||
|  | 	"github.com/pkg/errors" | ||||||
| 	apierrors "k8s.io/apimachinery/pkg/api/errors" | 	apierrors "k8s.io/apimachinery/pkg/api/errors" | ||||||
| 	"k8s.io/apimachinery/pkg/types" | 	"k8s.io/apimachinery/pkg/types" | ||||||
| 	k8s "sigs.k8s.io/controller-runtime/pkg/client" | 	k8s "sigs.k8s.io/controller-runtime/pkg/client" | ||||||
|  | @ -109,6 +112,8 @@ func (bar *BackupAndRestore) Validate() []string { | ||||||
| 
 | 
 | ||||||
| 	return messages | 	return messages | ||||||
| } | } | ||||||
|  | // helper value indicating no saved backup
 | ||||||
|  | const noBackup = "-1" | ||||||
| 
 | 
 | ||||||
| // Restore performs Jenkins restore backup operation
 | // Restore performs Jenkins restore backup operation
 | ||||||
| func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error { | func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error { | ||||||
|  | @ -121,7 +126,8 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error | ||||||
| 		bar.logger.V(log.VDebug).Info("Skipping restore backup, backup already restored") | 		bar.logger.V(log.VDebug).Info("Skipping restore backup, backup already restored") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	if jenkins.Status.LastBackup == 0 { | 
 | ||||||
|  | 	if jenkins.Status.LastBackup == 0 && jenkins.Spec.Restore.GetLatestAction.Exec == nil { | ||||||
| 		bar.logger.V(log.VDebug).Info("Skipping restore backup") | 		bar.logger.V(log.VDebug).Info("Skipping restore backup") | ||||||
| 		if jenkins.Status.PendingBackup == 0 { | 		if jenkins.Status.PendingBackup == 0 { | ||||||
| 			jenkins.Status.PendingBackup = 1 | 			jenkins.Status.PendingBackup = 1 | ||||||
|  | @ -130,14 +136,40 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var backupNumber uint64 | 	podName := resources.GetJenkinsMasterPodName(jenkins) | ||||||
|  | 	var backupNumber = jenkins.Status.LastBackup | ||||||
|  | 
 | ||||||
|  | 	if jenkins.Spec.Restore.GetLatestAction.Exec != nil { | ||||||
|  | 		command := jenkins.Spec.Restore.GetLatestAction.Exec.Command | ||||||
|  | 		backupNumberRaw, _, err := bar.Exec(podName, jenkins.Spec.Restore.ContainerName, command) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		backupNumberString := strings.TrimSuffix(backupNumberRaw.String(), "\n") | ||||||
|  | 		if backupNumberString == noBackup { | ||||||
|  | 			bar.logger.V(log.VDebug).Info("Skipping restore backup, get latest action returned -1") | ||||||
|  | 			jenkins.Status.LastBackup = 0 | ||||||
|  | 			jenkins.Status.PendingBackup = 1 | ||||||
|  | 			return bar.Client.Update(context.TODO(), jenkins) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		backupNumber, err = strconv.ParseUint(backupNumberString, 10, 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return errors.Wrapf(err, "invalid backup number '%s' returned by get last backup number action", backupNumberString) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if backupNumber < 1 { | ||||||
|  | 			return errors.Errorf("invalid backup number '%d' returned by get last backup number action", backupNumber) | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		bar.logger.V(log.VWarn).Info("spec.restore.getLatestAction not set, you may loose backup history when Jenkins CR status will be clear") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if jenkins.Spec.Restore.RecoveryOnce != 0 { | 	if jenkins.Spec.Restore.RecoveryOnce != 0 { | ||||||
| 		backupNumber = jenkins.Spec.Restore.RecoveryOnce | 		backupNumber = jenkins.Spec.Restore.RecoveryOnce | ||||||
| 	} else { |  | ||||||
| 		backupNumber = jenkins.Status.LastBackup |  | ||||||
| 	} | 	} | ||||||
| 	bar.logger.Info(fmt.Sprintf("Restoring backup '%d'", backupNumber)) | 	bar.logger.Info(fmt.Sprintf("Restoring backup '%d'", backupNumber)) | ||||||
| 	podName := resources.GetJenkinsMasterPodName(jenkins) |  | ||||||
| 	command := jenkins.Spec.Restore.Action.Exec.Command | 	command := jenkins.Spec.Restore.Action.Exec.Command | ||||||
| 	command = append(command, fmt.Sprintf("%d", backupNumber)) | 	command = append(command, fmt.Sprintf("%d", backupNumber)) | ||||||
| 	_, _, err := bar.Exec(podName, jenkins.Spec.Restore.ContainerName, command) | 	_, _, err := bar.Exec(podName, jenkins.Spec.Restore.ContainerName, command) | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createInitConfigurationConfigMap(met | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r *ReconcileJenkinsBaseConfiguration) createBaseConfigurationConfigMap(meta metav1.ObjectMeta) error { | func (r *ReconcileJenkinsBaseConfiguration) createBaseConfigurationConfigMap(meta metav1.ObjectMeta) error { | ||||||
| 	configMap, err := resources.NewBaseConfigurationConfigMap(meta, r.Configuration.Jenkins) | 	configMap, err := resources.NewBaseConfigurationConfigMap(meta, r.Configuration.Jenkins, r.KubernetesClusterDomain) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -126,7 +126,7 @@ if (kubernetes == null) { | ||||||
|     add = true |     add = true | ||||||
| 	kubernetes = new KubernetesCloud("kubernetes") | 	kubernetes = new KubernetesCloud("kubernetes") | ||||||
| } | } | ||||||
| kubernetes.setServerUrl("https://kubernetes.default.svc.cluster.local:443") | kubernetes.setServerUrl("https://kubernetes.default.svc.%s:443") | ||||||
| kubernetes.setNamespace("%s") | kubernetes.setNamespace("%s") | ||||||
| kubernetes.setJenkinsUrl("%s") | kubernetes.setJenkinsUrl("%s") | ||||||
| kubernetes.setJenkinsTunnel("%s") | kubernetes.setJenkinsTunnel("%s") | ||||||
|  | @ -178,16 +178,24 @@ func GetBaseConfigurationConfigMapName(jenkins *v1alpha2.Jenkins) string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewBaseConfigurationConfigMap builds Kubernetes config map used to base configuration.
 | // NewBaseConfigurationConfigMap builds Kubernetes config map used to base configuration.
 | ||||||
| func NewBaseConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *v1alpha2.Jenkins) (*corev1.ConfigMap, error) { | func NewBaseConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *v1alpha2.Jenkins, kubernetesClusterDomain string) (*corev1.ConfigMap, error) { | ||||||
| 	meta.Name = GetBaseConfigurationConfigMapName(jenkins) | 	meta.Name = GetBaseConfigurationConfigMapName(jenkins) | ||||||
| 	jenkinsServiceFQDN, err := GetJenkinsHTTPServiceFQDN(jenkins) | 	clusterDomain, err := getClusterDomain(kubernetesClusterDomain) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	jenkinsSlavesServiceFQDN, err := GetJenkinsSlavesServiceFQDN(jenkins) | 	jenkinsServiceFQDN, err := GetJenkinsHTTPServiceFQDN(jenkins, kubernetesClusterDomain) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | 	jenkinsSlavesServiceFQDN, err := GetJenkinsSlavesServiceFQDN(jenkins, kubernetesClusterDomain) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	suffix := "" | ||||||
|  | 	if prefix, ok := GetJenkinsOpts(*jenkins)["prefix"]; ok { | ||||||
|  | 		suffix = prefix | ||||||
|  | 	} | ||||||
| 	groovyScriptsMap := map[string]string{ | 	groovyScriptsMap := map[string]string{ | ||||||
| 		basicSettingsGroovyScriptName:             fmt.Sprintf(basicSettingsFmt, constants.DefaultAmountOfExecutors), | 		basicSettingsGroovyScriptName:             fmt.Sprintf(basicSettingsFmt, constants.DefaultAmountOfExecutors), | ||||||
| 		enableCSRFGroovyScriptName:                enableCSRF, | 		enableCSRFGroovyScriptName:                enableCSRF, | ||||||
|  | @ -195,13 +203,15 @@ func NewBaseConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *v1alpha2.Jen | ||||||
| 		enableMasterAccessControlGroovyScriptName: enableMasterAccessControl, | 		enableMasterAccessControlGroovyScriptName: enableMasterAccessControl, | ||||||
| 		disableInsecureFeaturesGroovyScriptName:   disableInsecureFeatures, | 		disableInsecureFeaturesGroovyScriptName:   disableInsecureFeatures, | ||||||
| 		configureKubernetesPluginGroovyScriptName: fmt.Sprintf(configureKubernetesPluginFmt, | 		configureKubernetesPluginGroovyScriptName: fmt.Sprintf(configureKubernetesPluginFmt, | ||||||
|  | 			clusterDomain, | ||||||
| 			jenkins.ObjectMeta.Namespace, | 			jenkins.ObjectMeta.Namespace, | ||||||
| 			fmt.Sprintf("http://%s:%d", jenkinsServiceFQDN, jenkins.Spec.Service.Port), | 			fmt.Sprintf("http://%s:%d%s", jenkinsServiceFQDN, jenkins.Spec.Service.Port, suffix), | ||||||
| 			fmt.Sprintf("%s:%d", jenkinsSlavesServiceFQDN, jenkins.Spec.SlaveService.Port), | 			fmt.Sprintf("%s:%d", jenkinsSlavesServiceFQDN, jenkins.Spec.SlaveService.Port), | ||||||
| 		), | 		), | ||||||
| 		configureViewsGroovyScriptName:              configureViews, | 		configureViewsGroovyScriptName:              configureViews, | ||||||
| 		disableJobDslScriptApprovalGroovyScriptName: disableJobDSLScriptApproval, | 		disableJobDslScriptApprovalGroovyScriptName: disableJobDSLScriptApproval, | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	if jenkins.Spec.Master.DisableCSRFProtection { | 	if jenkins.Spec.Master.DisableCSRFProtection { | ||||||
| 		delete(groovyScriptsMap, enableCSRFGroovyScriptName) | 		delete(groovyScriptsMap, enableCSRFGroovyScriptName) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ package resources | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" | 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/constants" | 	"github.com/jenkinsci/kubernetes-operator/pkg/constants" | ||||||
|  | @ -16,7 +17,7 @@ const ( | ||||||
| 	// JenkinsHomeVolumeName is the Jenkins home volume name
 | 	// JenkinsHomeVolumeName is the Jenkins home volume name
 | ||||||
| 	JenkinsHomeVolumeName    = "jenkins-home" | 	JenkinsHomeVolumeName    = "jenkins-home" | ||||||
| 	jenkinsPath              = "/var/jenkins" | 	jenkinsPath              = "/var/jenkins" | ||||||
| 
 | 	httpGetPath              = "/login" | ||||||
| 	jenkinsScriptsVolumeName = "scripts" | 	jenkinsScriptsVolumeName = "scripts" | ||||||
| 	// JenkinsScriptsVolumePath is a path where are scripts used to configure Jenkins
 | 	// JenkinsScriptsVolumePath is a path where are scripts used to configure Jenkins
 | ||||||
| 	JenkinsScriptsVolumePath = jenkinsPath + "/scripts" | 	JenkinsScriptsVolumePath = jenkinsPath + "/scripts" | ||||||
|  | @ -233,6 +234,8 @@ func NewJenkinsMasterContainer(jenkins *v1alpha2.Jenkins) corev1.Container { | ||||||
| 		envs = append(envs, jenkinsHomeEnvVar) | 		envs = append(envs, jenkinsHomeEnvVar) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	setLivenessAndReadinessPath(jenkins) | ||||||
|  | 
 | ||||||
| 	return corev1.Container{ | 	return corev1.Container{ | ||||||
| 		Name:            JenkinsMasterContainerName, | 		Name:            JenkinsMasterContainerName, | ||||||
| 		Image:           jenkinsContainer.Image, | 		Image:           jenkinsContainer.Image, | ||||||
|  | @ -259,6 +262,53 @@ func NewJenkinsMasterContainer(jenkins *v1alpha2.Jenkins) corev1.Container { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func setLivenessAndReadinessPath(jenkins *v1alpha2.Jenkins) { | ||||||
|  | 	ReadinessProbePath := jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path | ||||||
|  | 	LivenessProbePath := jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path | ||||||
|  | 
 | ||||||
|  | 	if prefix, ok := GetJenkinsOpts(*jenkins)["prefix"]; ok { | ||||||
|  | 		if !strings.HasPrefix(ReadinessProbePath, prefix) { | ||||||
|  | 			jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path = prefix + httpGetPath | ||||||
|  | 		} | ||||||
|  | 		if !strings.HasPrefix(LivenessProbePath, prefix) { | ||||||
|  | 			jenkins.Spec.Master.Containers[0].LivenessProbe.HTTPGet.Path = prefix + httpGetPath | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if ReadinessProbePath != httpGetPath { | ||||||
|  | 			jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path = httpGetPath | ||||||
|  | 		} | ||||||
|  | 		if LivenessProbePath != httpGetPath { | ||||||
|  | 			jenkins.Spec.Master.Containers[0].LivenessProbe.HTTPGet.Path = httpGetPath | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetJenkinsOpts gets JENKINS_OPTS env parameter, parses it's values and returns it as a map`
 | ||||||
|  | func GetJenkinsOpts(jenkins v1alpha2.Jenkins) map[string]string { | ||||||
|  | 	envs := jenkins.Spec.Master.Containers[0].Env | ||||||
|  | 	jenkinsOpts := make(map[string]string) | ||||||
|  | 
 | ||||||
|  | 	for key, value := range envs { | ||||||
|  | 		if value.Name == "JENKINS_OPTS" { | ||||||
|  | 			jenkinsOptsEnv := envs[key] | ||||||
|  | 			jenkinsOptsWithDashes := jenkinsOptsEnv.Value | ||||||
|  | 			if len(jenkinsOptsWithDashes) == 0 { | ||||||
|  | 				return nil | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			jenkinsOptsWithEqOperators := strings.Split(jenkinsOptsWithDashes, " ") | ||||||
|  | 
 | ||||||
|  | 			for _, vx := range jenkinsOptsWithEqOperators { | ||||||
|  | 				opt := strings.Split(vx, "=") | ||||||
|  | 				jenkinsOpts[strings.ReplaceAll(opt[0], "--", "")] = opt[1] | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return jenkinsOpts | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // ConvertJenkinsContainerToKubernetesContainer converts Jenkins container to Kubernetes container
 | // ConvertJenkinsContainerToKubernetesContainer converts Jenkins container to Kubernetes container
 | ||||||
| func ConvertJenkinsContainerToKubernetesContainer(container v1alpha2.Container) corev1.Container { | func ConvertJenkinsContainerToKubernetesContainer(container v1alpha2.Container) corev1.Container { | ||||||
| 	return corev1.Container{ | 	return corev1.Container{ | ||||||
|  |  | ||||||
|  | @ -0,0 +1,229 @@ | ||||||
|  | package resources | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 
 | ||||||
|  | 	corev1 "k8s.io/api/core/v1" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var jenkins = v1alpha2.Jenkins{ | ||||||
|  | 	Spec: v1alpha2.JenkinsSpec{ | ||||||
|  | 		Master: v1alpha2.JenkinsMaster{ | ||||||
|  | 			Containers: []v1alpha2.Container{ | ||||||
|  | 				{ | ||||||
|  | 					Env: []corev1.EnvVar{}, | ||||||
|  | 					ReadinessProbe: &corev1.Probe{ | ||||||
|  | 						Handler: corev1.Handler{ | ||||||
|  | 							HTTPGet: &corev1.HTTPGetAction{}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 					LivenessProbe: &corev1.Probe{ | ||||||
|  | 						Handler: corev1.Handler{ | ||||||
|  | 							HTTPGet: &corev1.HTTPGetAction{}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestGetJenkinsOpts(t *testing.T) { | ||||||
|  | 	t.Run("JENKINS_OPTS is uninitialized", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "", Value: ""}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		opts := GetJenkinsOpts(jenkins) | ||||||
|  | 		assert.Equal(t, 0, len(opts)) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS is empty", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "JENKINS_OPTS", Value: ""}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		opts := GetJenkinsOpts(jenkins) | ||||||
|  | 		assert.Equal(t, 0, len(opts)) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS have --prefix argument ", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins"}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		opts := GetJenkinsOpts(jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, 1, len(opts)) | ||||||
|  | 		assert.NotContains(t, opts, "httpPort") | ||||||
|  | 		assert.Contains(t, opts, "prefix") | ||||||
|  | 		assert.Equal(t, opts["prefix"], "/jenkins") | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS have --prefix and --httpPort argument", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins --httpPort=8080"}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		opts := GetJenkinsOpts(jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, 2, len(opts)) | ||||||
|  | 
 | ||||||
|  | 		assert.Contains(t, opts, "prefix") | ||||||
|  | 		assert.Equal(t, opts["prefix"], "/jenkins") | ||||||
|  | 
 | ||||||
|  | 		assert.Contains(t, opts, "httpPort") | ||||||
|  | 		assert.Equal(t, opts["httpPort"], "8080") | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS have --httpPort argument", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "JENKINS_OPTS", Value: "--httpPort=8080"}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		opts := GetJenkinsOpts(jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, 1, len(opts)) | ||||||
|  | 		assert.NotContains(t, opts, "prefix") | ||||||
|  | 		assert.Contains(t, opts, "httpPort") | ||||||
|  | 		assert.Equal(t, opts["httpPort"], "8080") | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS have --httpPort=--8080 argument", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "JENKINS_OPTS", Value: "--httpPort=--8080"}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		opts := GetJenkinsOpts(jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, 1, len(opts)) | ||||||
|  | 		assert.NotContains(t, opts, "prefix") | ||||||
|  | 		assert.Contains(t, opts, "httpPort") | ||||||
|  | 		assert.Equal(t, opts["httpPort"], "--8080") | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestSetLivenessAndReadinessPath(t *testing.T) { | ||||||
|  | 	t.Run("JENKINS_OPTS uninitialized. Probes' paths default.", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = []corev1.EnvVar{} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].ReadinessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].LivenessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		setLivenessAndReadinessPath(&jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, httpGetPath, jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path) | ||||||
|  | 		assert.Equal(t, httpGetPath, jenkins.Spec.Master.Containers[0].LivenessProbe.HTTPGet.Path) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS initialized. Probes' paths default", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins"}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].ReadinessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].LivenessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		setLivenessAndReadinessPath(&jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, "/jenkins/login", jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path) | ||||||
|  | 		assert.Equal(t, "/jenkins/login", jenkins.Spec.Master.Containers[0].LivenessProbe.HTTPGet.Path) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS initialized. Probes' paths customized", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = | ||||||
|  | 			[]corev1.EnvVar{ | ||||||
|  | 				{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins"}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].ReadinessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/jenkins/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].LivenessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/jenkins/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		setLivenessAndReadinessPath(&jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, "/jenkins/login", jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path) | ||||||
|  | 		assert.Equal(t, "/jenkins/login", jenkins.Spec.Master.Containers[0].LivenessProbe.HTTPGet.Path) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("JENKINS_OPTS uninitialized. Probes' paths customized", func(t *testing.T) { | ||||||
|  | 		jenkins.Spec.Master.Containers[0].Env = []corev1.EnvVar{} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].ReadinessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/jenkins/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		jenkins.Spec.Master.Containers[0].LivenessProbe = | ||||||
|  | 			&corev1.Probe{ | ||||||
|  | 				Handler: corev1.Handler{ | ||||||
|  | 					HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 						Path: "/jenkins/login", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		setLivenessAndReadinessPath(&jenkins) | ||||||
|  | 
 | ||||||
|  | 		assert.Equal(t, "/login", jenkins.Spec.Master.Containers[0].ReadinessProbe.HTTPGet.Path) | ||||||
|  | 		assert.Equal(t, "/login", jenkins.Spec.Master.Containers[0].LivenessProbe.HTTPGet.Path) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | @ -50,8 +50,8 @@ func GetJenkinsSlavesServiceName(jenkins *v1alpha2.Jenkins) string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetJenkinsHTTPServiceFQDN returns Kubernetes service FQDN used for expose Jenkins HTTP endpoint
 | // GetJenkinsHTTPServiceFQDN returns Kubernetes service FQDN used for expose Jenkins HTTP endpoint
 | ||||||
| func GetJenkinsHTTPServiceFQDN(jenkins *v1alpha2.Jenkins) (string, error) { | func GetJenkinsHTTPServiceFQDN(jenkins *v1alpha2.Jenkins, kubernetesClusterDomain string) (string, error) { | ||||||
| 	clusterDomain, err := getClusterDomain() | 	clusterDomain, err := getClusterDomain(kubernetesClusterDomain) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  | @ -60,8 +60,8 @@ func GetJenkinsHTTPServiceFQDN(jenkins *v1alpha2.Jenkins) (string, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetJenkinsSlavesServiceFQDN returns Kubernetes service FQDN used for expose Jenkins slave endpoint
 | // GetJenkinsSlavesServiceFQDN returns Kubernetes service FQDN used for expose Jenkins slave endpoint
 | ||||||
| func GetJenkinsSlavesServiceFQDN(jenkins *v1alpha2.Jenkins) (string, error) { | func GetJenkinsSlavesServiceFQDN(jenkins *v1alpha2.Jenkins, kubernetesClusterDomain string) (string, error) { | ||||||
| 	clusterDomain, err := getClusterDomain() | 	clusterDomain, err := getClusterDomain(kubernetesClusterDomain) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  | @ -70,12 +70,12 @@ func GetJenkinsSlavesServiceFQDN(jenkins *v1alpha2.Jenkins) (string, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // GetClusterDomain returns Kubernetes cluster domain, default to "cluster.local"
 | // GetClusterDomain returns Kubernetes cluster domain, default to "cluster.local"
 | ||||||
| func getClusterDomain() (string, error) { | func getClusterDomain(kubernetesClusterDomain string) (string, error) { | ||||||
| 	clusterDomain := "cluster.local" | 	isRunningInCluster, err := isRunningInCluster() | ||||||
| 
 | 	if !isRunningInCluster { | ||||||
| 	if ok, err := isRunningInCluster(); !ok { | 		return kubernetesClusterDomain, nil | ||||||
| 		return clusterDomain, nil | 	} | ||||||
| 	} else if err != nil { | 	if err != nil { | ||||||
| 		return "", nil | 		return "", nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -86,11 +86,11 @@ func getClusterDomain() (string, error) { | ||||||
| 		return "", stackerr.WithStack(err) | 		return "", stackerr.WithStack(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	clusterDomain = strings.TrimPrefix(cname, "kubernetes.default.svc") | 	kubernetesClusterDomain = strings.TrimPrefix(cname, "kubernetes.default.svc") | ||||||
| 	clusterDomain = strings.TrimPrefix(clusterDomain, ".") | 	kubernetesClusterDomain = strings.TrimPrefix(kubernetesClusterDomain, ".") | ||||||
| 	clusterDomain = strings.TrimSuffix(clusterDomain, ".") | 	kubernetesClusterDomain = strings.TrimSuffix(kubernetesClusterDomain, ".") | ||||||
| 
 | 
 | ||||||
| 	return clusterDomain, nil | 	return kubernetesClusterDomain, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func isRunningInCluster() (bool, error) { | func isRunningInCluster() (bool, error) { | ||||||
|  | @ -99,7 +99,7 @@ func isRunningInCluster() (bool, error) { | ||||||
| 		if err == k8sutil.ErrNoNamespace || err == k8sutil.ErrRunLocal { | 		if err == k8sutil.ErrNoNamespace || err == k8sutil.ErrRunLocal { | ||||||
| 			return false, nil | 			return false, nil | ||||||
| 		} | 		} | ||||||
| 		return true, nil |  | ||||||
| 	} |  | ||||||
| 		return false, stackerr.WithStack(err) | 		return false, stackerr.WithStack(err) | ||||||
| 	} | 	} | ||||||
|  | 	return true, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -36,6 +36,7 @@ type Configuration struct { | ||||||
| 	Scheme                       *runtime.Scheme | 	Scheme                       *runtime.Scheme | ||||||
| 	Config                       *rest.Config | 	Config                       *rest.Config | ||||||
| 	JenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings | 	JenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings | ||||||
|  | 	KubernetesClusterDomain      string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RestartJenkinsMasterPod terminate Jenkins master pod and notifies about it.
 | // RestartJenkinsMasterPod terminate Jenkins master pod and notifies about it.
 | ||||||
|  |  | ||||||
|  | @ -1,144 +0,0 @@ | ||||||
| package configuration |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"testing" |  | ||||||
| 
 |  | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" |  | ||||||
| 	"github.com/stretchr/testify/assert" |  | ||||||
| 	corev1 "k8s.io/api/core/v1" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func TestGetJenkinsOpts(t *testing.T) { |  | ||||||
| 	t.Run("JENKINS_OPTS is uninitialized", func(t *testing.T) { |  | ||||||
| 		jenkins := v1alpha2.Jenkins{ |  | ||||||
| 			Spec: v1alpha2.JenkinsSpec{ |  | ||||||
| 				Master: v1alpha2.JenkinsMaster{ |  | ||||||
| 					Containers: []v1alpha2.Container{ |  | ||||||
| 						{ |  | ||||||
| 							Env: []corev1.EnvVar{ |  | ||||||
| 								{Name: "", Value: ""}, |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		opts := GetJenkinsOpts(jenkins) |  | ||||||
| 		assert.Equal(t, 0, len(opts)) |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	t.Run("JENKINS_OPTS is empty", func(t *testing.T) { |  | ||||||
| 		jenkins := v1alpha2.Jenkins{ |  | ||||||
| 			Spec: v1alpha2.JenkinsSpec{ |  | ||||||
| 				Master: v1alpha2.JenkinsMaster{ |  | ||||||
| 					Containers: []v1alpha2.Container{ |  | ||||||
| 						{ |  | ||||||
| 							Env: []corev1.EnvVar{ |  | ||||||
| 								{Name: "JENKINS_OPTS", Value: ""}, |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		opts := GetJenkinsOpts(jenkins) |  | ||||||
| 		assert.Equal(t, 0, len(opts)) |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	t.Run("JENKINS_OPTS have --prefix argument ", func(t *testing.T) { |  | ||||||
| 		jenkins := v1alpha2.Jenkins{ |  | ||||||
| 			Spec: v1alpha2.JenkinsSpec{ |  | ||||||
| 				Master: v1alpha2.JenkinsMaster{ |  | ||||||
| 					Containers: []v1alpha2.Container{ |  | ||||||
| 						{ |  | ||||||
| 							Env: []corev1.EnvVar{ |  | ||||||
| 								{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins"}, |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		opts := GetJenkinsOpts(jenkins) |  | ||||||
| 
 |  | ||||||
| 		assert.Equal(t, 1, len(opts)) |  | ||||||
| 		assert.NotContains(t, opts, "httpPort") |  | ||||||
| 		assert.Contains(t, opts, "prefix") |  | ||||||
| 		assert.Equal(t, opts["prefix"], "/jenkins") |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	t.Run("JENKINS_OPTS have --prefix and --httpPort argument", func(t *testing.T) { |  | ||||||
| 		jenkins := v1alpha2.Jenkins{ |  | ||||||
| 			Spec: v1alpha2.JenkinsSpec{ |  | ||||||
| 				Master: v1alpha2.JenkinsMaster{ |  | ||||||
| 					Containers: []v1alpha2.Container{ |  | ||||||
| 						{ |  | ||||||
| 							Env: []corev1.EnvVar{ |  | ||||||
| 								{Name: "JENKINS_OPTS", Value: "--prefix=/jenkins --httpPort=8080"}, |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		opts := GetJenkinsOpts(jenkins) |  | ||||||
| 
 |  | ||||||
| 		assert.Equal(t, 2, len(opts)) |  | ||||||
| 
 |  | ||||||
| 		assert.Contains(t, opts, "prefix") |  | ||||||
| 		assert.Equal(t, opts["prefix"], "/jenkins") |  | ||||||
| 
 |  | ||||||
| 		assert.Contains(t, opts, "httpPort") |  | ||||||
| 		assert.Equal(t, opts["httpPort"], "8080") |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	t.Run("JENKINS_OPTS have --httpPort argument", func(t *testing.T) { |  | ||||||
| 		jenkins := v1alpha2.Jenkins{ |  | ||||||
| 			Spec: v1alpha2.JenkinsSpec{ |  | ||||||
| 				Master: v1alpha2.JenkinsMaster{ |  | ||||||
| 					Containers: []v1alpha2.Container{ |  | ||||||
| 						{ |  | ||||||
| 							Env: []corev1.EnvVar{ |  | ||||||
| 								{Name: "JENKINS_OPTS", Value: "--httpPort=8080"}, |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		opts := GetJenkinsOpts(jenkins) |  | ||||||
| 
 |  | ||||||
| 		assert.Equal(t, 1, len(opts)) |  | ||||||
| 		assert.NotContains(t, opts, "prefix") |  | ||||||
| 		assert.Contains(t, opts, "httpPort") |  | ||||||
| 		assert.Equal(t, opts["httpPort"], "8080") |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	t.Run("JENKINS_OPTS have --httpPort=--8080 argument", func(t *testing.T) { |  | ||||||
| 		jenkins := v1alpha2.Jenkins{ |  | ||||||
| 			Spec: v1alpha2.JenkinsSpec{ |  | ||||||
| 				Master: v1alpha2.JenkinsMaster{ |  | ||||||
| 					Containers: []v1alpha2.Container{ |  | ||||||
| 						{ |  | ||||||
| 							Env: []corev1.EnvVar{ |  | ||||||
| 								{Name: "JENKINS_OPTS", Value: "--httpPort=--8080"}, |  | ||||||
| 							}, |  | ||||||
| 						}, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		opts := GetJenkinsOpts(jenkins) |  | ||||||
| 
 |  | ||||||
| 		assert.Equal(t, 1, len(opts)) |  | ||||||
| 		assert.NotContains(t, opts, "prefix") |  | ||||||
| 		assert.Contains(t, opts, "httpPort") |  | ||||||
| 		assert.Equal(t, opts["httpPort"], "--8080") |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
|  | @ -370,7 +370,7 @@ func (s *seedJobs) createAgent(jenkinsClient jenkinsclient.Jenkins, k8sClient cl | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	deployment, err := agentDeployment(jenkinsManifest, namespace, agentName, secret) | 	deployment, err := agentDeployment(jenkinsManifest, namespace, agentName, secret, s.KubernetesClusterDomain) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | @ -392,15 +392,20 @@ func agentDeploymentName(jenkins v1alpha2.Jenkins, agentName string) string { | ||||||
| 	return fmt.Sprintf("%s-%s", agentName, jenkins.Name) | 	return fmt.Sprintf("%s-%s", agentName, jenkins.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func agentDeployment(jenkins *v1alpha2.Jenkins, namespace string, agentName string, secret string) (*appsv1.Deployment, error) { | func agentDeployment(jenkins *v1alpha2.Jenkins, namespace string, agentName string, secret string, kubernetesDomainName string) (*appsv1.Deployment, error) { | ||||||
| 	jenkinsSlavesServiceFQDN, err := resources.GetJenkinsSlavesServiceFQDN(jenkins) | 	jenkinsSlavesServiceFQDN, err := resources.GetJenkinsSlavesServiceFQDN(jenkins, kubernetesDomainName) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	jenkinsHTTPServiceFQDN, err := resources.GetJenkinsHTTPServiceFQDN(jenkins) | 	jenkinsHTTPServiceFQDN, err := resources.GetJenkinsHTTPServiceFQDN(jenkins, kubernetesDomainName) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	suffix := "" | ||||||
|  | 	if prefix, ok := resources.GetJenkinsOpts(*jenkins)["prefix"]; ok { | ||||||
|  | 		suffix = prefix | ||||||
|  | 	} | ||||||
| 	return &appsv1.Deployment{ | 	return &appsv1.Deployment{ | ||||||
| 		ObjectMeta: metav1.ObjectMeta{ | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
| 			Name:      agentDeploymentName(*jenkins, agentName), | 			Name:      agentDeploymentName(*jenkins, agentName), | ||||||
|  | @ -443,10 +448,10 @@ func agentDeployment(jenkins *v1alpha2.Jenkins, namespace string, agentName stri | ||||||
| 								}, | 								}, | ||||||
| 								{ | 								{ | ||||||
| 									Name: "JENKINS_URL", | 									Name: "JENKINS_URL", | ||||||
| 									Value: fmt.Sprintf("http://%s:%d", | 									Value: fmt.Sprintf("http://%s:%d%s", | ||||||
| 										jenkinsHTTPServiceFQDN, | 										jenkinsHTTPServiceFQDN, | ||||||
| 										jenkins.Spec.Service.Port, | 										jenkins.Spec.Service.Port, | ||||||
| 									), | 										suffix), | ||||||
| 								}, | 								}, | ||||||
| 								{ | 								{ | ||||||
| 									Name:  "JENKINS_AGENT_WORKDIR", | 									Name:  "JENKINS_AGENT_WORKDIR", | ||||||
|  |  | ||||||
|  | @ -50,8 +50,8 @@ var _ reconcile.Reconciler = &ReconcileJenkins{} | ||||||
| 
 | 
 | ||||||
| // Add creates a newReconcilierConfiguration Jenkins Controller and adds it to the Manager. The Manager will set fields on the Controller
 | // Add creates a newReconcilierConfiguration Jenkins Controller and adds it to the Manager. The Manager will set fields on the Controller
 | ||||||
| // and Start it when the Manager is Started.
 | // and Start it when the Manager is Started.
 | ||||||
| func Add(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) error { | func Add(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, kubernetesClusterDomain string, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) error { | ||||||
| 	reconciler := newReconciler(mgr, jenkinsAPIConnectionSettings, clientSet, config, notificationEvents) | 	reconciler := newReconciler(mgr, jenkinsAPIConnectionSettings, kubernetesClusterDomain, clientSet, config, notificationEvents) | ||||||
| 	return add(mgr, reconciler) | 	return add(mgr, reconciler) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ type ReconcileJenkins struct { | ||||||
| 	clientSet                    kubernetes.Clientset | 	clientSet                    kubernetes.Clientset | ||||||
| 	config                       rest.Config | 	config                       rest.Config | ||||||
| 	notificationEvents           *chan event.Event | 	notificationEvents           *chan event.Event | ||||||
|  | 	KubernetesClusterDomain      string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r *ReconcileJenkins) newReconcilierConfiguration(jenkins *v1alpha2.Jenkins) configuration.Configuration { | func (r *ReconcileJenkins) newReconcilierConfiguration(jenkins *v1alpha2.Jenkins) configuration.Configuration { | ||||||
|  | @ -32,12 +33,13 @@ func (r *ReconcileJenkins) newReconcilierConfiguration(jenkins *v1alpha2.Jenkins | ||||||
| 		Scheme:                       r.scheme, | 		Scheme:                       r.scheme, | ||||||
| 		Config:                       &r.config, | 		Config:                       &r.config, | ||||||
| 		JenkinsAPIConnectionSettings: r.jenkinsAPIConnectionSettings, | 		JenkinsAPIConnectionSettings: r.jenkinsAPIConnectionSettings, | ||||||
|  | 		KubernetesClusterDomain:      r.KubernetesClusterDomain, | ||||||
| 	} | 	} | ||||||
| 	return config | 	return config | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // newReconciler returns a newReconcilierConfiguration reconcile.Reconciler.
 | // newReconciler returns a newReconcilierConfiguration reconcile.Reconciler.
 | ||||||
| func newReconciler(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) reconcile.Reconciler { | func newReconciler(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclient.JenkinsAPIConnectionSettings, kubernetesClusterDomain string, clientSet kubernetes.Clientset, config rest.Config, notificationEvents *chan event.Event) reconcile.Reconciler { | ||||||
| 	return &ReconcileJenkins{ | 	return &ReconcileJenkins{ | ||||||
| 		client:                       mgr.GetClient(), | 		client:                       mgr.GetClient(), | ||||||
| 		scheme:                       mgr.GetScheme(), | 		scheme:                       mgr.GetScheme(), | ||||||
|  | @ -45,5 +47,6 @@ func newReconciler(mgr manager.Manager, jenkinsAPIConnectionSettings jenkinsclie | ||||||
| 		clientSet:                    clientSet, | 		clientSet:                    clientSet, | ||||||
| 		config:                       config, | 		config:                       config, | ||||||
| 		notificationEvents:           notificationEvents, | 		notificationEvents:           notificationEvents, | ||||||
|  | 		KubernetesClusterDomain:      kubernetesClusterDomain, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,13 +1,13 @@ | ||||||
| package plugins | package plugins | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	configurationAsCodePlugin           = "configuration-as-code:1.38" | 	configurationAsCodePlugin           = "configuration-as-code:1.46" | ||||||
| 	gitPlugin                           = "git:4.2.2" | 	gitPlugin                           = "git:4.4.5" | ||||||
| 	jobDslPlugin                        = "job-dsl:1.77" | 	jobDslPlugin                        = "job-dsl:1.77" | ||||||
| 	kubernetesCredentialsProviderPlugin = "kubernetes-credentials-provider:0.13" | 	kubernetesCredentialsProviderPlugin = "kubernetes-credentials-provider:0.15" | ||||||
| 	kubernetesPlugin                    = "kubernetes:1.25.2" | 	kubernetesPlugin                    = "kubernetes:1.27.6" | ||||||
| 	workflowAggregatorPlugin            = "workflow-aggregator:2.6" | 	workflowAggregatorPlugin            = "workflow-aggregator:2.6" | ||||||
| 	workflowJobPlugin                   = "workflow-job:2.39" | 	workflowJobPlugin                   = "workflow-job:2.40" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // basePluginsList contains plugins to install by operator.
 | // basePluginsList contains plugins to install by operator.
 | ||||||
|  |  | ||||||
|  | @ -137,8 +137,8 @@ func TestPlugins(t *testing.T) { | ||||||
| 	require.NoError(t, err, job) | 	require.NoError(t, err, job) | ||||||
| 	i, err := job.InvokeSimple(map[string]string{}) | 	i, err := job.InvokeSimple(map[string]string{}) | ||||||
| 	require.NoError(t, err, i) | 	require.NoError(t, err, i) | ||||||
| 
 | 	// FIXME: waitForJobToFinish use
 | ||||||
| 	waitForJobToFinish(t, job, 2*time.Second, 2*time.Minute) | 	time.Sleep(80 * time.Second) // wait for the build to complete
 | ||||||
| 
 | 
 | ||||||
| 	job, err = jenkinsClient.GetJob(jobID) | 	job, err = jenkinsClient.GetJob(jobID) | ||||||
| 	require.NoError(t, err, job) | 	require.NoError(t, err, job) | ||||||
|  |  | ||||||
|  | @ -116,10 +116,10 @@ func createJenkinsCR(t *testing.T, name, namespace string, seedJob *[]v1alpha2.S | ||||||
| 					}, | 					}, | ||||||
| 				}, | 				}, | ||||||
| 				Plugins: []v1alpha2.Plugin{ | 				Plugins: []v1alpha2.Plugin{ | ||||||
| 					{Name: "audit-trail", Version: "2.4"}, | 					{Name: "audit-trail", Version: "3.7"}, | ||||||
| 					{Name: "simple-theme-plugin", Version: "0.5.1"}, | 					{Name: "simple-theme-plugin", Version: "0.6"}, | ||||||
| 					{Name: "github", Version: "1.29.4"}, | 					{Name: "github", Version: "1.32.0"}, | ||||||
| 					{Name: "devoptics", Version: "1.1863", DownloadURL: "https://jenkins-updates.cloudbees.com/download/plugins/devoptics/1.1863/devoptics.hpi"}, | 					{Name: "devoptics", Version: "1.1905", DownloadURL: "https://jenkins-updates.cloudbees.com/download/plugins/devoptics/1.1905/devoptics.hpi"}, | ||||||
| 				}, | 				}, | ||||||
| 				PriorityClassName: priorityClassName, | 				PriorityClassName: priorityClassName, | ||||||
| 				NodeSelector:      map[string]string{"kubernetes.io/os": "linux"}, | 				NodeSelector:      map[string]string{"kubernetes.io/os": "linux"}, | ||||||
|  |  | ||||||
|  | @ -42,13 +42,24 @@ func TestBackupAndRestore(t *testing.T) { | ||||||
| 	// FIXME: waitForJobToFinish use
 | 	// FIXME: waitForJobToFinish use
 | ||||||
| 	time.Sleep(60 * time.Second) // wait for the build to complete
 | 	time.Sleep(60 * time.Second) // wait for the build to complete
 | ||||||
| 
 | 
 | ||||||
|  | 	jenkins = getJenkins(t, jenkins.Namespace, jenkins.Name) | ||||||
|  | 	lastDoneBackup := jenkins.Status.LastBackup | ||||||
| 	restartJenkinsMasterPod(t, jenkins) | 	restartJenkinsMasterPod(t, jenkins) | ||||||
| 	waitForRecreateJenkinsMasterPod(t, jenkins) | 	waitForRecreateJenkinsMasterPod(t, jenkins) | ||||||
| 	waitForJenkinsUserConfigurationToComplete(t, jenkins) | 	waitForJenkinsUserConfigurationToComplete(t, jenkins) | ||||||
|  | 	jenkins = getJenkins(t, jenkins.Namespace, jenkins.Name) | ||||||
|  | 	assert.Equal(t, lastDoneBackup, jenkins.Status.RestoredBackup) | ||||||
| 	jenkinsClient2, cleanUpFunc2 := verifyJenkinsAPIConnection(t, jenkins, namespace) | 	jenkinsClient2, cleanUpFunc2 := verifyJenkinsAPIConnection(t, jenkins, namespace) | ||||||
| 	defer cleanUpFunc2() | 	defer cleanUpFunc2() | ||||||
| 	waitForJob(t, jenkinsClient2, jobID) | 	waitForJob(t, jenkinsClient2, jobID) | ||||||
| 	verifyJobBuildsAfterRestoreBackup(t, jenkinsClient2, jobID) | 	verifyJobBuildsAfterRestoreBackup(t, jenkinsClient2, jobID) | ||||||
|  | 
 | ||||||
|  | 	jenkins = getJenkins(t, jenkins.Namespace, jenkins.Name) | ||||||
|  | 	lastDoneBackup = jenkins.Status.LastBackup | ||||||
|  | 	resetJenkinsStatus(t, jenkins) | ||||||
|  | 	waitForJenkinsUserConfigurationToComplete(t, jenkins) | ||||||
|  | 	jenkins = getJenkins(t, jenkins.Namespace, jenkins.Name) | ||||||
|  | 	assert.Equal(t, lastDoneBackup, jenkins.Status.RestoredBackup) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func waitForJob(t *testing.T, jenkinsClient client.Jenkins, jobID string) { | func waitForJob(t *testing.T, jenkinsClient client.Jenkins, jobID string) { | ||||||
|  | @ -106,6 +117,11 @@ func createJenkinsWithBackupAndRestoreConfigured(t *testing.T, name, namespace s | ||||||
| 			}, | 			}, | ||||||
| 			Restore: v1alpha2.Restore{ | 			Restore: v1alpha2.Restore{ | ||||||
| 				ContainerName: containerName, | 				ContainerName: containerName, | ||||||
|  | 				GetLatestAction: v1alpha2.Handler{ | ||||||
|  | 					Exec: &corev1.ExecAction{ | ||||||
|  | 						Command: []string{"/home/user/bin/get-latest.sh"}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
| 				Action: v1alpha2.Handler{ | 				Action: v1alpha2.Handler{ | ||||||
| 					Exec: &corev1.ExecAction{ | 					Exec: &corev1.ExecAction{ | ||||||
| 						Command: []string{"/home/user/bin/restore.sh"}, | 						Command: []string{"/home/user/bin/restore.sh"}, | ||||||
|  | @ -125,7 +141,7 @@ func createJenkinsWithBackupAndRestoreConfigured(t *testing.T, name, namespace s | ||||||
| 					}, | 					}, | ||||||
| 					{ | 					{ | ||||||
| 						Name:            containerName, | 						Name:            containerName, | ||||||
| 						Image:           "virtuslab/jenkins-operator-backup-pvc:v0.0.6", | 						Image:           "virtuslab/jenkins-operator-backup-pvc:v0.1.0", | ||||||
| 						ImagePullPolicy: corev1.PullIfNotPresent, | 						ImagePullPolicy: corev1.PullIfNotPresent, | ||||||
| 						Env: []corev1.EnvVar{ | 						Env: []corev1.EnvVar{ | ||||||
| 							{ | 							{ | ||||||
|  | @ -191,3 +207,10 @@ func createJenkinsWithBackupAndRestoreConfigured(t *testing.T, name, namespace s | ||||||
| 
 | 
 | ||||||
| 	return jenkins | 	return jenkins | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func resetJenkinsStatus(t *testing.T, jenkins *v1alpha2.Jenkins) { | ||||||
|  | 	jenkins = getJenkins(t, jenkins.Namespace, jenkins.Name) | ||||||
|  | 	jenkins.Status = v1alpha2.JenkinsStatus{} | ||||||
|  | 	err := framework.Global.Client.Update(context.TODO(), jenkins) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -13,7 +13,6 @@ import ( | ||||||
| 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client" | 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources" | 	"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources" | ||||||
| 
 | 
 | ||||||
| 	"github.com/bndr/gojenkins" |  | ||||||
| 	framework "github.com/operator-framework/operator-sdk/pkg/test" | 	framework "github.com/operator-framework/operator-sdk/pkg/test" | ||||||
| 	"github.com/pkg/errors" | 	"github.com/pkg/errors" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
|  | @ -34,28 +33,6 @@ var ( | ||||||
| // checkConditionFunc is used to check if a condition for the jenkins CR is set
 | // checkConditionFunc is used to check if a condition for the jenkins CR is set
 | ||||||
| type checkConditionFunc func(*v1alpha2.Jenkins, error) bool | type checkConditionFunc func(*v1alpha2.Jenkins, error) bool | ||||||
| 
 | 
 | ||||||
| func waitForJobToFinish(t *testing.T, job *gojenkins.Job, tick, timeout time.Duration) { |  | ||||||
| 	err := try.Until(func() (end bool, err error) { |  | ||||||
| 		t.Logf("Waiting for job `%s` to finish", job.GetName()) |  | ||||||
| 		running, err := job.IsRunning() |  | ||||||
| 		if err != nil { |  | ||||||
| 			return false, err |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		queued, err := job.IsQueued() |  | ||||||
| 		if err != nil { |  | ||||||
| 			return false, err |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if !running && !queued { |  | ||||||
| 			return true, nil |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return false, nil |  | ||||||
| 	}, tick, timeout) |  | ||||||
| 	require.NoError(t, err) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func waitForJenkinsBaseConfigurationToComplete(t *testing.T, jenkins *v1alpha2.Jenkins) { | func waitForJenkinsBaseConfigurationToComplete(t *testing.T, jenkins *v1alpha2.Jenkins) { | ||||||
| 	t.Log("Waiting for Jenkins base configuration to complete") | 	t.Log("Waiting for Jenkins base configuration to complete") | ||||||
| 	_, err := WaitUntilJenkinsConditionSet(retryInterval, 170, jenkins, func(jenkins *v1alpha2.Jenkins, err error) bool { | 	_, err := WaitUntilJenkinsConditionSet(retryInterval, 170, jenkins, func(jenkins *v1alpha2.Jenkins, err error) bool { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue