Problem with parsing XML file in Groovy script running in Jenkins pipeline - groovy

I need to get some data from an XML document in a groovy script running in the Jenkins pipeline. For this, I use XmlParser(). The problem is that the code I wrote fully works in Groovy on my machine, but as soon as I run it from Jenkins I get an error.
The Groovy code:
#NonCPS
def callTests (String configFile, String pathProjectForAsseration) {
def configFileAsXML = new XmlParser().parseText(configFile)
configFileAsXML.testcases.testcase.each { testline ->
String testFileName = testline['#filename']
String testEndpoint = testline['#endpoint']
String testPassword = testline['#password']
// далее следует логика, не относящаяся к вопросу
}
}
def runTests() {
pathToConfigFileForGroovy = "${PATH_TO_CONFIG_FILE}".replace("\\", "/")
String configFile = readFile(pathToConfigFileForGroovy)
callTests(configFile, pathProjectForAsseration)
}
Example of XML file:
<configuration someAttribute="seomeValue">
<testcases>
<testcase filename="filename" password="password" login="login"/>
<testcase filename="filename" password="password" login="login"
isReal="false"/>
<testcase filename="filename" password="password" login="login"/>
<testcase filename="filename" password="password" login="login"
isReal="false"/>
</testcases>
</configuration>
An error occurs on this line:
configFileAsXML.testcases.testcase.each { testline ->
The error:
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: No such field found: field groovy.util.Node testcases.

Related

Properly encode URL for Webtest configuration XML with Terraform on Azure

I'm trying to setup a azurerm_application_insights_web_test with Terraform. Currently having issues with the Url parameter in the configuration WebTest XML.
I'm just not figuring out how I'd have to properly encode the string. For "simple" URLs, it's no problem. But what about eg. https://a.skwar.me/example=yes? The problem is with the "=" (equal) sign in the URL.
If I set Url="https://a.skwar.me/example=yes" in the XML, terraform apply fails:
2021-12-03T08:32:47.4173868Z Error: creating/updating Application Insights Web Test: (Name "dummy3aaiwt" / Resource Group "SharedienDevopsTesting"): insights.WebTestsClient#CreateOrUpdate: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="BadRequest" Message="Specified argument was out of the range of valid values.\r\nParameter name: Web test 'dummy3aaiwt' is invalid. Ensure it is a well formed XML and that it adheres to the web test schema. Technical error: '=' is an unexpected token. The expected token is ';'. Line 23, position 33." InnerError={"diagnosticcontext":"6a6fb5be-fba9-4110-be6a-beffd2a44ef1","time":"2021-12-03T08:32:47.3359710Z"}
Note: Technical error: '=' is an unexpected token. The expected token is ';'
I tried to simply urlencode() the whole URL. Apply works, but no tests are being done. If I go Azure Portal, I see that the parameter hasn't been decoded; ie. I see https%3A%2F%2Fa.skwar.me%2Fexample%3Dyes. I also cannot save the test, as the URL is invalid (… d'oh!)
I've got this:
resource "azurerm_application_insights_web_test" "dummy3" {
name = "dummy3aaiwt"
location = local.ai_this.location
resource_group_name = local.ai_this.resource_group_name
application_insights_id = local.ai_this.id
kind = "ping"
frequency = 900
timeout = 120
enabled = true
retry_enabled = true
geo_locations = split(",", local.test_locations)
configuration = <<XML
<WebTest
Name="abcdefXML"
Id="${random_uuid.dummy.result}"
Enabled="True"
CssProjectStructure=""
CssIteration=""
Timeout="120"
WorkItemIds=""
xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"
Description=""
CredentialUserName=""
CredentialPassword=""
PreAuthenticate="True"
Proxy="default"
StopOnError="False"
RecordedResultFile=""
ResultsLocale="">
<Items>
<Request
Method="GET"
Guid="${random_uuid.dummy2.result}"
Version="1.1"
Url="${urlencode("https://a.skwar.me/some-exampe?foo=bar")}"
ThinkTime="0"
Timeout="120"
ParseDependentRequests="False"
FollowRedirects="True"
RecordResult="True"
Cache="False"
ResponseTimeGoal="0"
Encoding="utf-8"
ExpectedHttpStatusCode="302"
ExpectedResponseUrl=""
ReportingName=""
IgnoreHttpStatusCode="False" />
</Items>
</WebTest>
XML
}
Using Terraform Version 1.0.11 and provider registry.terraform.io/hashicorp/azurerm v2.86.0 , if I try to use urlencode in the url parameter then I am also facing the same issue that you see in portal as below:
But directly providing the URL using the below code succeeds and URL is also correctly defined in portal and can be saved as well.
resource "azurerm_application_insights_web_test" "example" {
name = "tf-test-appinsights-webtest"
location = data.azurerm_application_insights.example.location
resource_group_name = data.azurerm_application_insights.example.resource_group_name
application_insights_id = data.azurerm_application_insights.example.id
kind = "ping"
frequency = 300
timeout = 60
enabled = true
geo_locations = ["us-ca-sjc-azr", "us-va-ash-azr"]
configuration = <<XML
<WebTest
Name="WebTest1"
Id="ABD48585-0831-40CB-9069-682EA6BB3583"
Enabled="True"
CssProjectStructure=""
CssIteration=""
Timeout="120"
WorkItemIds=""
xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"
Description=""
CredentialUserName=""
CredentialPassword=""
PreAuthenticate="True"
Proxy="default"
StopOnError="False"
RecordedResultFile=""
ResultsLocale="">
<Items>
<Request
Method="GET"
Guid="a5f10126-e4cd-570d-961c-cea43999a200"
Version="1.1"
Url="https://a.skwar.me/some-exampe?foo=bar"
ThinkTime="0"
Timeout="300"
ParseDependentRequests="False"
FollowRedirects="True"
RecordResult="True"
Cache="False"
ResponseTimeGoal="0"
Encoding="utf-8"
ExpectedHttpStatusCode="302"
ExpectedResponseUrl=""
ReportingName=""
IgnoreHttpStatusCode="False" />
</Items>
</WebTest>
XML
}
Output:

