Jenkins [Dynamic Choice Parameter (Scriptler)] failing when querying credentials information - jenkins

I am bit stuck on why when I run the following script in Jenkins Scriptler and the Script Console it works, yet when used in the Dynamic Choice Parameter (Scriptler), it fails with the error:
Error: groovy.lang.MissingPropertyException: No such property: com for class: Script1
I can only assume that it is to do with the used class com.cloudbees.plugins.credentials.CredentialsProvider is called.
Here is the script:
/*** BEGIN META {
"name" : "GetRemoteNasFolderList",
"comment" : "Retrieve a list of folder names (in reverse order) from a remote NAS location.",
"parameters" : [ 'ENVIRONMENT', 'SHARE_PATH', 'FOLDER_PATH' ],
"core": "1.565",
"authors" : [{
name : "Authors Name"
}]
} END META**/
import jenkins.model.Jenkins
try {
// params
def env = ENVIRONMENT // 'DEV" or 'TEST' or 'PROD'
def share_path = SHARE_PATH
def folder_path = FOLDER_PATH
String user_domain = ''
String nas_path = ''
switch (env) {
case 'DEV':
user_domain = 'dev';
nas_path = 'nas_host.dev.company.com.au';
break;
case 'TEST':
user_domain = 'test';
nas_path = 'nas_host.test.company.com.au';
break;
case 'PROD':
default:
user_domain = 'prod';
nas_path = 'nas_host.prod.company.com.au';
}
String user_name = 'myUserName'
def full_name = user_domain + '\\' + user_name
String pass_word = ''
def found = false
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
Jenkins.instance,
null,
null
);
for (c in creds) {
if (c.username == full_name) {
pass_word = c.password
found = true
}
}
if (found == true) {
url = "smb://" + nas_path + "/" + share_path + "/" + folder_path;
println("Url: "+url)
// println(user_domain+"\\"+user_name+", "+pass_word)
auth = new jcifs.smb.NtlmPasswordAuthentication(user_domain, user_name, pass_word);
dir = new jcifs.smb.SmbFile(url, auth);
folders = []
for (jcifs.smb.SmbFile f : dir.listFiles())
{
folders.push(f.getName().replace('/',''))
}
return folders.sort().reverse()
} else {
print("Credential entry not found for ( " + full_name + " )")
}
} catch (e) {
return ["Error: "+e]
} finally {
}
Any thoughts, anyone.

Error: groovy.lang.MissingPropertyException: No such property: xx for class: yy
Typical error message if your missing an import reference, have you tried referencing everything?
import jenkins.model.*
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.common.*
import com.cloudbees.plugins.credentials.domains.*;
Perhaps this is what the Jenkins Scriptler and the Script Console do by default, where as the Dynamic Choice Parameter (Scriptler) doesn't.
Ref: https://github.com/chef-cookbooks/jenkins/issues/174

Switched to using a different plugin (Active Choices Parameter) that makes use of Scriptler scripts and is now working.

Related

"No such library resource" error in JenkinsFile

When I run build I get this error:
ERROR SENDING EMAIL hudson.AbortException: No such library resource build/email.html.groovy could be found.
The file "email.html.groovy" is in the same directory.
An error appears on the line:
def fileContents = libraryResource(fileName)
My Groovy file with 2 functions:
package workflowlibs.manager;
import groovy.text.StreamingTemplateEngine
/**
* This method returns a string with the template filled with groovy variables
*/
def emailTemplate(params) {
def fileName = "build/email.html.groovy"
def fileContents = libraryResource(fileName)
def engine = new StreamingTemplateEngine()
return engine.createTemplate(fileContents).make(params).toString()
}
/**
* This method send an email generated with data from Jenkins
* #param buildStatus String with job result
* #param emailRecipients Array with emails: emailRecipients = []
*/
def notifyEmail(buildStatus, emailRecipients) {
try {
def icon = "✅"
def statusSuccess = true
def hasArtifacts = true
if(buildStatus != "SUCCESSFUL") {
icon = "❌"
statusSuccess = false
hasArtifacts = false
}
def body = emailTemplate([
"jenkinsText" : env.JOB_NAME,
"jenkinsUrl" : env.BUILD_URL,
"statusSuccess" : statusSuccess,
"hasArtifacts" : hasArtifacts,
"downloadUrl" : "www.downloadurl.com"
]);
mail (to: emailRecipients.join(","),
subject: "${icon} [ ${env.JOB_NAME} ] [${env.BUILD_NUMBER}] - ${buildStatus} ",
body: body,
mimeType: 'text/html'
);
} catch (e){
println "ERROR SENDING EMAIL ${e}"
}
}
return this;

