Templates Webinar Follow-up Q&A

Written by: Stephen Connolly

Last Tuesday I ran a webinar on the Jenkins Enterprise Templates functionality. There were a number of follow-up questions that attendees had, so in this post I will try my best to group similar questions together and answer them.

Q. Are templates available in the new version only? We are on Jenkins 1.502, I do not see the template option? etc.

In life, some things are free much as the way the air that we breathe is free (unless you live on planet spaceball ), some things are free much as the beer in “tell me your name and you can have a beer,” and some things you have to pay for.

In Jenkins, some plugins written by CloudBees are free (as in free air) for example the Credentials plugin ; some plugins written by CloudBees are free (as in “tell me your name and you can have a beer”) such as the Folders plugin ; and then there are the Jenkins Enterprise by CloudBees plugins , which you have to pay for.

The Templates plugin is one of those plugins that requires a Jenkins Enterprise license. You can try the Jenkins Enterprise plugins out with an evaluation license, but after the trial period expires you will face the choice of either paying for a Jenkins Enterprise license (that also includes technical support from CloudBees) or uninstalling the Jenkins Enterprise plugins.

There are a number of options for getting Jenkins Enterprise, but the two easiest routes are:

  • You can just download one of the pre-packaged Jenkins Enterprise distributions and replace your existing OSS jenkins.war with a Jenkins Enterprise jenkins.war. This works best if you are on an LTS release (as we have drop-in builds for all of the LTS versions of Jenkins that we support).

  • You can use the meta-plugin to convert any version of Jenkins OSS into Jenkins Enterprise (i.e., install all the plugins).This will require that you are on at least Jenkins 1.509 or newer (as a side-effect of the fox for JENKINS-10502 breaking backwards compatibility).

Due to the way our support terms work, it is best to go for one of the pre-packaged Jenkins Enterprise distributions, but if you need a fix/feature in a newer version of Jenkins OSS, the meta-plugin can give you the Jenkins Enterprise features until that fix/feature is picked up by the next LTS.

Q. Can we have a community where we can share these templates with each other, this way we have a quick ramp up? It would be nice if we have some more examples for reference?

This type of feature is on our roadmap awaiting product management to schedule. I have also asked for the simpler idea of a shared public repository as that would be easy to get in place.

