Merge "Fix kill stuck jobs pipeline"
diff --git a/cicd-lab-pipeline.groovy b/cicd-lab-pipeline.groovy
index b68fc4e..08b21eb 100644
--- a/cicd-lab-pipeline.groovy
+++ b/cicd-lab-pipeline.groovy
@@ -148,7 +148,10 @@
             }
 
             stage("Deploy Docker services") {
-                salt.enforceState(saltMaster, 'I@docker:swarm:role:master', 'docker.client')
+                retry(2) {
+                    sleep(5)
+                    salt.enforceState(saltMaster, 'I@docker:swarm:role:master', 'docker.client')
+                }
             }
 
             stage("Configure CI/CD services") {
diff --git a/gating-pipeline.groovy b/gating-pipeline.groovy
index c056f38..89ac78f 100644
--- a/gating-pipeline.groovy
+++ b/gating-pipeline.groovy
@@ -20,8 +20,9 @@
           def gerritProjectArray = GERRIT_PROJECT.tokenize("/")
           def gerritProject = gerritProjectArray[gerritProjectArray.size() - 1]
           def jobsNamespace = JOBS_NAMESPACE
+          def plural_namespaces = ['salt-formulas', 'salt-models']
           // remove plural s on the end of job namespace
-          if (JOBS_NAMESPACE[JOBS_NAMESPACE.length() - 1].equals("s")){
+          if (JOBS_NAMESPACE in plural_namespaces){
             jobsNamespace = JOBS_NAMESPACE.substring(0, JOBS_NAMESPACE.length() - 1)
           }
           def testJob = String.format("test-%s-%s", jobsNamespace, gerritProject)
@@ -57,4 +58,4 @@
 @NonCPS
 def _jobExists(jobName){
   return Jenkins.instance.items.find{it -> it.name.equals(jobName)}
-}
\ No newline at end of file
+}
diff --git a/generate-cookiecutter-products.groovy b/generate-cookiecutter-products.groovy
index 0986c4e..4092068 100644
--- a/generate-cookiecutter-products.groovy
+++ b/generate-cookiecutter-products.groovy
@@ -28,16 +28,19 @@
         def modelEnv = "${env.WORKSPACE}/model"
 
         try {
-            def templateContext = python.loadJson(COOKIECUTTER_TEMPLATE_CONTEXT)
+            def templateContext = readYaml text: COOKIECUTTER_TEMPLATE_CONTEXT
             def templateDir = "${templateEnv}/template/dir"
             def templateOutputDir = "${env.WORKSPACE}/template"
             def cutterEnv = "${env.WORKSPACE}/cutter"
             def jinjaEnv = "${env.WORKSPACE}/jinja"
-            def clusterName = templateContext.cluster_name
-            def clusterDomain = templateContext.cluster_domain
+            def clusterName = templateContext.default_context.cluster_name
+            def clusterDomain = templateContext.default_context.cluster_domain
             def targetBranch = "feature/${clusterName}"
             def outputDestination = "${modelEnv}/classes/cluster/${clusterName}"
 
+            currentBuild.description = clusterName
+            print("Using context:\n" + COOKIECUTTER_TEMPLATE_CONTEXT)
+
             stage ('Download Cookiecutter template') {
                 git.checkoutGitRepository(templateEnv, COOKIECUTTER_TEMPLATE_URL, COOKIECUTTER_TEMPLATE_BRANCH, COOKIECUTTER_TEMPLATE_CREDENTIALS)
             }
@@ -54,7 +57,7 @@
                 sh "mkdir -p ${templateOutputDir}"
                 sh "mkdir -p ${outputDestination}"
                 python.setupCookiecutterVirtualenv(cutterEnv)
-                python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+                python.buildCookiecutterTemplate(templateDir, COOKIECUTTER_TEMPLATE_CONTEXT, templateOutputDir, cutterEnv)
                 sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
             }
 
@@ -64,7 +67,7 @@
                     templateOutputDir = "${env.WORKSPACE}/template/output/cicd"
                     sh "mkdir -p ${templateOutputDir}"
                     python.setupCookiecutterVirtualenv(cutterEnv)
-                    python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+                    python.buildCookiecutterTemplate(templateDir, COOKIECUTTER_TEMPLATE_CONTEXT, templateOutputDir, cutterEnv)
                     sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
                 }
             }
@@ -75,7 +78,7 @@
                     templateOutputDir = "${env.WORKSPACE}/template/output/opencontrail"
                     sh "mkdir -p ${templateOutputDir}"
                     python.setupCookiecutterVirtualenv(cutterEnv)
-                    python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+                    python.buildCookiecutterTemplate(templateDir, COOKIECUTTER_TEMPLATE_CONTEXT, templateOutputDir, cutterEnv)
                     sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
                 }
             }