How to update credentials of specific folder in Jenkins using Groovy script?

I want to update a credentials object of an existing folder. How can I do that using groovy?
Here is what I have so far:
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import com.cloudbees.hudson.plugins.folder.Folder
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl
// Init
String user_name = "my_user_name"
String user_pass = "my_new_pass"
String folderName = "Projects"
Folder targetFolder = null
// Get folder:
def allJenkinsItems = Jenkins.getInstance().getItems();
for (currentJenkinsItem in allJenkinsItems)
{
if(!(currentJenkinsItem instanceof Folder)) {continue}
if(((Folder)currentJenkinsItem).getFullName().equals(folderName))
{
targetFolder = (Folder)currentJenkinsItem;
}
}
if (targetFolder == null) {println "Failed to find folder: folderName"; return}
// Get target credentials of that folder:
def credsList = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernameCredentials.class,
targetFolder,
null,
null
);
// Get target creds out of the list - will get the first one it encounters:
def targetCreds = credsList.findResult { it.username == user_name ? it : null }
if (targetCreds == null) {println "Failed to find username: $user_name under credentials of folder: $folderName"; return}
// Gets store - how to get the folder's store??
def credentials_store = Jenkins.instance.getExtensionList(
'com.cloudbees.plugins.credentials.SystemCredentialsProvider'
)[0].getStore()
// Try to update the creds of the folder.
// **updateResult is always 'false' here**
def updateResult = credentials_store.updateCredentials(
com.cloudbees.plugins.credentials.domains.Domain.global(),
targetCreds,
new UsernamePasswordCredentialsImpl(targetCreds.scope, targetCreds.id, targetCreds.description, targetCreds.username, user_pass)
)
if (updateResult) {
println "Success changing password for ${user_name}"
} else {
println "Failed changing password for ${user_name}"
}
But when I am trying to update - I get a updateResult == false.
How can I update the credentials after they are found?
Found it myself:
/*
* Configures single (username & password) credentials for a folder in global domain
* if already exists a credentials with defined username - it will update it
* if more than one exists - the first one it encounters will be updated
*/
import java.util.logging.Logger
import jenkins.model.*
import com.cloudbees.hudson.plugins.folder.*;
import com.cloudbees.hudson.plugins.folder.properties.*;
import com.cloudbees.hudson.plugins.folder.properties.FolderCredentialsProvider.FolderCredentialsProperty;
import com.cloudbees.plugins.credentials.impl.*;
import com.cloudbees.plugins.credentials.*;
import com.cloudbees.plugins.credentials.domains.*;
// Init
def logger = Logger.getLogger("")
jenkins = Jenkins.instance
String user_name = "my_user_name"
String user_pass = "my_new_pass"
String description = "my desc"
String folderName = "Projects"
String id = java.util.UUID.randomUUID().toString()
Credentials c = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, id, "description: "+id, user_name, user_pass)
logger.info("Configuring domain credentials for folder: $folderName")
for (folder in jenkins.getAllItems(Folder.class)) {
if(folder.name.equals(folderName)) {
AbstractFolder<?> folderAbs = AbstractFolder.class.cast(folder)
FolderCredentialsProperty property = folderAbs.getProperties().get(FolderCredentialsProperty.class)
// If not defined FolderCredentialsProperty yet - define and finish
if(property == null) {
logger.info("Initializing folder credentials store and add credentials in global store")
property = new FolderCredentialsProperty([c])
folderAbs.addProperty(property)
jenkins.save()
return
}
// Check for existing credentials - and update their password & description
// will update the first credentials it encounters
def credentials_store = property.getStore()
List<com.cloudbees.plugins.credentials.Credentials> folderCredentialsList = property.getCredentials()
for (creds in folderCredentialsList) {
logger.info("Checking existing credentials of folder: $folderName for user: $user_name")
if (creds.username.equals(user_name)) {
// Found username - updating it
// Try to update the creds of the folder:
def updateResult = credentials_store.updateCredentials(
com.cloudbees.plugins.credentials.domains.Domain.global(),
creds,
new UsernamePasswordCredentialsImpl(creds.scope, creds.id, description, creds.username, user_pass)
)
if (updateResult) {
println "Update successful"
} else {
println "Update failed"
}
jenkins.save()
return
}
}
logger.info("Didn't find credntials with username: $user_name - adding new one")
// If got here - then:
// 1. There is already a FolderCredentials property defined for folder: folderName
// 2. didn't find any credentials(of username & password type) with username == user_name
// so just add the new credentials
property.getStore().addCredentials(Domain.global(), c)
jenkins.save()
return
}
}

