Merge "Move common Ceph function to Ceph class"
diff --git a/src/com/mirantis/mcp/Validate.groovy b/src/com/mirantis/mcp/Validate.groovy
index 0c90320..b1755b2 100644
--- a/src/com/mirantis/mcp/Validate.groovy
+++ b/src/com/mirantis/mcp/Validate.groovy
@@ -41,11 +41,12 @@
  * @param env_var               Environment variables to set in container
  * @param entrypoint            Set entrypoint to /bin/bash or leave default
  * @param mounts                Map with mounts for container
+ * @param output_replacing      Maps with regex with should be hide from output (passwords, etc)
 **/
 
 def runContainer(Map params){
     def common = new com.mirantis.mk.Common()
-    defaults = ["name": "cvp", "env_var": [], "entrypoint": true]
+    defaults = ["name": "cvp", "env_var": [], "entrypoint": true, "mounts": [:], "output_replacing": []]
     params = defaults + params
     def salt = new com.mirantis.mk.Salt()
     def variables = ''
@@ -71,8 +72,11 @@
     params.mounts.each { local, container ->
         mounts = mounts + " -v ${local}:${container}"
     }
-    salt.cmdRun(params.master, params.target, "docker run -tid --net=host --name=${params.name}" +
-                                "${mounts} -u root ${entry_point} ${variables} ${params.dockerImageLink}")
+    salt.cmdRun(params.master, params.target,
+                "docker run -tid --net=host --name=${params.name}" +
+                    "${mounts} -u root ${entry_point} ${variables} ${params.dockerImageLink}",
+                true, null, true, [],
+                params.output_replacing)
 }
 
 def runContainer(master, target, dockerImageLink, name='cvp', env_var=[], entrypoint=true, mounts=[:]){
diff --git a/src/com/mirantis/mk/Common.groovy b/src/com/mirantis/mk/Common.groovy
index 8eee149..401f4f0 100644
--- a/src/com/mirantis/mk/Common.groovy
+++ b/src/com/mirantis/mk/Common.groovy
@@ -147,6 +147,16 @@
 }
 
 /**
+ * Print informational message
+ *
+ * @param msg
+ * @param color Colorful output or not
+ */
+def infoSensitivityMsg(msg, color = true, replacing = []) {
+    printSensitivityMsg(msg, "cyan", replacing)
+}
+
+/**
  * Print error message
  *
  * @param msg
@@ -215,6 +225,25 @@
 }
 
 /**
+ * Print sensitivity message
+ *
+ * @param msg Message to be printed
+ * @param color Color to use for output
+ * @param replacing List with maps for deletion (passwords, logins, etc).
+ *                  The first () matching is mandatory !
+ *                  Example:
+ *                  [/ (OS_PASSWORD=)(.*?)+ /,
+ *                   / (password = )(.*?)+ /,
+ *                   / (password )(.*?) / ]
+ */
+def printSensitivityMsg(msg, color, replacing = []) {
+    for (i in replacing) {
+        msg = msg.replaceAll(i, ' $1XXXXXX ')
+    }
+    printMsg(msg, color)
+}
+
+/**
  * Traverse directory structure and return list of files
  *
  * @param path Path to search
diff --git a/src/com/mirantis/mk/ReleaseWorkflow.groovy b/src/com/mirantis/mk/ReleaseWorkflow.groovy
index adb49a6..c27fa8a 100644
--- a/src/com/mirantis/mk/ReleaseWorkflow.groovy
+++ b/src/com/mirantis/mk/ReleaseWorkflow.groovy
@@ -69,10 +69,30 @@
 }
 
 /**
- * Update release metadata value and upload CR to release metadata repository
+ * Get release metadata value for given key
  *
  * @param key metadata key
- * @param value metadata value
+ * @param metadataDir metadata directory
+ * @param dirdepth the level at which YAML file should be created
+ */
+
+def precreateKeyReleaseMetadataFile(String key, String metadataDir, Integer dirdepth = 0) {
+    def keySize = key.split(':').size() - 1
+    if (dirdepth > 0 && dirdepth - 1 <= keySize) {
+        def dirPath = metadataDir + '/' + key.split(':')[0..dirdepth - 1].join('/')
+        sh "if ! test -d \"${dirPath}\" ; then mkdir -p \"${dirPath}\"; fi"
+        if (dirdepth - 1 != keySize) {
+            def pathToDummyFile = dirPath + '/' + key.split(':')[dirdepth] + '.yml'
+            sh "if ! test -f \"${pathToDummyFile}\" ; then touch \"${pathToDummyFile}\"; fi"
+        }
+    }
+}
+
+/**
+ * Update release metadata value and upload CR to release metadata repository
+ *
+ * @param key metadata key (Several keys could be passed joined by ';' character)
+ * @param value metadata value (Several values could be passed joined by ';' character)
  * @param params map with expected parameters:
  *    - metadataCredentialsId
  *    - metadataGitRepoUrl
@@ -138,18 +158,17 @@
             git.createGitBranch(repoDir, crTopic)
         }
 
-        def keySize = key.split(':').size() - 1
-        if (dirdepth > 0 && dirdepth - 1 <= keySize) {
-            def dirPath = metadataDir + '/' + key.split(':')[0..dirdepth - 1].join('/')
-            sh "if ! test -d \"${dirPath}\" ; then mkdir -p \"${dirPath}\"; fi"
-            if (dirdepth - 1 != keySize) {
-                def pathToDummyFile = dirPath + '/' + key.split(':')[dirdepth] + '.yml'
-                sh "if ! test -f \"${pathToDummyFile}\" ; then touch \"${pathToDummyFile}\"; fi"
+        def keyArr = key.split(';')
+        def valueArr = value.split(';')
+        if (keyArr.size() == valueArr.size()) {
+            for (i in 0..keyArr.size()-1) {
+                precreateKeyReleaseMetadataFile(keyArr[i], metadataDir, dirdepth)
+
+                cmdText = "python '${repoDir}/utils/app.py' --path '${metadataDir}' update --key '${keyArr[i]}' --value '${valueArr[i]}'"
+                python.runVirtualenvCommand(venvDir, cmdText)
             }
         }
 
-        cmdText = "python '${repoDir}/utils/app.py' --path '${metadataDir}' update --key '${key}' --value '${value}'"
-        python.runVirtualenvCommand(venvDir, cmdText)
         commitMessage =
                 """${comment}
 
diff --git a/src/com/mirantis/mk/Salt.groovy b/src/com/mirantis/mk/Salt.groovy
index 8c6384c..f4147e0 100644
--- a/src/com/mirantis/mk/Salt.groovy
+++ b/src/com/mirantis/mk/Salt.groovy
@@ -331,12 +331,13 @@
  * @param batch salt batch parameter integer or string with percents (optional, default null - disable batch)
  * @param output do you want to print output
  * @param saltArgs additional salt args eq. ["runas=aptly"]
+ * @param replacing list with maps for deletion in info message (passwords, logins, etc)
  * @return output of salt command
  */
-def cmdRun(saltId, target, cmd, checkResponse = true, batch=null, output = true, saltArgs = []) {
+def cmdRun(saltId, target, cmd, checkResponse = true, batch=null, output = true, saltArgs = [], replacing = []) {
     def common = new com.mirantis.mk.Common()
     def originalCmd = cmd
-    common.infoMsg("Running command ${cmd} on ${target}")
+    common.infoSensitivityMsg("Running command ${cmd} on ${target}", true, replacing)
     if (checkResponse) {
       cmd = cmd + " && echo Salt command execution success"
     }