Merge "waitForInputThenPass helper"
diff --git a/src/com/mirantis/mcp/SlackNotification.groovy b/src/com/mirantis/mcp/SlackNotification.groovy
new file mode 100644
index 0000000..d78d63a
--- /dev/null
+++ b/src/com/mirantis/mcp/SlackNotification.groovy
@@ -0,0 +1,76 @@
+package com.mirantis.mcp
+
+/**
+ * Send POST request to url with some params
+ * @param urlString url
+ * @param paramString JSON string
+ */
+def sendPostRequest(String urlString, String paramString){
+    def url = new URL(urlString)
+    def conn = url.openConnection()
+    conn.setDoOutput(true)
+    def writer = new OutputStreamWriter(conn.getOutputStream())
+    writer.write(paramString)
+    writer.flush()
+    String line
+    def reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))
+    while ((line = reader.readLine()) != null) {
+        println line
+    }
+    writer.close()
+    reader.close()
+}
+
+/**
+ * Send slack notification
+ * @param buildStatusParam message type (success, warning, error)
+ * @param jobName job name param, if empty env.JOB_NAME will be used
+ * @param buildNumber build number param, if empty env.BUILD_NUM will be used
+ * @param buildUrl build url param, if empty env.BUILD_URL will be used
+ * @param channel param, default is '#mk-ci'
+ * @param credentialsId slack hook url credential, default is 'SLACK_WEBHOOK_URL'
+ */
+def jobResultNotification(String buildStatusParam, String channel = "#mk-ci",
+                          String jobName=null,
+                          Number buildNumber=null, String buildUrl=null,
+                          String credentialsId="SLACK_WEBHOOK_URL") {
+    def jobNameParam = jobName != null && jobName != "" ? jobName : env.JOB_NAME
+    def buildUrlParam = buildUrl != null && buildUrl != "" ? buildUrl : env.BUILD_URL
+    def buildNumberParam = buildNumber != null && buildNumber != "" ? buildNumber : env.BUILD_NUMBER
+
+
+    def common = new com.mirantis.mk.Common()
+    cred = common.getCredentialsById(credentialsId)
+    hook_url_parsed = cred.getSecret().toString()
+    if (buildStatusParam.toLowerCase().equals("success")) {
+        colorCode = "#00FF00"
+        colorName = "green"
+    } else if (buildStatusParam.toLowerCase().equals("unstable")) {
+        colorCode = "#FFFF00"
+        colorName = "yellow"
+    } else if (buildStatusParam.toLowerCase().equals("failure")) {
+        colorCode = "#FF0000"
+        colorName = "red"
+    }
+
+    queryString = 'payload={' +
+            "'text':'${buildStatusParam.toUpperCase()}: Job <${buildUrlParam}|${jobNameParam} [${buildNumberParam}]>', " +
+            "'color':'${colorCode}'," +
+            "'pretext': '', " +
+            '"icon_url": "https://cfr.slack-edge.com/ae7f/img/services/jenkins-ci_192.png",' +
+            "'channel': '${channel}', " +
+            '}'
+    sendPostRequest(hook_url_parsed, queryString)
+
+}
+
+/*
+node {
+    jobResultNotification(
+            "success",
+            "#test_reclass_notify",
+            "test-reclass-system",
+            44,
+            "https://ci.mcp.mirantis.net/",)
+}
+*/
diff --git a/src/com/mirantis/mk/Aws.groovy b/src/com/mirantis/mk/Aws.groovy
index 6a9c8ae..5c07193 100644
--- a/src/com/mirantis/mk/Aws.groovy
+++ b/src/com/mirantis/mk/Aws.groovy
@@ -123,14 +123,14 @@
 
                 // check for desired state
                 if (stack_info['StackStatus'] == state) {
-                    common.successMsg("Stack ${stack_name} in in state ${state}")
+                    common.successMsg("Stack ${stack_name} is in state ${state}")
                     common.prettyPrint(stack_info)
                     break
                 }
 
                 // check for failed state
                 if (state_failed.contains(stack_info['StackStatus'])) {
-                    throw new Exception("Stack ${stack_name} in in failed state")
+                    throw new Exception("Stack ${stack_name} is in failed state")
                 }
 
                 // print stack resources
