Ant property value as parameter variable In JENKINS - jenkins

I am working on Jenkins.
I have built a job1 with secret text: username and Password variable as
APP1_Dev_password
And using this variable from my ANT script by sending this variable in the predefined parameter to my other job2. I am accessing this variable using
<property name="DBPassword" value="${APP1_Dev_password}"/>
This works well.
But my ant script is a single generalized script for all my applications.
So I have get this APP1_Dev_password string constructed automatically from my ant script using
<property name="constructPasswordVariable" value="${APPLICATIONNAME}_${ENVIRON}_password"/>
<echo message= "constructPasswordVariable: ${constructPasswordVariable}" />
This clearly prints me constructPasswordVariable as APP1_Dev_password.
Now i have to use this value of the constructPasswordVariable property as a variable to fetch from the job1.
<echo message= "PasswordValue: ${${constructPasswordVariable}}" />
This statement fails. Can you guide me of how to work on this.
SOLUTION
<property name="constructPasswordVariable" value="${env.Module}_${env.Environment}_password"/>
<echo message= "constructPasswordVariable: ${constructPasswordVariable}" />
<propertycopy name="prop" from="${constructPasswordVariable}"/>
<echo message= "ENV VALUE: ${prop}" />
Output
constructPasswordVariable: APP1_Dev_password
ENV VALUE: asdhasd

Ant says nested property is not directly supported. Referring documentation from here
However, it can be achieved using library Flaka
Sample: from above reference
<project xmlns:fl="antlib:it.haefelinger.flaka">
<fl:install-property-handler/>
<property name="foo" value="foo.value"/>
<property name="var" value="foo" />
<property name="buildtype" value="test"/>
<property name="appserv_test" value="//testserver"/>
<echo>
#{${var}} = foo.value
<!-- nested property -->
#{appserv_${buildtype}}
</echo>
</project>
There is another reference here which make it possible without additional library as well.
Sample:
<project default="test">
<property name="foo" value="ABC"/>
<property name="pfoo" value="foo"/>
<target name="test">
<echo file="deref.properties">
deref: $${${pfoo}}
</echo>
<property file="deref.properties"/>
</target>

Related

Use Property value as a Key to read another value from Properties file

