Merge "vars/iam.groovy ---------------   o Oh yea, to handle call arg closure properly pass, assign and call body()."
diff --git a/jjb/pipeline/voltha/playground/physical-build.groovy b/jjb/pipeline/voltha/playground/physical-build.groovy
index 5779ac1..856006e 100644
--- a/jjb/pipeline/voltha/playground/physical-build.groovy
+++ b/jjb/pipeline/voltha/playground/physical-build.groovy
@@ -33,13 +33,32 @@
 // -----------------------------------------------------------------------
 def getIam(String func)
 {
+    /*
+     [TODO]
+     -----------------------------------------------------------------------
+     java stack trace is hosed due to jenkins internal meddeling to support
+     serializable.  Lets see if groovy Throwable wrapper can produce a
+     better answer.
+     -----------------------------------------------------------------------
+
+    try
+    {
+        throw new Exception('Generating a stacktrace')
+    }
+    catch (Throwable err)
+    {
+        // https://docs.groovy-lang.org/2.4.7/html/api/org/codehaus/groovy/GroovyException.html
+        err.printStackTrace()
+        stack = err.getStackTrace()
+    }
+
     // Cannot rely on a stack trace due to jenkins manipulation
     String src = [
         'jjb',
         'pipeline',
         'voltha',
         'playground',
-        'voltha-tt-physical-functional-tests.groovy'
+        'physical-build.groovy'
     ].join('/')
 
     String iam = [src, func].join('::')
@@ -78,24 +97,25 @@
     {
         stage('Download Code')
         {
-            iam(this)
+            steps
             {
-                enter = true
-                label = getIam()
-            }
+                iam(this)
+                {
+                    enter = true
+                    label = getIam()
+                }
 
-            steps {
                 getVolthaCode([
                     branch: "${branch}",
                     volthaSystemTestsChange: "${volthaSystemTestsChange}",
                     volthaHelmChartsChange: "${volthaHelmChartsChange}",
                 ])
-            }
 
-            iam(this)
-            {
-                leave = true
-                label = getIam()
+                iam(this)
+                {
+                    leave = true
+                    label = getIam()
+                }
             }
         }
 
diff --git a/jjb/pipeline/voltha/playground/voltha-tt-physical-functional-tests.groovy b/jjb/pipeline/voltha/playground/voltha-tt-physical-functional-tests.groovy
index f0965ff..39e543f 100644
--- a/jjb/pipeline/voltha/playground/voltha-tt-physical-functional-tests.groovy
+++ b/jjb/pipeline/voltha/playground/voltha-tt-physical-functional-tests.groovy
@@ -73,14 +73,14 @@
         // -----------------------------------------------------------------------
         stage('Clone voltha-system-tests')
         {
+            iam(this)
+            {
+                enter = true
+                label = getIam()
+            }
+
             steps
             {
-                iam(this)
-                {
-                    enter = true
-                    label = getIam()
-                }
-
                 step([$class: 'WsCleanup'])
                 checkout([
                     $class: 'GitSCM',
@@ -109,13 +109,13 @@
               exit 1  # verify fail
             fi
             """)
+                } // step
 
                 iam(this)
                 {
                     leave = true
                     label = getIam()
                 }
-                } // step
             } // steps
         } // stage
 
diff --git a/vars/iam.groovy b/vars/iam.groovy
index 75f204d..cafd8f2 100644
--- a/vars/iam.groovy
+++ b/vars/iam.groovy
@@ -110,9 +110,18 @@
 //         tans = fans
 //     }
 // -----------------------------------------------------------------------
-Boolean call(def self, Map argv)
+Boolean call\
+    (
+    def body,  // jenkins closure attached to the call iam() {closure}
+    def self,  // jenkins env object for access to primitives like echo()
+    )
 {
-    argv = argv ?: [:] // {ternary,elvis} operator
+    // evaluate the body block and collect configuration into the object
+    Map argv = [:] // {ternary,elvis} operator
+    body.resolveStrategy = Closure.DELEGATE_FIRST
+    body.delegate = config
+    body()
+
     String iam = getIam(argv, 'main')
 
     println("** ${iam}: argv=${argv}")
@@ -123,6 +132,7 @@
         // [WIP] type(self) needed to quiet lint complaint.
         // npm-groovy-lint:  def for method parameter type should not be used  NoDef
         print(" ** $iam: Type of self variable is =" + self.getClass())
+        print(" ** $iam: Type of body variable is =" + body.getClass())
         // if (! self instanceof jenkins_object) { throw }
 
         if (process(argv))
@@ -150,5 +160,11 @@
     return(true)
 }
 
-// [EOF]
+/*
+ * -----------------------------------------------------------------------
+[SEE ALSO]
+  o https://rtyler.github.io/jenkins.io/doc/book/pipeline/shared-libraries/#defining-a-more-structured-dsl
+ * -----------------------------------------------------------------------
+ */
 
+// [EOF]