From 516418f97f7fc138f9a6525a5fbfe6aa236e2573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20S=C4=99k?= Date: Fri, 11 Jan 2019 07:56:03 +0100 Subject: [PATCH] Fix calculating hash for user/base configuration --- Makefile | 2 +- .../jenkins/configuration/base/reconcile.go | 59 +++++++------------ .../jenkins/configuration/base/resources.go | 6 +- .../jenkins/configuration/user/reconcile.go | 13 +++- .../jenkins/configuration/user/theme/theme.go | 25 -------- pkg/controller/jenkins/groovy/groovy.go | 23 +++++++- 6 files changed, 56 insertions(+), 72 deletions(-) delete mode 100644 pkg/controller/jenkins/configuration/user/theme/theme.go diff --git a/Makefile b/Makefile index 4d2e4870..52e9e586 100644 --- a/Makefile +++ b/Makefile @@ -328,7 +328,7 @@ deepcopy-gen: ## Generate deepcopy golang code start-minikube: ## Start minikube @echo "+ $@" @minikube status && exit 0 || \ - minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --vm-driver=$(MINIKUBE_DRIVER) --memory 2048 + minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --vm-driver=$(MINIKUBE_DRIVER) --memory 4096 .PHONY: bump-version BUMP := patch diff --git a/pkg/controller/jenkins/configuration/base/reconcile.go b/pkg/controller/jenkins/configuration/base/reconcile.go index a056be90..c7af77dd 100644 --- a/pkg/controller/jenkins/configuration/base/reconcile.go +++ b/pkg/controller/jenkins/configuration/base/reconcile.go @@ -2,11 +2,8 @@ package base import ( "context" - "crypto/sha256" - "encoding/base64" "fmt" "reflect" - "sort" "time" virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" @@ -35,7 +32,7 @@ const ( // ReconcileJenkinsBaseConfiguration defines values required for Jenkins base configuration type ReconcileJenkinsBaseConfiguration struct { - client client.Client + k8sClient client.Client scheme *runtime.Scheme logger logr.Logger jenkins *virtuslabv1alpha1.Jenkins @@ -46,12 +43,12 @@ type ReconcileJenkinsBaseConfiguration struct { func New(client client.Client, scheme *runtime.Scheme, logger logr.Logger, jenkins *virtuslabv1alpha1.Jenkins, local, minikube bool) *ReconcileJenkinsBaseConfiguration { return &ReconcileJenkinsBaseConfiguration{ - client: client, - scheme: scheme, - logger: logger, - jenkins: jenkins, - local: local, - minikube: minikube, + k8sClient: client, + scheme: scheme, + logger: logger, + jenkins: jenkins, + local: local, + minikube: minikube, } } @@ -128,7 +125,7 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (*reconcile.Result, jenk if err != nil { return &reconcile.Result{}, nil, err } - if err := r.client.Delete(context.TODO(), currentJenkinsMasterPod); err != nil { + if err := r.k8sClient.Delete(context.TODO(), currentJenkinsMasterPod); err != nil { return &reconcile.Result{}, nil, err } } @@ -180,7 +177,7 @@ func isPluginInstalled(plugins *gojenkins.Plugins, requiredPlugin plugin.Plugin) func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta metav1.ObjectMeta) error { found := &corev1.Secret{} - err := r.client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.jenkins), Namespace: r.jenkins.ObjectMeta.Namespace}, found) + err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.jenkins), Namespace: r.jenkins.ObjectMeta.Namespace}, found) if err != nil && apierrors.IsNotFound(err) { return r.createResource(resources.NewOperatorCredentialsSecret(meta, r.jenkins)) @@ -222,9 +219,9 @@ func (r *ReconcileJenkinsBaseConfiguration) createBaseConfigurationConfigMap(met func (r *ReconcileJenkinsBaseConfiguration) createUserConfigurationConfigMap(meta metav1.ObjectMeta) error { currentConfigMap := &corev1.ConfigMap{} - err := r.client.Get(context.TODO(), types.NamespacedName{Name: resources.GetUserConfigurationConfigMapName(r.jenkins), Namespace: r.jenkins.Namespace}, currentConfigMap) + err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: resources.GetUserConfigurationConfigMapName(r.jenkins), Namespace: r.jenkins.Namespace}, currentConfigMap) if err != nil && errors.IsNotFound(err) { - return r.client.Create(context.TODO(), resources.NewUserConfigurationConfigMap(meta, r.jenkins)) + return r.k8sClient.Create(context.TODO(), resources.NewUserConfigurationConfigMap(meta, r.jenkins)) } else if err != nil { return err } @@ -267,7 +264,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createService(meta metav1.ObjectMeta func (r *ReconcileJenkinsBaseConfiguration) getJenkinsMasterPod(meta metav1.ObjectMeta) (*corev1.Pod, error) { jenkinsMasterPod := resources.NewJenkinsMasterPod(meta, r.jenkins) currentJenkinsMasterPod := &corev1.Pod{} - err := r.client.Get(context.TODO(), types.NamespacedName{Name: jenkinsMasterPod.Name, Namespace: jenkinsMasterPod.Namespace}, currentJenkinsMasterPod) + err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: jenkinsMasterPod.Name, Namespace: jenkinsMasterPod.Namespace}, currentJenkinsMasterPod) if err != nil { return nil, err } @@ -324,7 +321,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createJenkinsMasterPod(meta metav1.O if currentJenkinsMasterPod != nil && recreatePod && currentJenkinsMasterPod.ObjectMeta.DeletionTimestamp == nil { r.logger.Info(fmt.Sprintf("Terminating Jenkins Master Pod %s/%s", currentJenkinsMasterPod.Namespace, currentJenkinsMasterPod.Name)) - if err := r.client.Delete(context.TODO(), currentJenkinsMasterPod); err != nil { + if err := r.k8sClient.Delete(context.TODO(), currentJenkinsMasterPod); err != nil { return nil, err } return &reconcile.Result{Requeue: true}, nil @@ -368,7 +365,7 @@ func (r *ReconcileJenkinsBaseConfiguration) getJenkinsClient(meta metav1.ObjectM r.logger.V(log.VDebug).Info(fmt.Sprintf("Jenkins API URL %s", jenkinsURL)) credentialsSecret := &corev1.Secret{} - err = r.client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.jenkins), Namespace: r.jenkins.ObjectMeta.Namespace}, credentialsSecret) + err = r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.jenkins), Namespace: r.jenkins.ObjectMeta.Namespace}, credentialsSecret) if err != nil { return nil, err } @@ -421,7 +418,7 @@ func (r *ReconcileJenkinsBaseConfiguration) getJenkinsClient(meta metav1.ObjectM } func (r *ReconcileJenkinsBaseConfiguration) baseConfiguration(jenkinsClient jenkinsclient.Jenkins) (*reconcile.Result, error) { - groovyClient := groovy.New(jenkinsClient, r.client, 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() if err != nil { @@ -429,30 +426,16 @@ func (r *ReconcileJenkinsBaseConfiguration) baseConfiguration(jenkinsClient jenk } configuration := &corev1.ConfigMap{} - namespaceName := types.NamespacedName{Namespace: r.jenkins.Namespace, Name: resources.GetUserConfigurationConfigMapName(r.jenkins)} - err = r.client.Get(context.TODO(), namespaceName, configuration) - if err != nil { - return &reconcile.Result{}, err - } - hash := sha256.New() - - var keys []string - for key := range configuration.Data { - keys = append(keys, key) - } - sort.Strings(keys) - for _, key := range keys { - hash.Write([]byte(key)) - hash.Write([]byte(configuration.Data[key])) - } - - encodedHash := base64.URLEncoding.EncodeToString(hash.Sum(nil)) - - done, err := groovyClient.EnsureGroovyJob(encodedHash, r.jenkins) + namespaceName := types.NamespacedName{Namespace: r.jenkins.Namespace, Name: resources.GetBaseConfigurationConfigMapName(r.jenkins)} + err = r.k8sClient.Get(context.TODO(), namespaceName, configuration) if err != nil { return &reconcile.Result{}, err } + done, err := groovyClient.EnsureGroovyJob(configuration.Data, r.jenkins) + if err != nil { + return &reconcile.Result{}, err + } if !done { return &reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil } diff --git a/pkg/controller/jenkins/configuration/base/resources.go b/pkg/controller/jenkins/configuration/base/resources.go index 6286ca79..8168bfe2 100644 --- a/pkg/controller/jenkins/configuration/base/resources.go +++ b/pkg/controller/jenkins/configuration/base/resources.go @@ -21,7 +21,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createResource(obj metav1.Object) er return err } - return r.client.Create(context.TODO(), runtimeObj) + return r.k8sClient.Create(context.TODO(), runtimeObj) } func (r *ReconcileJenkinsBaseConfiguration) updateResource(obj metav1.Object) error { @@ -33,7 +33,7 @@ func (r *ReconcileJenkinsBaseConfiguration) updateResource(obj metav1.Object) er // set Jenkins instance as the owner and controller, don't check error(can be already set) _ = controllerutil.SetControllerReference(r.jenkins, obj, r.scheme) - return r.client.Update(context.TODO(), runtimeObj) + return r.k8sClient.Update(context.TODO(), runtimeObj) } func (r *ReconcileJenkinsBaseConfiguration) createOrUpdateResource(obj metav1.Object) error { @@ -45,7 +45,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createOrUpdateResource(obj metav1.Ob // set Jenkins instance as the owner and controller, don't check error(can be already set) _ = controllerutil.SetControllerReference(r.jenkins, obj, r.scheme) - err := r.client.Create(context.TODO(), runtimeObj) + err := r.k8sClient.Create(context.TODO(), runtimeObj) if err != nil && errors.IsAlreadyExists(err) { return r.updateResource(obj) } else if err != nil && !errors.IsAlreadyExists(err) { diff --git a/pkg/controller/jenkins/configuration/user/reconcile.go b/pkg/controller/jenkins/configuration/user/reconcile.go index 46a22b2f..301aa426 100644 --- a/pkg/controller/jenkins/configuration/user/reconcile.go +++ b/pkg/controller/jenkins/configuration/user/reconcile.go @@ -1,6 +1,7 @@ package user import ( + "context" "fmt" "time" @@ -8,12 +9,13 @@ import ( jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client" "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources" "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/constants" "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/groovy" "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/jobs" "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" k8s "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -78,7 +80,14 @@ func (r *ReconcileUserConfiguration) userConfiguration(jenkinsClient jenkinsclie return &reconcile.Result{}, err } - done, err := groovyClient.EnsureGroovyJob(theme.SetThemeGroovyScript, r.jenkins) + configuration := &corev1.ConfigMap{} + namespaceName := types.NamespacedName{Namespace: r.jenkins.Namespace, Name: resources.GetUserConfigurationConfigMapName(r.jenkins)} + err = r.k8sClient.Get(context.TODO(), namespaceName, configuration) + if err != nil { + return &reconcile.Result{}, err + } + + done, err := groovyClient.EnsureGroovyJob(configuration.Data, r.jenkins) if err != nil { return &reconcile.Result{}, err } diff --git a/pkg/controller/jenkins/configuration/user/theme/theme.go b/pkg/controller/jenkins/configuration/user/theme/theme.go deleted file mode 100644 index 66fc9a5c..00000000 --- a/pkg/controller/jenkins/configuration/user/theme/theme.go +++ /dev/null @@ -1,25 +0,0 @@ -package theme - -// SetThemeGroovyScript it's a groovy script which set custom jenkins theme -// TODO move to base configuration -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-light-green.css")); -decorator.setElements(configElements); -decorator.save(); - -jenkins.save() -` diff --git a/pkg/controller/jenkins/groovy/groovy.go b/pkg/controller/jenkins/groovy/groovy.go index fda2c0c4..980b8f18 100644 --- a/pkg/controller/jenkins/groovy/groovy.go +++ b/pkg/controller/jenkins/groovy/groovy.go @@ -1,7 +1,10 @@ package groovy import ( + "crypto/sha256" + "encoding/base64" "fmt" + "sort" virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client" @@ -41,17 +44,31 @@ func (g *Groovy) ConfigureGroovyJob() error { } // EnsureGroovyJob executes groovy script and verifies jenkins job status according to reconciliation loop lifecycle -// see https://wiki.jenkins.io/display/JENKINS/Jenkins+Script+Console -func (g *Groovy) EnsureGroovyJob(hash string, jenkins *virtuslabv1alpha1.Jenkins) (bool, error) { +func (g *Groovy) EnsureGroovyJob(secretOrConfigMapData map[string]string, jenkins *virtuslabv1alpha1.Jenkins) (bool, error) { jobsClient := jobs.New(g.jenkinsClient, g.k8sClient, g.logger) - done, err := jobsClient.EnsureBuildJob(g.jobName, hash, map[string]string{}, jenkins, true) + done, err := jobsClient.EnsureBuildJob(g.jobName, g.calculateHash(secretOrConfigMapData), map[string]string{}, jenkins, true) if err != nil { return false, err } return done, nil } +func (g *Groovy) 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 { + hash.Write([]byte(key)) + hash.Write([]byte(secretOrConfigMapData[key])) + } + return base64.URLEncoding.EncodeToString(hash.Sum(nil)) +} + const configurationJobXMLFmt = `