Seed Jobs refactoring

- add new CreateOrUpdateJob function for Jenkins client
- better naming
This commit is contained in:
antoniaklja 2018-12-21 16:13:28 +01:00
parent 43d45cda31
commit 25d63a881f
4 changed files with 57 additions and 38 deletions

View File

@ -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

View File

@ -1,2 +1,2 @@
// Package user is responsible for Jenkins user configuration
// Package user implements Jenkins user configuration and reconciliation
package user

View File

@ -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
}

View File

@ -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/>