Jenkins API to update library configuration - jenkins

I am trying to update a library in "Configuration" we use in Jenkins through Python, but do not see any way to do this through Jenkins API. Is there a way to update the version to 1.1.0 via Jenkins API?

Assuming you are ok with using a groovy script to configure the library version, you can use the following script to set the default version of an Global existing library:
def jenkins = Jenkins.getInstance()
def globalLibraryDescriptor = jenkins.getDescriptor("org.jenkinsci.plugins.workflow.libs.GlobalLibraries")
def config = globalLibraryDescriptor.getLibraries().find {
it.name == '1.1.0' // Find your existing library by name
}
config.setDefaultVersion("THE_NEW_VERION") // Update the default version value
If you also want to create library configurations in the global settings via API you can use the following script as a usage example for the groovy API.
If you want to configure a Folder level Existing library you can use the following code:
def jenkins = Jenkins.getInstance()
def folderLibrary = jenkins.getItem("FOLDER_NAME").getProperties().find {it.class =~ 'FolderLibraries'}
def config = folderLibrary.getLibraries().find {
it.name == '1.1.0' // Find your existing library by name
}
config.setDefaultVersion("THE_NEW_VERION") // Update the default version value

Update: We got it to work with Shared Library using the following code (if anyone runs into needing this to work):
for (LibraryResolver resolver : ExtensionList.lookup(LibraryResolver.class)) {
for (LibraryConfiguration cfg : resolver.forJob(currentBuild.rawBuild.getParent(), [:])) {
if (cfg.getName == libraryName){
cfg.setDefaultVersion("1.1.0")
}
}
}

Related

Access managed files, local files and remote files ssh during Jenkins pre-build stages

I have a parametrized build and I'd like to populate parameter values based on contents of files/directories on the local slave and/or on a remote box accessible via ssh.
It's not a problem to access local and remote files during build stages, but I need to make it work in an Active Choice Plugin (or something similar).
Apparently, sh function doesn't work, but some Java-like Groovy API is still available (as described here: https://wiki.jenkins.io/display/JENKINS/Active+Choices+Plugin)
jenkinsURL=jenkins.model.Jenkins.instance.getRootUrl()
def propFile=vPropFile //name of properties file
def propKey=vPropKey // name of properties key
def relPropFileUrl=vRelPropFileUrl // userContent/properties/
def propAddress="${jenkinsURL}${relPropFileUrl}$propFile"
def props= new Properties()
props.load(new URL(propAddress).openStream())
def choices=[]
props.get(propKey.toString()).split(",").each{
choices.add(it)
}
return choices
I wonder if it's possible to access managed files the same way or better yet to access something remotely using SSH.
Is there an API for that?
I couldn't find a solution that would allow to SSH during during Active Choices parameter script execution.
However, I was able to use configuration file(s) managed by Jenkins. Here's the code that can be run from the Active Choices parameter script:
def gcf = org.jenkinsci.plugins.configfiles.GlobalConfigFiles.get()
// Read different file based on referencedParameter ENVIRONMENT
def deploymentFileName = 'deployment.' + ENVIRONMENT + '.properties'
def deploymentFile = gcf.getById(deploymentFileName)
def deploymentProperties = new Properties();
deploymentProperties.load(new java.io.StringReader(deploymentFile.content))
def choices = []
// Make use of Properties object here to return list of choices
return choices
Later in the main Groovy Script of the pipeline it's possible to update file the same way, but the file has to be read/loaded again as the script context is different:
def gcf = org.jenkinsci.plugins.configfiles.GlobalConfigFiles.get()
def deploymentFile = gcf.getById(deploymentFileName)
def deploymentProperties.load(new java.io.StringReader(deploymentFile.content))
// Update deploymentProperties as necessary here.
def stringWriter = new java.io.StringWriter()
deploymentProperties.store(stringWriter, "comments")
// Content of the deploymentFile object is immutable.
// So need to create new instance and reuse the same file id to overwrite the file.
def newDeploymentFile = deploymentFile.getDescriptor().newConfig(
deploymentFile.id, deploymentFile.name, deploymentFile.comment, stringWriter.toString())
gcf.save(newDeploymentFile)
Of course, all necessary API permissions have to be granted in Jenkins.

Groovy Missing Property Exception

