Refactor jenkins.client.node

   Get rid of inline groovy
   Remove duplicate code

Change-Id: Ieaae8354201c04a378723e3783b9f1a6b955b0f5
diff --git a/_modules/jenkins_common.py b/_modules/jenkins_common.py
index 348aa09..377a71f 100644
--- a/_modules/jenkins_common.py
+++ b/_modules/jenkins_common.py
@@ -148,3 +148,45 @@
     """
     if isinstance(password, str):
         return bcrypt.hashpw(password, bcrypt.gensalt(prefix=b"2a"))
+
+def load_template(salt_url, env):
+    """
+       Return content of file `salt_url`
+    """
+
+    template_path = __salt__['cp.cache_file'](salt_url, env)
+    with open(template_path, 'r') as template_file:
+        template = template_file.read()
+
+    return template
+
+def api_call(name, template, success_msgs, params, display_name):
+    test = __opts__['test']  # noqa
+    ret = {
+        'name': name,
+        'changes': {},
+        'result': False,
+        'comment': '',
+    }
+    result = False
+    if test:
+        status = success_msgs[0]
+        ret['changes'][name] = status
+        ret['comment'] = '%s "%s" %s' % (display_name, name, status.lower())
+    else:
+        call_result = call_groovy_script(template, params)
+        if call_result["code"] == 200 and call_result["msg"].strip() in success_msgs:
+            status = call_result["msg"]
+            if status == success_msgs[0]:
+                ret['changes'][name] = status
+            ret['comment'] = '%s "%s" %s' % (display_name, name, status.lower())
+            result = True
+        else:
+            status = 'FAILED'
+            logger.error(
+                'Jenkins API call failure: %s', call_result["msg"])
+            ret['comment'] = 'Jenkins API call failure: %s' % (call_result[
+                "msg"])
+    ret['result'] = None if test else result
+    return ret
+
diff --git a/_states/jenkins_node.py b/_states/jenkins_node.py
index fe0d0eb..29e9c2c 100644
--- a/_states/jenkins_node.py
+++ b/_states/jenkins_node.py
@@ -1,110 +1,3 @@
-import logging
-
-logger = logging.getLogger(__name__)
-
-create_node_groovy = u"""\
-import jenkins.model.*
-import hudson.model.*
-import hudson.slaves.*
-import hudson.plugins.sshslaves.*
-
-def launcherName = ${launcher}.getClass().getName()
-def retStrategyName = new hudson.slaves.RetentionStrategy.${ret_strategy}().getClass().getName()
-
-
-switch (launcherName) {
-  case 'hudson.slaves.JNLPLauncher':
-    result = Jenkins.instance.slaves.find{
-               it.name == "${name}" &&
-               it.numExecutors == ${num_executors} &&
-               it.nodeDescription == "${desc}" &&
-               it.remoteFS == "${remote_home}" &&
-               it.labelString == "${label}" &&
-               it.mode == Node.Mode.${node_mode} &&
-               it.launcher.tunnel == ("${tunnel}" ?: null) &&
-               it.launcher.vmargs == ("${jvmopts}" ?: null) &&
-               it.launcher.getClass().getName().equals(launcherName) &&
-               it.retentionStrategy.getClass().getName().equals(retStrategyName)
-             }
-    break
-  default:
-    result = Jenkins.instance.slaves.find{
-               it.name == "${name}" &&
-               it.numExecutors == ${num_executors} &&
-               it.nodeDescription == "${desc}" &&
-               it.remoteFS == "${remote_home}" &&
-               it.labelString == "${label}" &&
-               it.mode == Node.Mode.${node_mode} &&
-               it.launcher.jvmOptions == "${jvmopts}" &&
-               it.launcher.getClass().getName().equals(launcherName) &&
-               it.retentionStrategy.getClass().getName().equals(retStrategyName)
-             }
-    break
-}
-
-if(result){
-  print("EXISTS")
-}else{
-  Slave slave = new DumbSlave(
-                    "${name}",
-                    "${desc}",
-                    "${remote_home}",
-                    "${num_executors}",
-                    Node.Mode.${node_mode},
-                    "${label}",
-                    ${launcher},
-                    new RetentionStrategy.${ret_strategy}(),
-                    new LinkedList())
-  Jenkins.instance.addNode(slave)
-  print("CREATED")
-}
-"""  # noqa
-
-create_lbl_groovy = u"""\
-hudson = hudson.model.Hudson.instance
-updated = false
-hudson.slaves.find { slave -> slave.nodeName.equals("${name}")
-  if({append}){
-    slave.labelString = slave.labelString + " " + "${lbl_text}"
-  }else{
-    slave.labelString = "${lbl_text}"
-  }
-  updated = true
-  print "${lbl_text}"
-}
-if(!updated){
-    print "FAILED"
-}
-hudson.save()
-"""  # noqa
-
-configure_master_groovy = u"""\
-def instance = Jenkins.instance
-def changed = false
-
-if(Jenkins.instance.numExecutors != ${num_executors}){
-    Jenkins.instance.setNumExecutors(${num_executors})
-    changed = true
-}
-
-if(!Jenkins.instance.mode.name.equals(new String("${node_mode}").toUpperCase())){
-    Jenkins.instance.setMode(Node.Mode.${node_mode})
-    changed = true
-}
-
-if(!Jenkins.instance.labelString.equals("${labels}")){
-    Jenkins.instance.setLabelString("${labels}")
-    changed = true
-}
-if(changed){
-    Jenkins.instance.save()
-    print("CREATED")
-}else{
-    print("EXISTS")
-}
-"""
-
-
 def __virtual__():
     '''
     Only load if jenkins_common module exist.
@@ -125,35 +18,17 @@
     :param lbl_text: label text
     :returns: salt-specified state dict
     """
