Seed Jobs refactoring
- add new CreateOrUpdateJob function for Jenkins client - better naming
This commit is contained in:
		
							parent
							
								
									43d45cda31
								
							
						
					
					
						commit
						25d63a881f
					
				|  | @ -8,6 +8,7 @@ import ( | |||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/bndr/gojenkins" | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| // Jenkins defines Jenkins API
 | ||||
|  | @ -20,6 +21,7 @@ type Jenkins interface { | |||
| 	CreateFolder(name string, parents ...string) (*gojenkins.Folder, error) | ||||
| 	CreateJobInFolder(config string, jobName string, parentIDs ...string) (*gojenkins.Job, error) | ||||
| 	CreateJob(config string, options ...interface{}) (*gojenkins.Job, error) | ||||
| 	CreateOrUpdateJob(config string, options ...interface{}) (*gojenkins.Job, error) | ||||
| 	RenameJob(job string, name string) *gojenkins.Job | ||||
| 	CopyJob(copyFrom string, newName string) (*gojenkins.Job, error) | ||||
| 	DeleteJob(name string) (bool, error) | ||||
|  | @ -53,6 +55,34 @@ type jenkins struct { | |||
| 	gojenkins.Jenkins | ||||
| } | ||||
| 
 | ||||
| // CreateOrUpdateJob creates or updates a job from config
 | ||||
| func (jenkins *jenkins) CreateOrUpdateJob(config string, options ...interface{}) (*gojenkins.Job, error) { | ||||
| 	// taken from gojenkins.CreateJob
 | ||||
| 	qr := make(map[string]string) | ||||
| 	if len(options) > 0 { | ||||
| 		qr["name"] = options[0].(string) | ||||
| 	} else { | ||||
| 		return nil, errors.New("error creating job, job name is missing") | ||||
| 	} | ||||
| 	// create or update
 | ||||
| 	job, err := jenkins.GetJob(qr["name"]) | ||||
| 	if jobNotExists(err) { | ||||
| 		_, err := jenkins.CreateJob(config, options) | ||||
| 		return nil, err | ||||
| 	} else if err != nil { | ||||
| 		err := job.UpdateConfig(config) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return job, err | ||||
| } | ||||
| 
 | ||||
| func jobNotExists(err error) bool { | ||||
| 	if err != nil { | ||||
| 		return err.Error() == errors.New("404").Error() | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // BuildJenkinsAPIUrl returns Jenkins API URL
 | ||||
| func BuildJenkinsAPIUrl(namespace, serviceName string, portNumber int, local, minikube bool) (string, error) { | ||||
| 	// Get Jenkins URL from minikube command
 | ||||
|  |  | |||
|  | @ -1,2 +1,2 @@ | |||
| // Package user is responsible for Jenkins user configuration
 | ||||
| // Package user implements Jenkins user configuration and reconciliation
 | ||||
| package user | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ func (r *ReconcileUserConfiguration) Reconcile() (*reconcile.Result, error) { | |||
| 		return &reconcile.Result{}, nil | ||||
| 	} | ||||
| 
 | ||||
| 	err := seedjobs.ConfigureSeedJobs(r.jenkinsClient, r.k8sClient, r.jenkins) | ||||
| 	err := seedjobs.EnsureSeedJobs(r.jenkinsClient, r.k8sClient, r.jenkins) | ||||
| 	if err != nil { | ||||
| 		return &reconcile.Result{}, err | ||||
| 	} | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ import ( | |||
| 	k8s "sigs.k8s.io/controller-runtime/pkg/client" | ||||
| 
 | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
|  | @ -24,20 +23,35 @@ const ( | |||
| 	displayNameParameterName      = "SEED_JOB_DISPLAY_NAME" | ||||
| ) | ||||
| 
 | ||||
| // ConfigureSeedJobs configures and triggers seed job pipeline for every Jenkins.Spec.SeedJobs entry
 | ||||
| func ConfigureSeedJobs(jenkinsClient jenkins.Jenkins, k8sClient k8s.Client, jenkins *virtuslabv1alpha1.Jenkins) error { | ||||
| 	err := configureSeedJobsPipeline(jenkinsClient) | ||||
| // EnsureSeedJobs configures seed job and runs it for every entry from Jenkins.Spec.SeedJobs
 | ||||
| func EnsureSeedJobs(jenkinsClient jenkins.Jenkins, k8sClient k8s.Client, jenkins *virtuslabv1alpha1.Jenkins) error { | ||||
| 	err := configureSeedJob(jenkinsClient) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	err = buildAndVerifySeedJobs(jenkinsClient, k8sClient, jenkins) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func configureSeedJob(jenkinsClient jenkins.Jenkins) error { | ||||
| 	_, err := jenkinsClient.CreateOrUpdateJob(seedJobConfigXML, ConfigureSeedJobsName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func buildAndVerifySeedJobs(jenkinsClient jenkins.Jenkins, k8sClient k8s.Client, jenkins *virtuslabv1alpha1.Jenkins) error { | ||||
| 	seedJobs := jenkins.Spec.SeedJobs | ||||
| 	for _, seedJob := range seedJobs { | ||||
| 		privateKey, err := extractPrivateKey(k8sClient, jenkins.Namespace, seedJob) | ||||
| 		privateKey, err := privateKeyFromSecret(k8sClient, jenkins.Namespace, seedJob) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		err = triggerConfigureSeedJobsPipeline( | ||||
| 		err = buildAndVerifySeedJob( | ||||
| 			jenkinsClient, | ||||
| 			seedJob.ID, | ||||
| 			privateKey, | ||||
|  | @ -50,33 +64,9 @@ func ConfigureSeedJobs(jenkinsClient jenkins.Jenkins, k8sClient k8s.Client, jenk | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // configureSeedJobsPipeline configures seed jobs and deploy keys
 | ||||
| func configureSeedJobsPipeline(jenkinsClient jenkins.Jenkins) error { | ||||
| 	return createOrUpdateSeedJob(jenkinsClient) | ||||
| } | ||||
| 
 | ||||
| // FIXME this function should be part of jenkins client API
 | ||||
| func createOrUpdateSeedJob(jenkinsClient jenkins.Jenkins) error { | ||||
| 	job, err := jenkinsClient.GetJob(ConfigureSeedJobsName) | ||||
| 	if jobNotExists(err) { | ||||
| 		_, err := jenkinsClient.CreateJob(seedJobConfigXML, ConfigureSeedJobsName) | ||||
| 		return err | ||||
| 	} else if err != nil { | ||||
| 		err := job.UpdateConfig(seedJobConfigXML) | ||||
| 		return err | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func jobNotExists(err error) bool { | ||||
| 	if err != nil { | ||||
| 		return err.Error() == errors.New("404").Error() | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // triggerConfigureSeedJobsPipeline triggers and configures seed job for specific GitHub repository
 | ||||
| func triggerConfigureSeedJobsPipeline(jenkinsClient jenkins.Jenkins, deployKeyID, privateKey, repositoryURL, repositoryBranch, targets, displayName string) error { | ||||
| func buildAndVerifySeedJob(jenkinsClient jenkins.Jenkins, deployKeyID, privateKey, repositoryURL, repositoryBranch, targets, displayName string) error { | ||||
| 	// FIXME this function should build job and verify job status when finished (state in cr status)
 | ||||
| 	// requeue when job is running and check job status next time
 | ||||
| 	options := map[string]string{ | ||||
| 		deployKeyIDParameterName:      deployKeyID, | ||||
| 		privateKeyParameterName:       privateKey, | ||||
|  | @ -85,7 +75,6 @@ func triggerConfigureSeedJobsPipeline(jenkinsClient jenkins.Jenkins, deployKeyID | |||
| 		targetsParameterName:          targets, | ||||
| 		displayNameParameterName:      displayName, | ||||
| 	} | ||||
| 	// FIXME implement EnsureJob()
 | ||||
| 	_, err := jenkinsClient.BuildJob(ConfigureSeedJobsName, options) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|  | @ -93,7 +82,7 @@ func triggerConfigureSeedJobsPipeline(jenkinsClient jenkins.Jenkins, deployKeyID | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func extractPrivateKey(k8sClient k8s.Client, namespace string, seedJob virtuslabv1alpha1.SeedJob) (string, error) { | ||||
| func privateKeyFromSecret(k8sClient k8s.Client, namespace string, seedJob virtuslabv1alpha1.SeedJob) (string, error) { | ||||
| 	if seedJob.PrivateKey.SecretKeyRef != nil { | ||||
| 		deployKeySecret := &v1.Secret{} | ||||
| 		namespaceName := types.NamespacedName{Namespace: namespace, Name: seedJob.PrivateKey.SecretKeyRef.Name} | ||||
|  | @ -106,7 +95,7 @@ func extractPrivateKey(k8sClient k8s.Client, namespace string, seedJob virtuslab | |||
| 	return "", nil | ||||
| } | ||||
| 
 | ||||
| // FIXME use mask-password plugin for params.PRIVATE_KEY
 | ||||
| // FIXME consider to use mask-password plugin for params.PRIVATE_KEY
 | ||||
| var seedJobConfigXML = ` | ||||
| <flow-definition plugin="workflow-job@2.30"> | ||||
|   <actions/> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue