Logo

MacStadium Blog

Automating Jenkins Deployments in K8s with Docker and Groovy - Part II

In part 2, learn to incorporate an additional Groovy Init Hook script that will install and configure the Orka plugin for Jenkins.

In our last installment of “How to K8s,” we introduced the concepts needed to automate the deployment of a Jenkins server to Kubernetes. We did so through a look at the process of automating user creation upon startup of a dockerized Jenkins server.

Today, we will build upon that foundation as we incorporate additional Groovy code to our Groovy Init Hook script that will install and configure the Orka plugin for Jenkins. This will enable this Jenkins server to execute jobs in a MacStadium’s Orka for macOS and iOS CI. The principles covered here can easily be adapted to other cloud providers with a Jenkins integration plugin.

As we introduced each of the three files discussed here in the previous post, we will move it along and just highlight the additions. The full source code is available here.

Dockerfile

This file, aside from the introduction of the ENV variables, is what we were working with in the previous post. Check it out for any missing details. Briefly, we are copying in our plugins, installing them, and copying our Groovy Init Hook script, init-cloud.groovy.

# Dockerfile

FROM jenkins/jenkins:lts

ENV JENKINS_USER admin
ENV JENKINS_PASS admin

# Skip initial setup
ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false

COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt

COPY init-cloud.groovy /usr/share/jenkins/ref/init.groovy.d/init-cloud.groovy

plugins.txt

Simply a text file containing a list of required plugins. Formatting is as so: <plugin>:<tag></tag></plugin>.

# plugins.txt

credentials-binding:latest
embeddable-build-status:latest
ssh-agent:latest
timestamper:latest
gradle:latest
workflow-aggregator:latest
git:latest
git-parameter:latest
ssh-slaves:latest
greenballs:latest
macstadium-orka:latest

init-cloud.groovy

This is the meat of our work today. As you can see, our list of imports has grown considerably.

#!/usr/bin/env groovy

import com.cloudbees.plugins.credentials.Credentials
import com.cloudbees.plugins.credentials.CredentialsScope
import com.cloudbees.plugins.credentials.domains.Domain
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
import com.cloudbees.plugins.credentials.SystemCredentialsProvider
import hudson.model.AdministrativeMonitor
import hudson.model.Node.Mode
import io.jenkins.plugins.orka.OrkaCloud
import io.jenkins.plugins.orka.AgentTemplate
import io.jenkins.plugins.orka.RunOnceCloudRetentionStrategy
import java.util.ArrayList
import java.util.Collections
import jenkins.model.Jenkins

In addition to the credentials plugin we handled last time, we now also have to account for our interface with Orka. As such, we will have to import plugins to configure our build templates.

After handling our imports, we will continue in the same Groovy file and initialize our required variables. Notice that ORKA_ENDPOINT, ORKA_USERNAME and ORKA_PASSWORD are required values.

String orkaEndpoint = System.getenv()['ORKA_ENDPOINT'];

String orkaUsername = System.getenv()['ORKA_USERNAME'];
String orkaPassword = System.getenv()['ORKA_PASSWORD'];
String sshUsername =  System.getenv()['SSH_USERNAME'] ?: "admin"
String sshPassword =  System.getenv()['SSH_PASSWORD'] ?: "admin"

String vmConfigName = System.getenv()['VM_CONFIG_NAME'] ?: "orka-jenkins"
String vmBaseImage = System.getenv()['VM_BASE_IMAGE'];
String vmCpuCountString = System.getenv()['VM_CPU_COUNT'] ?: 3
int vmCpuCount = Integer.parseInt(vmCpuCountString);
String agentLabel = System.getenv()['AGENT_LABEL'] ?: "orka"

String remoteFs = System.getenv()['REMOTE_FS_ROOT'] ?: "/Users/admin"

String sshUserCredentialsId = java.util.UUID.randomUUID().toString()
String orkaUserCredentialsId = java.util.UUID.randomUUID().toString()

With our variables assigned, we can generate both tiers of our required credentials.

Credentials sshCredentials = (Credentials) new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, sshUserCredentialsId, "VM SSH credentials", sshUsername, sshPassword)
SystemCredentialsProvider.getInstance().getStore().addCredentials(Domain.global(), sshCredentials)

Credentials orkaCredentials = (Credentials) new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, orkaUserCredentialsId, "Orka credentials", orkaUsername, orkaPassword)
SystemCredentialsProvider.getInstance().getStore().addCredentials(Domain.global(), orkaCredentials)

Finally, with all our pieces in hand, we can generate our build agent template, pass that in the instantiation of our OrkaCloud, pass our cloud instance to Jenkins, disable various administrativeMonitors, and finally save the updated Jenkins instance.

AgentTemplate template = new AgentTemplate(sshUserCredentialsId, null, true, vmConfigName,
   vmBaseImage, vmCpuCount, 1, remoteFs,
   Mode.NORMAL, agentLabel, new RunOnceCloudRetentionStrategy(5), Collections.emptyList());

ArrayList<agenttemplate> templates = new ArrayList<agenttemplate>()</agenttemplate></agenttemplate>
templates.add(template)

OrkaCloud cloud = new OrkaCloud("Orka Cloud", orkaUserCredentialsId, orkaEndpoint, null, templates)

Jenkins.instance.clouds.add(cloud)

Jenkins.instance.administrativeMonitors.each { x->
   String name = x.getClass().name
   if (name.contains("SecurityIsOffMonitor") ||
       name.contains("URICheckEncodingMonitor") ||
       name.contains("UpdateCenter") ||
       name.contains("UpdateSiteWarningsMonitor") ||
       name.contains("RootUrlNotSetMonitor") ||
       name.contains("CSRFAdministrativeMonitor")) {
       x.disable(true)
   }
}

Jenkins.instance.save()

TL;DR

Today, we have taken what we learned in the previous “How to K8s” post, and extended it so that Jenkins can actually create and communicate with an Orka environment. This process is fully automated to include the creation of a Jenkins user. To learn more, check out How to K8s: Jenkins Deployments in Kubernetes with Docker and Groovy.

Logo

Orka, Orka Workspace and Orka Pulse are trademarks of MacStadium, Inc. Apple, Mac, Mac mini, Mac Pro, Mac Studio, and macOS are trademarks of Apple Inc. The names and logos of third-party products and companies shown on the website are the property of their respective owners and may also be trademarked.

©2023 MacStadium, Inc. is a U.S. corporation headquartered at 3525 Piedmont Road, NE, Building 7, Suite 700, Atlanta, GA 30305. MacStadium, Ltd. is registered in Ireland, company no. 562354.