Jenkins JobDSL generation failure after plugin updates - jenkins-job-dsl

We have been using same JobDSL generation scripts for ages and after we did have some plugin updates to latest ones, JobDSL generation started to fail and not finding how to get it fixed.
Here is example what we are doing
package foobar.qvantel.dsl.builders;
import javaposse.jobdsl.dsl.Context:
import javaposse.jobdsl.dsl.Item;
import groovy.json.JsonSlurper;
import com.foobar.dsl.builders.PipelineJobBuilder;
import com.foobar.dsl.common.CommonConstants;
class StackstormJobBuilder {
Map mapping = [:];
String resourcePath = 'default'
Item build(Context context) {
def mappingFile = context.readFileFromWorkspace(CommonConstants.RESOURCES_PATH +'stackstorm/' + this.resourcePath + '/mapping.json');
def mappingData = new JsonSlurper().parseText(mappingFile);
def combinedMapping = mappingData + this.mapping
def eventMapping = ' def mapping = [\n'
eventMapping += combinedMapping.collect { key, value ->
def content = " '${key}': [\n"
content += value.collect { source, target ->
def line = " '${source}': ["
if (target instanceof List) {
line += target.collect { "'${it}'" }.join(', ')
} else {
line += "'${target}'"
}
line += ']'
return line
}.join(',\n')
content += '\n ]'
return content
}.join(',\n')
eventMapping += '\n ]'
def pipelineScript = """
try {
${eventMapping}
if (mapping[INSTANCE] && mapping[INSTANCE][JOB]) {
for (job in mapping[INSTANCE][JOB]) {
build job: job, wait: false
}
} else {
unstable "No matching event mapping found."
}
} catch (all) {
echo 'ERROR: ' + all.toString();
currentBuild.result = 'FAILURE';
}
"""
Here is example mapping.json content processed by above snippet:
{
"auto-jenkins": {
"devops_jenkins-config-as-code_pipeline/master": "deploy_jenkins-config-as-code"
}
}
Previously / expected output in generated job config would be something like this:
try {
def mapping = [
'auto-jenkins': [
'devops_jenkins-config-as-code_pipeline/master': ['deploy_jenkins-config-as-code']
]
]
if (mapping[INSTANCE] && mapping[INSTANCE][JOB]) {
for (job in mapping[INSTANCE][JOB]) {
build job: job, wait: false
}
} else {
unstable "No matching event mapping found."
}
} catch (all) {
echo 'ERROR: ' + all.toString();
currentBuild.result = 'FAILURE';
}
But actual failure in JobDSL generation is like this:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object ' 'devops_jenkins-config-as-code_pipeline/master': ['deploy_jenkins-config-as-code']' with class 'org.codehaus.groovy.runtime.GStringImpl' to class 'javaposse.jobdsl.dsl.Item'
And it is coming exactly from this line above:
return line
And unfortunately these JobDSL stuff are not my core knowledge area (guy who has implemented this stuff not available anymore), so any help is highly appreciated!

Related

Jacoco doesnt report coverage correctly

I'm trying to set up jacoco for an android project, but there are two issues with the generated report.
1- I declared the destination folder for HTML and XML report but the generated report appears in build/reports/coverage/androidTest/debug
2- the generated report is incorrect and shows that the adder class is not covered, which is wrong.
adder class
class Adder {
fun adder(a:Int,b:Int):Int{
return a+b
}
fun subtractor(a:Int,b:Int):Int{
return a-b
}
}
test class
class AdderTest {
#Test
fun `test`(){
assertEquals(3,Adder().adder(1,2))
}
#Test
fun `substract`(){
assertEquals(-1,Adder().subtractor(1,2))
}
}
jacoco script
apply plugin: 'jacoco'
project.afterEvaluate { project ->
setupAndroidReporting()
}
def setupAndroidReporting() {
tasks.withType(Test) {
// Whether or not classes without source location should be instrumented
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect { type ->
type.name
}
def productFlavors = android.productFlavors.collect { flavor ->
flavor.name
}
// When no product flavors defined, use empty
if (!productFlavors) productFlavors.add('')
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
def sourceName, sourcePath
if (!productFlavorName) {
sourceName = sourcePath = "${buildTypeName}"
} else {
sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
sourcePath = "${productFlavorName}/${buildTypeName}"
}
def testTaskName = "test${sourceName.capitalize()}UnitTest"
System.out.println("Task -> $testTaskName")
// Create coverage task of form 'testFlavorTypeCoverage' depending on 'testFlavorTypeUnitTest'
task "${testTaskName}Coverage1"(type: JacocoReport, dependsOn: "$testTaskName") {
group = "Reporting"
description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
if (buildTypeName == 'debug') {
reports {
csv.enabled true // change if needed
xml.enabled false // change if needed
xml.setDestination(new File("${project.rootDir.path}/coverage-report"))
html {
enabled true
destination new File("${project.rootDir.path}/coverage-report")
}
}
def fileFilter = [
]
def javaTree = fileTree(dir: "${project.buildDir}/intermediates/javac/$sourceName/classes", excludes: fileFilter)
def kotlinTree = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/$sourceName", excludes: fileFilter)
classDirectories.from = files([javaTree], [kotlinTree])
executionData.from = files("${project.buildDir}/jacoco/${testTaskName}.exec")
def coverageSourceDirs = ["src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java"]
sourceDirectories.setFrom(files(coverageSourceDirs))
additionalSourceDirs.setFrom(files(coverageSourceDirs))
println "xml report: file://${reports.xml.destination}"
println "html report: file://${reports.html.destination}/index.html"
}
}
}
}
}
android {
buildTypes {
debug {
testCoverageEnabled true
}
}
}
report

Google.Cloud.RecaptchaEnterprise error on CreateAssessment() - "Request contains an invalid argument"

I'm trying to use the Google.Cloud.RecaptchaEnterprise library to validate captcha requests for the new enterprise key my client has obtained.
string _siteKey = ConfigurationManager.AppSettings["GoogleCaptcha.CheckboxCaptcha.SiteKey"];
string _apiKey = ConfigurationManager.AppSettings["GoogleCaptcha.ApiKey"];
string _projectId = ConfigurationManager.AppSettings["GoogleCaptcha.ProjectId"];
string recaptchaAction = "CreateAccountAssessment";
try {
var appPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
string credential_path = appPath + "googlecredentials.json";
System.Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", credential_path);
RecaptchaEnterpriseServiceClient client =
RecaptchaEnterpriseServiceClient.Create();
CreateAssessmentRequest createAssessmentRequest = new CreateAssessmentRequest()
{
Assessment = new Assessment()
{
Event = new Event()
{
SiteKey = _siteKey,
Token = formResponse,
ExpectedAction = "Create_Account"
},
Name = recaptchaAction,
},
Parent = _projectId
};
Assessment response = client.CreateAssessment(createAssessmentRequest);
if (response.TokenProperties.Valid == false)
{
Sitecore.Diagnostics.Log.Error("The CreateAssessment() call failed " +
"because the token was invalid for the following reason: " +
response.TokenProperties.InvalidReason.ToString(), this);
return "Invalid captcha.";
}
else
{
if (response.Event.ExpectedAction == recaptchaAction)
{
Sitecore.Diagnostics.Log.Error("The reCAPTCHA score for this token is: " +
response.RiskAnalysis.Score.ToString(), this);
return "";
}
else
{
Sitecore.Diagnostics.Log.Error("The action attribute in your reCAPTCHA " +
"tag does not match the action you are expecting to score", this);
return "Invalid captcha.";
}
}
}
catch (Exception ex)
{
Sitecore.Diagnostics.Log.Error("Error validating captcha on " + _url + "; " + ex.Message, this);
return "Unable to connect to captcha service.";
}
As far as I can tell all my properties are correct, but it throws an error on Assessment response = client.CreateAssessment(createAssessmentRequest);:
Status(StatusCode="InvalidArgument", Detail="Request contains an invalid argument.", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"#1621287236.280000000","description":"Error received from peer ipv6:[2607:f8b0:4006:81a::200a]:443","file":"T:\src\github\grpc\workspace_csharp_ext_windows_x64\src\core\lib\surface\call.cc","file_line":1062,"grpc_message":"Request contains an invalid argument.","grpc_status":3}")
I strongly suspect the problem (or at least a problem) is the Parent property of the request.
From the documentation:
The name of the project in which the assessment will be created, in the format "projects/{project}".
... whereas I suspect your project ID is just the ID, rather than the resource name starting with "projects/".
I would recommend using the generated resource name classes as far as possible, with the corresponding properties. So in this case, you'd have:
CreateAssessmentRequest createAssessmentRequest = new CreateAssessmentRequest
{
Assessment = new Assessment
{
Event = new Event
{
SiteKey = _siteKey,
Token = formResponse,
ExpectedAction = "Create_Account"
},
Name = recaptchaAction,
},
ParentAsProjectName = new ProjectName(_projectId)
};

Akka Cluster starding not able to register to Coordinator

I am trying to create an Akka Sharding Cluster. I want to use proxy only mode on one of the nodes just to route the message to the shard regions. I am getting the following Warning:
[WARN] [02/11/2019 17:04:17.819] [ClusterSystem-akka.actor.default-dispatcher-21] [akka.tcp://ClusterSystem#127.0.0.1:2555/system/sharding/ShardnameProxy] Trying to register to coordinator at [Some(ActorSelection[Anchor(akka.tcp://ClusterSystem#127.0.0.1:2551/), Path(/system/sharding/ShardnameCoordinator/singleton/coordinator)])], but no acknowledgement. Total [1] buffered messages.
**Main.java: ** Starts the cluster using the configuration from application.conf(code added latter)
object Main {
val shardName = "Shardname"
val role = "Master"
var shardingProbeLocalRegin: Option[ActorRef] = None
def main(args: Array[String]): Unit = {
val conf = ConfigFactory.load()
val system = ActorSystem("ClusterSystem",conf.getConfig("main"))
ClusterSharding(system).start(shardName,Test.props,ClusterShardingSettings(system),ShardDetails.extractEntityId,ShardDetails.extractShardId)
}
}
Test.java : Entity for the Sharding Cluster
object Test {
def props: Props = Props(classOf[Test])
class Test extends Actor {
val log = Logger.getLogger(getClass.getName)
override def receive = {
case msg: String =>
log.info("Message from " + sender().path.toString + " Message is " + msg)
sender() ! "Done"
}
}
}
MessageProducer.java(Proxy Only Mode) Message Producer sends a message to the Shard every second.
object MessageProducer {
var shardingProbeLocalRegin: Option[ActorRef] = None
object DoSharding
def prop:Props = Props(classOf[MessageProducer])
var numeric : Long = 0
def main(args: Array[String]): Unit = {
val conf = ConfigFactory.load
val system = ActorSystem("ClusterSystem",conf.getConfig("messgaeProducer"))
ClusterSharding(system).startProxy(Main.shardName,None,extractEntityId,extractShardId)
shardingProbeLocalRegin = Some(ClusterSharding(system).shardRegion(Main.shardName))
val actor = system.actorOf(Props[MessageProducer],"message")
}
}
class RemoteAddressExtensionImpl(system: ExtendedActorSystem) extends Extension {
def address = system.provider.getDefaultAddress
}
object RemoteAddressExtension extends ExtensionKey[RemoteAddressExtensionImpl]
class MessageProducer extends Actor{
val log = Logger.getLogger(getClass.getName)
override def preStart(): Unit = {
println("Starting "+self.path.address)
context.system.scheduler.schedule(10 seconds,1 second ,self,DoSharding)
}
override def receive = {
case DoSharding =>
log.info("sending message" + MessageProducer.numeric)
MessageProducer.shardingProbeLocalRegin.foreach(_ ! "" + (MessageProducer.numeric))
MessageProducer.numeric += 1
}
}
**application.conf: ** Configuration File
main {
akka {
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = on
netty.tcp {
hostname = "127.0.0.1"
port = 2551
}
}
cluster {
seed-nodes = [
"akka.tcp://ClusterSystem#127.0.0.1:2551"
]
sharding.state-store-mode = ddata
auto-down-unreachable-after = 1s
}
akka.extensions = ["akka.cluster.metrics.ClusterMetricsExtension", "akka.cluster.ddata.DistributedData"]
}
}
messgaeProducer {
akka {
actor {
provider = "akka.cluster.ClusterActorRefProvider"
}
remote {
log-remote-lifecycle-events = on
netty.tcp {
hostname = "192.168.2.96"
port = 2554
}
}
cluster {
seed-nodes = [
"akka.tcp://ClusterSystem#127.0.0.1:2551"
//, "akka.tcp://ClusterSystem#127.0.0.1:2552"
]
sharding.state-store-mode = ddata
auto-down-unreachable-after = 1s
}
akka.extensions = ["akka.cluster.metrics.ClusterMetricsExtension", "akka.cluster.ddata.DistributedData"]
}
}
Am I doing anything wrong? Is there any other way to apply for this approach. My main aim is to avoid Single Point of failure for my cluster. If any node goes down then it should not affect any other state. Can anyone help me with this?
Is it solved?
If not, please check your akka.cluster configuration.
You have to set config like this. It works to me
for proxy
akka.cluster {
roles = ["Proxy"]
sharding {
role = "Master"
}
}
for master
akka.cluster {
roles = ["Master"]
sharding {
role = "Master"
}
}

Grails Unit Test with Filter does not return content

So i have this filter
package filter.api
import grails.converters.JSON
class ApiFilters {
def apiService
def filters = {
apiSafetyCheck(namespace: "api", controller: "customer|status", action: "*") {
before = {
if(!apiService?.checkIncludedApiKey(params)) { //Simply returns true if the apiKey was found in the database!
def returnMap = [
"error": "API key was not found",
"statusCode": 401 //Just for testing!
]
if(params.outputFormat && params.outputFormat ?.equals("xml")) {
def textToRender = apiService?.createXmlFromMapInstance(returnMap)
owner?.render(status: 401, contentType: "text/xml", text: textToRender)
} else owner?.render(status: 401, contentType: "application/json", text: (returnMap as JSON))
return false //We don't want the action to be processed!
}
}
}
}
My Unit Test looks like this:
package api
import grails.test.mixin.Mock
import grails.test.mixin.support.GrailsUnitTestMixin
import grails.test.mixin.TestMixin
import grails.test.mixin.TestFor
import groovy.json.JsonSlurper
import groovy.util.XmlSlurper
import java.io.ByteArrayInputStream
import java.io.InputStream
import org.xml.sax.InputSource
import static javax.servlet.http.HttpServletResponse.*
import spock.lang.Specification
#TestMixin([GrailsUnitTestMixin])
#TestFor(BearbeitungController)
#Mock(filter.api.ApiFilters)
class ApiZugriffSpec extends Specification {
void "Test API wihtout Api Key JSON"() {
when:
withFilters(action: "customer") {
controller.someAction()
}
then:
println "Response from Server " + response.text?.toString()
println "Test 1 " + response?.getRedirectUrl()
println "Test 2 " + response?.getRedirectedUrl()
println "Test 3 " + response?.text
println "Test 4 " + response.contentType
def obj = new JsonSlurper().parseText(response.text?.toString())
println "obj?.statusCode " + obj?.statusCode
response.contentType == "application/json;charset=UTF-8"
obj?.statusCode?.toString() == SC_UNAUTHORIZED.toString()
}
void "Test API wihtout Api Key XML"() {
when:
params.outputFormat = "xml"
withFilters(action: "customer") {
controller.someAction()
}
then:
println "Response from Server " + response.text?.toString()
println "Test 1 " + response?.getRedirectUrl()
println "Test 2 " + response?.getRedirectedUrl()
println "Test 3 " + response?.text
println "Test 4 " + response.contentType
def xmlSlurperInstance = new XmlSlurper()
xmlSlurperInstance?.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false)
xmlSlurperInstance?.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false)
def inputStream = new ByteArrayInputStream(response.text?.toString()?.getBytes())
def testXMLArray = xmlSlurperInstance?.parse(new InputSource(inputStream))
response.contentType == "text/xml"
}
}
On Output "Test 3", nothing is visible, though here should be the content which i render from the filter... it also is the same response if i code the Filter to redirect to another controller in the namespace "api", which will handle the render task.
Anyone experienced something similar already or may know a workaround to get the expected result?
I already got it solved myself, i only removed the namespace from my filter, so that the filter will look like this:
package filter.api
import grails.converters.JSON
class ApiFilters {
def apiService
def filters = {
apiSafetyCheck(controller: "customer|status", action: "*") {
before = {
if(!apiService?.checkIncludedApiKey(params)) { //Simply returns true if the apiKey was found in the database!
def returnMap = [
"error": "API key was not found",
"statusCode": 401 //Just for testing!
]
if(params.outputFormat && params.outputFormat ?.equals("xml")) {
def textToRender = apiService?.createXmlFromMapInstance(returnMap)
owner?.render(status: 401, contentType: "text/xml", text: textToRender)
} else owner?.render(status: 401, contentType: "application/json", text: (returnMap as JSON))
return false //We don't want the action to be processed!
}
}
}
}
That's it, and it works for me :-)

Run JavaExec task in background and then terminate when build completes

I'm trying to figure out how to launch a JavaExec task that spawns a Jetty server without blocking subsequent tasks. Also, I will need to terminate this server after the build completes. Any idea how I can do this?
I know the thread is from 2011, but I still stumbled across the problem. So here's a solution working with Gradle 2.14:
import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class RunAsyncTask extends DefaultTask {
String taskToExecute = '<YourTask>'
#TaskAction
def startAsync() {
ExecutorService es = Executors.newSingleThreadExecutor()
es.submit({taskToExecute.execute()} as Callable)
}
}
task runRegistry(type: RunAsyncTask, dependsOn: build){
taskToExecute = '<NameOfYourTaskHere>'
}
I updated solution from #chrishuen because you cannot call execute on task anymore. Here is my working build.gradle
import java.time.LocalDateTime
import java.util.concurrent.Callable
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
group 'sk.bsmk'
version '1.0-SNAPSHOT'
apply plugin: 'java'
task wrapper(type: Wrapper) {
gradleVersion = '3.4'
}
class RunAsyncTask extends DefaultTask {
#TaskAction
def startAsync() {
ExecutorService es = Executors.newSingleThreadExecutor()
es.submit({
project.javaexec {
classpath = project.sourceSets.main.runtimeClasspath
main = "Main"
}
} as Callable)
}
}
task helloAsync(type: RunAsyncTask, dependsOn: compileJava) {
doLast {
println LocalDateTime.now().toString() + 'sleeping'
sleep(2 * 1000)
}
}
Hope this snippet will give you some insight on how it can be done.
You can used build listener closures to run code on build start/finish. However, for some reason, gradle.buildStarted closure does not work in milestone-3, so I have replaced it with gradle.taskGraph.whenReady which does the trick.
Then you can call the runJetty task using Task#execute() (Note, this API is not official and may disappear), and additionally, run it from an ExecutorService to get some asynchronous behaviour.
import java.util.concurrent.*
task myTask << {
println "Do usual tasks here"
}
task runJetty << {
print "Pretend we are running Jetty ..."
while(!stopJetty){
Thread.sleep(100)
}
println "Jetty Stopped."
}
stopJetty = false
es = Executors.newSingleThreadExecutor()
jettyFuture = null
//gradle.buildStarted { ... }
gradle.taskGraph.whenReady { g ->
jettyFuture = es.submit({ runJetty.execute() } as Callable)
}
gradle.buildFinished {
println "Stopping Jetty ... "
stopJetty = true
//This is optional. Could be useful when debugging.
try{
jettyFuture?.get()
}catch(ExecutionException e){
println "Error during Jetty execution: "
e.printStackTrace()
}
}
You can't do it with JavaExec; you'll have to write your own task.
Based on previous answers, here is my take:
abstract class RunAsyncTask extends DefaultTask {
#Input
abstract Property<FileCollection> getClasspath()
#Input
abstract Property<String> getMain()
#Input
abstract ListProperty<String> getArgs()
#TaskAction
def startAsync() {
// do get all the parameters before going asynch, otherwise it sometimes blocks
def cp = classpath.get().asPath
def m = main.get()
def a = args.get()
ExecutorService es = Executors.newSingleThreadExecutor()
es.submit({
def command = ["java", "-cp", cp, m] + a
ProcessBuilder builder = new ProcessBuilder(command.toList())
builder.redirectErrorStream(true)
builder.directory(project.projectDir)
Process process = builder.start()
InputStream stdout = process.getInputStream()
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))
def line
while ((line = reader.readLine()) != null) {
println line
}
} as Callable)
}
}
task startServer(type: RunAsyncTask) {
classpath = ...
main = '...'
args = [...]
doLast {
// sleep 3 seconds to give the server time to startup
Thread.sleep(3000)
}
}