diff --git a/src/com/mirantis/mk/Debian.groovy b/src/com/mirantis/mk/Debian.groovy
index 94b0598..4d7b1ee 100644
--- a/src/com/mirantis/mk/Debian.groovy
+++ b/src/com/mirantis/mk/Debian.groovy
@@ -29,7 +29,7 @@
     def imageArray = image.split(":")
     def os = imageArray[0]
     def dist = imageArray[1]
-    def img = dockerLib.getImage("tcpcloud/debian-build-${os}-${dist}:latest", image)
+    def img = dockerLib.getImage("mirantis/debian-build-${os}-${dist}:latest", image)
     def workspace = common.getWorkspace()
     def debug = env.getEnvironment().containsKey("DEBUG") && env["DEBUG"].toBoolean() ? "true" : ""
 
@@ -92,7 +92,7 @@
     def imageArray = image.split(":")
     def os = imageArray[0]
     def dist = imageArray[1]
-    def img = dockerLib.getImage("tcpcloud/debian-build-${os}-${dist}:latest", image)
+    def img = dockerLib.getImage("mirantis/debian-build-${os}-${dist}:latest", image)
     def workspace = common.getWorkspace()
 
     img.inside("-u root:root" ) {
@@ -123,7 +123,7 @@
     def imageArray = image.split(":")
     def os = imageArray[0]
     def dist = imageArray[1]
-    def img = dockerLib.getImage("tcpcloud/debian-build-${os}-${dist}:latest", image)
+    def img = dockerLib.getImage("mirantis/debian-build-${os}-${dist}:latest", image)
 
     img.inside("-u root:root") {
 
@@ -186,7 +186,7 @@
     def imageArray = image.split(":")
     def os = imageArray[0]
     def dist = imageArray[1]
-    def img = dockerLib.getImage("tcpcloud/debian-build-${os}-${dist}:latest", image)
+    def img = dockerLib.getImage("mirantis/debian-build-${os}-${dist}:latest", image)
     img.inside("-u root:root") {
         sh("""cd ${workspace} && apt-get update && apt-get install -y lintian &&
             lintian -Ii -E --pedantic --profile=${profile} ${changes}""")
diff --git a/src/com/mirantis/mk/Docker.groovy b/src/com/mirantis/mk/Docker.groovy
index 7b57e5b..796cc3c 100644
--- a/src/com/mirantis/mk/Docker.groovy
+++ b/src/com/mirantis/mk/Docker.groovy
@@ -35,7 +35,7 @@
 /**
  * Build step to build docker image.
  *
- * @param dockerHubImg     Name of image on dockerhub (ie: tcpcloud/salt-models-testing)
+ * @param dockerHubImg     Name of image on dockerhub (ie: mirantis/salt-models-testing)
  * @param defaultImg       Image to use if dockerHubImg is not found
  * @return img             Docker image
  */
diff --git a/src/com/mirantis/mk/Orchestrate.groovy b/src/com/mirantis/mk/Orchestrate.groovy
index a5beb4d..f9a5ab8 100644
--- a/src/com/mirantis/mk/Orchestrate.groovy
+++ b/src/com/mirantis/mk/Orchestrate.groovy
@@ -42,9 +42,12 @@
         salt.runSaltProcessStep(master, '*', 'cmd.shell', ["salt-call state.sls linux.network; salt-call service.restart salt-minion"], null, true, 60)
     }
     salt.enforceState(master, 'I@linux:network:interface', ['linux.network.interface'])
+    sleep(5)
     salt.enforceState(master, 'I@linux:system', ['linux', 'openssh', 'ntp', 'rsyslog'])
     salt.enforceState(master, '*', ['salt.minion'], true, false, null, false, 60, 2)
     sleep(5)
+
+    salt.fullRefresh(master, "*")
     salt.runSaltProcessStep(master, '*', 'mine.update', [], null, true)
     salt.enforceState(master, '*', ['linux.network.host'])
 
@@ -79,8 +82,11 @@
     salt.enforceState(master, target, ['salt.minion'], true, false, null, false, 60, 2)
     salt.enforceState(master, target, ['salt.minion'])
     salt.enforceState(master, target, ['linux.network.interface'])
+    sleep(5)
     salt.enforceState(master, target, ['linux', 'openssh', 'ntp', 'rsyslog'])
     sleep(5)
+
+    salt.fullRefresh(master, target)
     salt.runSaltProcessStep(master, target, 'mine.update', [], null, true)
     salt.enforceState(master, target, ['linux.network.host'])
 }
@@ -607,6 +613,9 @@
         salt.enforceState(master, 'I@kubernetes:master and *01*', 'etcd.server.setup')
     }
 
