Customization with Groovy Scripts and CasC

Customize Operator Service for Jenkins

This tutorial outlines a step by step guide on how to customize a Jenkins instance after successful deployment.

How Jenkins Customization Works

The current configuration mechanism is based on Kubernetes Custom Resource which is automatically created during the installation phase and then used as a customization file by operator. Every time you want to customize Jenkins, it needs to be done in code by modifying the existing Custom Resource file. Any manual changes from the web interface will be overridden by automation or after the Jenkins restart. In the future, we are planning to introduce a web interface and infrastructure as a code SDK to make these changes programmatically without requiring Kubernetes-specific knowledge. The following Sections will show you how to configure Jenkins using Groovy Scripts and Configuration as Code (CasC).

Customization via Groovy Scripts and yamls

Jenkins instance can be customized using Groovy scripts or Configuration as Code (thanks to pre-installed configuration as code plugin). CasC scripts are more readable and simplier to write so this should be your default choice. However, when something is not supported by the CasC plugin or for more complex and low-level configuration Groovy scripts are better. They allow you to use jenkins-internal-api. Let’s take a look at some examples below.

Customization of Jenkins with Groovy Scripts

The overall process of configuration can be divided into:

Creating a Custom Resource JenkinsGroovyScript, which contains the Groovy script you want to execute. Optionally creating a Kubernetes Secret if you need to store secrets like password or certificates.

1. Creating a JenkinsGroovyScript

We need to create a JenkinsGroovyScript config file containing the configuration we want to apply. In the data section we can use Groovy scripts to write configuration code. Since the secret is already present in the Cluster before JenkinsGroovyScript we can safely reference its value.

apiVersion: operator-service.com/v1beta1
kind: JenkinsGroovyScript
metadata:
  name: groovy-script
  namespace: jenkins
  labels:
    operator-service.com/jenkins: jenkins
spec:
  secretRef:
    namespace: jenkins
    name: jenkins-conf-secrets
  data: |
    import jenkins.model.Jenkins

    def systemMessage = "Hello " + secrets

    Jenkins jenkins = Jenkins.getInstance()
    jenkins.setSystemMessage(systemMessage)
    jenkins.save()    

Now we can safely create this JenkinsGroovyScript.

$ kubectl apply -f jenkins-groovy-script.yaml 

2. Creating Secret

In case we want to use confidential data, we have to start by creating a Secret resource to wrap it in. Kubernetes stores secrets in base64 format, so we have to encode it. Running:

$ echo -n "Hello World" | base64

will produce the following output:

SGVsbG8gd29ybGQ=

which we can place in a Secret config file as the value of secrets key.

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: jenkins-conf-secrets
  namespace: jenkins
data:
  SYSTEM_MESSAGE: SGVsbG8gd29ybGQ=

We have to create the Secret resource in Kubernetes using this config file, and save it somewhere in the catalogue, for example in deploy folder.

$ kubectl apply -f deploy/secret.yaml

This event will trigger the Jenkins Groovy script reconcile loop and our configuration will be applied automatically. You will see a tiny “Hello World” on the main page.

Customization of Jenkins with Configuration as Code (CasC)

The overall process of customization can be divided into:

Creating a JenkinsConfigurationAsCode Custom Resource, which contains configuration code in the data section. Optionally creating a Kubernetes Secret if you need to store secrets like passwords or certificates.

1.Creating Secret config file and creating it in Kubernetes as a resource

In case we want to use confidential data, we have to start by creating a Secret resource to wrap it in. Since it’s a secret, it would be a good idea to encode it. Type the following on the command line:

$ echo -n "Hello World" | base64

The output is

SGVsbG8gd29ybGQ=

Now we can place it in the Secret config file as the value of the SYSTEM_MESSAGE key.

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: jenkins-conf-secrets
  namespace: jenkins
data:
  SYSTEM_MESSAGE: SGVsbG8gd29ybGQ=

We need to create the Secret resource in Kubernetes using this config file and save it somewhere in the catalogue, for example in deploy folder.

$ kubectl -n jenkins apply -f deploy/secret.yaml

2. Creating JekinsConfigurationAsCode

We need to create a JekinsConfigurationAsCode config file containing the configuration we want to apply. In the data field value we can use yaml syntax to add fields with the configuration code. Since the secret is already present in the Cluster before JekinsConfigurationAsCode we can safely reference its value.

apiVersion: operator-service.com/v1beta1
kind: JenkinsConfigurationAsCode
metadata:
  name: op-svc-jenkins-user-configuration
  namespace: jenkins
  labels:
    operator-service.com/jenkins: jenkins
spec:
  secretRef:
    namespace: jenkins
    name: jenkins-conf-secrets
data: |
    jenkins:
      systemMessage: ${SYSTEM_MESSAGE}    

Now we can safely create this JenkinsConfigurationAsCode with following command:

$ kubectl -n jenkins apply -f jenkins-casc.yaml

Our Jenkins instance will see it and can bind it to previously created Secret, thanks to references we created. This event will trigger the CasC reconcile loop and our configuration will be applied. You will see a tiny “Hello World” on the main page.