@@ -86,7 +89,7 @@
                     templateOutputDir = "${env.WORKSPACE}/template/output/kubernetes"
                     sh "mkdir -p ${templateOutputDir}"
                     python.setupCookiecutterVirtualenv(cutterEnv)
-                    python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+                    python.buildCookiecutterTemplate(templateDir, COOKIECUTTER_TEMPLATE_CONTEXT, templateOutputDir, cutterEnv)
                     sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
                 }
             }
@@ -97,7 +100,7 @@
                     templateOutputDir = "${env.WORKSPACE}/template/output/openstack"
                     sh "mkdir -p ${templateOutputDir}"
                     python.setupCookiecutterVirtualenv(cutterEnv)
-                    python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+                    python.buildCookiecutterTemplate(templateDir, COOKIECUTTER_TEMPLATE_CONTEXT, templateOutputDir, cutterEnv)
                     sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
                 }
             }
@@ -108,7 +111,7 @@
                     templateOutputDir = "${env.WORKSPACE}/template/output/stacklight"
                     sh "mkdir -p ${templateOutputDir}"
                     python.setupCookiecutterVirtualenv(cutterEnv)
-                    python.buildCookiecutterTemplate(templateDir, templateContext, templateOutputDir, cutterEnv)
+                    python.buildCookiecutterTemplate(templateDir, COOKIECUTTER_TEMPLATE_CONTEXT, templateOutputDir, cutterEnv)
                     sh "mv -v ${templateOutputDir}/${clusterName}/* ${outputDestination}"
                 }
             }
@@ -130,12 +133,6 @@
                 writeFile(file: nodeFile, text: nodeString)
             }
 
-            stage('Inject changes to Reclass model') {
-                def outputSource = "${env.WORKSPACE}/template/output/"
-                sh "mkdir -p ${outputDestination}"
-                sh(returnStdout: true, script: "cp -vr ${outputSource} ${outputDestination}")
-            }
-
             stage ('Save changes to Reclass model') {
                 if (COMMIT_CHANGES.toBoolean()) {
                     git.changeGitBranch(modelEnv, targetBranch)
diff --git a/lab-pipeline.groovy b/lab-pipeline.groovy
index 5b7cc11..ae22301 100644
--- a/lab-pipeline.groovy
+++ b/lab-pipeline.groovy
@@ -308,7 +308,10 @@
                     // populate keystone services/tenants/roles/users
 
                     // keystone:client must be called locally
-                    salt.runSaltProcessStep(saltMaster, 'I@keystone:client', 'cmd.run', ['salt-call state.sls keystone.client'], null, true)
+                    //salt.runSaltProcessStep(saltMaster, 'I@keystone:client', 'cmd.run', ['salt-call state.sls keystone.client'], null, true)
+                    salt.runSaltProcessStep(saltMaster, 'I@keystone:server', 'service.restart', ['apache2'])
+                    salt.enforceState(saltMaster, 'I@keystone:client', 'keystone.client', true)
+                    salt.enforceState(saltMaster, 'I@keystone:client', 'keystone.client', true)
                     salt.runSaltProcessStep(saltMaster, 'I@keystone:server', 'cmd.run', ['. /root/keystonerc; keystone service-list'], null, true)
 
                     // Install glance and ensure glusterfs clusters
diff --git a/test-nodejs-pipeline.groovy b/test-nodejs-pipeline.groovy
index 30ea642..d0365a4 100644
--- a/test-nodejs-pipeline.groovy
+++ b/test-nodejs-pipeline.groovy
@@ -21,14 +21,40 @@
     }
 }
 
+
+def gerritRef
+try {
+    gerritRef = GERRIT_REFSPEC
+} catch (MissingPropertyException e) {
+    gerritRef = null
+}
+
+def defaultGitRef, defaultGitUrl
+try {
+    defaultGitRef = DEFAULT_GIT_REF
+    defaultGitUrl = DEFAULT_GIT_URL
+} catch (MissingPropertyException e) {
+    defaultGitRef = null
+    defaultGitUrl = null
+}
+def checkouted = false
+
 node("docker") {
     def containerId
     try {
         stage('Checkout source code') {
-            gerrit.gerritPatchsetCheckout ([
-              credentialsId : CREDENTIALS_ID,
-              withWipeOut : true,
-            ])
+            if (gerritRef) {
+                // job is triggered by Gerrit
+                checkouted = gerrit.gerritPatchsetCheckout ([
+                    credentialsId : CREDENTIALS_ID,
+                    withWipeOut : true,
+                ])
+             } else if(defaultGitRef && defaultGitUrl) {
+                 checkouted = gerrit.gerritPatchsetCheckout(defaultGitUrl, defaultGitRef, "HEAD", CREDENTIALS_ID)
+             }
+             if(!checkouted){
+                 throw new Exception("Cannot checkout gerrit patchset, GERRIT_REFSPEC and DEFAULT_GIT_REF is null")
+             }
         }
         stage('Start container') {
             def workspace = common.getWorkspace()