Ant-contrib foreach task - last value in the list
Asked Answered
D

1

2

I am currently executing a deploy using foreach ant task and the list has app server names (2 servers). There is a logic to wait for 2 mins (sleep) before moving to next app server.

The logic is working fine but the sleeps is applied even after the 2nd (last) app server, which is adding additional 2 minutes.

Is there a way to find that I have reached the last value in the list? so that I can exit without waiting.

sl.app.server.list=lstrdrasv01.str.staples.com

<foreach list="${sl.app.server.list}" param="sl.app.server" target="Storelocator.app.deploy" parallel="false" inheritall="true"/>

<sshexec host="${sl.app.server}" 
                username="${sl.app.username}" 
                password="${sl.as.password}"
                trust="true"
                output="output"
                command="${start}"/>

    <echo message="Waiting for Rolling deploy 2 min..."/>   
            <sleep seconds="120"/>

    </target>

The sleep is executed 2 times where my list contains 2 servers, ideally speaking it should sleep only 1 time because there is no more servers after the 2nd server.

Doorstep answered 17/3, 2014 at 1:40 Comment(2)
Can you show us your build.xml? It's hard to help you with so little information.Zoophilous
I have added the code logic. The entire file is too big, just the part where help is needed as been posted. Thank you!Doorstep
P
3

You should use for instead of foreach, as foreach uses antcall whereas for uses macrodef.
Note : works with antcontrib1.0b2, the latest release antcontrib1.0b3 has some bugs and will fail with :

BUILD FAILED
if doesn't support the nested "isgreaterthan" element.

A solution with for, no extra target needed, all work is done within sequential :

    <project>
    <!-- Import AntContrib -->
    <taskdef resource="net/sf/antcontrib/antlib.xml" />

    <property name="sl.app.server.list" value="server1,server2"/>
    <!-- make use of jdk builtin javascript engine (since jdk 1.6.0_06) -->
    <script language="javascript">
     project.setProperty('serveritems', project.getProperty("sl.app.server.list").split(',').length);
    </script>

    <for list="${sl.app.server.list}" param="server" delimiter=",">
     <sequential>
      <echo>
       Remaining $${serveritems} => ${serveritems}
       process Server : @{server}
      </echo>

      <!--
       NOTE : you have to use @{..} syntax here !
       <sshexec host="@{server}" ...
      -->

      <if>
       <isgreaterthan arg1="${serveritems}" arg2="1"/>
        <then>
         <echo>Waiting for Rolling deploy 2 min...</echo>
         <sleep seconds="120"/>
        </then>
      </if>

      <!-- this doesn't work correctly, note the output
       Remaining ${serveritems} => -1 in second loop -->
      <!--
      <math result="serveritems" operand1="${serveritems}" operation="-" operand2="1" datatype="int"/>
      -->
      <!-- decrease serveritems -->
      <script language="javascript">
       project.setProperty('serveritems', parseInt(project.getProperty('serveritems')) - 1);
      </script>
     </sequential>
    </for>
    </project>

output with wrong working <math result ... /> for decrease serveritems :

[echo]         Remaining ${serveritems} => 2
[echo]         process Server : server1
[echo]     
[echo] Waiting for Rolling deploy 2 min...
[echo]         Remaining ${serveritems} => -1
[echo]         process Server : server2
[echo] 

output with script language javascript decreasing of serveritems :

 [echo]    Remaining ${serveritems} => 2
 [echo]    process Server : server1
 [echo]   
 [echo] Waiting for Rolling deploy 2 min...
 [echo]    Remaining ${serveritems} => 1
 [echo]    process Server : server2
 [echo] 

Finally => Note the use of @{..} for parameter substition as in macrodef within sequential !

Paterfamilias answered 17/3, 2014 at 12:26 Comment(1)
Great tip on the 1.0b2 diff. Solved it for me.Ardehs

© 2022 - 2024 — McMap. All rights reserved.