I have a jenkins build that needs to get the filenames for all files checked in within a changeset.
I have installed groovy on the slave computer and configured Jenkins to use it. I am running the below script that should return the names (or so I assume as this may be wrong as well) and print to the console screen however I am getting this error:
groovy.lang.MissingPropertyException: No such property: paths for class: hudson.plugins.tfs.model.ChangeSet
Here is the Groovy System Script:
import hudson.plugins.tfs.model.ChangeSet
// work with current build
def build = Thread.currentThread()?.executable
// get ChangesSets with all changed items
def changeSet= build.getChangeSet()
def items = changeSet.getItems()
def affectedFiles = items.collect { it.paths }
// get file names
def fileNames = affectedFiles.flatten().findResults
fileNames.each {
println "Item: $it" // `it` is an implicit parameter corresponding to the current element
}
I am very new to Groovy and Jenkins so if its syntax issue or if I'm missing a step please let me know.
I don't know the version of jenkins you are using but according to the sourcecode of ChangeSet that you can find here I suggest you to replace line 9 with:
def affectedFiles = items.collect { it.getAffectedPaths() }
// or with the equivalent more groovy-idiomatic version
def affectedFiles = items.collect { it.affectedPaths }
Feel free to comment the answer if there will be more issues.

Jenkins: Configure ActiveDirectorySecurityRealm Plugin using Groovy