Q. Is it possible to set a default value for all builds in a Jenkins instance with the templates? (I would like to set the “Discard Old Builds » Max # of builds to keep” to 20 and the “Archive the artifacts » Discard all but the last…” to true for all builds)

The answer to this is a qualified yes.

First off, templates can only control the jobs that are based on the template. So you cannot force every single job in Jenkins to have Discard Old Builds » Max # of builds to keep = 20, but you can force all the jobs based on the XYZ template to have Discard Old Builds » Max # of builds to keep = 20 (or whatever it is you want).

So if you let people create freestyle jobs or any of the other job types directly (i.e., without using a template) then those non-template based jobs will be free to ignore your edicts.

Using the Jenkins Enterprise Role-based Access Control (RBAC) plugin and using our Folders plugin you can restrict people from creating jobs outside of folders and you can restrict the job types that can be created within folders to only those templates that you approve… in other words, you can make it so that the only jobs in your instance are template backed jobs.

Now to the specifics, basically in your template transformer you just need to ensure that the correct config.xml is generated, so you could just include the relevant values, so you would probably have something like:

<?xml version='1.0' encoding='UTF-8'?> <project>
  ...
  <logRotator>
    ...
    <strong>&#x3C;artifactNumToKeep>20&#x3C;/artifactNumToKeep></strong>   &#x3C;/logRotator>
  ...
  &#x3C;publishers>     &#x3C;hudson.tasks.ArtifactArchiver>
      ...
      <strong>&#x3C;latestOnly>true&#x3C;/latestOnly></strong>     &#x3C;/hudson.tasks.ArtifactArchiver>   &#x3C;/publishers>
  ...
&#x3C;/project>

For more finesse, you could define some attributes:

and then use an EL expression to pull those values in:

Q. How hard is it to define a few default job settings for the template and then allow jobs created using the template to fully configure a job accessing all the available plugins in Jenkins except those defined in the template?

This really depends on which plugins you want to lock down with the templates plugin.

If you want to default some things like artifact retention and source control system and leave the rest of the job free for configuration by your users, that is easy to achieve. You just add attributes for configuring the locked down sections and fully specify those locked down sections in your build.

If, on the other hand, you want to force that, for example, all Maven build steps must be just so, but then let the user add whatever other build steps they want (except Maven) then you will hit issues.

The key here is that there are fundamentally three routes to achieve this functionality, in each case you will be adding an attribute… the question is what kind of attribute.

  • You can add a “Heterogeneous components from descriptors” attribute that lets people add multiple ‘items’ of a specific type in Jenkins, e.g. just like the ‘Build Steps’ in the freestyle project type.

  • You can add a “Heterogeneous components from descriptors (only one instance per descriptor)” that lets people select from multiple types of objects and choose to either add some or none, but configure them as they see fit, e.g. just like the ‘Publishers’ in the freestyle project type.

  • You can add a “Single Describable object” which allows one and only one instance, but the user can select the type of object from all the available subclasses of that type, e.g. just like the ‘SCM’ in the freestyle project type.

  • Finally, you can create auxiliary models for each type you want to be included, allowing control over how those specific types can be used, and then allow the user to either pick one or many of those auxiliary models, e.g. you can have this behave like any of the previous options, but by only creating the auxiliary model types that you want people to be able to instantiate, you can control what bits they can create.

In each case you are going to end up with a chunk of model XML that gets inserted into your template when the template is instantiated. If we look at the freetyle job type base XML, we see something like:

&#x3C;?xml version='1.0' encoding='UTF-8'?>
 &#x3C;project>
   &#x3C;actions/>
   &#x3C;description/>
   &#x3C;logRotator/>
   &#x3C;/logRotator>
   &#x3C;keepDependencies/>
   <strong>&#x3C;properties/></strong> 
    … &#x3C;!-- can have multiple entries here, one of each type -->
  <strong>&#x3C;/properties></strong> 
   <strong>&#x3C;scm></strong> 
… &#x3C;!-- can have one entry here -->
<strong>&#x3C;/scm></strong> 
   &#x3C;canRoam/>
   &#x3C;disabled/>
   &#x3C;blockBuildWhenDownstreamBuilding/>
   &#x3C;blockBuildWhenUpstreamBuilding/>
   &#x3C;jdk/>
   <strong>&#x3C;triggers></strong> 
    … &#x3C;!-- can have multiple entries here, one of each type -->
  <strong>&#x3C;/triggers></strong> 
   &#x3C;concurrentBuild/>
   <strong>&#x3C;builders></strong> 
    … &#x3C;!-- can have multiple entries here, many of each type -->
  <strong>&#x3C;/builders>
   &#x3C;publishers></strong> 
    … &#x3C;!-- can have multiple entries here, one of each type -->
  <strong>&#x3C;/publishers>
   &#x3C;buildWrappers></strong> 
    … &#x3C;!-- can have multiple entries here, one of each type -->
  <strong>&#x3C;/buildWrappers></strong> 
&#x3C;/project>

Now I have highlighted the sections where you would be injecting the attribute XML. If the bit you want to lock down is in the same block as the bit where you want flexibility, then you are facing a difficult challenge. If you want the flexibility in a different block, then you are on easy street.

So, say you want to mandate that all projects build with ANT, you have defined an attribute for the ANT goal and you define the build step that goes in the “<builders>” section. If you want to give full free-form for the publishers, that is easy. On the other hand if you want to allow the addition of additional builders after the ANT build while removing the use of the ANT build step in these additional builders then you face the only way you can currently enforce that restriction is by using auxiliary models, which is not pretty. The area where you are most likely to hit this issue though, is the “<publishers>” section as you may want to enforce artifact archiving and fingerprinting but allow users to add in, e.g. code quality or unit test reporting.

It is very easy to do that, but just a lot of work defining the auxiliary template tree to use to enforce the restriction… we have a roadmap RFE to address this issue though.

TL;DR If you want to lock down in a different bag from the bag that gets flexibility then easy, otherwise not hard but a lot of work.

Q. Do we have an equivalent plugin available in open source Jenkins which can be used as template plugin?

There are a number of plugins in this space, including:

None of these fully provide the flexibility and power provided by the CloudBees templates plugin… but we would say that wouldn't we? ;-)

Q. Can I get access to the CloudBees templates and GitHub repository used in the webinar?

No problem! The GitHub repository is easy to find. And I have added a repository to hold the templates used in the webinar .

Stephen Connolly
Elite Developer and Architect
CloudBees

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.