diff --git a/pkg/controller/jenkins/configuration/base/reconcile.go b/pkg/controller/jenkins/configuration/base/reconcile.go index ea2476d7..142a18f5 100644 --- a/pkg/controller/jenkins/configuration/base/reconcile.go +++ b/pkg/controller/jenkins/configuration/base/reconcile.go @@ -77,6 +77,11 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (*reconcile.Result, jenk } r.logger.V(log.VDebug).Info("Base configuration config map is present") + if err := r.createUserConfigurationConfigMap(metaObject); err != nil { + return &reconcile.Result{}, nil, err + } + r.logger.V(log.VDebug).Info("User configuration config map is present") + if err := r.createService(metaObject); err != nil { return &reconcile.Result{}, nil, err } @@ -185,27 +190,40 @@ func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta } func (r *ReconcileJenkinsBaseConfiguration) createScriptsConfigMap(meta metav1.ObjectMeta) error { - scripts, err := resources.NewScriptsConfigMap(meta, r.jenkins) + configMap, err := resources.NewScriptsConfigMap(meta, r.jenkins) if err != nil { return err } - return r.createOrUpdateResource(scripts) + return r.createOrUpdateResource(configMap) } func (r *ReconcileJenkinsBaseConfiguration) createInitConfigurationConfigMap(meta metav1.ObjectMeta) error { - scripts, err := resources.NewInitConfigurationConfigMap(meta, r.jenkins) + configMap, err := resources.NewInitConfigurationConfigMap(meta, r.jenkins) if err != nil { return err } - return r.createOrUpdateResource(scripts) + return r.createOrUpdateResource(configMap) } func (r *ReconcileJenkinsBaseConfiguration) createBaseConfigurationConfigMap(meta metav1.ObjectMeta) error { - scripts, err := resources.NewBaseConfigurationConfigMap(meta, r.jenkins) + configMap, err := resources.NewBaseConfigurationConfigMap(meta, r.jenkins) if err != nil { return err } - return r.createOrUpdateResource(scripts) + return r.createOrUpdateResource(configMap) +} + +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) + if err != nil && errors.IsNotFound(err) { + return r.client.Create(context.TODO(), resources.NewUserConfigurationConfigMap(meta, r.jenkins)) + } else if err != nil { + return err + } + //TODO make sure labels are fine + + return nil } func (r *ReconcileJenkinsBaseConfiguration) createService(meta metav1.ObjectMeta) error { @@ -381,13 +399,11 @@ func (r *ReconcileJenkinsBaseConfiguration) baseConfiguration(jenkinsClient jenk 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 } diff --git a/pkg/controller/jenkins/configuration/base/resources/base_configuration_configmap.go b/pkg/controller/jenkins/configuration/base/resources/base_configuration_configmap.go index e6a722a8..71fce773 100644 --- a/pkg/controller/jenkins/configuration/base/resources/base_configuration_configmap.go +++ b/pkg/controller/jenkins/configuration/base/resources/base_configuration_configmap.go @@ -125,28 +125,6 @@ jenkins.clouds.add(kubernetes) jenkins.save() ` -const configureTheme = ` -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() -` - // GetBaseConfigurationConfigMapName returns name of Kubernetes config map used to base configuration func GetBaseConfigurationConfigMapName(jenkins *virtuslabv1alpha1.Jenkins) string { return fmt.Sprintf("%s-base-configuration-%s", constants.OperatorName, jenkins.ObjectMeta.Name) @@ -167,7 +145,6 @@ func NewBaseConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *virtuslabv1a "5-disable-insecure-features.groovy": disableInsecureFeatures, "6-configure-kubernetes-plugin.groovy": fmt.Sprintf(configureKubernetesPluginFmt, jenkins.ObjectMeta.Namespace, GetResourceName(jenkins), HTTPPortInt), - "7-configure-theme.groovy": configureTheme, }, }, nil } diff --git a/pkg/controller/jenkins/configuration/base/resources/pod.go b/pkg/controller/jenkins/configuration/base/resources/pod.go index cdce8828..6741014f 100644 --- a/pkg/controller/jenkins/configuration/base/resources/pod.go +++ b/pkg/controller/jenkins/configuration/base/resources/pod.go @@ -2,7 +2,6 @@ package resources import ( "fmt" - virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" corev1 "k8s.io/api/core/v1" @@ -26,8 +25,14 @@ const ( jenkinsBaseConfigurationVolumeName = "base-configuration" // JenkinsBaseConfigurationVolumePath is a path where are groovy scripts used to configure Jenkins + // this scripts are provided by jenkins-operator JenkinsBaseConfigurationVolumePath = "/var/jenkins/base-configuration" + jenkinsUserConfigurationVolumeName = "user-configuration" + // JenkinsUserConfigurationVolumePath is a path where are groovy scripts used to configure Jenkins + // this scripts are provided by user + JenkinsUserConfigurationVolumePath = "/var/jenkins/user-configuration" + httpPortName = "http" slavePortName = "slavelistener" // HTTPPortInt defines Jenkins master HTTP port @@ -136,6 +141,11 @@ func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *virtuslabv1alpha MountPath: JenkinsBaseConfigurationVolumePath, ReadOnly: true, }, + { + Name: jenkinsUserConfigurationVolumeName, + MountPath: JenkinsUserConfigurationVolumePath, + ReadOnly: true, + }, { Name: jenkinsOperatorCredentialsVolumeName, MountPath: jenkinsOperatorCredentialsVolumePath, @@ -181,6 +191,16 @@ func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *virtuslabv1alpha }, }, }, + { + Name: jenkinsUserConfigurationVolumeName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: GetUserConfigurationConfigMapName(jenkins), + }, + }, + }, + }, { Name: jenkinsOperatorCredentialsVolumeName, VolumeSource: corev1.VolumeSource{ diff --git a/pkg/controller/jenkins/configuration/base/resources/user_configuration_configmap.go b/pkg/controller/jenkins/configuration/base/resources/user_configuration_configmap.go new file mode 100644 index 00000000..d918c4e9 --- /dev/null +++ b/pkg/controller/jenkins/configuration/base/resources/user_configuration_configmap.go @@ -0,0 +1,50 @@ +package resources + +import ( + "fmt" + virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1" + "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const configureTheme = ` +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() +` + +// GetUserConfigurationConfigMapName returns name of Kubernetes config map used to user configuration +func GetUserConfigurationConfigMapName(jenkins *virtuslabv1alpha1.Jenkins) string { + return fmt.Sprintf("%s-user-configuration-%s", constants.OperatorName, jenkins.ObjectMeta.Name) +} + +// NewUserConfigurationConfigMap builds Kubernetes config map used to user configuration +func NewUserConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *virtuslabv1alpha1.Jenkins) *corev1.ConfigMap { + meta.Name = GetUserConfigurationConfigMapName(jenkins) + meta.Labels[constants.LabelWatchKey] = constants.LabelWatchValue // add watch for resource + + return &corev1.ConfigMap{ + TypeMeta: buildConfigMapTypeMeta(), + ObjectMeta: meta, + Data: map[string]string{ + "1-configure-theme.groovy": configureTheme, + }, + } +} diff --git a/pkg/controller/jenkins/configuration/user/reconcile.go b/pkg/controller/jenkins/configuration/user/reconcile.go index 34f602d2..46a22b2f 100644 --- a/pkg/controller/jenkins/configuration/user/reconcile.go +++ b/pkg/controller/jenkins/configuration/user/reconcile.go @@ -1,11 +1,16 @@ package user import ( + "fmt" "time" 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/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" @@ -40,7 +45,7 @@ func (r *ReconcileUserConfiguration) Reconcile() (*reconcile.Result, error) { return result, err } - return nil, nil + return r.userConfiguration(r.jenkinsClient) } func (r *ReconcileUserConfiguration) reconcileSeedJobs() (*reconcile.Result, error) { @@ -64,3 +69,23 @@ func (r *ReconcileUserConfiguration) reconcileSeedJobs() (*reconcile.Result, err } return nil, nil } + +func (r *ReconcileUserConfiguration) userConfiguration(jenkinsClient jenkinsclient.Jenkins) (*reconcile.Result, error) { + groovyClient := groovy.New(jenkinsClient, r.k8sClient, r.logger, fmt.Sprintf("%s-user-configuration", constants.OperatorName), resources.JenkinsUserConfigurationVolumePath) + + err := groovyClient.ConfigureGroovyJob() + if err != nil { + return &reconcile.Result{}, err + } + + done, err := groovyClient.EnsureGroovyJob(theme.SetThemeGroovyScript, r.jenkins) + if err != nil { + return &reconcile.Result{}, err + } + + if !done { + return &reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil + } + + return nil, nil +} diff --git a/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go b/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go index f4166875..784aadc4 100644 --- a/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go +++ b/pkg/controller/jenkins/configuration/user/seedjobs/seedjobs.go @@ -207,7 +207,6 @@ SystemCredentialsProvider.getInstance().getStore().addCredentials(Domain.global( Jenkins jenkins = Jenkins.instance - def jobDslSeedName = "${params.DEPLOY_KEY_ID}-job-dsl-seed" def jobDslDeployKeyName = "${params.DEPLOY_KEY_ID}" def jobRef = jenkins.getItem(jobDslSeedName) @@ -243,7 +242,9 @@ jobRef.setAssignedLabel(new LabelAtom("master")) // disable Job DSL script approval GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).useScriptSecurity=false -GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).save() +GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).save() +jenkins.getQueue().schedule(jobRef) + false diff --git a/pkg/controller/jenkins/constants/labels.go b/pkg/controller/jenkins/constants/labels.go index 93b478b0..6d139b3f 100644 --- a/pkg/controller/jenkins/constants/labels.go +++ b/pkg/controller/jenkins/constants/labels.go @@ -1,11 +1,16 @@ package constants const ( - LabelAppKey = "app" + // LabelAppKey application Kubernetes label name + LabelAppKey = "app" + // LabelAppValue application Kubernetes label value LabelAppValue = OperatorName - LabelWatchKey = "watch" + // LabelWatchKey Kubernetes label used to enable watch for reconcile loop + LabelWatchKey = "watch" + // LabelWatchValue Kubernetes label value to enable watch for reconcile loop LabelWatchValue = "true" + // LabelJenkinsCRKey Kubernetes label name which contains Jenkins CR name LabelJenkinsCRKey = "jenkins-cr" )