For Ant Script I have following myBuild.properties file
p.buildpath=c:\production\build
d.buildpath=c:\development\build
I wrote following build.xml:
<?xml version="1.0"?>
<project name="Test Project" default="info">
<property file="myBuild.properties"/>
<target name="info">
<input
message="Please enter the Server Name(p: production, d: development)?"
validargs="p,d"
addproperty="do.Server"
/>
<echo>Your Server type: ${do.Server} </echo>
<property name="myserv.buildpath" value="${do.Server}.buildpath" />
<property name="newProperty" value="${myserv.buildpath}" />
<echo>New Property Value: ${newProperty}</echo>
<!-- Following is an incorrect syntax -->
<echo>Build Path: ${${newProperty}}</echo>
</target>
</project>
When I run it using:
c:\>ant
I get following Output:
Buildfile: C:\build.xml
info:
[input] Please enter the Server Name(p: production, d: development)? (p, d)
p
[echo] Your Server type : p
[echo] New Property Value: p.buildpath
[echo] Build Path: ${${newProperty}}
BUILD SUCCESSFUL
Total time: 2 seconds
I want to echo the "Build Path" value same as p.buildpath value.
How is it possible to do in above case?
Taking the macrodef advice of Ant Faq you need no Ant addons like antcontrib, it's foolproof :
<project>
<macrodef name="cp_property">
<attribute name="name"/>
<attribute name="from"/>
<sequential>
<property name="#{name}" value="${#{from}}"/>
</sequential>
</macrodef>
<property file="myBuild.properties"/>
<input
message="Please enter the Server Name(p: production, d: development)?"
validargs="p,d"
addproperty="do.Server"
/>
<echo>Your Server type: ${do.Server}</echo>
<cp_property name="myserv.buildpath" from="${do.Server}.buildpath"/>
<echo>$${myserv.buildpath} : ${myserv.buildpath}</echo>
</project>
output :
[input] Please enter the Server Name(p: production, d: development)? (p, d)
p
[echo] Your Server type: p
[echo] ${myserv.buildpath} : c:/production/build
btw. Within your propertyfile you need to change your path separator to either unix style '/' (when on windows ant will handle it correctly) or double '\\' , otherwise with :
p.buildpath=c:\production\build
d.buildpath=c:\development\build
you'll get something like :
[input] Please enter the Server Name(p: production, d: development)? (p, d)
p
[echo] Your Server type: p
[echo] ${myserv.buildpath} : c:productionbuild
Also see https://stackoverflow.com/a/25681686/130683 for a very similar problem solved with Props antlib
You can do it without additional tools this way (edited/revised version):
<project name="Test Project" default="info">
<property file="myBuild.properties"/>
<target name="info">
<input
message="Please enter the Server Name(p: production, d: development)?"
validargs="p,d"
addproperty="do.Server"
/>
<echo>Your Server type: ${do.Server} </echo>
<property name="buildstage.production" value="p.buildpath" />
<property name="myserv.buildpath" value="${do.Server}.buildpath" />
<echo>New Property Value: ${myserv.buildpath}</echo>
<condition property="isProduction">
<equals arg1="${buildstage.production}" arg2="${myserv.buildpath}" />
</condition>
<antcall target="production" />
<antcall target="development" />
</target>
<target name="production" if="${isProduction}">
<echo>Build Path: ${p.buildpath}</echo>
</target>
<target name="development" unless="${isProduction}">
<echo>Build Path: ${d.buildpath}</echo>
</target>
</project>
Core idea is using a <conditional> task for a test on the selected property key and calling two tasks named production and development, where the first runs if the property isProduction is avaluated to true, the second if not (unlesss).
The condition is checked against a property named buildstage.production which is set to the property key p.buildpath as discriminator.
With "property key" I reference to the keys in the properties file. A hole bunch of "properties" here, could be confusing :)
By the way: you need to escape the backslashs in the property values as follows, otherwise they won't be echoed:
p.buildpath=c:\\production\\build
d.buildpath=c:\\development\\build
How it says in this post (http://ant.apache.org/faq#propertyvalue-as-name-for-property), without any external help, it's tricky.
With AntContrib (external task library) you can do <propertycopy name="prop" from="${anotherprop}"/>.
Anyway, there are other alternatives in the same post.
Hope it helps you.
There is a much simpler way that does not require macrodef or antcontrib:
<property name="a" value="Hello"/>
<property name="newProperty" value="a"/>
<loadresource property="b">
<propertyresource name="${newProperty}"/>
</loadresource>
<echo message="a='${a}'"/>
<echo message="b='${b}'"/>

Available tag in ant is always true if a file is unavailable also

This code is always returning a true value even if file at given path does not exists
<available file="${x}/schema/#{componentname}-schema.sql" type="file" property="schema.file" />
<if>
<equals arg1="true" arg2="${schema.file}" />
<then>
<debug message="****schemafile is ${schema.file} ******" />
</then>
</if>
Output is always :-
*schemafile is true***
even if file is not available at that path.
Please help me to find the error.
I've refactored your example, in order to use standard ANT tasks:
<project name="demo" default="run" xmlns:if="ant:if">
<property name="src.dir" location="src"/>
<target name="run">
<available file="${src.dir}/schema/schema.sql" type="file" property="schema.file" />
<echo message="****schemafile is ${schema.file} ******" if:set="schema.file"/>
</target>
</project>
Notes:
I don't recognise the "debug" task so use the standard "echo" task instead
I recommend not using the ant-contrib "if" task. ANT 1.9.1 introduced an if attribute which can be used instead.
The following alternative variant will work with older versions of ANT. It uses an "if" target attribute to perform conditional execution:
<project name="demo" default="run">
<property name="src.dir" location="src"/>
<available file="${src.dir}/schema/schema.sql" type="file" property="schema.file" />
<target name="run" if="schema.file">
<echo message="****schemafile is ${schema.file} ******"/>
</target>
</project>
problem was i was iterating above code in for loop, and since property is immutable, it is always set to true if set at-least once. Thats why after 1 iteration even if the file was not found, it echoes schemafile is true** .
i have added below code to set property to false after that code
<var name="schema.file" unset="true"/>
<property name="schema.file" value="false"/>

Unusual ant behavior with presetdef and antcall

Consider the following excerpt from an ant build.xml:
<presetdef name="echo1def">
<echo message="prop: ${foo}" />
</presetdef>
<presetdef name="echo2def">
<sequential>
<echo message="prop: ${foo}" />
</sequential>
</presetdef>
<target name="echotarget1">
<property name="foo" value="bar" />
<echo1def/>
</target>
<target name="echotarget2">
<property name="foo" value="bar" />
<echo2def/>
</target>
<target name="echo1">
<antcall target="echotarget1" />
</target>
<target name="echo2">
<antcall target="echotarget2" />
</target>
Calling any of {echotarget1, echotarget2, echo1} produce the expected output of prop: bar. Calling echo2, however, produces prop: ${foo}.
Why can't the echo2def resolve the ${foo} property? It's defined immediately before, in the same project (i.e., not even on the other side of the antcall). The echo1 call, which does the same thing except the presetdef is not wrapped in <sequential>, has no issue.
Finally,
<target name="echo3">
<property name="foo" value="baz" />
<antcall target="echotarget2" />
</target>
reports prop: baz - so the property from the antcalling project can be seen, even though it is defined after the presetdef is.
Just get rid of <sequential> in your echo2def presetdef, means :
<presetdef name="echo2def">
<echo message="prop: ${foo}" />
</presetdef>
and all will work as expected.
It's because property scopes exist at Apache Ant's various "block" levels including sequential, that's how i.e. the local task (new in Ant 1.8.0) works.
antcall opens a new project scope, without antcall - means calling those targets echotarget1 and echotarget2 directly - it works also, resolving the property ${foo}.

How to pass multiple parameters to a target in Ant?

I have this dummy target:
<mkdir dir="${project.stage}/release
<war destfile="${project.stage}/release/sigma.war">
...
...
</war>
What I want to do is provide two parameters say "abc" & "xyz" which will replace the word release with the values of abc and xyz parameters respectively.
For the first parameter say abc="test", the code above will create a test directory and put the war inside it.Similarly for xyz="production" it will create a folder production and put the war file inside it.
I tried this by using
<antcall target="create.war">
<param name="test" value="${test.param.name}"/>
<param name="production" value="${prod.param.name}"/>
</antcall>
in the target which depends on the dummy target provided above.
Is this the right way to do this.I guess there must be some way to pass multiple parameters and then loop through the parameters one at a time.
unfortunately ant doesn't support iteration like for or foreach loops unless you are refering to files. There is however the ant contrib tasks which solve most if not all of your iteration problems.
You will have to install the .jar first by following the instructions here : http://ant-contrib.sourceforge.net/#install
This should take about 10 seconds. After you can simply use the foreach task to iterate through you custom list. As an example you can follow the below build.xml file :
<project name="test" default="build">
<!--Needed for antcontrib-->
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<target name="build">
<property name="test" value="value_1"/>
<property name="production" value="value_2"/>
<!--Iterate through every token and call target with parameter dir-->
<foreach list="${test},${production}" param="dir" target="create.war"/>
</target>
<target name="create.war">
<echo message="My path is : ${dir}"/>
</target>
</project>
Output :
build:
create.war:
[echo] My path is : value_1
create.war:
[echo] My path is : value_2
BUILD SUCCESSFUL
Total time: 0 seconds
I hope it helps :)
Second solution without using ant contrib. You could encapsulate all your logic into a macrodef and simply call it twice. In any case you would need to write the two parameters at some point in your build file. I don't think there is any way to iterate through properties without using external .jars or BSF languages.
<project name="test" default="build">
<!--Needed for antcontrib-->
<macrodef name="build.war">
<attribute name="dir"/>
<attribute name="target"/>
<sequential>
<antcall target="#{target}">
<param name="path" value="#{dir}"/>
</antcall>
</sequential>
</macrodef>
<target name="build">
<property name="test" value="value_1"/>
<property name="production" value="value_2"/>
<build.war dir="${test}" target="create.war"/>
<build.war dir="${production}" target="create.war"/>
</target>
<target name="create.war">
<echo message="My path is : ${path}"/>
</target>
</project>
I admit that I don't understand the question in detail. Is ${project.stage} the same as the xyz and abc parameters? And why are there two parameters xyz and abc mentioned, when only the word "release" should be replaced?
What I know is, that macrodef (docu) is something very versatile and that it might be of good use here:
<project name="Foo" default="create.wars">
<macrodef name="createwar">
<attribute name="stage" />
<sequential>
<echo message="mkdir dir=#{stage}/release " />
<echo message="war destfile=#{stage}/release/sigma.war" />
</sequential>
</macrodef>
<target name="create.wars">
<createwar stage="test" />
<createwar stage="production" />
</target>
</project>
The output will be:
create.wars:
[echo] mkdir dir=test/release
[echo] war destfile=test/release/sigma.war
[echo] mkdir dir=production/release
[echo] war destfile=production/release/sigma.war
Perhaps we can start from here and adapt this example as required.

