Added TestPlugins, TestRestart and TestRestoreBackup (#504)
Co-authored-by: Tomasz Sęk
This commit is contained in:
		
							parent
							
								
									294be87c64
								
							
						
					
					
						commit
						021ebb4745
					
				|  | @ -211,14 +211,6 @@ func (r *JenkinsReconciler) reconcile(request reconcile.Request) (reconcile.Resu | ||||||
| 		return reconcile.Result{Requeue: true}, jenkins, nil | 		return reconcile.Result{Requeue: true}, jenkins, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	requeue, err = r.handleDeprecatedData(jenkins) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return reconcile.Result{}, jenkins, err |  | ||||||
| 	} |  | ||||||
| 	if requeue { |  | ||||||
| 		return reconcile.Result{Requeue: true}, jenkins, nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	config := r.newJenkinsReconcilier(jenkins) | 	config := r.newJenkinsReconcilier(jenkins) | ||||||
| 	// Reconcile base configuration
 | 	// Reconcile base configuration
 | ||||||
| 	baseConfiguration := base.New(config, r.JenkinsAPIConnectionSettings) | 	baseConfiguration := base.New(config, r.JenkinsAPIConnectionSettings) | ||||||
|  | @ -367,7 +359,7 @@ func (r *JenkinsReconciler) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool | ||||||
| 	if jenkinsContainer.ReadinessProbe == nil { | 	if jenkinsContainer.ReadinessProbe == nil { | ||||||
| 		logger.Info("Setting default Jenkins readinessProbe") | 		logger.Info("Setting default Jenkins readinessProbe") | ||||||
| 		changed = true | 		changed = true | ||||||
| 		jenkinsContainer.ReadinessProbe = resources.NewSimpleProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 30) | 		jenkinsContainer.ReadinessProbe = resources.NewProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 30, 1, 3) | ||||||
| 	} | 	} | ||||||
| 	if jenkinsContainer.LivenessProbe == nil { | 	if jenkinsContainer.LivenessProbe == nil { | ||||||
| 		logger.Info("Setting default Jenkins livenessProbe") | 		logger.Info("Setting default Jenkins livenessProbe") | ||||||
|  | @ -493,7 +485,3 @@ func basePlugins() (result []v1alpha2.Plugin) { | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 |  | ||||||
| func (r *JenkinsReconciler) handleDeprecatedData(_ *v1alpha2.Jenkins) (requeue bool, err error) { |  | ||||||
| 	return false, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ import ( | ||||||
| 	"k8s.io/apimachinery/pkg/util/intstr" | 	"k8s.io/apimachinery/pkg/util/intstr" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func NewSimpleProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds int32) *corev1.Probe { | func NewProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds, timeoutSeconds, failureThreshold int32) *corev1.Probe { | ||||||
| 	return &corev1.Probe{ | 	return &corev1.Probe{ | ||||||
| 		Handler: corev1.Handler{ | 		Handler: corev1.Handler{ | ||||||
| 			HTTPGet: &corev1.HTTPGetAction{ | 			HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | @ -15,14 +15,9 @@ func NewSimpleProbe(uri string, port string, scheme corev1.URIScheme, initialDel | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		InitialDelaySeconds: initialDelaySeconds, | 		InitialDelaySeconds: initialDelaySeconds, | ||||||
|  | 		TimeoutSeconds:      timeoutSeconds, | ||||||
|  | 		FailureThreshold:    failureThreshold, | ||||||
| 		SuccessThreshold:    int32(1), | 		SuccessThreshold:    int32(1), | ||||||
| 		PeriodSeconds:       int32(1), | 		PeriodSeconds:       int32(1), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| func NewProbe(uri string, port string, scheme corev1.URIScheme, initialDelaySeconds, timeoutSeconds, failureThreshold int32) *corev1.Probe { |  | ||||||
| 	p := NewSimpleProbe(uri, port, scheme, initialDelaySeconds) |  | ||||||
| 	p.TimeoutSeconds = timeoutSeconds |  | ||||||
| 	p.FailureThreshold = failureThreshold |  | ||||||
| 	return p |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -23,49 +23,6 @@ import ( | ||||||
| 
 | 
 | ||||||
| const e2e = "e2e" | const e2e = "e2e" | ||||||
| 
 | 
 | ||||||
| // FIXME
 |  | ||||||
| /*func TestPlugins(t *testing.T) { |  | ||||||
| 	t.Parallel() |  | ||||||
| 	namespace, ctx := setupTest(t) |  | ||||||
| 	// Deletes test namespace
 |  | ||||||
| 	defer showLogsAndCleanup(t, ctx) |  | ||||||
| 
 |  | ||||||
| 	jobID := "k8s-e2e" |  | ||||||
| 
 |  | ||||||
| 	priorityClassName := "" |  | ||||||
| 	seedJobs := &[]v1alpha2.SeedJob{ |  | ||||||
| 		{ |  | ||||||
| 			ID:                    "jenkins-operator", |  | ||||||
| 			CredentialID:          "jenkins-operator", |  | ||||||
| 			JenkinsCredentialType: v1alpha2.NoJenkinsCredentialCredentialType, |  | ||||||
| 			Targets:               "cicd/jobs/k8s.jenkins", |  | ||||||
| 			Description:           "Jenkins Operator repository", |  | ||||||
| 			RepositoryBranch:      "master", |  | ||||||
| 			RepositoryURL:         "https://github.com/jenkinsci/kubernetes-operator.git", |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	jenkins := createJenkinsCR(t, "k8s-e2e", namespace, seedJobs, v1alpha2.GroovyScripts{}, v1alpha2.ConfigurationAsCode{}, priorityClassName) |  | ||||||
| 	waitForJenkinsUserConfigurationToComplete(t, jenkins) |  | ||||||
| 
 |  | ||||||
| 	jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(t, jenkins, namespace) |  | ||||||
| 	defer cleanUpFunc() |  | ||||||
| 	waitForJob(t, jenkinsClient, jobID) |  | ||||||
| 	job, err := jenkinsClient.GetJob(jobID) |  | ||||||
| 
 |  | ||||||
| 	require.NoError(t, err, job) |  | ||||||
| 	i, err := job.InvokeSimple(map[string]string{}) |  | ||||||
| 	require.NoError(t, err, i) |  | ||||||
| 	// FIXME: waitForJobToFinish use
 |  | ||||||
| 	time.Sleep(100 * time.Second) // wait for the build to complete
 |  | ||||||
| 
 |  | ||||||
| 	job, err = jenkinsClient.GetJob(jobID) |  | ||||||
| 	require.NoError(t, err, job) |  | ||||||
| 	build, err := job.GetLastBuild() |  | ||||||
| 	require.NoError(t, err) |  | ||||||
| 	assert.True(t, build.IsGood()) |  | ||||||
| }*/ |  | ||||||
| 
 |  | ||||||
| func createUserConfigurationSecret(namespace string, stringData map[string]string) { | func createUserConfigurationSecret(namespace string, stringData map[string]string) { | ||||||
| 	By("creating user configuration secret") | 	By("creating user configuration secret") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -139,3 +139,58 @@ var _ = Describe("Jenkins controller priority class", func() { | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
| }) | }) | ||||||
|  | 
 | ||||||
|  | var _ = Describe("Jenkins controller plugins test", func() { | ||||||
|  | 
 | ||||||
|  | 	const ( | ||||||
|  | 		jenkinsCRName     = e2e | ||||||
|  | 		priorityClassName = "" | ||||||
|  | 		jobID             = "k8s-e2e" | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	var ( | ||||||
|  | 		namespace *corev1.Namespace | ||||||
|  | 		jenkins   *v1alpha2.Jenkins | ||||||
|  | 		mySeedJob = seedJobConfig{ | ||||||
|  | 			SeedJob: v1alpha2.SeedJob{ | ||||||
|  | 				ID:                    "jenkins-operator", | ||||||
|  | 				CredentialID:          "jenkins-operator", | ||||||
|  | 				JenkinsCredentialType: v1alpha2.NoJenkinsCredentialCredentialType, | ||||||
|  | 				Targets:               "cicd/jobs/k8s.jenkins", | ||||||
|  | 				Description:           "Jenkins Operator repository", | ||||||
|  | 				RepositoryBranch:      "master", | ||||||
|  | 				RepositoryURL:         "https://github.com/jenkinsci/kubernetes-operator.git", | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 		groovyScripts = v1alpha2.GroovyScripts{ | ||||||
|  | 			Customization: v1alpha2.Customization{ | ||||||
|  | 				Configurations: []v1alpha2.ConfigMapRef{}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 		casc = v1alpha2.ConfigurationAsCode{ | ||||||
|  | 			Customization: v1alpha2.Customization{ | ||||||
|  | 				Configurations: []v1alpha2.ConfigMapRef{}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	BeforeEach(func() { | ||||||
|  | 		namespace = createNamespace() | ||||||
|  | 		jenkins = createJenkinsCRSafe(jenkinsCRName, namespace.Name, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	AfterEach(func() { | ||||||
|  | 		destroyNamespace(namespace) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	Context("when deploying CR with a SeedJob to cluster", func() { | ||||||
|  | 		It("runs kubernetes plugin job successfully", func() { | ||||||
|  | 			waitForJenkinsUserConfigurationToComplete(jenkins) | ||||||
|  | 			jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name) | ||||||
|  | 			defer cleanUpFunc() | ||||||
|  | 			waitForJobCreation(jenkinsClient, jobID) | ||||||
|  | 			verifyJobCanBeRun(jenkinsClient, jobID) | ||||||
|  | 			verifyJobHasBeenRunCorrectly(jenkinsClient, jobID) | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,108 @@ | ||||||
|  | package e2e | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
|  | 
 | ||||||
|  | 	. "github.com/onsi/ginkgo" | ||||||
|  | 	. "github.com/onsi/gomega" | ||||||
|  | 	corev1 "k8s.io/api/core/v1" | ||||||
|  | 	// +kubebuilder:scaffold:imports
 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var _ = Describe("Jenkins controller", func() { | ||||||
|  | 
 | ||||||
|  | 	const ( | ||||||
|  | 		jenkinsCRName     = e2e | ||||||
|  | 		priorityClassName = "" | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	var ( | ||||||
|  | 		namespace     *corev1.Namespace | ||||||
|  | 		jenkins       *v1alpha2.Jenkins | ||||||
|  | 		groovyScripts = v1alpha2.GroovyScripts{ | ||||||
|  | 			Customization: v1alpha2.Customization{ | ||||||
|  | 				Configurations: []v1alpha2.ConfigMapRef{}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 		casc = v1alpha2.ConfigurationAsCode{ | ||||||
|  | 			Customization: v1alpha2.Customization{ | ||||||
|  | 				Configurations: []v1alpha2.ConfigMapRef{}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	BeforeEach(func() { | ||||||
|  | 		namespace = createNamespace() | ||||||
|  | 
 | ||||||
|  | 		configureAuthorizationToUnSecure(namespace.Name, userConfigurationConfigMapName) | ||||||
|  | 		jenkins = createJenkinsCR(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	AfterEach(func() { | ||||||
|  | 		destroyNamespace(namespace) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	Context("when restarting Jenkins master pod", func() { | ||||||
|  | 		It("new Jenkins Master pod should be created", func() { | ||||||
|  | 			waitForJenkinsBaseConfigurationToComplete(jenkins) | ||||||
|  | 			restartJenkinsMasterPod(jenkins) | ||||||
|  | 			waitForRecreateJenkinsMasterPod(jenkins) | ||||||
|  | 			checkBaseConfigurationCompleteTimeIsNotSet(jenkins) | ||||||
|  | 			waitForJenkinsBaseConfigurationToComplete(jenkins) | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var _ = Describe("Jenkins controller", func() { | ||||||
|  | 
 | ||||||
|  | 	const ( | ||||||
|  | 		jenkinsCRName     = e2e | ||||||
|  | 		priorityClassName = "" | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	var ( | ||||||
|  | 		namespace     *corev1.Namespace | ||||||
|  | 		jenkins       *v1alpha2.Jenkins | ||||||
|  | 		groovyScripts = v1alpha2.GroovyScripts{ | ||||||
|  | 			Customization: v1alpha2.Customization{ | ||||||
|  | 				Configurations: []v1alpha2.ConfigMapRef{ | ||||||
|  | 					{ | ||||||
|  | 						Name: userConfigurationConfigMapName, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 		casc = v1alpha2.ConfigurationAsCode{ | ||||||
|  | 			Customization: v1alpha2.Customization{ | ||||||
|  | 				Configurations: []v1alpha2.ConfigMapRef{}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	BeforeEach(func() { | ||||||
|  | 		namespace = createNamespace() | ||||||
|  | 
 | ||||||
|  | 		configureAuthorizationToUnSecure(namespace.Name, userConfigurationConfigMapName) | ||||||
|  | 		jenkins = createJenkinsCRSafeRestart(jenkinsCRName, namespace.Name, nil, groovyScripts, casc, priorityClassName) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	AfterEach(func() { | ||||||
|  | 		destroyNamespace(namespace) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	Context("when running Jenkins safe restart", func() { | ||||||
|  | 		It("authorization strategy is not overwritten", func() { | ||||||
|  | 			waitForJenkinsBaseConfigurationToComplete(jenkins) | ||||||
|  | 			waitForJenkinsUserConfigurationToComplete(jenkins) | ||||||
|  | 			jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name) | ||||||
|  | 			defer cleanUpFunc() | ||||||
|  | 			checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient) | ||||||
|  | 
 | ||||||
|  | 			err := jenkinsClient.SafeRestart() | ||||||
|  | 			Expect(err).NotTo(HaveOccurred()) | ||||||
|  | 			waitForJenkinsSafeRestart(jenkinsClient) | ||||||
|  | 
 | ||||||
|  | 			checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient) | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
|  | @ -0,0 +1,61 @@ | ||||||
|  | package e2e | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
|  | 
 | ||||||
|  | 	. "github.com/onsi/ginkgo" | ||||||
|  | 	corev1 "k8s.io/api/core/v1" | ||||||
|  | 	// +kubebuilder:scaffold:imports
 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var _ = Describe("Jenkins controller backup and restore", func() { | ||||||
|  | 
 | ||||||
|  | 	const ( | ||||||
|  | 		jenkinsCRName = e2e | ||||||
|  | 		jobID         = "e2e-jenkins-operator" | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	var ( | ||||||
|  | 		namespace *corev1.Namespace | ||||||
|  | 		jenkins   *v1alpha2.Jenkins | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	BeforeEach(func() { | ||||||
|  | 		namespace = createNamespace() | ||||||
|  | 
 | ||||||
|  | 		createPVC(namespace.Name) | ||||||
|  | 		jenkins = createJenkinsWithBackupAndRestoreConfigured(jenkinsCRName, namespace.Name) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	AfterEach(func() { | ||||||
|  | 		destroyNamespace(namespace) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	Context("when deploying CR with backup enabled to cluster", func() { | ||||||
|  | 		It("performs backups before pod deletion and restores them even Jenkins status is restarted", func() { | ||||||
|  | 			waitForJenkinsUserConfigurationToComplete(jenkins) | ||||||
|  | 			jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(jenkins, namespace.Name) | ||||||
|  | 			defer cleanUpFunc() | ||||||
|  | 			waitForJobCreation(jenkinsClient, jobID) | ||||||
|  | 			verifyJobCanBeRun(jenkinsClient, jobID) | ||||||
|  | 
 | ||||||
|  | 			jenkins = getJenkins(jenkins.Namespace, jenkins.Name) | ||||||
|  | 			restartJenkinsMasterPod(jenkins) | ||||||
|  | 			waitForRecreateJenkinsMasterPod(jenkins) | ||||||
|  | 			waitForJenkinsUserConfigurationToComplete(jenkins) | ||||||
|  | 			jenkinsClient2, cleanUpFunc2 := verifyJenkinsAPIConnection(jenkins, namespace.Name) | ||||||
|  | 			defer cleanUpFunc2() | ||||||
|  | 			waitForJobCreation(jenkinsClient2, jobID) | ||||||
|  | 			verifyJobBuildsAfterRestoreBackup(jenkinsClient2, jobID) | ||||||
|  | 
 | ||||||
|  | 			resetJenkinsStatus(jenkins) | ||||||
|  | 			jenkins = getJenkins(jenkins.Namespace, jenkins.Name) | ||||||
|  | 			checkBaseConfigurationCompleteTimeIsNotSet(jenkins) | ||||||
|  | 			waitForJenkinsUserConfigurationToComplete(jenkins) | ||||||
|  | 			jenkinsClient3, cleanUpFunc3 := verifyJenkinsAPIConnection(jenkins, namespace.Name) | ||||||
|  | 			defer cleanUpFunc3() | ||||||
|  | 			waitForJobCreation(jenkinsClient3, jobID) | ||||||
|  | 			verifyJobBuildsAfterRestoreBackup(jenkinsClient3, jobID) | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
|  | @ -152,6 +152,112 @@ func createJenkinsCR(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovy | ||||||
| 	return jenkins | 	return jenkins | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func createJenkinsCRSafeRestart(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovyScripts v1alpha2.GroovyScripts, casc v1alpha2.ConfigurationAsCode, priorityClassName string) *v1alpha2.Jenkins { | ||||||
|  | 	var seedJobs []v1alpha2.SeedJob | ||||||
|  | 	if seedJob != nil { | ||||||
|  | 		seedJobs = append(seedJobs, *seedJob...) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	jenkins := &v1alpha2.Jenkins{ | ||||||
|  | 		TypeMeta: v1alpha2.JenkinsTypeMeta(), | ||||||
|  | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 			Name:      name, | ||||||
|  | 			Namespace: namespace, | ||||||
|  | 		}, | ||||||
|  | 		Spec: v1alpha2.JenkinsSpec{ | ||||||
|  | 			GroovyScripts:       groovyScripts, | ||||||
|  | 			ConfigurationAsCode: casc, | ||||||
|  | 			Master: v1alpha2.JenkinsMaster{ | ||||||
|  | 				Annotations: map[string]string{"test": "label"}, | ||||||
|  | 				Containers: []v1alpha2.Container{ | ||||||
|  | 					{ | ||||||
|  | 						Name: resources.JenkinsMasterContainerName, | ||||||
|  | 						Env: []corev1.EnvVar{ | ||||||
|  | 							{ | ||||||
|  | 								Name:  "TEST_ENV", | ||||||
|  | 								Value: "test_env_value", | ||||||
|  | 							}, | ||||||
|  | 						}, | ||||||
|  | 						ReadinessProbe: &corev1.Probe{ | ||||||
|  | 							Handler: corev1.Handler{ | ||||||
|  | 								HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 									Path:   "/login", | ||||||
|  | 									Port:   intstr.FromString("http"), | ||||||
|  | 									Scheme: corev1.URISchemeHTTP, | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							InitialDelaySeconds: int32(80), | ||||||
|  | 							TimeoutSeconds:      int32(4), | ||||||
|  | 							FailureThreshold:    int32(10), | ||||||
|  | 							SuccessThreshold:    int32(1), | ||||||
|  | 							PeriodSeconds:       int32(1), | ||||||
|  | 						}, | ||||||
|  | 						LivenessProbe: &corev1.Probe{ | ||||||
|  | 							Handler: corev1.Handler{ | ||||||
|  | 								HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 									Path:   "/login", | ||||||
|  | 									Port:   intstr.FromString("http"), | ||||||
|  | 									Scheme: corev1.URISchemeHTTP, | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							InitialDelaySeconds: int32(100), | ||||||
|  | 							TimeoutSeconds:      int32(5), | ||||||
|  | 							FailureThreshold:    int32(12), | ||||||
|  | 							SuccessThreshold:    int32(1), | ||||||
|  | 							PeriodSeconds:       int32(5), | ||||||
|  | 						}, | ||||||
|  | 						VolumeMounts: []corev1.VolumeMount{ | ||||||
|  | 							{ | ||||||
|  | 								Name:      "plugins-cache", | ||||||
|  | 								MountPath: "/usr/share/jenkins/ref/plugins", | ||||||
|  | 							}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:  "envoyproxy", | ||||||
|  | 						Image: "envoyproxy/envoy-alpine:v1.14.1", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				Plugins: []v1alpha2.Plugin{ | ||||||
|  | 					{Name: "audit-trail", Version: "3.7"}, | ||||||
|  | 					{Name: "simple-theme-plugin", Version: "0.6"}, | ||||||
|  | 					{Name: "github", Version: "1.32.0"}, | ||||||
|  | 					{Name: "devoptics", Version: "1.1905", DownloadURL: "https://jenkins-updates.cloudbees.com/download/plugins/devoptics/1.1905/devoptics.hpi"}, | ||||||
|  | 				}, | ||||||
|  | 				PriorityClassName: priorityClassName, | ||||||
|  | 				NodeSelector:      map[string]string{"kubernetes.io/os": "linux"}, | ||||||
|  | 				Volumes: []corev1.Volume{ | ||||||
|  | 					{ | ||||||
|  | 						Name: "plugins-cache", | ||||||
|  | 						VolumeSource: corev1.VolumeSource{ | ||||||
|  | 							EmptyDir: &corev1.EmptyDirVolumeSource{}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			SeedJobs: seedJobs, | ||||||
|  | 			Service: v1alpha2.Service{ | ||||||
|  | 				Type: corev1.ServiceTypeNodePort, | ||||||
|  | 				Port: constants.DefaultHTTPPortInt32, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	jenkins.Spec.Roles = []rbacv1.RoleRef{ | ||||||
|  | 		{ | ||||||
|  | 			APIGroup: "rbac.authorization.k8s.io", | ||||||
|  | 			Kind:     "Role", | ||||||
|  | 			Name:     resources.GetResourceName(jenkins), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	updateJenkinsCR(jenkins) | ||||||
|  | 
 | ||||||
|  | 	_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins) | ||||||
|  | 
 | ||||||
|  | 	Expect(k8sClient.Create(context.TODO(), jenkins)).Should(Succeed()) | ||||||
|  | 
 | ||||||
|  | 	return jenkins | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func createJenkinsAPIClientFromServiceAccount(jenkins *v1alpha2.Jenkins, jenkinsAPIURL string) (jenkinsclient.Jenkins, error) { | func createJenkinsAPIClientFromServiceAccount(jenkins *v1alpha2.Jenkins, jenkinsAPIURL string) (jenkinsclient.Jenkins, error) { | ||||||
| 	podName := resources.GetJenkinsMasterPodName(jenkins) | 	podName := resources.GetJenkinsMasterPodName(jenkins) | ||||||
| 
 | 
 | ||||||
|  | @ -224,12 +330,18 @@ func verifyJenkinsAPIConnection(jenkins *v1alpha2.Jenkins, namespace string) (je | ||||||
| 	return jenkinsClient, cleanUpFunc | 	return jenkinsClient, cleanUpFunc | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*func restartJenkinsMasterPod(jenkins *v1alpha2.Jenkins) { | func restartJenkinsMasterPod(jenkins *v1alpha2.Jenkins) { | ||||||
| 	_, _ = fmt.Fprintf(GinkgoWriter, "Restarting Jenkins master pod") | 	_, _ = fmt.Fprintf(GinkgoWriter, "Restarting Jenkins master pod\n") | ||||||
| 	jenkinsPod := getJenkinsMasterPod(jenkins) | 	jenkinsPod := getJenkinsMasterPod(jenkins) | ||||||
| 	Expect(k8sClient.Delete(context.TODO(), jenkinsPod)).Should(Succeed()) | 	Expect(k8sClient.Delete(context.TODO(), jenkinsPod)).Should(Succeed()) | ||||||
| 	_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins master pod has been restarted") | 
 | ||||||
| }*/ | 	Eventually(func() (bool, error) { | ||||||
|  | 		jenkinsPod = getJenkinsMasterPod(jenkins) | ||||||
|  | 		return jenkinsPod.DeletionTimestamp != nil, nil | ||||||
|  | 	}, 30*retryInterval, retryInterval).Should(BeTrue()) | ||||||
|  | 
 | ||||||
|  | 	_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins master pod has been restarted\n") | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| func getJenkinsService(jenkins *v1alpha2.Jenkins, serviceKind string) *corev1.Service { | func getJenkinsService(jenkins *v1alpha2.Jenkins, serviceKind string) *corev1.Service { | ||||||
| 	service := &corev1.Service{} | 	service := &corev1.Service{} | ||||||
|  |  | ||||||
|  | @ -1,70 +1,20 @@ | ||||||
| package e2e | package e2e | ||||||
| 
 | 
 | ||||||
| // TODO
 |  | ||||||
| /* |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"testing" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" | 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
| 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client" | 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client" | ||||||
| 
 | 
 | ||||||
| 	framework "github.com/operator-framework/operator-sdk/pkg/test" | 	. "github.com/onsi/ginkgo" | ||||||
| 	"github.com/stretchr/testify/require" | 	. "github.com/onsi/gomega" | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
| 	"k8s.io/apimachinery/pkg/types" | 	"k8s.io/apimachinery/pkg/types" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func TestJenkinsMasterPodRestart(t *testing.T) { | func configureAuthorizationToUnSecure(namespace, configMapName string) { | ||||||
| 	t.Parallel() |  | ||||||
| 	namespace, ctx := setupTest(t) |  | ||||||
| 
 |  | ||||||
| 	defer showLogsAndCleanup(t, ctx) |  | ||||||
| 
 |  | ||||||
| 	jenkins := createJenkinsCR(t, "e2e", namespace, nil, v1alpha2.GroovyScripts{}, v1alpha2.ConfigurationAsCode{}, "") |  | ||||||
| 	waitForJenkinsBaseConfigurationToComplete(t, jenkins) |  | ||||||
| 	restartJenkinsMasterPod(t, jenkins) |  | ||||||
| 	waitForRecreateJenkinsMasterPod(t, jenkins) |  | ||||||
| 	checkBaseConfigurationCompleteTimeIsNotSet(t, jenkins) |  | ||||||
| 	waitForJenkinsBaseConfigurationToComplete(t, jenkins) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestSafeRestart(t *testing.T) { |  | ||||||
| 	if skipTestSafeRestart { |  | ||||||
| 		t.Skip() |  | ||||||
| 	} |  | ||||||
| 	t.Parallel() |  | ||||||
| 	namespace, ctx := setupTest(t) |  | ||||||
| 	// Deletes test namespace
 |  | ||||||
| 	defer ctx.Cleanup() |  | ||||||
| 
 |  | ||||||
| 	jenkinsCRName := "e2e" |  | ||||||
| 	configureAuthorizationToUnSecure(t, namespace, userConfigurationConfigMapName) |  | ||||||
| 	groovyScriptsConfig := v1alpha2.GroovyScripts{ |  | ||||||
| 		Customization: v1alpha2.Customization{ |  | ||||||
| 			Configurations: []v1alpha2.ConfigMapRef{ |  | ||||||
| 				{ |  | ||||||
| 					Name: userConfigurationConfigMapName, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 	} |  | ||||||
| 	jenkins := createJenkinsCR(t, jenkinsCRName, namespace, nil, groovyScriptsConfig, v1alpha2.ConfigurationAsCode{}, "") |  | ||||||
| 	waitForJenkinsBaseConfigurationToComplete(t, jenkins) |  | ||||||
| 	waitForJenkinsUserConfigurationToComplete(t, jenkins) |  | ||||||
| 	jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(t, jenkins, namespace) |  | ||||||
| 	defer cleanUpFunc() |  | ||||||
| 	checkIfAuthorizationStrategyUnsecuredIsSet(t, jenkinsClient) |  | ||||||
| 
 |  | ||||||
| 	err := jenkinsClient.SafeRestart() |  | ||||||
| 	require.NoError(t, err) |  | ||||||
| 	waitForJenkinsSafeRestart(t, jenkinsClient) |  | ||||||
| 
 |  | ||||||
| 	checkIfAuthorizationStrategyUnsecuredIsSet(t, jenkinsClient) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func configureAuthorizationToUnSecure(t *testing.T, namespace, configMapName string) { |  | ||||||
| 	limitRange := &corev1.ConfigMap{ | 	limitRange := &corev1.ConfigMap{ | ||||||
| 		ObjectMeta: metav1.ObjectMeta{ | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
| 			Name:      configMapName, | 			Name:      configMapName, | ||||||
|  | @ -83,11 +33,12 @@ jenkins.save() | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err := framework.Global.Client.Create(context.TODO(), limitRange, nil) | 	Expect(k8sClient.Create(context.TODO(), limitRange)).Should(Succeed()) | ||||||
| 	require.NoError(t, err) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func checkIfAuthorizationStrategyUnsecuredIsSet(t *testing.T, jenkinsClient jenkinsclient.Jenkins) { | func checkIfAuthorizationStrategyUnsecuredIsSet(jenkinsClient jenkinsclient.Jenkins) { | ||||||
|  | 	By("checking if Authorization Strategy Unsecured is set") | ||||||
|  | 
 | ||||||
| 	logs, err := jenkinsClient.ExecuteScript(` | 	logs, err := jenkinsClient.ExecuteScript(` | ||||||
| 	import hudson.security.* | 	import hudson.security.* | ||||||
| 
 | 
 | ||||||
|  | @ -97,18 +48,18 @@ func checkIfAuthorizationStrategyUnsecuredIsSet(t *testing.T, jenkinsClient jenk | ||||||
| 	  throw new Exception('AuthorizationStrategy.Unsecured is not set') | 	  throw new Exception('AuthorizationStrategy.Unsecured is not set') | ||||||
| 	} | 	} | ||||||
| 	`) | 	`) | ||||||
| 	require.NoError(t, err, logs) | 	Expect(err).NotTo(HaveOccurred(), logs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func checkBaseConfigurationCompleteTimeIsNotSet(t *testing.T, jenkins *v1alpha2.Jenkins) { | func checkBaseConfigurationCompleteTimeIsNotSet(jenkins *v1alpha2.Jenkins) { | ||||||
| 	jenkinsStatus := &v1alpha2.Jenkins{} | 	By("checking that Base Configuration's complete time is not set") | ||||||
| 	namespaceName := types.NamespacedName{Namespace: jenkins.Namespace, Name: jenkins.Name} | 
 | ||||||
| 	err := framework.Global.Client.Get(context.TODO(), namespaceName, jenkinsStatus) | 	Eventually(func() (bool, error) { | ||||||
| 	if err != nil { | 		actualJenkins := &v1alpha2.Jenkins{} | ||||||
| 		t.Fatal(err) | 		err := k8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, actualJenkins) | ||||||
| 	} | 		if err != nil { | ||||||
| 	if jenkinsStatus.Status.BaseConfigurationCompletedTime != nil { | 			return false, err | ||||||
| 		t.Fatalf("Status.BaseConfigurationCompletedTime is set after pod restart, status %+v", jenkinsStatus.Status) | 		} | ||||||
| 	} | 		return actualJenkins.Status.BaseConfigurationCompletedTime == nil, nil | ||||||
|  | 	}, time.Duration(110)*retryInterval, time.Second).Should(BeTrue()) | ||||||
| } | } | ||||||
| */ |  | ||||||
|  |  | ||||||
|  | @ -1,21 +1,17 @@ | ||||||
| package e2e | package e2e | ||||||
| 
 | 
 | ||||||
| // TODO
 |  | ||||||
| /* |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"testing" | 	"fmt" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/internal/try" | 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" |  | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/client" | 	"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/jenkinsci/kubernetes-operator/pkg/constants" | 	"github.com/jenkinsci/kubernetes-operator/pkg/constants" | ||||||
| 
 | 
 | ||||||
| 	framework "github.com/operator-framework/operator-sdk/pkg/test" | 	. "github.com/onsi/ginkgo" | ||||||
| 	"github.com/stretchr/testify/assert" | 	. "github.com/onsi/gomega" | ||||||
| 	"github.com/stretchr/testify/require" |  | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	"k8s.io/apimachinery/pkg/api/resource" | 	"k8s.io/apimachinery/pkg/api/resource" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | @ -23,64 +19,33 @@ import ( | ||||||
| 
 | 
 | ||||||
| const pvcName = "pvc-jenkins" | const pvcName = "pvc-jenkins" | ||||||
| 
 | 
 | ||||||
| func TestBackupAndRestore(t *testing.T) { | func waitForJobCreation(jenkinsClient client.Jenkins, jobID string) { | ||||||
| 	t.Parallel() | 	By("waiting for Jenkins job creation") | ||||||
| 	namespace, ctx := setupTest(t) |  | ||||||
| 
 | 
 | ||||||
| 	defer showLogsAndCleanup(t, ctx) | 	var err error | ||||||
| 
 | 	Eventually(func() (bool, error) { | ||||||
| 	jobID := "e2e-jenkins-operator" |  | ||||||
| 	createPVC(t, namespace) |  | ||||||
| 	jenkins := createJenkinsWithBackupAndRestoreConfigured(t, "e2e", namespace) |  | ||||||
| 	waitForJenkinsUserConfigurationToComplete(t, jenkins) |  | ||||||
| 
 |  | ||||||
| 	jenkinsClient, cleanUpFunc := verifyJenkinsAPIConnection(t, jenkins, namespace) |  | ||||||
| 	defer cleanUpFunc() |  | ||||||
| 	waitForJob(t, jenkinsClient, jobID) |  | ||||||
| 	job, err := jenkinsClient.GetJob(jobID) |  | ||||||
| 	require.NoError(t, err, job) |  | ||||||
| 	i, err := job.InvokeSimple(map[string]string{}) |  | ||||||
| 	require.NoError(t, err, i) |  | ||||||
| 	// FIXME: waitForJobToFinish use
 |  | ||||||
| 	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) |  | ||||||
| 	waitForRecreateJenkinsMasterPod(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) |  | ||||||
| 	defer cleanUpFunc2() |  | ||||||
| 	waitForJob(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) { |  | ||||||
| 	err := try.Until(func() (end bool, err error) { |  | ||||||
| 		_, err = jenkinsClient.GetJob(jobID) | 		_, err = jenkinsClient.GetJob(jobID) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return false, err | ||||||
|  | 		} | ||||||
| 		return err == nil, err | 		return err == nil, err | ||||||
| 	}, time.Second*2, time.Minute*3) | 	}, time.Minute*3, time.Second*2).Should(BeTrue()) | ||||||
| 	require.NoErrorf(t, err, "Jenkins job '%s' not created by seed job", jobID) | 
 | ||||||
|  | 	Expect(err).NotTo(HaveOccurred()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func verifyJobBuildsAfterRestoreBackup(t *testing.T, jenkinsClient client.Jenkins, jobID string) { | func verifyJobBuildsAfterRestoreBackup(jenkinsClient client.Jenkins, jobID string) { | ||||||
|  | 	By("checking if job builds after restoring backup") | ||||||
|  | 
 | ||||||
| 	job, err := jenkinsClient.GetJob(jobID) | 	job, err := jenkinsClient.GetJob(jobID) | ||||||
| 	require.NoError(t, err) | 	Expect(err).NotTo(HaveOccurred()) | ||||||
| 	build, err := job.GetLastBuild() | 	build, err := job.GetLastBuild() | ||||||
| 	require.NoError(t, err) | 	Expect(err).NotTo(HaveOccurred()) | ||||||
| 	assert.Equal(t, int64(1), build.GetBuildNumber()) | 
 | ||||||
|  | 	Expect(build.GetBuildNumber()).To(Equal(int64(1))) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func createPVC(t *testing.T, namespace string) { | func createPVC(namespace string) { | ||||||
| 	pvc := &corev1.PersistentVolumeClaim{ | 	pvc := &corev1.PersistentVolumeClaim{ | ||||||
| 		ObjectMeta: metav1.ObjectMeta{ | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
| 			Name:      pvcName, | 			Name:      pvcName, | ||||||
|  | @ -96,11 +61,10 @@ func createPVC(t *testing.T, namespace string) { | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err := framework.Global.Client.Create(context.TODO(), pvc, nil) | 	Expect(k8sClient.Create(context.TODO(), pvc)).Should(Succeed()) | ||||||
| 	require.NoError(t, err) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func createJenkinsWithBackupAndRestoreConfigured(t *testing.T, name, namespace string) *v1alpha2.Jenkins { | func createJenkinsWithBackupAndRestoreConfigured(name, namespace string) *v1alpha2.Jenkins { | ||||||
| 	containerName := "backup" | 	containerName := "backup" | ||||||
| 	jenkins := &v1alpha2.Jenkins{ | 	jenkins := &v1alpha2.Jenkins{ | ||||||
| 		TypeMeta: v1alpha2.JenkinsTypeMeta(), | 		TypeMeta: v1alpha2.JenkinsTypeMeta(), | ||||||
|  | @ -130,6 +94,16 @@ func createJenkinsWithBackupAndRestoreConfigured(t *testing.T, name, namespace s | ||||||
| 					}, | 					}, | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
|  | 			GroovyScripts: v1alpha2.GroovyScripts{ | ||||||
|  | 				Customization: v1alpha2.Customization{ | ||||||
|  | 					Configurations: []v1alpha2.ConfigMapRef{}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			ConfigurationAsCode: v1alpha2.ConfigurationAsCode{ | ||||||
|  | 				Customization: v1alpha2.Customization{ | ||||||
|  | 					Configurations: []v1alpha2.ConfigMapRef{}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
| 			Master: v1alpha2.JenkinsMaster{ | 			Master: v1alpha2.JenkinsMaster{ | ||||||
| 				Containers: []v1alpha2.Container{ | 				Containers: []v1alpha2.Container{ | ||||||
| 					{ | 					{ | ||||||
|  | @ -201,19 +175,20 @@ func createJenkinsWithBackupAndRestoreConfigured(t *testing.T, name, namespace s | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	updateJenkinsCR(t, jenkins) |  | ||||||
| 
 | 
 | ||||||
| 	t.Logf("Jenkins CR %+v", *jenkins) | 	updateJenkinsCR(jenkins) | ||||||
| 	err := framework.Global.Client.Create(context.TODO(), jenkins, nil) | 
 | ||||||
| 	require.NoError(t, err) | 	_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins CR %+v\n", *jenkins) | ||||||
|  | 
 | ||||||
|  | 	Expect(k8sClient.Create(context.TODO(), jenkins)).Should(Succeed()) | ||||||
| 
 | 
 | ||||||
| 	return jenkins | 	return jenkins | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func resetJenkinsStatus(t *testing.T, jenkins *v1alpha2.Jenkins) { | func resetJenkinsStatus(jenkins *v1alpha2.Jenkins) { | ||||||
| 	jenkins = getJenkins(t, jenkins.Namespace, jenkins.Name) | 	By("resetting Jenkins status") | ||||||
|  | 
 | ||||||
|  | 	jenkins = getJenkins(jenkins.Namespace, jenkins.Name) | ||||||
| 	jenkins.Status = v1alpha2.JenkinsStatus{} | 	jenkins.Status = v1alpha2.JenkinsStatus{} | ||||||
| 	err := framework.Global.Client.Update(context.TODO(), jenkins) | 	Expect(k8sClient.Status().Update(context.TODO(), jenkins)).Should(Succeed()) | ||||||
| 	require.NoError(t, err) |  | ||||||
| } | } | ||||||
| */ |  | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user/seedjobs" | 	"github.com/jenkinsci/kubernetes-operator/pkg/configuration/user/seedjobs" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/constants" | 	"github.com/jenkinsci/kubernetes-operator/pkg/constants" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/bndr/gojenkins" | ||||||
| 	. "github.com/onsi/ginkgo" | 	. "github.com/onsi/ginkgo" | ||||||
| 	. "github.com/onsi/gomega" | 	. "github.com/onsi/gomega" | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
|  | @ -27,12 +28,13 @@ type seedJobConfig struct { | ||||||
| 	PrivateKey string   `json:"privateKey,omitempty"` | 	PrivateKey string   `json:"privateKey,omitempty"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*type seedJobsConfig struct { | /* | ||||||
|  | type seedJobsConfig struct { | ||||||
| 	SeedJobs []seedJobConfig `json:"seedJobs,omitempty"` | 	SeedJobs []seedJobConfig `json:"seedJobs,omitempty"` | ||||||
| }*/ | } | ||||||
| 
 | 
 | ||||||
| // FIXME
 | // FIXME
 | ||||||
| /*func TestSeedJobs(t *testing.T) { | func TestSeedJobs(t *testing.T) { | ||||||
| 	t.Parallel() | 	t.Parallel() | ||||||
| 	if seedJobConfigurationFile == nil || len(*seedJobConfigurationFile) == 0 { | 	if seedJobConfigurationFile == nil || len(*seedJobConfigurationFile) == 0 { | ||||||
| 		t.Skipf("Skipping test because flag '%+v' is not set", seedJobConfigurationFile) | 		t.Skipf("Skipping test because flag '%+v' is not set", seedJobConfigurationFile) | ||||||
|  | @ -63,22 +65,22 @@ type seedJobConfig struct { | ||||||
| 	verifyJenkinsSeedJobs(t, jenkinsClient, seedJobsConfig.SeedJobs) | 	verifyJenkinsSeedJobs(t, jenkinsClient, seedJobsConfig.SeedJobs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func loadSeedJobsConfig(t *testing.T) seedJobsConfig { | func loadSeedJobsConfig() seedJobsConfig { | ||||||
|  | 	//seedJobConfigurationFile = flag.String(seedJobConfigurationParameterName, "", "path to seed job config")
 | ||||||
| 	jsonFile, err := os.Open(*seedJobConfigurationFile) | 	jsonFile, err := os.Open(*seedJobConfigurationFile) | ||||||
| 	assert.NoError(t, err) | 	Expect(err).NotTo(HaveOccurred()) | ||||||
| 	defer func() { _ = jsonFile.Close() }() | 	defer func() { _ = jsonFile.Close() }() | ||||||
| 
 | 
 | ||||||
| 	byteValue, err := ioutil.ReadAll(jsonFile) | 	byteValue, err := ioutil.ReadAll(jsonFile) | ||||||
| 	assert.NoError(t, err) | 	Expect(err).NotTo(HaveOccurred()) | ||||||
| 
 | 
 | ||||||
| 	var result seedJobsConfig | 	var result seedJobsConfig | ||||||
| 	err = json.Unmarshal(byteValue, &result) | 	err = json.Unmarshal(byteValue, &result) | ||||||
| 	assert.NoError(t, err) | 	Expect(err).NotTo(HaveOccurred()) | ||||||
| 	assert.NotEmpty(t, result.SeedJobs) | 	Expect(result.SeedJobs).NotTo(BeEmpty()) | ||||||
| 	return result | 	return result | ||||||
| } | } | ||||||
| */ | */ | ||||||
| 
 |  | ||||||
| func createKubernetesCredentialsProviderSecret(namespace string, config seedJobConfig) { | func createKubernetesCredentialsProviderSecret(namespace string, config seedJobConfig) { | ||||||
| 	if config.JenkinsCredentialType == v1alpha2.NoJenkinsCredentialCredentialType { | 	if config.JenkinsCredentialType == v1alpha2.NoJenkinsCredentialCredentialType { | ||||||
| 		return | 		return | ||||||
|  | @ -112,7 +114,7 @@ func verifyJenkinsSeedJobs(jenkinsClient jenkinsclient.Jenkins, seedJobs []seedJ | ||||||
| 	for _, seedJob := range seedJobs { | 	for _, seedJob := range seedJobs { | ||||||
| 		if seedJob.JenkinsCredentialType == v1alpha2.BasicSSHCredentialType || seedJob.JenkinsCredentialType == v1alpha2.UsernamePasswordCredentialType { | 		if seedJob.JenkinsCredentialType == v1alpha2.BasicSSHCredentialType || seedJob.JenkinsCredentialType == v1alpha2.UsernamePasswordCredentialType { | ||||||
| 			err = verifyIfJenkinsCredentialExists(jenkinsClient, seedJob.CredentialID) | 			err = verifyIfJenkinsCredentialExists(jenkinsClient, seedJob.CredentialID) | ||||||
| 			Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Jenkins credential '%s' not created for seed job ID '%s'", seedJob.CredentialID, seedJob.ID)) | 			Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Jenkins credential '%s' not created for seed job ID '%s'\n", seedJob.CredentialID, seedJob.ID)) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		verifySeedJobProperties(jenkinsClient, seedJob) | 		verifySeedJobProperties(jenkinsClient, seedJob) | ||||||
|  | @ -122,7 +124,7 @@ func verifyJenkinsSeedJobs(jenkinsClient jenkinsclient.Jenkins, seedJobs []seedJ | ||||||
| 				_, err = jenkinsClient.GetJob(requireJobName) | 				_, err = jenkinsClient.GetJob(requireJobName) | ||||||
| 				return err == nil, err | 				return err == nil, err | ||||||
| 			}, time.Second*2, time.Minute*2) | 			}, time.Second*2, time.Minute*2) | ||||||
| 			Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Jenkins job '%s' not created by seed job ID '%s'", requireJobName, seedJob.ID)) | 			Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Jenkins job '%s' not created by seed job ID '%s'\n", requireJobName, seedJob.ID)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -292,3 +294,36 @@ for (BuildStep step : jobRef.getBuildersList()) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| `)) | `)) | ||||||
|  | 
 | ||||||
|  | func verifyJobCanBeRun(jenkinsClient jenkinsclient.Jenkins, jobID string) { | ||||||
|  | 	By("retrieving created Jenkins job") | ||||||
|  | 	job, err := jenkinsClient.GetJob(jobID) | ||||||
|  | 	Expect(err).To(BeNil()) | ||||||
|  | 
 | ||||||
|  | 	By("running Jenkins job") | ||||||
|  | 	_, err = job.InvokeSimple(map[string]string{}) | ||||||
|  | 	Expect(err).To(BeNil()) | ||||||
|  | 
 | ||||||
|  | 	// FIXME: waitForJobToFinish use
 | ||||||
|  | 	By("waiting for the job to finish") | ||||||
|  | 	time.Sleep(100 * time.Second) // wait for the build to complete
 | ||||||
|  | } | ||||||
|  | func verifyJobHasBeenRunCorrectly(jenkinsClient jenkinsclient.Jenkins, jobID string) { | ||||||
|  | 	By("retrieving finished job") | ||||||
|  | 
 | ||||||
|  | 	var ( | ||||||
|  | 		err   error | ||||||
|  | 		job   *gojenkins.Job | ||||||
|  | 		build *gojenkins.Build | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	Eventually(func() (bool, error) { | ||||||
|  | 		job, err = jenkinsClient.GetJob(jobID) | ||||||
|  | 		Expect(err).To(BeNil()) | ||||||
|  | 		build, err = job.GetLastBuild() | ||||||
|  | 		Expect(err).To(BeNil()) | ||||||
|  | 
 | ||||||
|  | 		By("evaluating correctness of the outcome") | ||||||
|  | 		return build.IsGood(), err | ||||||
|  | 	}, time.Duration(110)*retryInterval, retryInterval).Should(BeTrue()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -3,13 +3,20 @@ package e2e | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"net/http" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
|  | 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/client" | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources" | ||||||
|  | 
 | ||||||
| 	. "github.com/onsi/ginkgo" | 	. "github.com/onsi/ginkgo" | ||||||
| 	. "github.com/onsi/gomega" | 	. "github.com/onsi/gomega" | ||||||
|  | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | 	"k8s.io/apimachinery/pkg/labels" | ||||||
| 	"k8s.io/apimachinery/pkg/types" | 	"k8s.io/apimachinery/pkg/types" | ||||||
|  | 	"sigs.k8s.io/controller-runtime/pkg/client" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
|  | @ -36,26 +43,28 @@ func waitForJenkinsBaseConfigurationToComplete(jenkins *v1alpha2.Jenkins) { | ||||||
| 	Expect(k8sClient.Get(context.TODO(), namespacedName, jenkins)).Should(Succeed()) | 	Expect(k8sClient.Get(context.TODO(), namespacedName, jenkins)).Should(Succeed()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*func waitForRecreateJenkinsMasterPod(t *testing.T, jenkins *v1alpha2.Jenkins) { | func waitForRecreateJenkinsMasterPod(jenkins *v1alpha2.Jenkins) { | ||||||
| 	err := wait.Poll(retryInterval, 30*retryInterval, func() (bool, error) { | 	By("waiting for Jenkins Master Pod recreation") | ||||||
| 		lo := metav1.ListOptions{ | 
 | ||||||
| 			LabelSelector: labels.SelectorFromSet(resources.GetJenkinsMasterPodLabels(*jenkins)).String(), | 	Eventually(func() (bool, error) { | ||||||
|  | 		lo := &client.ListOptions{ | ||||||
|  | 			LabelSelector: labels.SelectorFromSet(resources.GetJenkinsMasterPodLabels(*jenkins)), | ||||||
|  | 			Namespace:     jenkins.Namespace, | ||||||
| 		} | 		} | ||||||
| 		podList, err := framework.Global.KubeClient.CoreV1().Pods(jenkins.ObjectMeta.Namespace).List(lo) | 		pods := &corev1.PodList{} | ||||||
|  | 		err := k8sClient.List(context.TODO(), pods, lo) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return false, err | 			return false, err | ||||||
| 		} | 		} | ||||||
| 		if len(podList.Items) != 1 { | 		if len(pods.Items) != 1 { | ||||||
| 			return false, nil | 			return false, nil | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return podList.Items[0].DeletionTimestamp == nil, nil | 		return pods.Items[0].DeletionTimestamp == nil, nil | ||||||
| 	}) | 	}, 30*retryInterval, retryInterval).Should(BeTrue()) | ||||||
| 	if err != nil { | 
 | ||||||
| 		t.Fatal(err) | 	_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins pod has been recreated\n") | ||||||
| 	} | } | ||||||
| 	_, _ = fmt.Fprintf(GinkgoWriter,"Jenkins pod has been recreated") |  | ||||||
| }*/ |  | ||||||
| 
 | 
 | ||||||
| func waitForJenkinsUserConfigurationToComplete(jenkins *v1alpha2.Jenkins) { | func waitForJenkinsUserConfigurationToComplete(jenkins *v1alpha2.Jenkins) { | ||||||
| 	By("waiting for Jenkins user configuration phase to complete") | 	By("waiting for Jenkins user configuration phase to complete") | ||||||
|  | @ -66,22 +75,23 @@ func waitForJenkinsUserConfigurationToComplete(jenkins *v1alpha2.Jenkins) { | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		return actualJenkins.Status.UserConfigurationCompletedTime, nil | 		return actualJenkins.Status.UserConfigurationCompletedTime, nil | ||||||
| 	}, time.Duration(110)*retryInterval, retryInterval).Should(Not(BeNil())) | 	}, time.Duration(110)*retryInterval, retryInterval).Should(Not(BeNil())) | ||||||
| 	_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins instance is up and ready\n") | 	_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins instance is up and ready\n") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*func waitForJenkinsSafeRestart(t *testing.T, jenkinsClient jenkinsclient.Jenkins) { | func waitForJenkinsSafeRestart(jenkinsClient jenkinsclient.Jenkins) { | ||||||
| 	err := try.Until(func() (end bool, err error) { | 	By("waiting for Jenkins safe restart") | ||||||
|  | 
 | ||||||
|  | 	Eventually(func() (bool, error) { | ||||||
| 		status, err := jenkinsClient.Poll() | 		status, err := jenkinsClient.Poll() | ||||||
|  | 		_, _ = fmt.Fprintf(GinkgoWriter, "Safe restart status: %+v, err: %s\n", status, err) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return false, err | 			return false, err | ||||||
| 		} | 		} | ||||||
| 		if status != http.StatusOK { | 		if status != http.StatusOK { | ||||||
| 			return false, errors.Wrap(err, "couldn't poll data from Jenkins API") | 			return false, err | ||||||
| 		} | 		} | ||||||
| 		return true, nil | 		return true, nil | ||||||
| 	}, time.Second, time.Second*70) | 	}, time.Second*200, time.Second*5).Should(BeTrue()) | ||||||
| 	require.NoError(t, err) | } | ||||||
| }*/ |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue