groovy - replace values in json when loading from jmx - groovy

I have a piece a code as below. This is loading data from JMX to monitoring tool. Unfortunately, there are some 'NaN' values, which are not read properly by monitoring tool, and this interrupts transfer. My intention is to replace 'on fly' values 'NaN' to 'null'.
Has anybody any idea how to do it?
BR
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import java.security.PrivilegedAction;
def hostName = hostProps.get("system.hostname")
def jmxPort = "10002"
def query = "Hadoop:service=hiveserver2,name=hiveserver2"
def metricsURL = "http://${hostName}:${jmxPort}/jmx?qry=${query}"
def ad = true
public class FetchMetrics implements PrivilegedAction {
def url;
public FetchMetrics(String url) {
this.url = url;
}
public Object run() {
URL urlObject = new URL(url);
def con = (HttpURLConnection) urlObject.openConnection();
return con.getInputStream();
}
}
lc = new LoginContext("Client");
lc.login();
Subject subject = lc.getSubject();
PrivilegedAction action = new FetchMetrics(metricsURL);
def metrics = Subject.doAsPrivileged(subject, action, null);
def jsonSlurper = new JsonSlurper()
def deviceMetrics = jsonSlurper.parse(metrics)
// Hit out endpoint and get our metrics
//deviceMetrics = jsonSlurper.parse(new URL(metricsURL))
deviceMetrics.'beans'[0].each {
println it
}
return 0

simplest way to use LAX json slurper, however it will parse NaN as a string "NaN"...
import groovy.json.JsonSlurper
import groovy.json.JsonParserType
import groovy.json.JsonBuilder
def jsonSlurper = new JsonSlurper().setType( JsonParserType.LAX )
def json = jsonSlurper.parseText('{ "a":111, "b": NaN}')
println new JsonBuilder(json).toPrettyString()
prints
{
"a": 111,
"b": "NaN"
}

Related

Trying to mock two classes with Groovy Spock Mock: GroovyCastException

I try to mock two classes in a Jenkins Pipeline var-script, but however I order the definition of the Mock I receive a GroovyCastException, while the mock for the second class is initiated
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'Mock for type 'ClassA'' with class 'com.pipeline.ClassA$$EnhancerByCGLIB$$9b005c28' to class 'com.pipeline.DBReader'
This is how my Spock-Test looks like:
import com.homeaway.devtools.jenkins.testing.JenkinsPipelineSpecification
import com.pipeline.ClassA
import com.pipeline.DBReader
import groovy.sql.Sql
import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException
import hudson.model.Result
class execScriptSpec extends JenkinsPipelineSpecification {
def execPipelineScript = null
def mockStage = [timeout: [time: 'mocktime']]
def mockScript = [...]
def setup() {
execPipelineScript = loadPipelineScriptForTest("vars/execScript.groovy")
}
def "Test Pipeline-Script"() {
setup:
GroovyMock(ClassA, global: true)
new ClassA(*_) >> Mock(ClassA) {
loadScope(_) >> null
loadJsonFromURL(_) >> null
}
GroovyMock(DBReader, global: true)
new DBReader(*_) >> Mock(DBReader) {
loadDBDriver(_) >> null
}
when:
execPipelineScript(mockScript, mockStage)
then:
true
And that is the code under test:
import com.pipeline.DBReader
import com.pipeline.ClassA
def call(script, stage) {
def pipelineConfig = script.pipelineConfig
def stageStatus = pipelineConfig.general.stageStatus
def projectName = script.env.project
// DB connection parameters
def dbName = script.deliveryConfig.system.dbName
def dbSchema = script.deliveryConfig.system.dbSchema
def dbServer = script.deliveryConfig.system.dbServer
def dbUser = script.deliveryConfig.system.dbUser
// DB Driver to use
def dbDriver = script.deliveryConfig.system.dbDriver
def dbPassword = script.env.password
// Create new DB-Client
DBReader dbClient = new DBReader(dbName, dbSchema, dbServer, dbUser, dbPassword, dbDriver)
dbClient.loadDBDriver()
def contextParameter = script.params['Context']
ClassA mapGavToVersionRange = new ClassA(projectName, contextParameter, script)
classAInstance.loadDeliveryScope( dbClient )
def url = 'https://some.valid.url'
classAInstance.loadJsonFromURL(url)
...
So don't get me wrong: The actual mocking of one or the other class works (if I put only one of them in my test), but as soon as I put both of them, the second one will not work. And I currently have no idea, why this happens.
Would be great, if anybody has an idea :-)
Thanks a lot!

Groovy throws MissingPropertyException when calling getter method

I'm writing a small Groovy script for Hybris.
For reasons unknown when I attempt to call .getCronExpression() Groovy tries to get a property named getCron.
Script execution has failed [reason: groovy.lang.MissingPropertyException: No such property: getCron for class: de.hybris.platform.cronjob.model.TriggerModel]
The getter which I try to call exists on the class.
def methods = TriggerModel.declaredMethods.findAll { !it.synthetic }.name
println methods;
//[getDaysOfWeek, getWeekInterval, setDaysOfWeek, setWeekInterval, getRelative, getJob, setActivationTime, setMaxAcceptableDelay, getTimeTable, setActive, setJob, getCronJob, getActivationTime, setDateRange, getDateRange, getMaxAcceptableDelay, getCronExpression, setCronExpression, setCronJob, getActive, setRelative, setDay, setHour, setMinute, setSecond, getHour, getMinute, getSecond, getYear, getMonth, setYear, setMonth, getDay]
Code part:
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active} IS true");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def x = at.getCronExpression(); // error
}
Update: the project uses hybris 5.7
Replacing the getter with the variable name fixed the issue.
Replace-
def x = at.getCronExpression(); // error
with
def xam = at.cronExpression; // working
Complete working groovy-
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active}='1'");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def xam = at.cronExpression; // working
}
}
Can you share your groovy part where you are loading activeTriggers?
I created a sample groovy to load Triggers and print CronExpression for 1st object and it worked like a charm.
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
flexibleQuery = new FlexibleSearchQuery("select {pk} from {Trigger}");
flexibleSearchService = spring.getBean("flexibleSearchService")
activeTriggers = flexibleSearchService.search(flexibleQuery).getResult();
def at = activeTriggers.get(0);
def x = at.getCronExpression();
OUTPUT
0 0 0/4 * * ? *
AFTER PO EDITED THE QUESTION I still don't see getCronExpression error, I believe you were calling the function on a different object then TriggerModel. Though there were some syntax errors in your groovy, a working version of the copy is as below. (Tested on 1905 version)
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active} = true");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS!=null && activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def x = at.getCronExpression(); // error
println x;
}
}

GitBlit add a hook

I have a GitBlit instance on a windows server, and i want to set a hook on post receive callback to start a gitlab ci pipeline on another server.
I already have set a GitlabCi trigger who works well, but my hook doesn't. Here is build-gitlab-ci.groovy file :
import com.gitblit.GitBlit
import com.gitblit.Keys
import com.gitblit.models.RepositoryModel
import com.gitblit.models.UserModel
import com.gitblit.utils.JGitUtils
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.transport.ReceiveCommand
import org.eclipse.jgit.transport.ReceiveCommand.Result
import org.slf4j.Logger
logger.info("Gitlab-CI hook triggered by ${user.username} for ${repository.name}")
// POST :
def sendPostRequest(urlString, paramString) {
def url = new URL(urlString)
def conn = url.openConnection()
conn.setDoOutput(true)
def writer = new OutputStreamWriter(conn.getOutputStream())
writer.write(paramString)
writer.flush()
String line
def reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))
while ((line = reader.readLine()) != null) {
println line
}
writer.close()
reader.close()
}
sendPostRequest("https://xxxxx/api/v4/projects/1/trigger/pipeline", "token=xxxxxxxx&ref=master")
The project configuration :
Moreover, i don't know where logger.info write the log, so i don't know if my script was executed well. Thanks for help
I found my problem, it was a SSL self-certificate problem. I added this code to ignore it :
import com.gitblit.GitBlit
import com.gitblit.Keys
import com.gitblit.models.RepositoryModel
import com.gitblit.models.UserModel
import com.gitblit.utils.JGitUtils
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.transport.ReceiveCommand
import org.eclipse.jgit.transport.ReceiveCommand.Result
import org.slf4j.Logger
logger.info("Gitlab-CI hook triggered by ${user.username} for ${repository.name}")
def nullTrustManager = [
checkClientTrusted: { chain, authType -> },
checkServerTrusted: { chain, authType -> },
getAcceptedIssuers: { null }
]
def nullHostnameVerifier = [
verify: { hostname, session -> hostname.startsWith('yuml.me')}
]
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL")
sc.init(null, [nullTrustManager as javax.net.ssl.X509TrustManager] as javax.net.ssl.X509TrustManager[], null)
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(nullHostnameVerifier as javax.net.ssl.HostnameVerifier)
def url = new URL("https://xxxx/api/v4/projects/{idProject}/trigger/pipeline")
def conn = url.openConnection()
conn.setDoOutput(true)
def writer = new OutputStreamWriter(conn.getOutputStream())
writer.write("token={token}&ref={branch}")
writer.flush()
String line
def reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))
while ((line = reader.readLine()) != null) {
println line
}
writer.close()
reader.close()
And I identified the error checking the logs in E:\gitblit-1.7.1\logs\gitblit-stdout.{date}.log.
NB : stdout file date can be very old. Gitblit doesn't create a file per day. Mine had a name expired 4 months ago.

How to run twice soap request in SoapUI using threads?

In SoapUI I prepared TestCase (Options - generate data) consisting of three test steps:
Properties
Groovy Script
Generate (disabled)
In this test I want to run third step only two times in the same time (that's why I don't use LoadTest) and verify obtained results - they should be different. For this, I wrote a simple script which is presented below.
def testData = testRunner.testCase.getTestStepByName("Properties");
class MyThread extends Thread {
def i;
def testData;
MyThread(def i, def testData) {
this.i = i;
this.testData = testData;
}
void run() {
generateData();
}
void generateData() {
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
def testCaseStep = testRunner.testCase.testSuite.testCases["Options - generate data"];
def soapStep = testCaseStep.testSteps["Generate"];
soapStep.run(testRunner, context);
def xmlResponse = groovyUtils.getXmlHolder("Generate#response")
def responseData = xmlResponse.getNodeValues("//ns2:getResponse/ns2:response");
def row = "row" + this.i;
this.testData.setPropertyValue(row, responseData.toString());
}
}
MyThread thread1 = new MyThread(0, testData);
MyThread thread2 = new MyThread(1, testData);
thread1.start();
thread2.start();
while ((thread1.isAlive() && thread2.isAlive())) {
def data1 = testData.getPropertyValue("row0");
def data2 = testData.getPropertyValue("row1");
assert data1 != data2;
}
Unfortunately this code doesn't work correctly - I don't have any error, but SOAP requests don't start, new variables are not created and assertion is failed.
Could you tell me what is necessary to obtain good result of this test?
I will be very grateful for any help.
Couple of things which are fixed in the code:
context is used in the method and is not available
threads to be joined
while getting the data, you need the object reference
Fixed code:
def testData = context.testCase.getTestStepByName("Properties")
class MyThread extends Thread {
def threadId
def testData
def context
MyThread(def i, def testData, def context) {
threadId = i
this.testData = testData
this.context = context
}
void run() {
generateData()
}
void generateData() {
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def soapStep = context.testCase.testSteps["Generate"]
soapStep.run(context.testRunner, context)
def xmlResponse = groovyUtils.getXmlHolder("Generate#response")
def responseData = xmlResponse.getNodeValues("//ns2:getResponse/ns2:response")
testData.setPropertyValue("row${threadId}" as String, responseData.toString())
}
}
MyThread thread1 = new MyThread(0, testData, context)
MyThread thread2 = new MyThread(1, testData, context)
thread1.start()
thread1.join()
thread2.start()
thread2.join()
while ((thread1.isAlive() && thread2.isAlive())) {
def data1 = thread1.testData.getPropertyValue(thread1.threadId)
def data2 = thread2.testData.getPropertyValue(thread2.threadId)
assert data1 != data2
}

Groovy map constructor keys to different variable names

I have JSON looking like:
{
"days": [
{
"mintemp": "21.8"
}
]
}
With Groovy, I parse it like this:
class WeatherRow {
String mintemp
}
def file = new File("data.json")
def slurper = new JsonSlurper().parse(file)
def days = slurper.days
def firstRow = days[0] as WeatherRow
println firstRow.mintemp
But actually, I would like to name my instance variable something like minTemp (or even something completely random, like numberOfPonies). Is there a way in Groovy to map a member of a map passed to a constructor to something else?
To clarify, I was looking for something along the lines of #XmlElement(name="mintemp"), but could not easily find it:
class WeatherRow {
#Element(name="mintemp")
String minTemp
}
Create a constructor that takes a map.
Runnable example:
import groovy.json.JsonSlurper
def testJsonStr = '''
{"days": [
{ "mintemp": "21.8" }
]}'''
class WeatherRow {
String minTemp
WeatherRow(map) {
println "Got called with constructor that takes a map: $map"
minTemp = map.mintemp
}
}
def slurper = new JsonSlurper().parseText(testJsonStr)
def days = slurper.days
def firstRow = days[0] as WeatherRow
println firstRow.minTemp
Result:
Got called with constructor that takes a map: [mintemp:21.8]
21.8
(of course you'd remove the println line, it's just there for the demo)
You can achieve this using annotation and simple custom annotation processor like this:
1. Create a Custom Annotation Class
#Retention(RetentionPolicy.RUNTIME)
#interface JsonDeserializer {
String[] names() default []
}
2. Annotate your instance fields with the custom annotation
class WeatherRow{
#JsonDeserializer(names = ["mintemp"])
String mintemp;
#JsonDeserializer(names = ["mintemp"])
String minTemp;
#JsonDeserializer(names = ["mintemp"])
String numberOfPonies;
}
3. Add custom json deserializer method using annotation processing:
static WeatherRow fromJson(def jsonObject){
WeatherRow weatherRow = new WeatherRow();
try{
weatherRow = new WeatherRow(jsonObject);
}catch(MissingPropertyException ex){
//swallow missing property exception.
}
WeatherRow.class.getDeclaredFields().each{
def jsonDeserializer = it.getDeclaredAnnotations()?.find{it.annotationType() == JsonDeserializer}
def fieldNames = [];
fieldNames << it.name;
if(jsonDeserializer){
fieldNames.addAll(jsonDeserializer.names());
fieldNames.each{i ->
if(jsonObject."$i")//TODO: if field type is not String type custom parsing here.
weatherRow."${it.name}" = jsonObject."$i";
}
}
};
return weatherRow;
}
Example:
def testJsonStr = '''
{
"days": [
{
"mintemp": "21.8"
}
]
}'''
def parsedWeatherRows = new JsonSlurper().parseText(testJsonStr);
assert WeatherRow.fromJson(parsedWeatherRows.days[0]).mintemp == "21.8"
assert WeatherRow.fromJson(parsedWeatherRows.days[0]).minTemp == "21.8"
assert WeatherRow.fromJson(parsedWeatherRows.days[0]).numberOfPonies == "21.8"
Check the full working code at groovyConsole.

Resources