Problem with jenkins pipeline script. No signature of method is applicable for argument types:(java.lang.String) values[string]

I have class Emails, that contain loginAndEmaildependency method:
class Emails{
static List<String> loginEmaildependency (String login){
Map<String, String> result = new HashMap<>()
result.put("abc", "abc#gmail.com")
result.put("cde", "cde#gmail.com")
....
....
if(result.get(login.toLowerCase()) != null){
return [result.get(login.toLowerCase())]
}
else {return ["xxx#gmail.com"]}
}
}
Also I have 2 pipeline scripts:
BuildEmailExt email = null
if (env.JOB_NAME =~ /TEST-/ || env.JOB_NAME =~ /test-/) {
def userLogin = currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserId()
email = new BuildEmailExt(this, Emails.loginEmailDependency(userLogin.toString()))
.jobParams(["gitRepoName" : env.gitRepoName,
"gitBranch " : env.gitBranch,
"skipInstallationTest": env.skipInstallationTest,
"skipDeployNexus" : env.skipDeployNexus,
"dockerImageMq" : dockerImageMq,
"dockerImageWas" : dockerImageWas,
"dockerImageDb" : dockerImageDb])
} else {
email = new BuildEmailExt(this, Emails.repoRecipientEmails(gitRepoName))
.jobParams(["gitBranch" : env.gitBranch,
"skipGuiTest" : env.skipGuiTest,
"skipDeployNexus": env.skipDeployNexus,
"forceWasInstall": env.forceWasInstall,
"dockerImageMq" : dockerImageMq,
"dockerImageWas" : dockerImageWas,
"dockerImageDb" : dockerImageDb])
}
if (env.JOB_NAME =~ /TEST-/ || env.JOB_NAME =~ /test-/) {
def userLogin = currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserId()
email = new BuildEmailExt(this, Emails.loginEmailDependency(userLogin.toString()))
.jobParams(["gitRepoName" : env.gitRepoName,
"gitBranch " : env.gitBranch,
"skipInstallationTest": env.skipInstallationTest,
"skipDeployNexus" : env.skipDeployNexus,
"dockerImageMq" : dockerImageMq,
"dockerImageWas" : dockerImageWas,
"dockerImageDb" : dockerImageDb])
} else {
email = new BuildEmailExt(this, Emails.Teams())
.jobParams(["gitBranch" : env.gitBranch,
"skipGuiTest" : env.skipGuiTest,
"skipDeployNexus": env.skipDeployNexus,
"forceWasInstall": env.forceWasInstall,
"dockerImageMq" : dockerImageMq,
"dockerImageWas" : dockerImageWas,
"dockerImageDb" : dockerImageDb])
}
In second script I use this script and all works successfull, but in first script i get exception: No signature of method: java.lang.Class.loginAndEmailDependency() is applicable for argument types:(java.lang.String) values:[abc]
What problem it can be?
It wasn't problem with code. It was problem with jenkins settings. Two scripts had different settings and in the second jenkins doesn't seen method "loginEmailDependency"

IllegalArgumentException: Expected named arguments (Jenkins)

