From 25d63a881f155964f24ee5c218c57a52a872212e Mon Sep 17 00:00:00 2001 From: antoniaklja Date: Fri, 21 Dec 2018 16:13:28 +0100 Subject: [PATCH] Seed Jobs refactoring - add new CreateOrUpdateJob function for Jenkins client - better naming --- pkg/controller/jenkins/client/jenkins.go | 30 +++++++++ .../jenkins/configuration/user/doc.go | 2 +- .../jenkins/configuration/user/reconcile.go | 2 +- .../configuration/user/seedjobs/seedjobs.go | 61 ++++++++----------- 4 files changed, 57 insertions(+), 38 deletions(-) diff --git a/pkg/controller/jenkins/client/jenkins.go b/pkg/controller/jenkins/client/jenkins.go index e73daea3..4ea5d99e 100644 --- a/pkg/controller/jenkins/client/jenkins.go +++ b/pkg/controller/jenkins/client/jenkins.go @@ -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 diff --git a/pkg/controller/jenkins/configuration/user/doc.go b/pkg/controller/jenkins/configuration/user/doc.go index fad5d9e4..809e2ce6 100644 --- a/pkg/controller/jenkins/configuration/user/doc.go +++ b/pkg/controller/jenkins/configuration/user/doc.go @@ -1,2 +1,2 @@ -// Package user is responsible for Jenkins user configuration +// Package user implements Jenkins user configuration and reconciliation package user diff --git a/pkg/controller/jenkins/configuration/user/reconcile.go b/pkg/controller/jenkins/configuration/user/reconcile.go index d8bf6cdd..9ecfb9eb 100644 --- a/pkg/controller/jenkins/configuration/user/reconcile.go +++ b/pkg/controller/jenkins/configuration/user/reconcile.go @@ -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 } diff --git a/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go b/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go index 871c3c40..9dc76d67 100644 --- a/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go +++ b/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go @@ -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 = `