Customize Jenkins with Configuration as Code

This document shows how to customize Jenkins with Configuration as Code (CasC).
CasC is applied to Jenkins before Groovy scripts.

Prerequisites

This tutorial assumes you have a running Jenkins instance set up, and that no JenkinsConfigurationAsCode CR (Custom Resources) has been created for that Jenkins instance.

If you haven’t installed Jenkins with Operator yet, visit Installation section to find out how to do it.

Below you can learn how to use JenkinsConfigurationAsCode CRs.

Users can only create 1 JenkinsConfigurationAsCode CR for a given Jenkins instance. Creating more will result in validation errors, which can be found in logs from Operator.

Using Configuration As Code without Secrets

If you don’t need to use any secret data in CasC, you only have to create JenkinsConfigurationAsCode CR.

Below you can find a yaml manifest containing an example JenkinsConfigurationAsCode CR. Copy it to a file, change jenkins-namespace and jenkins-cr-name to the namespace and name of Jenkins instance you’re customizing, then kubectl apply it.

Note the spec.data field - this is where you put your CasC configuration. When using your own configuration, you can paste the content of your CasC configuration file here - just remember to properly indent it.
apiVersion: carthago.cloud/v1beta1
kind: JenkinsConfigurationAsCode
metadata:
  name: carthago-op-jenkins-user-configuration
  namespace: <jenkins-namespace>
  labels:
    carthago.cloud/jenkins: <jenkins-cr-name>
spec:
  data: |
    jenkins:
      systemMessage: "Hello world!"    

This event will trigger JenkinsConfigurationAsCode reconcile loop and our configuration will be applied.

You should see “Hello World!” message in Jenkins dashboard.

Using Configuration As Code with Secrets

If you need to use confidential data in CasC, you have to start by creating a Secret resource to wrap it in. Then you can reference it in JenkinsConfigurationAsCode CR.

Creating a Secret with data to use in CasC

Kubernetes stores secrets in base64 format, so we have to encode our data. Running:

$ echo -n "Hello World!" | base64

will produce the following output:

SGVsbG8gd29ybGQ=

which we can use to create a Secret, so that we can safely access this data in Configuration As Code.

Copy the Secret manifest you can find below to a file, change jenkins-namespace to the namespace of Jenkins instance you’re customizing, then kubectl apply it.

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

Creating JekinsConfigurationAsCode CR

We still need to create JenkinsConfigurationAsCode CR containing the configuration we want to apply.

Since the secret is already present in the Cluster before we create JekinsConfigurationAsCode, we can safely reference its value in spec.secretRef section.

Below you can find JenkinsConfigurationAsCode manifest referencing the secret created earlier. Copy it to a file, change jenkins-namespace and jenkins-cr-name to the namespace and name of Jenkins instance you’re customizing, then kubectl apply it.

apiVersion: carthago.cloud/v1beta1
kind: JenkinsConfigurationAsCode
metadata:
  name: carthago-op-jenkins-user-configuration
  namespace: <jenkins-namespace>
  labels:
    carthago.cloud/jenkins: <jenkins-cr-name>
spec:
  secretRef:
    namespace: <jenkins-namespace>
      name: jenkins-conf-secrets
  data: |
    jenkins:
      systemMessage: ${SYSTEM_MESSAGE}    

This event will trigger JenkinsConfigurationAsCode reconcile loop and our configuration will be applied.

Our Jenkins instance will see it and bind it to previously created Secret, thanks to the reference we provided.

You should see “Hello World!” message in Jenkins dashboard.