Test NG Cucumber Parallel Automation with Dynamic test tags and param

I am currently looking to run multiple test in cucumber in parallel using testng and I successfully managed to do that.
Now my requirement is rather than having multiple Test TAGS in the testNG file with different parameters take it from the maven command line. So I can do automation without editing the testNg.xml file. Is there a way to achieve it? Please find my current testng.xml configuration.
testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Testng Cucumber Suite" thread-count="2" parallel="tests">
<!-- In order to run test cases please copy and one test and add make sure you add relevant parameters -->
<test name="Run_Nexus_06">
<parameter name="deviceName" value="Google Nexus 6" />
<parameter name="platformVersion" value="6.0" />
<classes>
<class name="cucumber.mobile.ParallelRunner">
</class>
</classes>
</test>
<test name="Run_Google_Pixel">
<parameter name="deviceName" value="Google Pixel" />
<parameter name="platformVersion" value="7.1" />
<classes>
<class name="cucumber.mobile.ParallelRunner">
</class>
</classes>
</test>
</suite>
Runner Class :
#CucumberOptions(plugin = {"pretty", "html:target/html/", "json:target/cucumber.json", "junit:TEST-all.xml"},
features = "src/test/resources/features/SignUp.feature", glue = {"steps"}, tags = {"#Mobile"})
public class ParallelRunner extends Hook{
List<Object[]> data;
//<parameter name="deviceName" value="Google Pixel" />
// <parameter name="platformVersion" value="7.1" />
#BeforeTest
#Parameters({"deviceName","platformVersion"})
public void bb(String deviceName, String platformVersion){
Device device = new Device();
device.setDeviceName(deviceName);
device.setOsVersion(platformVersion);
DeviceFactory.setDevice(device);
System.out.println("Device" + deviceName + "Os Version" + platformVersion + " " + Thread.currentThread().getId());
}
}
I was glad that I found this post. Very useful if anyone trying to achieve the same thing. Dynamic Test ng IAlterSuiteListener
Maven command :> mvn compile test -DdeviceFlavors="Google Nexus 6","Google Pixel" -DdeviceOsFlavors="6.0","7.1" -Dsurefire.suiteXmlFiles=testng.xml

Error processing / merging manifest

I get this error
W:\android-studio-projects\sharedid\app\build\intermediates\merged_manifests\flavor_customer1Debug\processFlavor_customer1DebugManifest\merged\AndroidManifest.xml:49:
error: resource string/MyAppName (aka
com.customer1.app:string/MyAppName) not found.
error: failed processing manifest.
...
My gradle contains this
flavor_customer1 {
java.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/java/"]
manifest.srcFile "W:/android-studio-projects/sharedid/app/src/customer1/AndroidManifest.xml"
assets.srcDirs = ["W:/android-studio-projects/sharedid/app/src/customer1/assets/"]
resources.srcDirs = ["W:/android-studio-projects/sharedid/app/src/main/res/", "W:/android-studio-projects/sharedid/app/src/customer1/res/"]
}
I have defined MyAppName in file
"W:/android-studio-projects/sharedid/app/src/customer1/res/values/strings_specific.xml"
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="MyAppName">Customer 1</string>
</resources>
In "W:/android-studio-projects/sharedid/app/src/customer1/AndroidManifest.xml" I use the string like this
<application
android:allowBackup="true"
android:icon="#drawable/app_logo__forlarge"
android:label="#string/MyAppName"
android:theme="#style/AppBaseTheme_Customer_One"
android:name="com.shared.app.MyApp"
>
...
What am I missing? I am trying to switch over to using product flavors
Apparentlt merge depends on "main" folder also containing strings.xml even though each flavor has their own