overwriting ANT properties file

How can i overwrite some existing property with a newly created properties file?
Here is the required structure:
initially load Master.properties
generate new.properties
load new.properties and master.properties
run master.xml (ANT script)
The idea is that Master.properties generates some product version which should be replaced by new.properties. However, other properties in Master.properties should be kept the same.
Reading this does not help as i do not know how can i load the new.properties file
EDIT Here is ANT Script:
<project name="nightly_build" default="main" basedir="C:\Work\NightlyBuild">
<target name="init1">
<sequential>
<property file="C:/Work/NightlyBuild/master.properties"/>
<exec executable="C:/Work/Searchlatestversion.exe">
<arg line='"/SASE Lab Tools" "${Product_Tip}/RELEASE_"'/>
</exec>
<sleep seconds="10"/>
<property file="C:/Work/new.properties"/>
</sequential>
</target>
<target name="init" depends="init1">
<sequential>
<echo message="The product version is ${Product_Version}"/>
<exec executable="C:/Work/checksnapshot.exe">
<arg line='-NightlyBuild ${Product_Version}-AppsMerge' />
</exec>
<sleep seconds="10"/>
<property file="C:/Work/checksnapshot.properties"/>
<tstamp>
<format property="suffix" pattern="yyyy-MM-dd.HHmm"/>
</tstamp>
</sequential>
</target>
<target name="main" depends="init">
<echo message="loading properties files.." />
<echo message="Backing up folder" />
<move file="C:\NightlyBuild\NightlyBuild" tofile="C:\NightlyBuild\NightlyBuild.${suffix}" failonerror="false" />
<exec executable="C:/Work/sortfolder.exe">
<arg line="6" />
</exec>
<exec executable="C:/Work/NightlyBuild/antc.bat">
</exec>
</target>
</project>
in the above script, <exec executable="C:/Work/NightlyBuild/antc.bat"> will run Master.xml ANT script. This Master.xml will load up Master.properties:
<project name="Master ANT Build" default="main" >
<taskdef name="CFileEdit" classname="com.ANT_Tasks.CFileEdit"/>
<!-- ========================================================== -->
<!-- init: sets global properties -->
<!-- ========================================================== -->
<target name="init">
<property environment="env"/>
<!-- ========================================================== -->
<!-- Set the timestamp format -->
<!-- ========================================================== -->
<property file="Master.properties"/>
...
</project>
You should be able to resolve this by looking at the order in which you load (or otherwise specify) your property values. You probably don't need to override property values at all, which something not supported by core Ant.
Maybe you can split your Master.properties into two files - one loaded before you generate new.properties and one loaded after?
Maybe you don't need to generate new.properties at all.
Could you give some more detail on what you need to do?
Since you eventually fork a new Ant process (exec antc.bat), does that not start a fresh environment anyway? If it just loads Master.properties, those are the only properties it will have.
Not sure what your antc.bat does, but it's pretty unusual to exec Ant from Ant in this way. There are two standard tasks which might be useful - Ant and AntCall.
OK running on from your later comments...
Let's say that instead of doing this:
<exec executable="antc.bat">
you instead did something like this:
<ant file="Master.xml" inheritall="false">
<property name="Product_Version" value="${Product_Version}"/>
</ant>
I think that is getting towards what you want. You selectively pass specific values that you have obtained by loading new.properties. See the documentation for the Ant task.
If you still have the problem that you already defined Product_Version before loading new.properties, then I would say get the script you have that produces new.properties to output the version with a different name, e.g. New_Product_Version. Then invoke your master build something like this:
<ant file="Master.xml" inheritall="false">
<property name="Product_Version" value="${New_Product_Version}"/>
</ant>
May be this is a old question. Hopefully OP is reading this.
You can just use the ant task "propertyfile". reference
it can read properties from the file and write back updated values to them.

Resources