I'm currently spending some time setting up a generic configuration using Jenkins AD-SecurityRealm (ActiveDirectorySecurityRealm) Plugin (v2.6) and stuck over a nasty issue: It seems that my approach to (auto) set up a valid AD-connection (following the corresponding documentation) is not working at all. Every time I'll re-init my Jenkins instance an incomplete config.xml will provide - the "bindName" property (XML-node) is always missing. This property is required by the ad-server I'll use and so I've to override the config manually to solve this issue.
I haven't the vaguest idea why this still happens.
my groovy code (excerpt)
String _domain = 'my-primary-ad-server-running.acme.org'
String _site = 'jenkins.acme.org'
String _bindName = 'ad-bind-user'
String _bindPassword = 'ad-bind-password-super-secret-123'
String _server = 'my-primary-ad-server-running.acme.org'
def hudsonActiveDirectoryRealm = new ActiveDirectorySecurityRealm(_domain, _site, _bindName, _bindPassword, _server)
def instance = Jenkins.getInstance()
instance.setSecurityRealm(hudsonActiveDirectoryRealm)
instance.save()
my config.xml result (excerpt)
<securityRealm class="hudson.plugins.active_directory.ActiveDirectorySecurityRealm" plugin="active-directory#2.6">
<domains>
<hudson.plugins.active__directory.ActiveDirectoryDomain>
<name>my-primary-ad-server-running.acme.org</name>
<servers>my-primary-ad-server-running.acme.org:3268</servers>
<bindPassword>{###-fancy-crypted-super-password-nobody-can-decrypt-anymore-###}</bindPassword>
</hudson.plugins.active__directory.ActiveDirectoryDomain>
</domains>
<startTls>true</startTls>
<groupLookupStrategy>AUTO</groupLookupStrategy>
<removeIrrelevantGroups>false</removeIrrelevantGroups>
<tlsConfiguration>TRUST_ALL_CERTIFICATES</tlsConfiguration>
</securityRealm>
my config.xml required (excerpt)
<securityRealm class="hudson.plugins.active_directory.ActiveDirectorySecurityRealm" plugin="active-directory#2.6">
<domains>
<hudson.plugins.active__directory.ActiveDirectoryDomain>
<name>my-primary-ad-server-running.acme.org</name>
<servers>my-primary-ad-server-running.acme.org:3268</servers>
<bindName>ad-bind-user</bindName>
<bindPassword>{###-fancy-crypted-super-password-nobody-can-decrypt-anymore-###}</bindPassword>
</hudson.plugins.active__directory.ActiveDirectoryDomain>
</domains>
<startTls>true</startTls>
<groupLookupStrategy>AUTO</groupLookupStrategy>
<removeIrrelevantGroups>false</removeIrrelevantGroups>
<tlsConfiguration>TRUST_ALL_CERTIFICATES</tlsConfiguration>
</securityRealm>
Thanks #kosta.
Following script also works using active-directory 2.10 and jenkins 2.150.1
This also include site information.
import hudson.plugins.active_directory.ActiveDirectoryDomain
import hudson.plugins.active_directory.ActiveDirectorySecurityRealm
import hudson.plugins.active_directory.GroupLookupStrategy
String _domain = 'dev.test.com'
String _site = 'HQ'
String _bindName = 'dev\jenkins'
String _bindPassword = 'test'
String _server = 'dev.test.com:2328'
def hudsonActiveDirectoryRealm = new ActiveDirectorySecurityRealm(_domain, _site, _bindName, _bindPassword, _server)
hudsonActiveDirectoryRealm.getDomains().each({
it.bindName = hudsonActiveDirectoryRealm.bindName
it.bindPassword = hudsonActiveDirectoryRealm.bindPassword
it.site = hudsonActiveDirectoryRealm.site
})
def instance = Jenkins.getInstance()
instance.setSecurityRealm(hudsonActiveDirectoryRealm)
instance.save()
Check this screenshot: Configure Global Security
If you look at the source code for ActiveDirectorySecurityRealm you will see that the bindName is marked as transient, thus it won't be persisted as part of the config XML.
The only solution to get the desired config.xml is to force the config.xml by providing a custom static one and not use the init script.
I was able to solve this issue by adding the following code at the end (Tested on 2.6 and 2.8). You also need to make sure that your credentials are valid because the plugin is doing an initial connectivity check https://issues.jenkins-ci.org/browse/JENKINS-48513
hudsonActiveDirectoryRealm.getDomains().each({
it.bindName = hudsonActiveDirectoryRealm.bindName
it.bindPassword = hudsonActiveDirectoryRealm.bindPassword
})
instance.setSecurityRealm(hudsonActiveDirectoryRealm)
instance.save()

eventConfigureTomcat Access to Config.groovy

Grails 2.5.0
I'm defining an alternate context root via _Events.groovy using the eventConfigureTomcat closure. To do this, I've got code like so..
eventConfigureTomcat = { tomcat ->
def newContextRoot = "/"
def newContextPath = new File("/full/path/to/context/root")
// more code below that doesn't matter for this question...
}
For the newContextPath I want to pull that value from my Config.groovy (which is actually pulling it from an external config file). I've tried using grails.util.Holders but it doesn't seem to be wired up at this specific event yet. Is this possible?
You can set the value from your Config.groovy as an environment variable and then use it in _Events.groovy. If you still need to pull from an external config file, run a bash script inside of .bashrc/.bashprofile (wherever you define the environment variable).
eventConfigureTomcat = { tomcat ->
String altctxroot = System.getenv("ALT_CTX_ROOT")
def newContextRoot = "/"
def newContextPath = new File("$altctxroot")
}

Access sub-project application properties in grails/groovy

I have a singleton class
#Singleton
class CustomerBundleSingleton {
def grailsApplication = Holders.getGrailsApplication()
String projName
private CustomerBundleSingleton() {
line 10: projName = // how to get sub-project name here ???
}
}
application.properties // my project is running
-----------------------
app.name = MyNewProject
application.properties // located in sub project
-----------------------
app.name = MySubProject
I tried grailsApplication.metadata['app.name'] in "line 10:" it returns "MyNewProject".Whereas I want a way to get the project name of the UserBundleSingleton located (MySubProjectName). Something like grailsApplication.current.metadata['app.name'] ???? .
So that it can give me back MySubProjectName instead of MyNewProject??
I have 3 suggestions depending on your requirements and your 'bundling'.
1) You don't have a bundle marker/descriptor
Assuming that you know the sub-project(Grails plugin) name, your life gets easier, instead of having to loop through all plugins...
You can probably use something among these lines.
// Plugin name is 'hibernate' in this example
import org.codehaus.groovy.grails.plugins.PluginManagerHolder
def hibernateVersion = PluginManagerHolder.pluginManager.getGrailsPlugin('hibernate').version
// Loop through all plugins
// PluginManagerHolder.pluginManager.getAllPlugins()
2) Using custom plugin properties to lookup plugins of interest
Other strategy, if you must lookup the bundle dynamically.
Create a custom marker property in each of your plugin descriptors
def specialProperty = "whatever"
Then inside your CustomerBundleSingleton
PluginManagerHolder.pluginManager.getAllPlugins().each {
if (it.properties.specialProperty) {
def subProjectName = it.name
def subProjectVersion = it.version
}
}
3) Custom bundle info resolution
You may also want to consider some metadata via META-INF/MANIFEST.MF or similar mechanism.
Hope it helps...

Resources