#8 Add Configuration as Code plugin integration
This commit is contained in:
		
							parent
							
								
									5af834869b
								
							
						
					
					
						commit
						ebf1163b28
					
				|  | @ -221,7 +221,6 @@ kubectl get configmap jenkins-operator-user-configuration-example -o yaml | ||||||
| apiVersion: v1 | apiVersion: v1 | ||||||
| data: | data: | ||||||
|   1-configure-theme.groovy: |2 |   1-configure-theme.groovy: |2 | ||||||
| 
 |  | ||||||
|     import jenkins.* |     import jenkins.* | ||||||
|     import jenkins.model.* |     import jenkins.model.* | ||||||
|     import hudson.* |     import hudson.* | ||||||
|  | @ -241,6 +240,9 @@ data: | ||||||
|     decorator.save(); |     decorator.save(); | ||||||
| 
 | 
 | ||||||
|     jenkins.save() |     jenkins.save() | ||||||
|  |   1-system-message.yaml: |2 | ||||||
|  |     jenkins: | ||||||
|  |       systemMessage: "Configuration as Code integration works!!!" | ||||||
| kind: ConfigMap | kind: ConfigMap | ||||||
| metadata: | metadata: | ||||||
|   labels: |   labels: | ||||||
|  | @ -251,7 +253,9 @@ metadata: | ||||||
|   namespace: default |   namespace: default | ||||||
| ```  | ```  | ||||||
| 
 | 
 | ||||||
| When **jenkins-operator-user-configuration-example** ConfigMap is updated Jenkins automatically runs the **jenkins-operator-user-configuration** Jenkins Job which executes all scripts. | When **jenkins-operator-user-configuration-example** ConfigMap is updated Jenkins automatically  | ||||||
|  | runs the **jenkins-operator-user-configuration** Jenkins Job which executes all scripts then | ||||||
|  | runs the **jenkins-operator-user-configuration-casc** Jenkins Job which applies Configuration as Code configuration. | ||||||
| 
 | 
 | ||||||
