Multiple source repositories and shared libraries
diff --git a/README.rst b/README.rst
index c11b4cf..2065890 100644
--- a/README.rst
+++ b/README.rst
@@ -160,31 +160,33 @@
           test_workflow_jenkins_simple:
             type: workflow
             display_name: Test jenkins simple workflow
-            script: |
-              node {
-                 stage 'Stage 1'
-                 echo 'Hello World 1'
-                 stage 'Stage 2'
-                 echo 'Hello World 2'
-              }
+            script:
+              content: |
+                node {
+                   stage 'Stage 1'
+                   echo 'Hello World 1'
+                   stage 'Stage 2'
+                   echo 'Hello World 2'
+                }
           test_workflow_jenkins_input:
             type: workflow
             display_name: Test jenkins workflow inputs
-            script: |
-              node {
-                 stage 'Enter string'
-                 input message: 'Enter job parameters', ok: 'OK', parameters: [
-                   string(defaultValue: 'default', description: 'Enter a string.', name: 'string'),
-                 ]
-                 stage 'Enter boolean'
-                 input message: 'Enter job parameters', ok: 'OK', parameters: [
-                   booleanParam(defaultValue: false, description: 'Select boolean.', name: 'Bool'),
-                 ]
-                 stage 'Enter text'
-                 input message: 'Enter job parameters', ok: 'OK', parameters: [
-                   text(defaultValue: '', description: 'Enter multiline', name: 'Multiline')
-                 ]
-              }
+            script:
+              content: |
+                node {
+                   stage 'Enter string'
+                   input message: 'Enter job parameters', ok: 'OK', parameters: [
+                     string(defaultValue: 'default', description: 'Enter a string.', name: 'string'),
+                   ]
+                   stage 'Enter boolean'
+                   input message: 'Enter job parameters', ok: 'OK', parameters: [
+                     booleanParam(defaultValue: false, description: 'Select boolean.', name: 'Bool'),
+                   ]
+                   stage 'Enter text'
+                   input message: 'Enter job parameters', ok: 'OK', parameters: [
+                     text(defaultValue: '', description: 'Enter multiline', name: 'Multiline')
+                   ]
+                }
 
 
 GIT controlled groovy script samples
@@ -194,19 +196,71 @@
     jenkins:
       client:
         source:
-          engine: git
-          address: repo_url
-          branch: branch
+          base:
+           engine: git
+            address: repo_url
+            branch: branch
+          domain:
+           engine: git
+            address: domain_url
+            branch: branch
         job:
           test_workflow_jenkins_simple:
             type: workflow
             display_name: Test jenkins simple workflow
-            script_file: jobs/test_workflow_jenkins_simple.groovy
+            param:
+              bool_param:
+                type: boolean
+                description: true/false
+                default: true
+            script:
+              repository: base
+              file: workflows/test_workflow_jenkins_simple.groovy
           test_workflow_jenkins_input:
             type: workflow
             display_name: Test jenkins workflow inputs
-            script_file: jobs/test_workflow_jenkins_input.groovy
+            script:
+              repository: domain
+              file: workflows/test_workflow_jenkins_input.groovy
+          test_workflow_jenkins_input_jenkinsfile:
+            type: workflow
+            display_name: Test jenkins workflow inputs (jenknisfile)
+            script:
+              repository: domain
+              file: workflows/test_workflow_jenkins_input/Jenkinsfile
 
+GIT controlled groovy script with shared libraries
+
+.. code-block:: yaml
+
+    jenkins:
+      client:
+        source:
+          base:
+           engine: git
+            address: repo_url
+            branch: branch
+          domain:
+           engine: git
+            address: domain_url
+            branch: branch
+        job:
+          test_workflow_jenkins_simple:
+            type: workflow
+            display_name: Test jenkins simple workflow
+            param:
+              bool_param:
+                type: boolean
+                description: true/false
+                default: true
+            script:
+              repository: base
+              file: workflows/test_workflow_jenkins_simple.groovy
+            libs:
+            - repository: base
+              file: macros/cookiecutter.groovy
+            - repository: base
+              file: macros/git.groovy
 
 Usage
 =====
diff --git a/jenkins/client.sls b/jenkins/client.sls
index 80a4af6..80cf45f 100644
--- a/jenkins/client.sls
+++ b/jenkins/client.sls
@@ -17,24 +17,28 @@
   - source: salt://jenkins/files/_jenkins.conf
   - template: jinja
 
-{%- if client.source.engine == "git" %}
+{%- for source_name, source in client.source.iteritems() %}
 
-reclass_data_source:
+{%- if source.engine == "git" %}
+
+jenkins_{{ source_name }}_source:
   git.latest:
-  - name: {{ client.source.address }}
-  - target: {{ client.dir.jenkins_root }}
-  - rev: {{ client.source.branch }}
+  - name: {{ source.address }}
+  - target: {{ client.dir.jenkins_root }}/{{ source_name }}
+  - rev: {{ source.branch }}
   - reload_pillar: True
 
 {%- elif client.source.engine == "local" %}
 
-reclass_data_dir:
+jenkins_{{ source_name }}_dir:
   file.managed:
-  - name: {{ client.dir.jenkins_root }}
+  - name: {{ client.dir.jenkins_root }}/{{ source_name }}
   - mode: 700
 
 {%- endif %}
 
+{%- endfor %}
+
 {{ client.dir.salt_root }}/_jenkins/jobs:
   file.symlink:
     - target: {{ client.dir.jenkins_root }}
diff --git a/jenkins/files/jobs/workflow.xml b/jenkins/files/jobs/workflow.xml
index 84b06bb..ce3faae 100644
--- a/jenkins/files/jobs/workflow.xml
+++ b/jenkins/files/jobs/workflow.xml
@@ -1,12 +1,19 @@
 {%- from "jenkins/map.jinja" import client with context %}
 {%- set job = salt['pillar.get']('jenkins:client:job:'+job_name) -%}
 {%- macro load_groovy_file() %}
-{%- set groovy_file='_jenkins/jobs/'+job.script_file %}
+{%- set groovy_file='_jenkins/jobs/'+job.script.repository+'/'+job.script.file %}
+{%- include groovy_file %}
+{%- endmacro %}
+{%- macro load_groovy_lib(lib) %}
+{%- set groovy_file='_jenkins/jobs/'+lib.repository+'/'+lib.file %}
 {%- include groovy_file %}
 {%- endmacro %}
 <?xml version='1.0' encoding='UTF-8'?>
 <flow-definition plugin="workflow-job@2.5">
-  <description>{{ job.get('description', 'Salt generated, do not edit.') }}</description>
+  <description>
+    Salt generated project, do not edit. Changes will be overwritten.
+    {{ job.get('description', '')|e }}
+  </description>
   {%- if job.display_name is defined %}
   <displayName>{{ job.display_name }}</displayName>
   {%- endif %}
@@ -41,7 +48,18 @@
     {%- endif %}
   </properties>
   <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.12">
-    <script>{% if job.script_file is defined %}{{ load_groovy_file()|e }}{% else %}{{ job.script|e }}{% endif %}</script>
+    <script>
+      {%- if job.libs is defined %}
+      {%- for lib in job.libs %}
+      {{- load_groovy_lib(lib)|e }}
+      {%- endfor %}
+      {%- endif %}
+      {%- if job.script.file is defined %}
+      {{- load_groovy_file()|e }}
+      {%- else %}
+      {{- job.script.get('content', '')|e }}
+      {%- endif %}
+    </script>
     <sandbox>true</sandbox>
   </definition>
   <triggers>