-    test = __opts__['test']  # noqa
-    ret = {
-        'name': name,
-        'changes': {},
-        'result': False,
-        'comment': '',
-    }
-    result = False
-    if test:
-        status = 'CREATED'
-        ret['changes'][name] = status
-        ret['comment'] = 'Label %s %s' % (name, status.lower())
-    else:
-        call_result = __salt__['jenkins_common.call_groovy_script'](
-            create_lbl_groovy, {'name': name, 'lbl_text': lbl_text, 'append': "true" if append else "false"})
-        if call_result["code"] == 200 and call_result["msg"].strip(
-        ) == lbl_text:
-            status = "CREATED"
-            ret['changes'][name] = status
-            ret['comment'] = 'Label %s %s ' % (name, status.lower())
-            result = True
-        else:
-            status = 'FAILED'
-            logger.error(
-                "Jenkins label API call failure: %s", call_result["msg"])
-            ret['comment'] = 'Jenkins label API call failure: %s' % (
-                call_result["msg"])
-    ret['result'] = None if test else result
-    return ret
+    template = __salt__['jenkins_common.load_template'](
+        'salt://jenkins/files/groovy/node_label.template',
+        __env__)
+    return __salt__['jenkins_common.api_call'](name, template,
+                        ["CREATED", lbl_text],
+                        {
+                            'name': name,
+                            'lbl_text': lbl_text,
+                            'append': "true" if append else "false"
+                        },
+                        'Node Label')
 
 
 def present(name, remote_home, launcher, num_executors="1",
@@ -171,64 +46,42 @@
     :param ret_strategy: node retention strategy from RetentionStrategy class
     :returns: salt-specified state dict
     """
-    test = __opts__['test']  # noqa
-    ret = {
-        'name': name,
-        'changes': {},
-        'result': False,
-        'comment': '',
-    }
-    result = False
-    if test:
-        status = 'CREATED'
-        ret['changes'][name] = status
-        ret['comment'] = 'Node %s %s' % (name, status.lower())
-    else:
-        label_string = " ".join(labels)
-        launcher_string = "new hudson.slaves.JNLPLauncher()"
-        tunnel_string = ""
-        jvmopts_string = ""
-        if "jvmopts" in launcher:
-            jvmopts_string = launcher["jvmopts"]
-        if launcher:
-            if launcher["type"] == "ssh":
-                launcher_string = 'new hudson.plugins.sshslaves.SSHLauncher("{}",{},"{}","{}","","{}","","","")'.format(
-                    launcher["host"], launcher["port"], launcher["username"],
-                    launcher["password"], jvmopts_string)
-            elif launcher["type"] == "jnlp":
-                if "tunnel" in launcher:
-                    tunnel_string = launcher["tunnel"]
-                launcher_string = 'new hudson.slaves.JNLPLauncher("{}","{}")'.format(
-                    tunnel_string, jvmopts_string)
+    template = __salt__['jenkins_common.load_template'](
+        'salt://jenkins/files/groovy/node.template',
+        __env__)
 
-        call_result = __salt__['jenkins_common.call_groovy_script'](
-            create_node_groovy,
-            {"name": name,
-                "desc": desc if desc else "",
-                "label": label_string if label_string else "",
-                "remote_home": remote_home if remote_home else "",
-                "num_executors": num_executors if num_executors else "1",
-                "launcher": launcher_string,
-                "tunnel": tunnel_string,
-                "jvmopts": jvmopts_string,
-                "node_mode": node_mode.upper(),
-                "ret_strategy": ret_strategy if ret_strategy else "Always"})
-        if call_result["code"] == 200 and call_result["msg"] in [
-                "CREATED", "EXISTS"]:
-            status = call_result["msg"]
-            if call_result["msg"] == "CREATED":
-                ret['changes'][name] = status
-            ret['comment'] = 'Node %s %s' % (name, status.lower())
-            result = True
-        else:
-            status = 'FAILED'
-            logger.error(
-                "Jenkins node API call failure: %s", call_result["msg"])
-            ret['comment'] = 'Jenkins node API call failure: %s' % (
-                call_result["msg"])
-    ret['result'] = None if test else result
-    return ret
+    label_string = " ".join(labels)
+    launcher_string = "new hudson.slaves.JNLPLauncher()"
+    tunnel_string = ""
+    jvmopts_string = ""
+    if "jvmopts" in launcher:
+        jvmopts_string = launcher["jvmopts"]
+    if launcher:
+        if launcher["type"] == "ssh":
+            launcher_string = 'new hudson.plugins.sshslaves.SSHLauncher("{}",{},"{}","{}","","{}","","","")'.format(
+                launcher["host"], launcher["port"], launcher["username"],
+                launcher["password"], jvmopts_string)
+        elif launcher["type"] == "jnlp":
+            if "tunnel" in launcher:
+                tunnel_string = launcher["tunnel"]
+            launcher_string = 'new hudson.slaves.JNLPLauncher("{}","{}")'.format(
+                tunnel_string, jvmopts_string)
 
+    return __salt__['jenkins_common.api_call'](name, template,
+        ["CREATED", "EXISTS"],
+        {
+            "name": name,
+            "desc": desc if desc else "",
+            "label": label_string if label_string else "",
+            "remote_home": remote_home if remote_home else "",
+            "num_executors": num_executors if num_executors else "1",
+            "launcher": launcher_string,
+            "tunnel": tunnel_string,
+            "jvmopts": jvmopts_string,
+            "node_mode": node_mode.upper(),
+            "ret_strategy": ret_strategy if ret_strategy else "Always"
+        },
+        'Node')
 
 def setup_master(name, num_executors="1", node_mode="Normal", labels=[]):
     """
@@ -240,33 +93,15 @@
     :param labels: array of labels
     :returns: salt-specified state dict
     """
-    test = __opts__['test']  # noqa
-    ret = {
-        'name': name,
-        'changes': {},
-        'result': False,
-        'comment': '',
-    }
-    result = False
-    if test:
-        status = 'CREATED'
-        ret['changes'][name] = status
-        ret['comment'] = 'Master node %s' % (status.lower())
-    else:
-        call_result = __salt__['jenkins_common.call_groovy_script'](
-            configure_master_groovy, {'num_executors': num_executors, 'labels': " ".join(labels), 'node_mode': node_mode.upper()})
-        if call_result["code"] == 200 and call_result["msg"] in [
-                "CREATED", "EXISTS"]:
-            status = call_result["msg"]
-            if status == "CREATED":
-                ret['changes'][name] = status
-            ret['comment'] = 'Master node configuration %s ' % (status.lower())
-            result = True
-        else:
-            status = 'FAILED'
-            logger.error(
-                "Jenkins master configure API call failure: %s", call_result["msg"])
-            ret['comment'] = 'Jenkins master configure API call failure: %s' % (
-                call_result["msg"])
-    ret['result'] = None if test else result
-    return ret
+    template = __salt__['jenkins_common.load_template'](
+        'salt://jenkins/files/groovy/master_node.template',
+        __env__)
+    return __salt__['jenkins_common.api_call'](name, template,
+        ["CREATED", "EXISTS"],
+        {
+            'num_executors': num_executors,
+            'labels': " ".join(labels),
+            'node_mode': node_mode.upper()
+        },
+        'Master node configuration')
+
diff --git a/jenkins/files/groovy/master_node.template b/jenkins/files/groovy/master_node.template
new file mode 100644
index 0000000..26d18d0
--- /dev/null
+++ b/jenkins/files/groovy/master_node.template
@@ -0,0 +1,25 @@
+#!groovy
+def instance = Jenkins.instance
+def changed = false
+
+if(Jenkins.instance.numExecutors != ${num_executors}){
+    Jenkins.instance.setNumExecutors(${num_executors})
+    changed = true
+}
+
+if(!Jenkins.instance.mode.name.equals(new String("${node_mode}").toUpperCase())){
+    Jenkins.instance.setMode(Node.Mode.${node_mode})
+    changed = true
+}
+
+if(!Jenkins.instance.labelString.equals("${labels}")){
+    Jenkins.instance.setLabelString("${labels}")
+    changed = true
+}
+if(changed){
+    Jenkins.instance.save()
+    print("CREATED")
+}else{
+    print("EXISTS")
+}
+
diff --git a/jenkins/files/groovy/node.template b/jenkins/files/groovy/node.template
new file mode 100644
index 0000000..827e928
--- /dev/null
+++ b/jenkins/files/groovy/node.template
@@ -0,0 +1,58 @@
+#!groovy
+
+import jenkins.model.*
+import hudson.model.*
+import hudson.slaves.*
+import hudson.plugins.sshslaves.*
+
+def launcherName = ${launcher}.getClass().getName()
+def retStrategyName = new hudson.slaves.RetentionStrategy.${ret_strategy}().getClass().getName()
+
+
+switch (launcherName) {
+  case 'hudson.slaves.JNLPLauncher':
+    result = Jenkins.instance.slaves.find{
+               it.name == "${name}" &&
+               it.numExecutors == ${num_executors} &&
+               it.nodeDescription == "${desc}" &&
+               it.remoteFS == "${remote_home}" &&
+               it.labelString == "${label}" &&
+               it.mode == Node.Mode.${node_mode} &&
+               it.launcher.tunnel == ("${tunnel}" ?: null) &&
+               it.launcher.vmargs == ("${jvmopts}" ?: null) &&
+               it.launcher.getClass().getName().equals(launcherName) &&
+               it.retentionStrategy.getClass().getName().equals(retStrategyName)
+             }
+    break
+  default:
+    result = Jenkins.instance.slaves.find{
+               it.name == "${name}" &&
+               it.numExecutors == ${num_executors} &&
+               it.nodeDescription == "${desc}" &&
+               it.remoteFS == "${remote_home}" &&
+               it.labelString == "${label}" &&
+               it.mode == Node.Mode.${node_mode} &&
+               it.launcher.jvmOptions == "${jvmopts}" &&
+               it.launcher.getClass().getName().equals(launcherName) &&
+               it.retentionStrategy.getClass().getName().equals(retStrategyName)
+             }
+    break
+}
+
+if(result){
+  print("EXISTS")
+}else{
+  Slave slave = new DumbSlave(
+                    "${name}",
+                    "${desc}",
+                    "${remote_home}",
+                    "${num_executors}",
+                    Node.Mode.${node_mode},
+                    "${label}",
+                    ${launcher},
+                    new RetentionStrategy.${ret_strategy}(),
+                    new LinkedList())
+  Jenkins.instance.addNode(slave)
+  print("CREATED")
+}
+
diff --git a/jenkins/files/groovy/node_label.template b/jenkins/files/groovy/node_label.template
new file mode 100644
index 0000000..3193cbb
--- /dev/null
+++ b/jenkins/files/groovy/node_label.template
@@ -0,0 +1,18 @@
+#!grovy
+
+hudson = hudson.model.Hudson.instance
+updated = false
+hudson.slaves.find { slave -> slave.nodeName.equals("${name}")
+  if({append}){
+    slave.labelString = slave.labelString + " " + "${lbl_text}"
+  }else{
+    slave.labelString = "${lbl_text}"
+  }
+  updated = true
+  print "${lbl_text}"
+}
+if(!updated){
+    print "FAILED"
+}
+hudson.save()
+