I am trying to create views programmatically when a Jenkins instance starts up.
We have a very automated cattle approach to our instances, and thus there is no “admin access” to customize an instance once it has been created.
My groovy code that implements the “create custom views” is (init.groovy.d/A998AddCustomViews.groovy):
import jenkins.model.Jenkins
import hudson.model.ListView
import java.util.logging.Logger
import org.yaml.snakeyaml.Yaml
Logger logger = Logger.getLogger('Custom Views')
logger.info("Custom Views -> Downloading custom views")
Yaml yaml = new Yaml()
String virtualHost = System.getenv('VIRTUAL_HOST')
virtualHost = virtualHost.toLowerCase()
String[] hostName = virtualHost.split('<REDACTED FQDN>')
String githubUrl = 'https://<URL to views.yaml>'
String viewsFile = "${githubUrl}/${hostName[0]}/views.yaml"
logger.info('Custom Views -> viewsFile URL: ' + viewsFile)
try {
logger.info('Custom Views -> Loading contents of views.yaml')
String viewsYaml = new URL(viewsFile).getText()
Map viewsMap = (Map) yaml.load(viewsYaml)
if (viewsMap.containsKey('jenkins')) {
Map tmpMap = viewsMap.jenkins
if (tmpMap.size() == 1 && tmpMap.containsKey('views')) {
logger.debug('Custom Views -> views.yaml contains views key')
List viewsList = tmpMap.views
instance = Jenkins.getInstanceOrNull()
instance.getViews().each { view ->
logger.info("Custom Views -> Existing view ${view.name}")
}
viewsList.each { input ->
input.each { key, value ->
logger.info("Custom Views -> Creating view ${value.name}")
switch (key) {
case "list":
ListView listView = new ListView(value.name)
listView.setColumns(value.columns)
listView.setJobNames((value.jobNames).flatten() as Set)
listView.setRecurse(value.recurse)
instance.addView(listView)
break
case "buildMonitor":
logger.info('Custom Views -> BuildMonitorView not supported yet')
break
case "myView":
logger.info('Custom Views -> myView not supported yet')
break
}
logger.info("Custom Views -> Get Views: ${instance.getViews()}")
}
}
logger.info('Custom Views -> Saving views')
instance.save()
logger.info("Custom Views -> Get all views: ${instance.getViews()}")
} else {
logger.severe('Custom Views -> views.yaml not formatted correctly!')
logger.severe(' -> Missing views or contains other keys - Aborting load')
}
} else {
logger.severe('Custom Views -> views.yaml not formatted correctly!')
logger.severe(' -> Missing jenkins - Aborting load')
}
} catch (FileNotFoundException e) {
logger.info('Custom Views -> No customization file found')
} catch (IllegalStateException e) {
logger.severe("Custom Views -> Exception caught: ${e.exception()}")
}
An example of a views.yaml file:
---
jenkins:
views:
- list:
name: "viewList1"
columns:
- "status"
- "weather"
- "jobName"
- "lastSuccess"
- "lastFailure"
- "lastDuration"
- "buildButton"
- "favoriteColumn"
jobNames:
- "jenkins-ci-test/aws-bundle-sample"
- "jenkins-ci-test/currentBuild.Result"
- "jenkins-ci-test/java-ee-sampleapp"
- "jenkins-ci-test/module-sample-app"
- "jenkins-ci-test/multiple-docker-builds"
- "jenkins-ci-test/multiple-java-installations"
- "jenkins-ci-test/multiple-nodejs-installations"
- "jenkins-ci-test/nytland-ping-test"
recurse: true
- list:
name: "viewList2"
columns:
- "status"
- "weather"
- "jobName"
jobNames:
- "jenkins-ci-test/autotaks-inbox-monitoring-lambda"
- "jenkins-ci-test/aws-bundle-sample-internal"
recurse: true
- buildMonitor:
name: "buildMonitor1"
includeRegex: ".*"
recurse: true
title: "buildMonitor1"
- buildMonitor:
name: "buildMonitor2"
includeRegex: ".*sample.*"
recurse: true
title: "buildMonitor2"
- myView:
description: "test hset"
name: "myView1"
The log tells me everything went well, however when I access the instance, there are no added views.
Any help will be appreciated.
Log output:
2023-05-04 08:25:41.974+0000 [id=30] INFO j.util.groovy.GroovyHookScript#execute: Executing /var/jenkins_home/init.groovy.d/A998AddCustomViews.groovy
2023-05-04 08:25:42.174+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> Downloading custom views
2023-05-04 08:25:42.176+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> viewsFile URL: https://<URL to views.yaml>/views.yaml
2023-05-04 08:25:42.176+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> Loading contents of views.yaml
2023-05-04 08:25:42.312+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> views.yaml contains views key
2023-05-04 08:25:42.317+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Existing view all
2023-05-04 08:25:42.318+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Creating view viewList1
2023-05-04 08:25:42.344+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Get Views: [hudson.model.AllView@25544e98[view/all/], hudson.model.ListView@2cc9a4fb[view/viewList1/]]
2023-05-04 08:25:42.344+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Creating view viewList2
2023-05-04 08:25:42.352+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Get Views: [hudson.model.AllView@25544e98[view/all/], hudson.model.ListView@2cc9a4fb[view/viewList1/], hudson.model.ListView@55020e7a[view/viewList2/]]
2023-05-04 08:25:42.352+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Creating view buildMonitor1
2023-05-04 08:25:42.353+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> buildMonitor -> [name:buildMonitor1, includeRegex:.*, recurse:true, title:buildMonitor1]
2023-05-04 08:25:42.353+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> BuildMonitorView not supported yet
2023-05-04 08:25:42.353+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Get Views: [hudson.model.AllView@25544e98[view/all/], hudson.model.ListView@2cc9a4fb[view/viewList1/], hudson.model.ListView@55020e7a[view/viewList2/]]
2023-05-04 08:25:42.353+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Creating view buildMonitor2
2023-05-04 08:25:42.353+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> buildMonitor -> [name:buildMonitor2, includeRegex:.*sample.*, recurse:true, title:buildMonitor2]
2023-05-04 08:25:42.354+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> BuildMonitorView not supported yet
2023-05-04 08:25:42.354+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Get Views: [hudson.model.AllView@25544e98[view/all/], hudson.model.ListView@2cc9a4fb[view/viewList1/], hudson.model.ListView@55020e7a[view/viewList2/]]
2023-05-04 08:25:42.354+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Creating view myView1
2023-05-04 08:25:42.354+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> myView not supported yet
2023-05-04 08:25:42.354+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Get Views: [hudson.model.AllView@25544e98[view/all/], hudson.model.ListView@2cc9a4fb[view/viewList1/], hudson.model.ListView@55020e7a[view/viewList2/]]
2023-05-04 08:25:42.354+0000 [id=30] INFO java_util_logging_Logger$info$0#call: Custom Views -> Saving views
2023-05-04 08:25:42.362+0000 [id=30] INFO o.c.g.r.c.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap#invoke: Custom Views -> Get all views: [hudson.model.AllView@25544e98[view/all/], hudson.model.ListView@2cc9a4fb[view/viewList1/], hudson.model.ListView@55020e7a[view/viewList2/]]