I am getting the following error when trying to run my jenkins job. Any help would be much appreciated
java.lang.IllegalArgumentException: Expected named arguments but got
[org.jenkinsci.plugins.workflow.cps.CpsClosure2#33c7c4a6,
org.jenkinsci.plugins.workflow.cps.CpsClosure2#79505a8c,
org.jenkinsci.plugins.workflow.cps.CpsClosure2#6a96df3,
org.jenkinsci.plugins.workflow.cps.CpsClosure2#1a0cb771,
org.jenkinsci.plugins.workflow.cps.CpsClosure2#17e3a262] at
org.jenkinsci.plugins.workflow.cps.DSL.singleParam(DSL.java:606) at
org.jenkinsci.plugins.workflow.cps.DSL.parseArgs(DSL.java:594) at
org.jenkinsci.plugins.workflow.cps.DSL.parseArgs(DSL.java:534) at
org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:219) at
org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:178) at
org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
at sun.reflect.GeneratedMethodAccessor102.invoke(Unknown Source)
My code is:
node("dvsacvsmgmt") {
stage("Build") {
def buildJobs = []
for (BACKEND_SERVICE in BACKEND_SERVICES) {
SVC = BACKEND_SERVICE.replaceAll('-','_')
switch (BRANCH_SVC) {
case ["develop","master"]:
def buildJob = {
build "${ROOT_FOLDER}/2_Build/Backend/${SVC}/job_build_backend_" + BRANCH_SVC + "_" + SVC +".groovy"
}
buildJobs.add(buildJob)
break
default:
def buildJob = {
build "job_${SVC}": "${ROOT_FOLDER}/2_Build/Backend/${SVC}/job_build_backend_" + BRANCH_SVC + "_" + SVC +".groovy",
parameters: [gitParameter(name: "BRANCH", value: BRANCH_SVC)]
}
buildJobs.add(buildJob)
break
}
}
parallel(buildJobs)
}
}
NOTE: My variables are defined at the top,
BRANCH, BRANCH_SVC, ROOT_FOLDER, BACKEND_SERVICES
You see this exception because buildJobs in your example is a list of closures and it should be a map instead. It would make sense to use backend service name as a key for the map you pass to parallel() method. Consider the following changes to your code:
node("dvsacvsmgmt") {
stage("Build") {
def buildJobs = [:]
for (BACKEND_SERVICE in BACKEND_SERVICES) {
SVC = BACKEND_SERVICE.replaceAll('-','_')
switch (BRANCH_SVC) {
case ["develop","master"]:
def buildJob = {
build "${ROOT_FOLDER}/2_Build/Backend/${SVC}/job_build_backend_" + BRANCH_SVC + "_" + SVC +".groovy"
}
buildJobs.put(BACKEND_SERVICE, buildJob)
break
default:
def buildJob = {
build "job_${SVC}": "${ROOT_FOLDER}/2_Build/Backend/${SVC}/job_build_backend_" + BRANCH_SVC + "_" + SVC +".groovy",
parameters: [gitParameter(name: "BRANCH", value: BRANCH_SVC)]
}
buildJobs.put(BACKEND_SERVICE, buildJob)
break
}
}
parallel(buildJobs)
}
}
It invokes
buildJobs.put(BACKEND_SERVICE, buildJob)
instead
buildJobs.add(buildJob)
to create a map that is seen as named arguments in parallel method call.

Jenkins pipeline: join file / URL paths

How can I join strings nicely into a path when programming Jenkins Groovy pipeline? So that I can join('http://example.com/', '/r', 'some.html') -> 'http://example.com/r/some.html'
This note suggests using new File(dir1, dir2) or Paths.get(dir1, dir2) in "pure" Groovy.
However in Jenkins pipeline, import java.nio.file.Paths gives me
No such static method found: staticMethod java.nio.file.Paths get java.lang.String org.codehaus.groovy.runtime.GStringImpl.
and with new File I get
Scripts not permitted to use new java.io.File java.lang.String java.lang.String. Administrators can decide whether to approve or reject this signature.
and I kinda agree with Jenkins on this do not want to allow this. Is there another way?
bad idea to build url with Paths or File objects because under windows you'll get wrong result.
you can build url with simple string concatenation and use URI.normalize() to remove extra slashes:
def u = new URI(['http://example.com/', '/r', 'some.html'].join('/')).normalize().toString()
Try this:
def join_two_urls(url1, url2) {
if (url1 == "" || url2 == "") {
println "Error: must provde two invalid urls."
return ""
}
println "Joining ${url1} and ${url2} ..."
if (url1 ==~ /.*\/$/) {
url1 = url1.substring(0, url1.length() - 1)
}
if (url2 ==~ /^\/.*/) {
url2 = url2.substring(1, url2.length())
}
return url1 + "/" + url2
}
def join_paths(String[] urls) {
if (urls.size() <= 1) {
println "Error: invalid urls."
return ""
}
conbined_url = ""
pre_url = ""
for (url in urls) {
if (pre_url == "") {
pre_url = url
continue
}
conbined_url += join_two_urls(pre_url, url)
}
return conbined_url
}
println join_paths("xx/", "xxx/" , "/fsdsdfsdf")

Resources