| ## Install Plugins | ## Install Plugins | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -451,7 +451,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsClient(meta metav1.Obje | ||||||
| func (r *ReconcileJenkinsBaseConfiguration) ensureBaseConfiguration(jenkinsClient jenkinsclient.Jenkins) (reconcile.Result, error) { | func (r *ReconcileJenkinsBaseConfiguration) ensureBaseConfiguration(jenkinsClient jenkinsclient.Jenkins) (reconcile.Result, error) { | ||||||
| 	groovyClient := groovy.New(jenkinsClient, r.k8sClient, r.logger, fmt.Sprintf("%s-base-configuration", constants.OperatorName), resources.JenkinsBaseConfigurationVolumePath) | 	groovyClient := groovy.New(jenkinsClient, r.k8sClient, r.logger, fmt.Sprintf("%s-base-configuration", constants.OperatorName), resources.JenkinsBaseConfigurationVolumePath) | ||||||
| 
 | 
 | ||||||
| 	err := groovyClient.ConfigureGroovyJob() | 	err := groovyClient.ConfigureJob() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return reconcile.Result{}, err | 		return reconcile.Result{}, err | ||||||
| 	} | 	} | ||||||
|  | @ -463,7 +463,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureBaseConfiguration(jenkinsClien | ||||||
| 		return reconcile.Result{}, stackerr.WithStack(err) | 		return reconcile.Result{}, stackerr.WithStack(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	done, err := groovyClient.EnsureGroovyJob(configuration.Data, r.jenkins) | 	done, err := groovyClient.Ensure(configuration.Data, r.jenkins) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return reconcile.Result{}, err | 		return reconcile.Result{}, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -0,0 +1,153 @@ | ||||||
|  | package casc | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"crypto/sha256" | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"fmt" | ||||||
|  | 	"sort" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" | ||||||
|  | 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/jobs" | ||||||
|  | 
 | ||||||
|  | 	"github.com/go-logr/logr" | ||||||
|  | 	k8s "sigs.k8s.io/controller-runtime/pkg/client" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	jobHashParameterName = "hash" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // ConfigurationAsCode defines API which configures Jenkins with help Configuration as a code plugin
 | ||||||
|  | type ConfigurationAsCode struct { | ||||||
|  | 	jenkinsClient jenkinsclient.Jenkins | ||||||
|  | 	k8sClient     k8s.Client | ||||||
|  | 	logger        logr.Logger | ||||||
|  | 	jobName       string | ||||||
|  | 	configsPath   string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // New creates new instance of ConfigurationAsCode
 | ||||||
|  | func New(jenkinsClient jenkinsclient.Jenkins, k8sClient k8s.Client, logger logr.Logger, jobName, configsPath string) *ConfigurationAsCode { | ||||||
|  | 	return &ConfigurationAsCode{ | ||||||
|  | 		jenkinsClient: jenkinsClient, | ||||||
|  | 		k8sClient:     k8sClient, | ||||||
|  | 		logger:        logger, | ||||||
|  | 		jobName:       jobName, | ||||||
|  | 		configsPath:   configsPath, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ConfigureJob configures jenkins job which configures Jenkins with help Configuration as a code plugin
 | ||||||
|  | func (g *ConfigurationAsCode) ConfigureJob() error { | ||||||
|  | 	_, created, err := g.jenkinsClient.CreateOrUpdateJob(fmt.Sprintf(configurationJobXMLFmt, g.configsPath), g.jobName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if created { | ||||||
|  | 		g.logger.Info(fmt.Sprintf("'%s' job has been created", g.jobName)) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Ensure configures Jenkins with help Configuration as a code plugin
 | ||||||
|  | func (g *ConfigurationAsCode) Ensure(secretOrConfigMapData map[string]string, jenkins *v1alpha1.Jenkins) (bool, error) { | ||||||
|  | 	jobsClient := jobs.New(g.jenkinsClient, g.k8sClient, g.logger) | ||||||
|  | 
 | ||||||
|  | 	hash := g.calculateHash(secretOrConfigMapData) | ||||||
|  | 	done, err := jobsClient.EnsureBuildJob(g.jobName, hash, map[string]string{jobHashParameterName: hash}, jenkins, true) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 	return done, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (g *ConfigurationAsCode) calculateHash(secretOrConfigMapData map[string]string) string { | ||||||
|  | 	hash := sha256.New() | ||||||
|  | 
 | ||||||
|  | 	var keys []string | ||||||
|  | 	for key := range secretOrConfigMapData { | ||||||
|  | 		keys = append(keys, key) | ||||||
|  | 	} | ||||||
|  | 	sort.Strings(keys) | ||||||
|  | 	for _, key := range keys { | ||||||
|  | 		if strings.HasSuffix(key, ".yaml") { | ||||||
|  | 			hash.Write([]byte(key)) | ||||||
|  | 			hash.Write([]byte(secretOrConfigMapData[key])) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return base64.StdEncoding.EncodeToString(hash.Sum(nil)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const configurationJobXMLFmt = `<?xml version='1.1' encoding='UTF-8'?> | ||||||
|  | <flow-definition plugin="workflow-job@2.31"> | ||||||
|  |   <actions/> | ||||||
|  |   <description></description> | ||||||
|  |   <keepDependencies>false</keepDependencies> | ||||||
|  |   <properties> | ||||||
|  |     <org.jenkinsci.plugins.workflow.job.properties.DisableConcurrentBuildsJobProperty/> | ||||||
|  |     <hudson.model.ParametersDefinitionProperty> | ||||||
|  |       <parameterDefinitions> | ||||||
|  |         <hudson.model.StringParameterDefinition> | ||||||
|  |           <name>` + jobHashParameterName + `</name> | ||||||
|  |           <description></description> | ||||||
|  |           <defaultValue></defaultValue> | ||||||
|  |           <trim>false</trim> | ||||||
|  |         </hudson.model.StringParameterDefinition> | ||||||
|  |       </parameterDefinitions> | ||||||
|  |     </hudson.model.ParametersDefinitionProperty> | ||||||
|  |   </properties> | ||||||
|  |   <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.61.1"> | ||||||
|  |     <script>import io.jenkins.plugins.casc.yaml.YamlSource; | ||||||
|  | 
 | ||||||
|  | def configsPath = '%s' | ||||||
|  | def expectedHash = params.hash | ||||||
|  | 
 | ||||||
|  | node('master') { | ||||||
|  |     def configsText = sh(script: "ls ${configsPath} | grep .yaml | sort", returnStdout: true).trim() | ||||||
|  |     def configs = [] | ||||||
|  |     configs.addAll(configsText.tokenize('\n')) | ||||||
|  |      | ||||||
|  |     stage('Synchronizing files') { | ||||||
|  |         def complete = false | ||||||
|  |         for(int i = 1; i <= 10; i++) { | ||||||
|  |             def actualHash = calculateHash((String[])configs, configsPath) | ||||||
|  |             println "Expected hash '${expectedHash}', actual hash '${actualHash}'" | ||||||
|  |             if(expectedHash == actualHash) { | ||||||
|  |                 complete = true | ||||||
|  |                 break | ||||||
|  |             } | ||||||
|  |             sleep 2 | ||||||
|  |         } | ||||||
|  |         if(!complete) { | ||||||
|  |             error("Timeout while synchronizing files") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     for(config in configs) { | ||||||
|  |         stage(config) { | ||||||
|  |             def path = java.nio.file.Paths.get("${configsPath}/${config}") | ||||||
|  |             def source = new YamlSource(path, YamlSource.READ_FROM_PATH) | ||||||
|  |             io.jenkins.plugins.casc.ConfigurationAsCode.get().configureWith(source) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @NonCPS | ||||||
|  | def calculateHash(String[] configs, String configsPath) { | ||||||
|  |     def hash = java.security.MessageDigest.getInstance("SHA-256") | ||||||
|  |     for(config in configs) { | ||||||
|  |         hash.update(config.getBytes()) | ||||||
|  |         def fileLocation = java.nio.file.Paths.get("${configsPath}/${config}") | ||||||
|  |         def fileData = java.nio.file.Files.readAllBytes(fileLocation) | ||||||
|  |         hash.update(fileData) | ||||||
|  |     } | ||||||
|  |     return Base64.getEncoder().encodeToString(hash.digest()) | ||||||
|  | }</script> | ||||||
|  |     <sandbox>false</sandbox> | ||||||
|  |   </definition> | ||||||
|  |   <triggers/> | ||||||
|  |   <disabled>false</disabled> | ||||||
|  | </flow-definition> | ||||||
|  | ` | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | // Package casc configures Jenkins with help Configuration as a code plugin
 | ||||||
|  | package casc | ||||||
|  | @ -7,6 +7,7 @@ import ( | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" | 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" | ||||||
| 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" | 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources" | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources" | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/user/casc" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/user/seedjobs" | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/user/seedjobs" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants" | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/groovy" | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/groovy" | ||||||
|  | @ -84,25 +85,35 @@ func (r *ReconcileUserConfiguration) ensureSeedJobs() (reconcile.Result, error) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r *ReconcileUserConfiguration) ensureUserConfiguration(jenkinsClient jenkinsclient.Jenkins) (reconcile.Result, error) { | func (r *ReconcileUserConfiguration) ensureUserConfiguration(jenkinsClient jenkinsclient.Jenkins) (reconcile.Result, error) { | ||||||
| 	groovyClient := groovy.New(jenkinsClient, r.k8sClient, r.logger, constants.UserConfigurationJobName, resources.JenkinsUserConfigurationVolumePath) |  | ||||||
| 
 |  | ||||||
| 	err := groovyClient.ConfigureGroovyJob() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return reconcile.Result{}, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	configuration := &corev1.ConfigMap{} | 	configuration := &corev1.ConfigMap{} | ||||||
| 	namespaceName := types.NamespacedName{Namespace: r.jenkins.Namespace, Name: resources.GetUserConfigurationConfigMapNameFromJenkins(r.jenkins)} | 	namespaceName := types.NamespacedName{Namespace: r.jenkins.Namespace, Name: resources.GetUserConfigurationConfigMapNameFromJenkins(r.jenkins)} | ||||||
| 	err = r.k8sClient.Get(context.TODO(), namespaceName, configuration) | 	err := r.k8sClient.Get(context.TODO(), namespaceName, configuration) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return reconcile.Result{}, errors.WithStack(err) | 		return reconcile.Result{}, errors.WithStack(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	done, err := groovyClient.EnsureGroovyJob(configuration.Data, r.jenkins) | 	groovyClient := groovy.New(jenkinsClient, r.k8sClient, r.logger, constants.UserConfigurationJobName, resources.JenkinsUserConfigurationVolumePath) | ||||||
|  | 	err = groovyClient.ConfigureJob() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return reconcile.Result{}, err | 		return reconcile.Result{}, err | ||||||
| 	} | 	} | ||||||
|  | 	done, err := groovyClient.Ensure(configuration.Data, r.jenkins) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return reconcile.Result{}, err | ||||||
|  | 	} | ||||||
|  | 	if !done { | ||||||
|  | 		return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
|  | 	configurationAsCodeClient := casc.New(jenkinsClient, r.k8sClient, r.logger, constants.UserConfigurationCASCJobName, resources.JenkinsUserConfigurationVolumePath) | ||||||
|  | 	err = configurationAsCodeClient.ConfigureJob() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return reconcile.Result{}, err | ||||||
|  | 	} | ||||||
|  | 	done, err = configurationAsCodeClient.Ensure(configuration.Data, r.jenkins) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return reconcile.Result{}, err | ||||||
|  | 	} | ||||||
| 	if !done { | 	if !done { | ||||||
| 		return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil | 		return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -11,4 +11,6 @@ const ( | ||||||
| 	DefaultJenkinsMasterImage = "jenkins/jenkins:lts" | 	DefaultJenkinsMasterImage = "jenkins/jenkins:lts" | ||||||
| 	// UserConfigurationJobName is the Jenkins job name used to configure Jenkins by groovy scripts provided by user
 | 	// UserConfigurationJobName is the Jenkins job name used to configure Jenkins by groovy scripts provided by user
 | ||||||
| 	UserConfigurationJobName = OperatorName + "-user-configuration" | 	UserConfigurationJobName = OperatorName + "-user-configuration" | ||||||
|  | 	// UserConfigurationCASCJobName is the Jenkins job name used to configure Jenkins by Configuration as code yaml configs provided by user
 | ||||||
|  | 	UserConfigurationCASCJobName = OperatorName + "-user-configuration-casc" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ import ( | ||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"sort" | 	"sort" | ||||||
|  | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" | 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" | ||||||
| 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" | 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" | ||||||
|  | @ -38,8 +39,8 @@ func New(jenkinsClient jenkinsclient.Jenkins, k8sClient k8s.Client, logger logr. | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ConfigureGroovyJob configures jenkins job for executing groovy scripts
 | // ConfigureJob configures jenkins job for executing groovy scripts
 | ||||||
| func (g *Groovy) ConfigureGroovyJob() error { | func (g *Groovy) ConfigureJob() error { | ||||||
| 	_, created, err := g.jenkinsClient.CreateOrUpdateJob(fmt.Sprintf(configurationJobXMLFmt, g.scriptsPath), g.jobName) | 	_, created, err := g.jenkinsClient.CreateOrUpdateJob(fmt.Sprintf(configurationJobXMLFmt, g.scriptsPath), g.jobName) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
|  | @ -50,8 +51,8 @@ func (g *Groovy) ConfigureGroovyJob() error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // EnsureGroovyJob executes groovy script and verifies jenkins job status according to reconciliation loop lifecycle
 | // Ensure executes groovy script and verifies jenkins job status according to reconciliation loop lifecycle
 | ||||||
| func (g *Groovy) EnsureGroovyJob(secretOrConfigMapData map[string]string, jenkins *v1alpha1.Jenkins) (bool, error) { | func (g *Groovy) Ensure(secretOrConfigMapData map[string]string, jenkins *v1alpha1.Jenkins) (bool, error) { | ||||||
| 	jobsClient := jobs.New(g.jenkinsClient, g.k8sClient, g.logger) | 	jobsClient := jobs.New(g.jenkinsClient, g.k8sClient, g.logger) | ||||||
| 
 | 
 | ||||||
| 	hash := g.calculateHash(secretOrConfigMapData) | 	hash := g.calculateHash(secretOrConfigMapData) | ||||||
|  | @ -71,8 +72,10 @@ func (g *Groovy) calculateHash(secretOrConfigMapData map[string]string) string { | ||||||
| 	} | 	} | ||||||
| 	sort.Strings(keys) | 	sort.Strings(keys) | ||||||
| 	for _, key := range keys { | 	for _, key := range keys { | ||||||
| 		hash.Write([]byte(key)) | 		if strings.HasSuffix(key, ".groovy") { | ||||||
| 		hash.Write([]byte(secretOrConfigMapData[key])) | 			hash.Write([]byte(key)) | ||||||
|  | 			hash.Write([]byte(secretOrConfigMapData[key])) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	return base64.StdEncoding.EncodeToString(hash.Sum(nil)) | 	return base64.StdEncoding.EncodeToString(hash.Sum(nil)) | ||||||
| } | } | ||||||
|  | @ -100,7 +103,7 @@ const configurationJobXMLFmt = `<?xml version='1.1' encoding='UTF-8'?> | ||||||
| def expectedHash = params.hash | def expectedHash = params.hash | ||||||
| 
 | 
 | ||||||
| node('master') { | node('master') { | ||||||
|     def scriptsText = sh(script: "ls ${scriptsPath} | sort", returnStdout: true).trim() |     def scriptsText = sh(script: "ls ${scriptsPath} | grep .groovy | sort", returnStdout: true).trim() | ||||||
|     def scripts = [] |     def scripts = [] | ||||||
|     scripts.addAll(scriptsText.tokenize('\n')) |     scripts.addAll(scriptsText.tokenize('\n')) | ||||||
|      |      | ||||||
|  |  | ||||||
|  | @ -2,12 +2,14 @@ package e2e | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"fmt" | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" | 	"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1" | ||||||
| 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" | 	jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/user/seedjobs" | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/user/seedjobs" | ||||||
| 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/plugins" | 	"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/plugins" | ||||||
| 
 | 
 | ||||||
|  | @ -27,8 +29,13 @@ func TestConfiguration(t *testing.T) { | ||||||
| 	// Deletes test namespace
 | 	// Deletes test namespace
 | ||||||
| 	defer ctx.Cleanup() | 	defer ctx.Cleanup() | ||||||
| 
 | 
 | ||||||
|  | 	jenkinsCRName := "e2e" | ||||||
|  | 	numberOfExecutors := 6 | ||||||
|  | 	systemMessage := "Configuration as Code integration works!!!" | ||||||
|  | 
 | ||||||
| 	// base
 | 	// base
 | ||||||
| 	jenkins := createJenkinsCR(t, "e2e", namespace) | 	createUserConfigurationConfigMap(t, jenkinsCRName, namespace, numberOfExecutors, systemMessage) | ||||||
|  | 	jenkins := createJenkinsCR(t, jenkinsCRName, namespace) | ||||||
| 	createDefaultLimitsForContainersInNamespace(t, namespace) | 	createDefaultLimitsForContainersInNamespace(t, namespace) | ||||||
| 	waitForJenkinsBaseConfigurationToComplete(t, jenkins) | 	waitForJenkinsBaseConfigurationToComplete(t, jenkins) | ||||||
| 
 | 
 | ||||||
|  | @ -39,6 +46,31 @@ func TestConfiguration(t *testing.T) { | ||||||
| 	// user
 | 	// user
 | ||||||
| 	waitForJenkinsUserConfigurationToComplete(t, jenkins) | 	waitForJenkinsUserConfigurationToComplete(t, jenkins) | ||||||
| 	verifyJenkinsSeedJobs(t, client, jenkins) | 	verifyJenkinsSeedJobs(t, client, jenkins) | ||||||
|  | 	verifyUserConfiguration(t, client, numberOfExecutors, systemMessage) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func createUserConfigurationConfigMap(t *testing.T, jenkinsCRName string, namespace string, numberOfExecutors int, systemMessage string) { | ||||||
|  | 	userConfiguration := &corev1.ConfigMap{ | ||||||
|  | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 			Name:      resources.GetUserConfigurationConfigMapName(jenkinsCRName), | ||||||
|  | 			Namespace: namespace, | ||||||
|  | 		}, | ||||||
|  | 		Data: map[string]string{ | ||||||
|  | 			"1-set-executors.groovy": fmt.Sprintf(` | ||||||
|  | import jenkins.model.Jenkins | ||||||
|  | 
 | ||||||
|  | Jenkins.instance.setNumExecutors(%d) | ||||||
|  | Jenkins.instance.save()`, numberOfExecutors), | ||||||
|  | 			"1-casc.yaml": fmt.Sprintf(` | ||||||
|  | jenkins: | ||||||
|  |   systemMessage: "%s"`, systemMessage), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.Logf("User configuration %+v", *userConfiguration) | ||||||
|  | 	if err := framework.Global.Client.Create(context.TODO(), userConfiguration, nil); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func createDefaultLimitsForContainersInNamespace(t *testing.T, namespace string) { | func createDefaultLimitsForContainersInNamespace(t *testing.T, namespace string) { | ||||||
|  | @ -171,3 +203,19 @@ func verifyJenkinsSeedJobs(t *testing.T, client jenkinsclient.Jenkins, jenkins * | ||||||
| 	}) | 	}) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func verifyUserConfiguration(t *testing.T, jenkinsClient jenkinsclient.Jenkins, amountOfExecutors int, systemMessage string) { | ||||||
|  | 	checkConfigurationViaGroovyScript := fmt.Sprintf(` | ||||||
|  | if (!new Integer(%d).equals(Jenkins.instance.numExecutors)) { | ||||||
|  | 	throw new Exception("Configuration via groovy scripts failed") | ||||||
|  | }`, amountOfExecutors) | ||||||
|  | 	logs, err := jenkinsClient.ExecuteScript(checkConfigurationViaGroovyScript) | ||||||
|  | 	assert.NoError(t, err, logs) | ||||||
|  | 
 | ||||||
|  | 	checkConfigurationAsCode := fmt.Sprintf(` | ||||||
|  | if (!"%s".equals(Jenkins.instance.systemMessage)) { | ||||||
|  | 	throw new Exception("Configuration as code failed") | ||||||
|  | }`, systemMessage) | ||||||
|  | 	logs, err = jenkinsClient.ExecuteScript(checkConfigurationAsCode) | ||||||
|  | 	assert.NoError(t, err, logs) | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue