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;
Related
We are creating API documentation for an existing Grails 4 App. We are having difficulties in understanding how to use Swagger annotations.
Let's assume the following Controller:
class IntegratorController {
def maintenanceService
def saveMaintenance() {
def message = 'success'
def status = '200'
try {
def maintenanceJson = request.JSON.maintenances
def ret=maintenanceService.processMaintenanceJSON(maintenanceJson)
} catch (Exception e) {
log.error("Error to process restricions", e)
message = 'error : ${e.getMessage()}'
status = '500'
}
def result = ['message':message]
render(status: status, contentType: "application/json", text: result as JSON)
}
}
This controller expects you to send a request JSON like this example:
{ "job":42,
"maintenances": [
{"idPort":42, "idMaintenance":42, "shipName":"myship01", "obs":"asap"},
{"idPort":43, "idMaintenance":43, "shipName":"myship02", "obs":"asap"}]}
A basic annotation will be this:
#Controller("/")
class IntegratorController {
def maintenanceService
#Post(uri="/saveMaintenance", produces = MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
#Operation(summary = "Create one or more ship maintenance")
#ApiResponse(responseCode = "500", description = "If internal service throws an Exception")
def saveMaintenance() {
def message = 'success'
def status = '200'
try {
def maintenanceJson = request.JSON.maintenances
def savedMaintenances=maintenanceService.processMaintenanceJSON(maintenanceJson)
} catch (Exception e) {
log.error("Error to process restricions", e)
message = 'error : ${e.getMessage()}'
status = '500'
}
def result = ['message':message]
render(status: status, contentType: "application/json", text: result as JSON)
}
}
Where and how to annotate the request JSON sent in the post operation?
Thank you!
The request object is "scoped" by Grails. So you need to use #RequestBody annotation to declare what it is outside the method declaration. You also need to create classes to describe what it is because the JSON deserialization is loosely typed.
This is an example:
#Post(uri="/saveMaintenance", produces = MediaType.APPLICATION_JSON)
#Operation(summary = "Summary here",
description = "Description here",
requestBody = #RequestBody(description = "Inside Operation"), tags = ["IntegratorWebController"])
#RequestBody(description = "Description here", required = true,
content = #Content(schema = #Schema(implementation = YourRequestDAO.class, anyOf = [YourRequestDAO.class, YourRequestDAODependency.class])))
#ApiResponses(value=[
#ApiResponse(responseCode="200", description = "Return status=OK in success", content = #Content(mediaType = "application/json", schema = #Schema(implementation = YourResponseDAO.class))),
#ApiResponse(responseCode="404", description = "Return status=BAD_REQUEST if you mess up", content = #Content(mediaType = "application/json", schema = #Schema(implementation = YourResponseDAO.class)))])
def saveOrUpdateActivity(){
(...)
Well Swagger and OpenAPI are 'schemas' that are preloaded at runtime to build the call structure; GraphQL also has a schema as well to load its call structure.
I did a video on it here to help you understand how this works: https://youtu.be/AJJVnwULbbc
The way Grails did this prior to 4.0 was with plugins like the 'swagger plugin' or with BeAPI plugin (which I maintain).
I don't see a supported plugin in 4.0 so I don't see how they are doing this now.
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"
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.
I've got groovy class which is calling AntBuilder.sshexec method to execute remote command. This is working fine when I'm running this Groovy class as Java application. But, when I'm trying to call this class/method from controller, I've got error "Could not create type sshexec due to java.lang.NoClassDefFoundError: com/jcraft/jsch/UserInfo".
Groovy class:
package filemanager
import com.jcraft.jsch.*
import com.jcraft.jsch.ChannelSftp.*
class FileWork {
String servName
String servUser
String servPassword
String servFolder
String localFolder
int servPort
String fileName
FileWork (String p_servName, String p_servUser, String p_servPassword, String p_servFolder, String p_localFolder, int p_servPort,String p_fileName) {
println 'Exec constructor'
this.servName = p_servName
this.servUser = p_servUser
this.servPassword = p_servPassword
this.servFolder = p_servFolder
this.localFolder = p_localFolder
this.servPort = p_servPort
this.fileName = p_fileName
}
.....
String runRemoteCommand () {//(Session p_ses) {
try {
def result = ''
def ant = new AntBuilder()
ant.sshexec(
host: servName,
port: servPort,
trust: true,
username: servUser,
password: servPassword,
command: "unzip -o ${servFolder}${fileName} -d ${servFolder}",
outputproperty: 'result',
verbose: false
)
return result
} catch (Exception e) {
println 'This is filemanager.FileWork.runRemoteCommandException'
e.printStackTrace();
}
}
}
Controller:
package filemanager
import com.jcraft.jsch.*
import com.jcraft.jsch.ChannelSftp.*
class ChooseToController {
def index(params) {
params.max = Math.min(max ?: 10, 100)
//render params
//model:[destServ: DestServ, fileName:fileName]
}
def copyToRemote(params) {
def destServ = DestServ.get(params.id)
//FileWork fileWork = new FileWork (destServ.getDestServName(), destServ.getDestServUser(), destServ.getDestServPassword(), destServ.getDestServFolder(), "C:/tmp/", destServ.getDestServPort(), params.fileName)
//Session ses = fileWork.connect()
//fileWork.copyToRemoteServ(ses)
//ses.disconnect()
FileWork fileWork3 = new FileWork ("###########", "test", "Test123", "/home/test/IN/", "C:/tmp/", 22, "1.zip")
String result = fileWork3.runRemoteCommand()
println(result)
}
}
Dependencies:
runtime "com.jcraft:jsch:0.1.51"
runtime "org.apache.ant:ant-jsch:1.8.1"
Error:
Could not create type sshexec due to java.lang.NoClassDefFoundError: com/jcraft/jsch/UserInfo
at org.apache.tools.ant.AntTypeDefinition.createAndSet(AntTypeDefinition.java:278)
at org.apache.tools.ant.AntTypeDefinition.icreate(AntTypeDefinition.java:219)
at org.apache.tools.ant.AntTypeDefinition.create(AntTypeDefinition.java:206)fro.....
Seems that not all classes are visible from grails runtime context...
Hi I have am trying to implement a file upload in my application where the file uploaded is parsed and an entry is created in the database using that information.
def save = {
def file = request.getFile("file");
def filename = file.getOriginalFilename();
def type = filename.split('\\.');
if(!file.isEmpty()){
if(type[1] == "properties"){
redirect(action:"parsePropertyFile", params:params);
}
}
}
def parsePropertyFile = {
println "\n"
println params.file;
println "\n";
def f = params.file;
println f;
def filename = f.getOriginalFilename();
println filename;
}
when I print out f this is output:
org.springframework.web.multipart.commons.CommonsMultipartFile#29d32df9
but when I try to call getOriginalFilename() on f I get the following error:
groovy.lang.MissingMethodException: No signature of method:
java.lang.String.getOriginalFilename() is applicable for argument types: () values: []
I also printed out file from the save function and the output of that is also:
org.springframework.web.multipart.commons.CommonsMultipartFile#29d32df9
so why am I getting the error?
Instead of redirecting, can you just call your another function? Redirect will issue an http redirect with the file as param with no need.
if(type[1] == "properties") {
parsePropertyFile(file)
}
And then:
private def parsePropertyFile(def file) {
String filename = file.getOriginalFilename();
...
}
In your parsePropertyFile action you aren't getting a File object, you're getting the String from params. Just like in your save action, you need to do
def f = request.getFile('file')
println f.getOriginalFilename()