vars/iam.groovy
---------------
  o Add a debug helper, identify caller with a banner for logging.

jjb/pipeline/voltha/playground/voltha-tt-physical-functional-tests.groovy
-------------------------------------------------------------------------
  o Try out the new method in playground

Change-Id: I4957a54d0e5d7c637c50b6f6379b572df4743fbc
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 7e8b5d9..569cf1d 100644
--- a/jjb/pipeline/voltha/playground/voltha-tt-physical-functional-tests.groovy
+++ b/jjb/pipeline/voltha/playground/voltha-tt-physical-functional-tests.groovy
@@ -69,19 +69,12 @@
 
 	// -----------------------------------------------------------------------
 	// -----------------------------------------------------------------------
-	stage('IAM')
-	{
-	    String iam = getIam('main')
-            println("** ${iam}: ENTER")
-            println("** ${iam}: LEAVE")
-	}
-
-	// -----------------------------------------------------------------------
-	// -----------------------------------------------------------------------
 	stage('Clone voltha-system-tests')
 	{
 	    steps
 	    {
+		iam(this) { enter = true }
+
 		step([$class: 'WsCleanup'])
 		checkout([
 		    $class: 'GitSCM',
@@ -110,6 +103,8 @@
               exit 1  # verify fail
             fi
             """)
+
+		iam(this) { leave = true }
 		} // step
 	    } // steps
 	} // stage
diff --git a/makefiles/lint/groovy/README.md b/makefiles/lint/groovy/README.md
new file mode 100644
index 0000000..aa9b41a
--- /dev/null
+++ b/makefiles/lint/groovy/README.md
@@ -0,0 +1,13 @@
+# lint: groovy source
+
+# Invoke the linting tool
+% make lint-groovy
+
+# Alt checking: groovy interpreter
+
+Odd syntax errors can be detected by the groovy interpreter.
+
+% groovy path/to/{source}.groovy
+
+jjb/ pipeline scripts will eventually due to syntax problems but groovy can
+still detect problems like mismatched quotes, invalid op tokens, etc.
diff --git a/makefiles/lint/groovy/urls b/makefiles/lint/groovy/urls
new file mode 100644
index 0000000..aa5c5eb
--- /dev/null
+++ b/makefiles/lint/groovy/urls
@@ -0,0 +1,8 @@
+# -*- makefile -*-
+
+# Config file and exclusions
+https://www.npmjs.com/package/npm-groovy-lint#Configuration
+
+https://github.com/nvuillam/npm-groovy-lint
+
+# [EOF]
diff --git a/vars/iam.groovy b/vars/iam.groovy
new file mode 100644
index 0000000..0a340b6
--- /dev/null
+++ b/vars/iam.groovy
@@ -0,0 +1,148 @@
+#!/usr/bin/env groovy
+// -----------------------------------------------------------------------
+// Copyright 2023 Open Networking Foundation (ONF) and the ONF Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// -----------------------------------------------------------------------
+// % npm-groovy-lint vars/iam.groovy
+// -----------------------------------------------------------------------
+
+// -----------------------------------------------------------------------
+// -----------------------------------------------------------------------
+String getIam(String func)
+{
+    // Cannot rely on a stack trace due to jenkins manipulation
+    // Report who and where caller came from.
+    String src = [
+        'repo:ci-management',
+        'vars',
+        'iam',
+    ].join('/')
+
+    String iam = [src, func].join('::')
+    return(iam)
+}
+
+// -----------------------------------------------------------------------
+// Intent: Display future enhancement list.
+// -----------------------------------------------------------------------
+void todo()
+{
+    String iam = getIam('todo')
+
+    println("""
+[TODO: $iam]
+ o Pass jenkins parameters so todo() function can be conditionally called.
+ o Add call parameters to:
+   - Specify {ENTER,LEAVE} strings for logging.
+   - Set methods for caller to specify an alternate getIam() path.
+""")
+
+    return
+}
+
+// -----------------------------------------------------------------------
+// Intent: Placeholder in case future enhancements are needed
+// -----------------------------------------------------------------------
+Boolean process(Map config)
+{
+    String iam = getIam('process')
+
+    Boolean leave = false
+
+    // Identify caller with a banner for logging
+    if (config.containsKey('enter')) {
+        println("** ${iam}: ENTER")
+    }
+    else if (config.containsKey('leave')) {
+	leave = true
+    }
+    else
+    {
+        println("** ${iam}: HELLO")
+    }
+ 
+    // Display future enhancement list
+    if (config.containsKey('todo')) {
+        todo()
+    }
+
+    // Maintain a sane logging enclosure block
+    if (leave)
+    {
+        println("** ${iam}: LEAVE")
+    }
+    
+    return(true)
+}
+
+// -----------------------------------------------------------------------
+// Intent: Debug method for jenkins jobs identifying caller for logging.
+// -----------------------------------------------------------------------
+// Given:
+//   self    jenkins environment pointer 'this'
+//   config  groovy closure used to pass key/value pairs into argv
+//     enter    Display "** {iam} ENTER"
+//     leave    Display "** {iam} LEAVE"
+//     todo     Display future enhancement list
+// -----------------------------------------------------------------------
+// Usage:
+//   o called from a jenkins {pipeline,stage,script} block.
+//   o iam(this)
+//     {
+//         foo  = bar    // paramter foo is...
+//         tans = fans
+//     }
+// -----------------------------------------------------------------------
+Boolean call(def self, Map config)
+{
+    String iam = getIam('main')
+
+    argv = argv ?: [:] // {ternary,elvis} operator
+    println("** ${iam}: argv=${argv}")
+
+    Boolean ranToCompletion = false
+    try
+    {
+        // [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())
+        // if (! self instanceof jenkins_object) { throw }
+
+        if (process(argv))
+        {
+            ranToCompletion = true
+        }
+    }
+    /* groovylint-disable*/ /* yuck! */
+    catch (Exception err)
+    /* groovylint-enable */
+    {
+        println("** ${iam}: EXCEPTION ${err}")
+        throw err
+    }
+    finally
+    {
+        println("** ${iam}: LEAVE")
+    }
+
+    if (!ranToCompletion)
+    {
+        throw new Exception("ERROR ${iam}: Detected incomplete script run")
+    }
+
+    return(true)
+}
+
+// [EOF]
+