From 0461e7983b0a5fca6d30ca04cb70076195b6a8db Mon Sep 17 00:00:00 2001 From: antoniaklja Date: Thu, 3 Jan 2019 16:08:38 +0100 Subject: [PATCH] Added jenkins theme and updated user reconciliation loop --- .../jenkins/configuration/user/reconcile.go | 39 +++++- .../configuration/user/reconcile_test.go | 114 ------------------ .../user/seedjobs/seedjobs_test.go | 83 ++++++++----- .../jenkins/configuration/user/theme/theme.go | 24 ++++ pkg/controller/jenkins/plugin/base_plugins.go | 1 + 5 files changed, 114 insertions(+), 147 deletions(-) delete mode 100644 pkg/controller/jenkins/configuration/user/reconcile_test.go create mode 100644 pkg/controller/jenkins/configuration/user/theme/theme.go diff --git a/pkg/controller/jenkins/configuration/user/reconcile.go b/pkg/controller/jenkins/configuration/user/reconcile.go index 8b242995..877365f4 100644 --- a/pkg/controller/jenkins/configuration/user/reconcile.go +++ b/pkg/controller/jenkins/configuration/user/reconcile.go @@ -6,6 +6,8 @@ import ( virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client" "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user/seedjobs" + "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user/theme" + "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/groovy" "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/jobs" "github.com/go-logr/logr" @@ -39,7 +41,18 @@ func (r *ReconcileUserConfiguration) Reconcile() (*reconcile.Result, error) { if err != nil { return result, err } - return result, nil + if result != nil { + return result, nil + } + + // reconcile custom groovy scripts + result, err = r.reconcileCustomGroovy() + if err != nil { + return result, err + } + if result != nil { + return result, nil + } return nil, nil } @@ -53,7 +66,7 @@ func (r *ReconcileUserConfiguration) reconcileSeedJobs() (*reconcile.Result, err return &reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil } // build failed and cannot be recovered - if err == jobs.ErrorUncoverBuildFailed { + if err == jobs.ErrorUnrecoverableBuildFailed { return nil, nil } // unexpected error - requeue reconciliation loop @@ -65,3 +78,25 @@ func (r *ReconcileUserConfiguration) reconcileSeedJobs() (*reconcile.Result, err } return nil, nil } + +func (r *ReconcileUserConfiguration) reconcileCustomGroovy() (*reconcile.Result, error) { + groovyClient := groovy.New(r.jenkinsClient, r.k8sClient, r.logger) + + err := groovyClient.ConfigureGroovyJob() + if err != nil { + return &reconcile.Result{}, err + } + + // set custom jenkins theme + done, err := groovyClient.EnsureGroovyJob(theme.SetThemeGroovyScript, r.jenkins) + if err != nil { + return &reconcile.Result{}, err + } + + // build not finished yet - requeue reconciliation loop with timeout + if !done { + return &reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil + } + + return nil, nil +} diff --git a/pkg/controller/jenkins/configuration/user/reconcile_test.go b/pkg/controller/jenkins/configuration/user/reconcile_test.go deleted file mode 100644 index 1de2b14e..00000000 --- a/pkg/controller/jenkins/configuration/user/reconcile_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package user - -import ( - "context" - "os" - "testing" - "time" - - virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" - "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client" - "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/jobs" - - "github.com/bndr/gojenkins" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes/scheme" - "sigs.k8s.io/controller-runtime/pkg/client/fake" - logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" -) - -func TestMain(m *testing.M) { - virtuslabv1alpha1.SchemeBuilder.AddToScheme(scheme.Scheme) - os.Exit(m.Run()) -} - -func TestReconcileUserConfiguration(t *testing.T) { - // given - logger := logf.ZapLogger(false) - ctrl := gomock.NewController(t) - ctx := context.TODO() - defer ctrl.Finish() - - jenkinsClient := client.NewMockJenkins(ctrl) - fakeClient := fake.NewFakeClient() - - jenkins := jenkinsCustomResource() - err := fakeClient.Create(ctx, jenkins) - assert.NoError(t, err) - - reconcile := New(fakeClient, jenkinsClient, logger, jenkins) - - // first run - should ensure seed jobs(configure seed jobs, run build) and requeue reconciliation loop - jenkinsClient. - EXPECT(). - CreateOrUpdateJob(gomock.Any(), gomock.Any()). - Return(nil, nil) - - jenkinsClient. - EXPECT(). - BuildJob(gomock.Any(), gomock.Any()). - Return(int64(1), nil) - - result, err := reconcile.Reconcile() - assert.NoError(t, err) - assert.NotNil(t, result) - assert.True(t, result.Requeue) - assert.Equal(t, result.RequeueAfter, time.Second*10) - - // second run - should ensure seed jobs(configure/update seed jobs, finish build) and requeue reconciliation loop - jenkinsClient. - EXPECT(). - GetBuild(gomock.Any(), gomock.Any()). - Return(&gojenkins.Build{ - Raw: &gojenkins.BuildResponse{ - Result: jobs.SuccessStatus, - }, - }, nil) - - jenkinsClient. - EXPECT(). - CreateOrUpdateJob(gomock.Any(), gomock.Any()). - Return(nil, nil) - - result, err = reconcile.Reconcile() - assert.NoError(t, err) - assert.Nil(t, result) -} - -func jenkinsCustomResource() *virtuslabv1alpha1.Jenkins { - return &virtuslabv1alpha1.Jenkins{ - ObjectMeta: metav1.ObjectMeta{ - Name: "jenkins", - Namespace: "default", - }, - Spec: virtuslabv1alpha1.JenkinsSpec{ - Master: virtuslabv1alpha1.JenkinsMaster{ - Image: "jenkins/jenkins", - Annotations: map[string]string{"test": "label"}, - Resources: corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("300m"), - corev1.ResourceMemory: resource.MustParse("500Mi"), - }, - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("2"), - corev1.ResourceMemory: resource.MustParse("2Gi"), - }, - }, - }, - SeedJobs: []virtuslabv1alpha1.SeedJob{ - { - ID: "jenkins-operator-e2e", - Targets: "cicd/jobs/*.jenkins", - Description: "Jenkins Operator e2e tests repository", - RepositoryBranch: "master", - RepositoryURL: "https://github.com/VirtusLab/jenkins-operator-e2e.git", - }, - }, - }, - } -} diff --git a/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs_test.go b/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs_test.go index c2b98b82..ac3b6471 100644 --- a/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs_test.go +++ b/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs_test.go @@ -2,6 +2,7 @@ package seedjobs import ( "context" + "fmt" "os" "testing" @@ -40,46 +41,66 @@ func TestEnsureSeedJobs(t *testing.T) { err := fakeClient.Create(ctx, jenkins) assert.NoError(t, err) - seedJobs := New(jenkinsClient, fakeClient, logger) + for reconcileAttempt := 1; reconcileAttempt <= 2; reconcileAttempt++ { + logger.Info(fmt.Sprintf("Reconcile attempt #%d", reconcileAttempt)) - // first run - should create job and schedule build - jenkinsClient. - EXPECT(). - CreateOrUpdateJob(seedJobConfigXML, ConfigureSeedJobsName). - Return(nil, nil) + seedJobs := New(jenkinsClient, fakeClient, logger) - jenkinsClient. - EXPECT(). - BuildJob(ConfigureSeedJobsName, gomock.Any()). - Return(int64(1), nil) + // first run - should create job and schedule build + if reconcileAttempt == 1 { + jenkinsClient. + EXPECT(). + CreateOrUpdateJob(seedJobConfigXML, ConfigureSeedJobsName). + Return(nil, nil) - done, err := seedJobs.EnsureSeedJobs(jenkins) + jenkinsClient. + EXPECT(). + GetJob(ConfigureSeedJobsName). + Return(&gojenkins.Job{ + Raw: &gojenkins.JobResponse{ + NextBuildNumber: int64(1), + }, + }, nil) - assert.NoError(t, err) - assert.False(t, done) + jenkinsClient. + EXPECT(). + BuildJob(ConfigureSeedJobsName, gomock.Any()). + Return(int64(0), nil) + } - // second run - should update and finish job - jenkinsClient. - EXPECT(). - CreateOrUpdateJob(seedJobConfigXML, ConfigureSeedJobsName). - Return(nil, nil) + // second run - should update and finish job + if reconcileAttempt == 2 { + jenkinsClient. + EXPECT(). + CreateOrUpdateJob(seedJobConfigXML, ConfigureSeedJobsName). + Return(nil, nil) - jenkinsClient. - EXPECT(). - GetBuild(ConfigureSeedJobsName, gomock.Any()). - Return(&gojenkins.Build{ - Raw: &gojenkins.BuildResponse{ - Result: jobs.SuccessStatus, - }, - }, nil) + jenkinsClient. + EXPECT(). + GetBuild(ConfigureSeedJobsName, gomock.Any()). + Return(&gojenkins.Build{ + Raw: &gojenkins.BuildResponse{ + Result: jobs.SuccessStatus, + }, + }, nil) + } - err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins) - assert.NoError(t, err) + done, err := seedJobs.EnsureSeedJobs(jenkins) + assert.NoError(t, err) - done, err = seedJobs.EnsureSeedJobs(jenkins) + err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins) + assert.NoError(t, err) - assert.NoError(t, err) - assert.True(t, done) + // first run - should create job and schedule build + if reconcileAttempt == 1 { + assert.False(t, done) + } + + // second run - should update and finish job + if reconcileAttempt == 2 { + assert.True(t, done) + } + } } func jenkinsCustomResource() *virtuslabv1alpha1.Jenkins { diff --git a/pkg/controller/jenkins/configuration/user/theme/theme.go b/pkg/controller/jenkins/configuration/user/theme/theme.go new file mode 100644 index 00000000..f813551d --- /dev/null +++ b/pkg/controller/jenkins/configuration/user/theme/theme.go @@ -0,0 +1,24 @@ +package theme + +// SetThemeGroovyScript it's a groovy script which set custom jenkins theme +var SetThemeGroovyScript = ` +import jenkins.* +import jenkins.model.* +import hudson.* +import hudson.model.* +import org.jenkinsci.plugins.simpletheme.ThemeElement +import org.jenkinsci.plugins.simpletheme.CssTextThemeElement +import org.jenkinsci.plugins.simpletheme.CssUrlThemeElement + +Jenkins jenkins = Jenkins.getInstance() + +def decorator = Jenkins.instance.getDescriptorByType(org.codefirst.SimpleThemeDecorator.class) + +List configElements = new ArrayList<>(); +configElements.add(new CssTextThemeElement("DEFAULT")); +configElements.add(new CssUrlThemeElement("https://cdn.rawgit.com/afonsof/jenkins-material-theme/gh-pages/dist/material-blue-grey.css")); +decorator.setElements(configElements); +decorator.save(); + +jenkins.save() +` diff --git a/pkg/controller/jenkins/plugin/base_plugins.go b/pkg/controller/jenkins/plugin/base_plugins.go index f0d0390b..bb4dcaa8 100644 --- a/pkg/controller/jenkins/plugin/base_plugins.go +++ b/pkg/controller/jenkins/plugin/base_plugins.go @@ -112,4 +112,5 @@ var BasePluginsMap = map[string][]Plugin{ Must(New("configuration-as-code:1.4")).String(): { Must(New("configuration-as-code-support:1.4")), }, + Must(New("simple-theme-plugin:0.5")).String(): {}, }