What would the easiest way to parse the Data section from this STAF command be?
Cannot find a STAF parameter which I can pass to the command to automatically do this,
so looks like parsing/regular expression might be best option?
Note: I do not want to use any external libraries.
[root#source ~]# STAF target PROCESS START SHELL COMMAND "ls" WAIT RETURNSTDOUT
Response
--------
{
Return Code: 0
Key : <None>
Files : [
{
Return Code: 0
Data : myFile.txt
myFile2.txt
myFile3.txt
}
]
}
Instead I would like the output/result to be formated like ..
[root#source ~]# STAF target PROCESS START SHELL COMMAND "ls" WAIT RETURNSTDOUT
myFile.txt
myFile2.txt
myFile3.txt
Best way to this is Create a XML file and use python script to access the data part of STAFResult since STAF Return data in Marshalled form as "CONTENT" and python can be use to grab that.
I will try to explain it with simple example, Its an HTTP request to server.
<stafcmd>
<location>'%s'%machineName</location>
<service>'http'</service>
<request>'DOGET URL %s?phno=%s&shortCode=%s&query=%s' % (url, phno, shortCode, escapeQuery)</request>
</stafcmd>
<if expr="RC == 0">
<sequence>
<call function="'func_Script'"></call>
<if expr="rc == 0"> <!-- Pass At First Query -->
<sequence>
<message>'PASS#Fisrt HTTPRequest: Keyword = %s,\nRequired Response = %s,\ncontent=%s' %(query, response, content)</message>
<tcstatus result="'pass'">'Pass:' </tcstatus>
</sequence>
<else> <!-- Check For MORE -->
<call function="'Validate_QueryMore'"> </call>
</else>
</if>
</sequence>
<else>
<message>'ERROR: HTTPRequest QUERY : RC = %s Result= %s' %(rc,STAFResult)</message>
</else>
</if>
<function name="func_Script">
<script>
import re
content = STAFResult['content'].lower()
response = response.lower()
test = content.find(response)
if test != -1:
rc = 0
else:
rc = 1
</script>
</function>
Hope It will give you some Help.
You can pipe the output of your command through an sed script that will filter out only the filenames for you. Here's a first cut:
sed -ne '/^[a-z]/p;/Data/s/[^:]*: \(.*\)/\1/p'
The idea is: If a line starts with a lower-case letter, that's a file name (expression up to the first semicolon). If the string "Data" is on the line, take everything that comes after the first colon in that line (expression after the semicolon). Everything else is ignored.
You might want to be more specific than just expecting a lower-case letter at the beginning (this would filter out the "Response" line at the beginning, but if your filename might start with an upper-case letter, that won't work). Also, just looking for the string "Data" might be a bit too general -- that string might occur in the filename as well. But hopefully you get the idea. To use this, run your command like this:
STAF ... | sed -ne ...
Related
What is the correct way to tokenize a string on double-forward-slash // in a Jenkinsfile?
The example below results in the string being tokenized on single-forward-slash / instead, which is not the desired behavior.
Jenkinsfile
An abbreviated, over-simplified example of the Jenkinsfile containing the relevant part is:
node {
// Clean workspace before doing anything
deleteDir()
try {
stage ('Clone') {
def theURL = "http://<ip-on-lan>:<port-num>/path/to/some.asset"
sh "echo 'theURL is: ${theURL}'"
def tokenizedURL = theURL.tokenize('//')
sh "echo 'tokenizedURL is: ${tokenizedURL}'"
}
} catch (err) {
currentBuild.result = 'FAILED'
throw err
}
}
The Logs:
The log output from the preceding is:
echo 'theURL is: http://<ip-on-lan>:<port-num>/path/to/some.asset'— Shell Script<1s
[ne_Branch-Name-M2X23QGNMETLDZWFK7IXVZQRCNSWYNTDFJZU54VP7DMIOD6Z4DGA] Running shell script
+ echo theURL is: http://<ip-on-lan>:<port-num>/path/to/some.asset
theURL is: http://<ip-on-lan>:<port-num>/path/to/some.asset
echo 'tokenizedURL is: [http:, <ip-on-lan>:<port-num>, path, to, some.asset]'— Shell Script<1s
[ne_Branch-Name-M2X23QGNMETLDZWFK7IXVZQRCNSWYNTDFJZU54VP7DMIOD6Z4DGA] Running shell script
+ echo tokenizedURL is: [http:, <ip-on-lan>:<port-num>, path, to, some.asset]
tokenizedURL is: [http:, <ip-on-lan>:<port-num>, path, to, some.asset]
Note that the logs show that the string is being tokeni on / instead of on //.
tokenize takes string as optional argument that may contain 1 or more characters as delimiters. It treats each character in string argument as separate delimiter so // is effectively same as /
To split on //, you may use split that supports regex:
theURL.split(/\/{2}/)
Code Demo
Below lines in my jenkins job configuration Execute shell retrieves jira key
JIRA_KEY=$(curl --request GET "http://jenkins-server/job/myProject/job/mySubProject/job/myComponent/${BUILD_NUMBER}/api/xml?xpath=/*/changeSet/item/comment" | sed -e "s/<comment>\(.*\)<\/comment>/\1/")
JIRA_KEY=$(echo $JIRA_KEY | cut -c10-17)
But in case if text doesn't start with jira key then as per the current logic it will assign any text in the range of 10-17. I need to store empty string "" in the variable JIRA_KEY when jira key is not present in the <comment>, how can we do that?
Here is the xml
<freeStyleBuild _class="hudson.model.FreeStyleBuild">
<changeSet _class="hudson.plugins.git.GitChangeSetList">
<item _class="hudson.plugins.git.GitChangeSet">
<comment>
JRA-1011 This is commit
message.
</comment>
</item>
</changeSet>
</freeStyleBuild>
As I mentioned in comment section it is not clear which output you need, so based on some assumptions, could you please try following and let me know on same.
I- If you need all the strings between to then you could run following.
awk '/<\/comment>/{a="";next}/<comment>/{a=1;next}a' Input_file
II- If you need to find only JRA string between to then you could do following.
awk '/<\/comment>/{a="";next}/<comment>/{a=1;next} a && /JRA/{match($0,/[a-zA-Z]+[^ ]*/);print substr($0,RSTART,RLENGTH)}' Input_file
I have a target that reads a .proj file with ReadLinesFromFile and then try to match a version number (e.g. 1.0.23) from the contained lines like:
<Target Name="GetRevision">
<ReadLinesFromFile File="$(MyDir)GetStuff.Data.proj">
<Output TaskParameter="Lines" ItemName="GetStuffLines" />
</ReadLinesFromFile>
<PropertyGroup>
<In>#(GetStuffLines)</In>
<Out>$([System.Text.RegularExpressions.Regex]::Match($(In), "(\d+)\.(\d+)\.(\d+)"))</Out>
</PropertyGroup>
<Message Text="Revision number [$(Out)]" />
<CreateProperty Value="$(Out)">
<Output TaskParameter="Value" PropertyName="RevisionNumber" />
</CreateProperty>
</Target>
The result is always empty.. Even if I try to do a simple Match($(In), "somestring") its not working correctly in linux/xbuild. This does work on windows/msbuild
Any tricks/ideas? An alternative would be to get the property version out of the first .proj file, instead of reading all lines and matching the number with a regex, but I don't even know if that is possible.
I am running versions:
XBuild Engine Version 12.0
Mono, Version 4.2.1.0
EDIT:
I've been able to trace it further down into the parameters that go into Match(), there is something wrong with the variables evaluation. The function actually works with for example Match("foobar","bar") I will get bar
But weird things happen with other inputs, e.g. Match($(In), "Get") will match Get because it is actually matching against the string "#(GetStuffLines)"
When I do Match($(In), "#..") I will get a match of #(G
But then, when I do Match($(In), "#.*") I actually get the entire content of the input file GetStuff.Data.proj which indicates that the variable was correctly expanded somewhere and the matching matched the entire input string.
I needed to circumvent Match() because it seems to be bugged at this point.
The ugly solution I came up with was to use Exec and grep the pattern like:
<Exec Command="grep -o -P '[0-9]+[.][0-9]+[.][0-9]+' $(MyDir)GetStuff.Data.proj > extractedRevisionNumber.tmp" Condition="$(OSTYPE.Contains('linux'))"/>
<ReadLinesFromFile File="$(ComponentRootDir)extractedRevisionNumber.tmp" Condition="$(OSTYPE.Contains('linux'))">
<Output TaskParameter="Lines" ItemName="GetExtractedRevisionNumber" />
</ReadLinesFromFile>
I couldn't even use the properties ConsoleToMSBuild and ConsoleOutput (https://msdn.microsoft.com/en-us/library/ms124731%28v=VS.110%29.aspx) because xbuild didn't recognize those.. That's why I grep the pattern and save it into a temp file which can be read with ReadLinesFromFile into the ItemName="GetExtractedRevisionNumber" that I use later.
I am trying to use Regexfilter in RollingFileAppender. For 1st matching instance it retreived the logger, but after that I different patttern but nothing is logged in the file. Here is what I am using:
Main Class:
public class MainApp {
public static void main(String[] args) {
final Logger logger = LogManager.getLogger(MainApp.class.getName());
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
logger.trace("NPF:Trace:Entering Log4j2 Example.");
logger.debug("NTL:debug Entering Log4j2 Example.");
obj.getMessage();
Company comp = new Company();
comp.setCompName("ANC");
comp.setEstablish(1889);
CompanyBusiness compBus = (CompanyBusiness)context.getBean("compBus");
compBus.finaceBusiness(comp.getCompName(), comp.getEstablish());
logger.trace("NTL: Trace: Exiting Log4j2 Example.");
}
}
log4j2.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd [%t] HH:mm:ss} %-5p %c{1}:%L - %m%X%n" />
</Console>
<RollingFile name="RollingFile" fileName="C:\logTest\runtime\tla\els3.log" append="true" filePattern="C:\logTest\runtime\tla\els3-%d{yyyy-MM-dd}-%i.log" >
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%X%n" />
<RegexFilter regex=".*business*." onMatch="ACCEPT" onMismatch="DENY"/>
<Policies>
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.anc" level="trace"/>
<Root level="trace">
<AppenderRef ref="STDOUT" />
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
When I ran for the first time, in my logfile I got logs having only "business" related line. Latter I changed the patter from .business (pattern has astreik before and after business word). to "business", logging did not happen in file nor on the console. Also my application terminated without any kind of logging.
Then I tried to revert back the pattern to '.business.' (pattern has astreik before and after business word), thereafter no logging happened on the log file, but on the console all the log trace is printed. When I comment out the Regexfilter after trying for long time, my logs was printed in the log file.
I am not sure if this is a bug of Regexfilter works only for one time. Also if we do not pass any patter matching characters, the application stops without any log printing either on console or file.
If you want to log all events containing the word "business", then you shall use the regex .*business.* instead of .*business*.. Here is an example:
<RegexFilter regex=".*business.*" onMatch="ACCEPT" onMismatch="DENY"/>
For information, .*business*. means: anything, followed by business, followed by s character 0 or more time, followed by any single character.
More explaining:
. means any single character
* means 0 or more times
so .* means any character, 0 or more times.
we have running tomcat server and in server.xml file we have password=secret I want to search and replace my password with xxxxxxx string. how do i craft regex for it? following is line where password i located in server.xml file
<Resource auth="Container" description="Database connection for Production" driverClassName="oracle.jdbc.OracleDriver" factory="org.apache.commons.dbcp.BasicDataSourceFactory" maxActive="25" maxIdle="5" maxWait="5000" name="jdbc/osdb" password="secret" type="javax.sql.DataSource" url="jdbc:oracle:thin:#DB0001" username="admin"/>
Would something like:
sed -i 's/password="[a-zA-Z0-9]\+"/password="foo"/g' server.xml
do the job for you or are you expecting there to be other lines like password="xyz" ?