Failing scripts in groovy using Grab

The following groovy scripts fail using command line
#Grab("org.apache.poi:poi:3.9")
println "test"
Error:
unexpected token: println # line 2, column 1.
println "test"
^
1 error
Removing the Grab, it works!
Anything I missed?
$>groovy -v
Groovy Version: 2.1.7 JVM: 1.7.0_25 Vendor: Oracle Corporation OS: Linux
Annotations can only be applied to certain targets. See SO: Why can't I do a method call after a #Grab declaration in a Groovy script?
#Grab("org.apache.poi:poi:3.9")
dummy = null
println "test"
Alternatively you can use grab as a method call:
import static groovy.grape.Grape.grab
grab(group: "org.apache.poi", module: "poi", version: "3.9")
println "test"
For more information refer to Groovy Language Documentation > Dependency management with Grape.
File 'Grabber.groovy'
package org.taste
import groovy.grape.Grape
//List<List[]> artifacts => [[<group>,<module>,<version>,[<Maven-URL>]],..]
static def grab (List<List[]> artifacts) {
ClassLoader classLoader = new groovy.lang.GroovyClassLoader()
def eal = Grape.getEnableAutoDownload()
artifacts.each { artifact -> {
Map param = [
classLoader: classLoader,
group : artifact.get(0),
module : artifact.get(1),
version : artifact.get(2),
classifier : (artifact.size() < 4) ? null : artifact.get(3)
]
println param
Grape.grab(param)
}
}
Grape.setEnableAutoDownload(eal)
}
Usage :
package org.taste
import org.taste.Grabber
Grabber.grab([
[ "org.codehaus.groovy.modules.http-builder", "http-builder", '0.7.1'],
[ "org.postgresql", "postgresql", '42.3.1', null ],
[ "com.oracle.database.jdbc", "ojdbc8", '12.2.0.1', null]
])

Parse XML using Groovy: How do I keep the CDATA when parsing a XML file

Using Groovy 2.0.5 JVM 1.6.0_31, I have created a script that takes an existing XML-file as input
def root = new XmlParser().parse(new File('filename'))
I parse the file and replaces certain attributes like this
root.Settings.Setting.each {
if (it.'#NAME' =~ 'CASEID_SEQUENCE_SIZE') {
it.'#VALUE' = '100'
And then at the end writes the changes to a new file like this
def outputfile = new File( levelConfig.RESULTFILE )
new XmlNodePrinter(new PrintWriter(outputfile)).print(root)
All this is fine, no problem, except when the XML has CDATA, like this
<HandlerURL>
<![CDATA[admin/MainWindow.jsp]]>
</HandlerURL>
the result is then
<HandlerURL>
admin/MainWindow.jsp
</HandlerURL>
Question is
How can I get my script to not do anything with the CDATA?
Found you can do:
import groovy.xml.*
import groovy.xml.dom.DOMCategory
def xml = '''<root>
| <Settings>
| <Setting name="CASEID_SEQUENCE_SIZE">
| <HandlerURL>
| <![CDATA[ admin/MainWindow.jsp ]]>
| </HandlerURL>
| </Setting>
| <Setting name="SOMETHING_ELSE">
| <HandlerURL>
| <![CDATA[ admin/MainWindow.jsp ]]>
| </HandlerURL>
| </Setting>
| </Settings>
|</root>'''.stripMargin()
def document = DOMBuilder.parse( new StringReader( xml ) )
def root = document.documentElement
use(DOMCategory) {
root.Settings.Setting.each {
if( it.'#name' == 'CASEID_SEQUENCE_SIZE' ) {
it[ '#value' ] = 100
}
}
}
def result = XmlUtil.serialize( root )
println result
To get the output:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Settings>
<Setting name="CASEID_SEQUENCE_SIZE" value="100">
<HandlerURL>
<![CDATA[ admin/MainWindow.jsp ]]>
</HandlerURL>
</Setting>
<Setting name="SOMETHING_ELSE">
<HandlerURL>
<![CDATA[ admin/MainWindow.jsp ]]>
</HandlerURL>
</Setting>
</Settings>
</root>

Resources