Validate Salt minion operates after state

This patch updates salt class enforceState method
to validate Salt minion and salt api are runing properly
after state execution.

Change-Id: Ifb9eccfa29b9961a97a1352a9aabb29d78003cc3
Related-PROD: PROD-16258
diff --git a/src/com/mirantis/mk/Salt.groovy b/src/com/mirantis/mk/Salt.groovy
index 3d89fb5..92d6727 100644
--- a/src/com/mirantis/mk/Salt.groovy
+++ b/src/com/mirantis/mk/Salt.groovy
@@ -170,6 +170,7 @@
             out = runSaltCommand(saltId, 'local', ['expression': target, 'type': 'compound'], 'state.sls', batch, [run_states], kwargs, -1, read_timeout)
             checkResult(out, failOnError, output)
         }
+        waitForMinion(out)
         return out
     } else {
         common.infoMsg("No Minions matched the target given, but 'optional' param was set to true - Pipeline continues. ")
@@ -592,6 +593,30 @@
 }
 
 /**
+* Parse salt API output to check minion restart and wait some time to be sure minion is up.
+* See https://mirantis.jira.com/browse/PROD-16258 for more details
+* TODO: change sleep to more tricky procedure.
+*
+* @param result    Parsed response of Salt API
+*/
+def waitForMinion(result) {
+    def common = new com.mirantis.mk.Common()
+    def matcher = result =~ /(?s).*salt_minion_service_restart.*?(changes:\[.*?\])/
+    def isMinionRestarted = false
+    while (matcher.find()) {
+        if (matcher.group(1) != null && matcher.group(1).contains("pid")) {
+            isMinionRestarted = true
+        }
+    }
+    // There is an exception when use sleep after defined Matcher. Therefore destroy the matcher.
+    matcher = null
+    if (isMinionRestarted){
+        common.infoMsg("Salt minion service restart detected. Sleep 10 seconds to wait minion restart")
+        sleep(10)
+    }
+}
+
+/**
  * Print salt command run results in human-friendly form
  *
  * @param result        Parsed response of Salt API