+    // Run k8s master at *01* to simplify namespaces creation
+    salt.enforceStateWithExclude(master, 'I@kubernetes:master and *01*', "kubernetes.master", "kubernetes.master.setup")
+
     // Run k8s without master.setup
     salt.enforceStateWithExclude(master, 'I@kubernetes:master', "kubernetes", "kubernetes.master.setup")
 
diff --git a/src/com/mirantis/mk/SaltModelTesting.groovy b/src/com/mirantis/mk/SaltModelTesting.groovy
index 77959db..f0921c4 100644
--- a/src/com/mirantis/mk/SaltModelTesting.groovy
+++ b/src/com/mirantis/mk/SaltModelTesting.groovy
@@ -24,7 +24,7 @@
   def saltOpts = "--retcode-passthrough --force-color"
   def common = new com.mirantis.mk.Common()
   def workspace = common.getWorkspace()
-  def img = docker.image("tcpcloud/salt-models-testing:latest")
+  def img = docker.image("mirantis/salt:saltstack-ubuntu-xenial-salt-2017.7")
   img.pull()
 
   if (!extraFormulas || extraFormulas == "") {
@@ -41,8 +41,8 @@
             "DEBUG=1", "MASTER_HOSTNAME=${masterName}", "CLUSTER_NAME=${clusterName}", "MINION_ID=${masterName}",
             "RECLASS_VERSION=${reclassVersion}", "RECLASS_IGNORE_CLASS_NOTFOUND=${ignoreClassNotfound}", "APT_REPOSITORY=${aptRepoUrl}",
             "APT_REPOSITORY_GPG=${aptRepoGPG}"]){
-
-        sh("""cp -r ${testDir}/* /srv/salt/reclass && echo '127.0.1.2  salt' >> /etc/hosts
+        sh("git clone https://github.com/salt-formulas/salt-formulas-scripts /srv/salt/scripts")
+        sh("""rsync -ah ${testDir}/* /srv/salt/reclass && echo '127.0.1.2  salt' >> /etc/hosts
               cd /srv/salt && find . -type f \\( -name '*.yml' -or -name '*.sh' \\) -exec sed -i 's/apt-mk.mirantis.com/apt.mirantis.net:8085/g' {} \\;
               cd /srv/salt && find . -type f \\( -name '*.yml' -or -name '*.sh' \\) -exec sed -i 's/apt.mirantis.com/apt.mirantis.net:8085/g' {} \\;""")
         sh("""for s in \$(python -c \"import site; print(' '.join(site.getsitepackages()))\"); do
@@ -51,15 +51,14 @@
                 done""")
         sh("""timeout ${testTimeout} bash -c 'source /srv/salt/scripts/bootstrap.sh; cd /srv/salt/scripts && source_local_envs && configure_salt_master && configure_salt_minion && install_salt_formula_pkg'
               bash -c 'source /srv/salt/scripts/bootstrap.sh; cd /srv/salt/scripts && saltservice_restart'""")
-
         sh("timeout ${testTimeout} bash -c 'source /srv/salt/scripts/bootstrap.sh; cd /srv/salt/scripts && source_local_envs && saltmaster_init'")
 
-        if (!legacyTestingMode) {
+        if (!legacyTestingMode.toBoolean()) {
            sh("bash -c 'source /srv/salt/scripts/bootstrap.sh; cd /srv/salt/scripts && verify_salt_minions'")
         }
     }
 
-    if (legacyTestingMode) {
+    if (legacyTestingMode.toBoolean()) {
       common.infoMsg("Running legacy mode test for master hostname ${masterName}")
       def nodes = sh script: "find /srv/salt/reclass/nodes -name '*.yml' | grep -v 'cfg*.yml'", returnStdout: true
       for (minion in nodes.tokenize()) {